@@ -156,6 +156,19 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
156
156
sv. ssavalue_uses[sv. currpc] = saved_uses
157
157
end
158
158
end
159
+ this_argtypes = isa (matches, MethodMatches) ? argtypes : matches. applicable_argtypes[i]
160
+ this_arginfo = ArgInfo (fargs, this_argtypes)
161
+
162
+ early_const_call_result = abstract_call_method_with_const_args_early (interp,
163
+ f, match, this_arginfo, sv)
164
+ if early_const_call_result != = nothing
165
+ this_conditional = this_rt = early_const_call_result. rt
166
+ (; effects, const_result) = early_const_call_result
167
+ tristate_merge! (sv, effects)
168
+ push! (const_results, const_result)
169
+ any_const_result = true
170
+ @goto call_computed
171
+ end
159
172
160
173
result = abstract_call_method (interp, method, sig, match. sparams, multiple_matches, sv)
161
174
this_conditional = ignorelimited (result. rt)
@@ -164,8 +177,6 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
164
177
edge != = nothing && push! (edges, edge)
165
178
# try constant propagation with argtypes for this match
166
179
# this is in preparation for inlining, or improving the return result
167
- this_argtypes = isa (matches, MethodMatches) ? argtypes : matches. applicable_argtypes[i]
168
- this_arginfo = ArgInfo (fargs, this_argtypes)
169
180
const_call_result = abstract_call_method_with_const_args (interp, result,
170
181
f, this_arginfo, match, sv)
171
182
effects = result. edge_effects
@@ -185,6 +196,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
185
196
push! (const_results, const_result)
186
197
any_const_result |= const_result != = nothing
187
198
end
199
+ @label call_computed
188
200
@assert ! (this_conditional isa Conditional) " invalid lattice element returned from inter-procedural context"
189
201
seen += 1
190
202
rettype = tmerge (rettype, this_rt)
@@ -674,10 +686,11 @@ end
674
686
function pure_eval_eligible (interp:: AbstractInterpreter ,
675
687
@nospecialize (f), applicable:: Vector{Any} , arginfo:: ArgInfo , sv:: InferenceState )
676
688
# XXX we need to check that this pure function doesn't call any overlayed method
677
- return f != = nothing &&
678
- length (applicable) == 1 &&
679
- is_method_pure (applicable[1 ]:: MethodMatch ) &&
680
- is_all_const_arg (arginfo)
689
+ f != = nothing || return false
690
+ length (applicable) == 1 || return false
691
+ match = applicable[1 ]:: MethodMatch
692
+ is_method_pure (match) || return false
693
+ return is_all_const_arg (arginfo)
681
694
end
682
695
683
696
function is_method_pure (method:: Method , @nospecialize (sig), sparams:: SimpleVector )
@@ -710,16 +723,17 @@ end
710
723
711
724
function concrete_eval_eligible (interp:: AbstractInterpreter ,
712
725
@nospecialize (f), result:: MethodCallResult , arginfo:: ArgInfo , sv:: InferenceState )
713
- # disable concrete-evaluation since this function call is tainted by some overlayed
714
- # method and currently there is no direct way to execute overlayed methods
726
+ # disable concrete-evaluation if this function call is tainted by some overlayed
727
+ # method since currently there is no direct way to execute overlayed methods
715
728
isoverlayed (method_table (interp)) && ! is_nonoverlayed (result. edge_effects) && return false
716
- return f != = nothing &&
717
- result. edge != = nothing &&
718
- is_concrete_eval_eligible (result. edge_effects) &&
719
- is_all_const_arg (arginfo)
729
+ f != = nothing || return false
730
+ result. edge != = nothing || return false
731
+ is_concrete_eval_eligible (result. edge_effects) || return false
732
+ return is_all_const_arg (arginfo)
720
733
end
721
734
722
- function is_all_const_arg ((; argtypes):: ArgInfo )
735
+ is_all_const_arg ((; argtypes):: ArgInfo ) = is_all_const_arg (argtypes)
736
+ function is_all_const_arg (argtypes:: Vector{Any} )
723
737
for i = 2 : length (argtypes)
724
738
a = widenconditional (argtypes[i])
725
739
isa (a, Const) || isconstType (a) || issingletontype (a) || return false
@@ -738,26 +752,61 @@ end
738
752
function concrete_eval_call (interp:: AbstractInterpreter ,
739
753
@nospecialize (f), result:: MethodCallResult , arginfo:: ArgInfo , sv:: InferenceState )
740
754
concrete_eval_eligible (interp, f, result, arginfo, sv) || return nothing
755
+ return _concrete_eval_call (interp, f, arginfo, result. edge, sv)
756
+ end
757
+
758
+ function _concrete_eval_call (interp:: AbstractInterpreter ,
759
+ @nospecialize (f), arginfo:: ArgInfo , edge:: MethodInstance , sv:: InferenceState )
741
760
args = collect_const_args (arginfo)
742
761
world = get_world_counter (interp)
743
762
value = try
744
763
Core. _call_in_world_total (world, f, args... )
745
764
catch
746
765
# The evaulation threw. By :consistent-cy, we're guaranteed this would have happened at runtime
747
- return ConstCallResults (Union{}, ConstResult (result . edge, result . edge_effects ), result . edge_effects )
766
+ return ConstCallResults (Union{}, ConstResult (edge, EFFECTS_THROWS ), EFFECTS_THROWS )
748
767
end
749
768
if is_inlineable_constant (value) || call_result_unused (sv)
750
769
# If the constant is not inlineable, still do the const-prop, since the
751
770
# code that led to the creation of the Const may be inlineable in the same
752
771
# circumstance and may be optimizable.
753
- return ConstCallResults (Const (value), ConstResult (result. edge, EFFECTS_TOTAL, value), EFFECTS_TOTAL)
772
+ return ConstCallResults (Const (value), ConstResult (edge, EFFECTS_TOTAL, value), EFFECTS_TOTAL)
773
+ end
774
+ return nothing
775
+ end
776
+
777
+ function early_concrete_eval_eligible (interp:: AbstractInterpreter ,
778
+ @nospecialize (f), match:: MethodMatch , arginfo:: ArgInfo , sv:: InferenceState )
779
+ # the effects for this match may not be derived yet, so disable concrete-evaluation
780
+ # immediately when the interpreter can use overlayed methods
781
+ isoverlayed (method_table (interp)) && return false
782
+ f != = nothing || return false
783
+ is_concrete_eval_eligible (decode_effects_override (match. method. purity)) || return false
784
+ return is_all_const_arg (arginfo)
785
+ end
786
+
787
+ function early_concrete_eval (interp:: AbstractInterpreter ,
788
+ @nospecialize (f), match:: MethodMatch , arginfo:: ArgInfo , sv:: InferenceState )
789
+ early_concrete_eval_eligible (interp, f, match, arginfo, sv) || return nothing
790
+ edge = specialize_method (match. method, match. spec_types, match. sparams)
791
+ edge === nothing && return nothing
792
+ return _concrete_eval_call (interp, f, arginfo, edge, sv)
793
+ end
794
+
795
+ function abstract_call_method_with_const_args_early (interp:: AbstractInterpreter ,
796
+ @nospecialize (f), match:: MethodMatch , arginfo:: ArgInfo , sv:: InferenceState )
797
+ const_prop_enabled (interp, sv, match) || return nothing
798
+ val = early_concrete_eval (interp, f, match, arginfo, sv)
799
+ if val != = nothing
800
+ add_backedge! (val. const_result. mi, sv)
801
+ return val
754
802
end
803
+ # TODO early constant prop' for `@nospecialize`d methods?
755
804
return nothing
756
805
end
757
806
758
807
function const_prop_enabled (interp:: AbstractInterpreter , sv:: InferenceState , match:: MethodMatch )
759
808
if ! InferenceParams (interp). ipo_constant_propagation
760
- add_remark! (interp, sv, " [constprop] Disabled by parameter" )
809
+ add_remark! (interp, sv, " [constprop] Disabled by inference parameter" )
761
810
return false
762
811
end
763
812
method = match. method
@@ -781,12 +830,10 @@ end
781
830
function abstract_call_method_with_const_args (interp:: AbstractInterpreter , result:: MethodCallResult ,
782
831
@nospecialize (f), arginfo:: ArgInfo , match:: MethodMatch ,
783
832
sv:: InferenceState )
784
- if ! const_prop_enabled (interp, sv, match)
785
- return nothing
786
- end
833
+ const_prop_enabled (interp, sv, match) || return nothing
787
834
val = concrete_eval_call (interp, f, result, arginfo, sv)
788
835
if val != = nothing
789
- add_backedge! (result . edge , sv)
836
+ add_backedge! (val . const_result . mi , sv)
790
837
return val
791
838
end
792
839
mi = maybe_get_const_prop_profitable (interp, result, f, arginfo, match, sv)
0 commit comments