From 2d9a2ee3c71a60d68386e3172f8f86adb5676fa0 Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki <40514306+aviatesk@users.noreply.github.com> Date: Fri, 15 Nov 2024 15:08:47 +0900 Subject: [PATCH] optimize `abstract_invoke` (#56560) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - removed unnecessary `Core.Box` allocation - made the type of the closure that is passed to `Future` concrete That said, it doesn’t seem ideal to require this sort of manual optimizations.. The value of using closures cannot be denied in this code base, and I feel that it would be better to work towards optimizing closures more (as we do with JuliaLang/julia#56532)? --- Compiler/src/abstractinterpretation.jl | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/Compiler/src/abstractinterpretation.jl b/Compiler/src/abstractinterpretation.jl index faaba0c2dc44f..093c5889f809e 100644 --- a/Compiler/src/abstractinterpretation.jl +++ b/Compiler/src/abstractinterpretation.jl @@ -2182,27 +2182,26 @@ function abstract_invoke(interp::AbstractInterpreter, arginfo::ArgInfo, si::Stmt lookupsig = rewrap_unionall(Tuple{ft, unwrapped.parameters...}, types)::Type nargtype = Tuple{ft, nargtype.parameters...} argtype = Tuple{ft, argtype.parameters...} - match, valid_worlds = findsup(lookupsig, method_table(interp)) - match === nothing && return Future(CallMeta(Any, Any, Effects(), NoCallInfo())) + matched, valid_worlds = findsup(lookupsig, method_table(interp)) + matched === nothing && return Future(CallMeta(Any, Any, Effects(), NoCallInfo())) update_valid_age!(sv, valid_worlds) - method = match.method + method = matched.method tienv = ccall(:jl_type_intersection_with_env, Any, (Any, Any), nargtype, method.sig)::SimpleVector ti = tienv[1] env = tienv[2]::SimpleVector mresult = abstract_call_method(interp, method, ti, env, false, si, sv)::Future match = MethodMatch(ti, env, method, argtype <: method.sig) - ft_box = Core.Box(ft) ft′_box = Core.Box(ft′) + lookupsig_box = Core.Box(lookupsig) + invokecall = InvokeCall(types, lookupsig) return Future{CallMeta}(mresult, interp, sv) do result, interp, sv (; rt, exct, effects, edge, volatile_inf_result) = result - local argtypes = arginfo.argtypes - local ft = ft_box.contents local ft′ = ft′_box.contents sig = match.spec_types - argtypes′ = invoke_rewrite(argtypes) + argtypes′ = invoke_rewrite(arginfo.argtypes) fargs = arginfo.fargs fargs′ = fargs === nothing ? nothing : invoke_rewrite(fargs) - arginfo = ArgInfo(fargs′, argtypes′) + arginfo′ = ArgInfo(fargs′, argtypes′) # # typeintersect might have narrowed signature, but the accuracy gain doesn't seem worth the cost involved with the lattice comparisons # for i in 1:length(argtypes′) # t, a = ti.parameters[i], argtypes′[i] @@ -2211,9 +2210,8 @@ function abstract_invoke(interp::AbstractInterpreter, arginfo::ArgInfo, si::Stmt 𝕃ₚ = ipo_lattice(interp) ⊑, ⋤, ⊔ = partialorder(𝕃ₚ), strictneqpartialorder(𝕃ₚ), join(𝕃ₚ) f = singleton_type(ft′) - invokecall = InvokeCall(types, lookupsig) const_call_result = abstract_call_method_with_const_args(interp, - result, f, arginfo, si, match, sv, invokecall) + result, f, arginfo′, si, match, sv, invokecall) const_result = volatile_inf_result if const_call_result !== nothing const_edge = nothing @@ -2227,8 +2225,8 @@ function abstract_invoke(interp::AbstractInterpreter, arginfo::ArgInfo, si::Stmt edge = const_edge end end - rt = from_interprocedural!(interp, rt, sv, arginfo, sig) - info = InvokeCallInfo(edge, match, const_result, lookupsig) + rt = from_interprocedural!(interp, rt, sv, arginfo′, sig) + info = InvokeCallInfo(edge, match, const_result, lookupsig_box.contents) if !match.fully_covers effects = Effects(effects; nothrow=false) exct = exct ⊔ TypeError