Skip to content

Commit

Permalink
optimizer: remove unnecessary checks (#42884)
Browse files Browse the repository at this point in the history
Now we never form `ConstCallInfo(::InvokeCallInfo, results)` and so the
`sig.f === Core.invoke` check is no longer needed.
This commit also abstracts the common `Core.invoke` rewrite pattern
into `invoke_rewrite(::Vector{Any})` utility.
  • Loading branch information
aviatesk authored Nov 1, 2021
1 parent 3863631 commit 6c274ed
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 36 deletions.
17 changes: 9 additions & 8 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1294,14 +1294,8 @@ function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgIn
match = MethodMatch(ti, env, method, argtype <: method.sig)
res = nothing
sig = match.spec_types
argtypes′ = argtypes[3:end]
argtypes′[1] = ft
if fargs === nothing
fargs′ = nothing
else
fargs′ = fargs[3:end]
fargs′[1] = fargs[1]
end
argtypes′ = invoke_rewrite(argtypes)
fargs′ = fargs === nothing ? nothing : invoke_rewrite(fargs)
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′)
Expand All @@ -1318,6 +1312,13 @@ function abstract_invoke(interp::AbstractInterpreter, (; fargs, argtypes)::ArgIn
return CallMeta(from_interprocedural!(rt, sv, arginfo, sig), InvokeCallInfo(match, res))
end

function invoke_rewrite(xs::Vector{Any})
x0 = xs[2]
newxs = xs[3:end]
newxs[1] = x0
return newxs
end

# call where the function is known exactly
function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
arginfo::ArgInfo, sv::InferenceState,
Expand Down
45 changes: 17 additions & 28 deletions base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,7 @@ function rewrite_apply_exprargs!(ir::IRCode, todo::Vector{Pair{Int, Any}}, idx::
if isa(info, ConstCallInfo)
if !is_stmt_noinline(flag) && maybe_handle_const_call!(
ir, state1.id, new_stmt, info, new_sig,
istate, flag, false, todo)
istate, flag, todo)
handled = true
else
info = info.call
Expand Down Expand Up @@ -716,15 +716,6 @@ function rewrite_apply_exprargs!(ir::IRCode, todo::Vector{Pair{Int, Any}}, idx::
return new_argexprs, new_atypes
end

function rewrite_invoke_exprargs!(expr::Expr)
argexprs = expr.args
argexpr0 = argexprs[2]
argexprs = argexprs[3:end]
argexprs[1] = argexpr0
expr.args = argexprs
return expr
end

function compileable_specialization(et::Union{EdgeTracker, Nothing}, match::MethodMatch)
mi = specialize_method(match; compilesig=true)
mi !== nothing && et !== nothing && push!(et, mi::MethodInstance)
Expand Down Expand Up @@ -874,6 +865,8 @@ function handle_single_case!(ir::IRCode, stmt::Expr, idx::Int, @nospecialize(cas
nothing
end

rewrite_invoke_exprargs!(expr::Expr) = (expr.args = invoke_rewrite(expr.args); expr)

function is_valid_type_for_apply_rewrite(@nospecialize(typ), params::OptimizationParams)
if isa(typ, Const) && isa(typ.val, SimpleVector)
length(typ.val) > params.MAX_TUPLE_SPLAT && return false
Expand Down Expand Up @@ -1023,10 +1016,7 @@ function inline_invoke!(ir::IRCode, idx::Int, sig::Signature, (; match, result):
return nothing
end

atypes = sig.atypes
atype0 = atypes[2]
atypes = atypes[4:end]
pushfirst!(atypes, atype0)
atypes = invoke_rewrite(sig.atypes)

if isa(result, InferenceResult) && !is_stmt_noinline(flag)
(; mi) = item = InliningTodo(result, atypes)
Expand Down Expand Up @@ -1226,7 +1216,7 @@ end
# TODO this function contains a lot of duplications with `analyze_single_call!`, factor them out
function maybe_handle_const_call!(
ir::IRCode, idx::Int, stmt::Expr, (; results)::ConstCallInfo, (; atypes, atype)::Signature,
state::InliningState, flag::UInt8, isinvoke::Bool, todo::Vector{Pair{Int, Any}})
state::InliningState, flag::UInt8, todo::Vector{Pair{Int, Any}})
cases = InliningCase[] # TODO avoid this allocation for single cases ?
local fully_covered = true
local signature_union = Bottom
Expand Down Expand Up @@ -1270,9 +1260,8 @@ function maybe_handle_const_call!(
# be able to do the inlining now (for constant cases), or push it directly
# onto the todo list
if fully_covered && length(cases) == 1
handle_single_case!(ir, stmt, idx, cases[1].item, isinvoke, todo)
handle_single_case!(ir, stmt, idx, cases[1].item, false, todo)
elseif length(cases) > 0
isinvoke && rewrite_invoke_exprargs!(stmt)
push!(todo, idx=>UnionSplit(fully_covered, atype, cases))
end
return true
Expand Down Expand Up @@ -1318,17 +1307,6 @@ function assemble_inline_todo!(ir::IRCode, state::InliningState)
continue
end

# if inference arrived here with constant-prop'ed result(s),
# we can perform a specialized analysis for just this case
if isa(info, ConstCallInfo)
if !is_stmt_noinline(flag)
maybe_handle_const_call!(
ir, idx, stmt, info, sig,
state, flag, sig.f === Core.invoke, todo) && continue
end
info = info.call # cascade to the non-constant handling
end

if isa(info, OpaqueClosureCallInfo)
result = info.result
if isa(result, InferenceResult)
Expand All @@ -1350,6 +1328,17 @@ function assemble_inline_todo!(ir::IRCode, state::InliningState)
continue
end

# if inference arrived here with constant-prop'ed result(s),
# we can perform a specialized analysis for just this case
if isa(info, ConstCallInfo)
if !is_stmt_noinline(flag)
maybe_handle_const_call!(
ir, idx, stmt, info, sig,
state, flag, todo) && continue
end
info = info.call # cascade to the non-constant handling
end

# Ok, now figure out what method to call
if isa(info, MethodMatchInfo)
infos = MethodMatchInfo[info]
Expand Down

0 comments on commit 6c274ed

Please sign in to comment.