@@ -111,7 +111,7 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
111111 result = abstract_call_method (interp, method, sig_n, svec (), multiple_matches, sv)
112112 rt = result. rt
113113 edge = result. edge
114- edge != = nothing && push! (edges, edge)
114+ edge === nothing || push! (edges, edge)
115115 this_argtypes = isa (matches, MethodMatches) ? argtypes : matches. applicable_argtypes[i]
116116 this_arginfo = ArgInfo (fargs, this_argtypes)
117117 const_call_result = abstract_call_method_with_const_args (interp, result,
@@ -136,25 +136,11 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
136136 this_conditional = ignorelimited (this_rt)
137137 this_rt = widenwrappedconditional (this_rt)
138138 else
139- if infer_compilation_signature (interp)
140- # Also infer the compilation signature for this method, so it's available
141- # to the compiler in case it ends up needing it (which is likely).
142- csig = get_compileable_sig (method, sig, match. sparams)
143- if csig != = nothing && csig != = sig
144- # The result of this inference is not directly used, so temporarily empty
145- # the use set for the current SSA value.
146- saved_uses = sv. ssavalue_uses[sv. currpc]
147- sv. ssavalue_uses[sv. currpc] = empty_bitset
148- abstract_call_method (interp, method, csig, match. sparams, multiple_matches, sv)
149- sv. ssavalue_uses[sv. currpc] = saved_uses
150- end
151- end
152-
153139 result = abstract_call_method (interp, method, sig, match. sparams, multiple_matches, sv)
154140 this_conditional = ignorelimited (result. rt)
155141 this_rt = widenwrappedconditional (result. rt)
156142 edge = result. edge
157- edge != = nothing && push! (edges, edge)
143+ edge === nothing || push! (edges, edge)
158144 # try constant propagation with argtypes for this match
159145 # this is in preparation for inlining, or improving the return result
160146 this_argtypes = isa (matches, MethodMatches) ? argtypes : matches. applicable_argtypes[i]
@@ -214,6 +200,26 @@ function abstract_call_gf_by_type(interp::AbstractInterpreter, @nospecialize(f),
214200
215201 rettype = from_interprocedural! (rettype, sv, arginfo, conditionals)
216202
203+ # Also considering inferring the compilation signature for this method, so
204+ # it is available to the compiler in case it ends up needing it.
205+ if infer_compilation_signature (interp) && 1 == seen == napplicable && rettype != = Any && rettype != = Union{} && ! is_removable_if_unused (all_effects)
206+ match = applicable[1 ]:: MethodMatch
207+ method = match. method
208+ sig = match. spec_types
209+ mi = specialize_method (match; preexisting= true )
210+ if mi != = nothing && ! const_prop_methodinstance_heuristic (interp, match, mi:: MethodInstance , arginfo, sv)
211+ csig = get_compileable_sig (method, sig, match. sparams)
212+ if csig != = nothing && csig != = sig
213+ # The result of this inference is not directly used, so temporarily empty
214+ # the use set for the current SSA value.
215+ saved_uses = sv. ssavalue_uses[sv. currpc]
216+ sv. ssavalue_uses[sv. currpc] = empty_bitset
217+ abstract_call_method (interp, method, csig, match. sparams, multiple_matches, sv)
218+ sv. ssavalue_uses[sv. currpc] = saved_uses
219+ end
220+ end
221+ end
222+
217223 if call_result_unused (sv) && ! (rettype === Bottom)
218224 add_remark! (interp, sv, " Call result type was widened because the return value is unused" )
219225 # We're mainly only here because the optimizer might want this code,
@@ -765,13 +771,25 @@ function collect_const_args((; argtypes)::ArgInfo)
765771 isa (a, Const) ? a. val :
766772 isconstType (a) ? (a:: DataType ). parameters[1 ] :
767773 (a:: DataType ). instance
768- end for i in 2 : length (argtypes) ]
774+ end for i = 2 : length (argtypes) ]
775+ end
776+
777+ struct InvokeCall
778+ types # ::Type
779+ lookupsig # ::Type
780+ InvokeCall (@nospecialize (types), @nospecialize (lookupsig)) = new (types, lookupsig)
769781end
770782
771783function concrete_eval_call (interp:: AbstractInterpreter ,
772- @nospecialize (f), result:: MethodCallResult , arginfo:: ArgInfo , sv:: InferenceState )
784+ @nospecialize (f), result:: MethodCallResult , arginfo:: ArgInfo , sv:: InferenceState ,
785+ invokecall:: Union{Nothing,InvokeCall} = nothing )
773786 concrete_eval_eligible (interp, f, result, arginfo, sv) || return nothing
774787 args = collect_const_args (arginfo)
788+ if invokecall != = nothing
789+ # this call should be `invoke`d, rewrite `args` back now
790+ pushfirst! (args, f, invokecall. types)
791+ f = invoke
792+ end
775793 world = get_world_counter (interp)
776794 value = try
777795 Core. _call_in_world_total (world, f, args... )
@@ -811,13 +829,13 @@ struct ConstCallResults
811829 new (rt, const_result, effects)
812830end
813831
814- function abstract_call_method_with_const_args (interp:: AbstractInterpreter , result :: MethodCallResult ,
815- @nospecialize (f), arginfo:: ArgInfo , match:: MethodMatch ,
816- sv:: InferenceState )
832+ function abstract_call_method_with_const_args (interp:: AbstractInterpreter ,
833+ result :: MethodCallResult , @nospecialize (f), arginfo:: ArgInfo , match:: MethodMatch ,
834+ sv:: InferenceState , invokecall :: Union{Nothing,InvokeCall} = nothing )
817835 if ! const_prop_enabled (interp, sv, match)
818836 return nothing
819837 end
820- val = concrete_eval_call (interp, f, result, arginfo, sv)
838+ val = concrete_eval_call (interp, f, result, arginfo, sv, invokecall )
821839 if val != = nothing
822840 add_backedge! (result. edge, sv)
823841 return val
@@ -1547,10 +1565,10 @@ function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgIn
15471565 nargtype isa DataType || return CallMeta (Any, Effects (), false ) # other cases are not implemented below
15481566 isdispatchelem (ft) || return CallMeta (Any, Effects (), false ) # check that we might not have a subtype of `ft` at runtime, before doing supertype lookup below
15491567 ft = ft:: DataType
1550- types = rewrap_unionall (Tuple{ft, unwrap_unionall (types). parameters... }, types):: Type
1568+ lookupsig = rewrap_unionall (Tuple{ft, unwrap_unionall (types). parameters... }, types):: Type
15511569 nargtype = Tuple{ft, nargtype. parameters... }
15521570 argtype = Tuple{ft, argtype. parameters... }
1553- match, valid_worlds, overlayed = findsup (types , method_table (interp))
1571+ match, valid_worlds, overlayed = findsup (lookupsig , method_table (interp))
15541572 match === nothing && return CallMeta (Any, Effects (), false )
15551573 update_valid_age! (sv, valid_worlds)
15561574 method = match. method
@@ -1569,8 +1587,10 @@ function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgIn
15691587 # t, a = ti.parameters[i], argtypes′[i]
15701588 # argtypes′[i] = t ⊑ a ? t : a
15711589 # end
1572- const_call_result = abstract_call_method_with_const_args (interp, result,
1573- overlayed ? nothing : singleton_type (ft′), arginfo, match, sv)
1590+ f = overlayed ? nothing : singleton_type (ft′)
1591+ invokecall = InvokeCall (types, lookupsig)
1592+ const_call_result = abstract_call_method_with_const_args (interp,
1593+ result, f, arginfo, match, sv, invokecall)
15741594 const_result = nothing
15751595 if const_call_result != = nothing
15761596 if const_call_result. rt ⊑ rt
0 commit comments