Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 52 additions & 8 deletions base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1310,6 +1310,46 @@ function handle_any_const_result!(cases::Vector{InliningCase}, @nospecialize(res
end
end

function info_effects(@nospecialize(result), match::MethodMatch, state::InliningState)
if isa(result, ConcreteResult)
return result.effects
elseif isa(result, SemiConcreteResult)
return result.effects
elseif isa(result, ConstPropResult)
return result.result.ipo_effects
else
mi = specialize_method(match; preexisting=true)
if isa(mi, MethodInstance)
code = get(state.mi_cache, mi, nothing)
if code isa CodeInstance
return decode_effects(code.ipo_purity_bits)
end
end
return Effects()
end
end

function compute_joint_effects(info::Union{ConstCallInfo, Vector{MethodMatchInfo}}, state::InliningState)
if isa(info, ConstCallInfo)
(; call, results) = info
infos = isa(call, MethodMatchInfo) ? MethodMatchInfo[call] : call.matches
else
results = nothing
infos = info
end
local all_result_count = 0
local joint_effects::Effects = EFFECTS_TOTAL
for i in 1:length(infos)
meth = infos[i].results
for (j, match) in enumerate(meth)
all_result_count += 1
result = results === nothing ? nothing : results[all_result_count]
joint_effects = merge_effects(joint_effects, info_effects(result, match, state))
end
end
return joint_effects
end

function compute_inlining_cases(info::Union{ConstCallInfo, Vector{MethodMatchInfo}},
flag::UInt8, sig::Signature, state::InliningState)
argtypes = sig.argtypes
Expand All @@ -1327,7 +1367,6 @@ function compute_inlining_cases(info::Union{ConstCallInfo, Vector{MethodMatchInf
local only_method = nothing
local meth::MethodLookupResult
local all_result_count = 0

for i in 1:length(infos)
meth = infos[i].results
if meth.ambig
Expand Down Expand Up @@ -1399,27 +1438,30 @@ function compute_inlining_cases(info::Union{ConstCallInfo, Vector{MethodMatchInf
filter!(case::InliningCase->isdispatchtuple(case.sig), cases)
end

return cases, handled_all_cases & any_fully_covered
# TODO fuse `compute_joint_effects` into the loop above, which currently causes compilation error
joint_effects = Effects(compute_joint_effects(info, state); nothrow=handled_all_cases)

return cases, (handled_all_cases & any_fully_covered), joint_effects
end

function handle_call!(
ir::IRCode, idx::Int, stmt::Expr, infos::Vector{MethodMatchInfo}, flag::UInt8,
sig::Signature, state::InliningState, todo::Vector{Pair{Int, Any}})
cases = compute_inlining_cases(infos, flag, sig, state)
cases === nothing && return nothing
cases, all_covered = cases
cases, all_covered, joint_effects = cases
handle_cases!(ir, idx, stmt, argtypes_to_type(sig.argtypes), cases,
all_covered, todo, state.params)
all_covered, todo, state.params, joint_effects)
end

function handle_const_call!(
ir::IRCode, idx::Int, stmt::Expr, info::ConstCallInfo, flag::UInt8,
sig::Signature, state::InliningState, todo::Vector{Pair{Int, Any}})
cases = compute_inlining_cases(info, flag, sig, state)
cases === nothing && return nothing
cases, all_covered = cases
cases, all_covered, joint_effects = cases
handle_cases!(ir, idx, stmt, argtypes_to_type(sig.argtypes), cases,
all_covered, todo, state.params)
all_covered, todo, state.params, joint_effects)
end

function handle_match!(
Expand Down Expand Up @@ -1475,7 +1517,7 @@ end

function handle_cases!(ir::IRCode, idx::Int, stmt::Expr, @nospecialize(atype),
cases::Vector{InliningCase}, fully_covered::Bool, todo::Vector{Pair{Int, Any}},
params::OptimizationParams)
params::OptimizationParams, joint_effects::Effects)
# If we only have one case and that case is fully covered, we may either
# be able to do the inlining now (for constant cases), or push it directly
# onto the todo list
Expand All @@ -1487,6 +1529,8 @@ function handle_cases!(ir::IRCode, idx::Int, stmt::Expr, @nospecialize(atype),
isa(case.sig, DataType) || return nothing
end
push!(todo, idx=>UnionSplit(fully_covered, atype, cases))
else
ir[SSAValue(idx)][:flag] |= flags_for_effects(joint_effects)
end
return nothing
end
Expand Down Expand Up @@ -1539,7 +1583,7 @@ function handle_finalizer_call!(

cases = compute_inlining_cases(infos, #=flag=#UInt8(0), sig, state)
cases === nothing && return nothing
cases, all_covered = cases
cases, all_covered, _ = cases
if all_covered && length(cases) == 1
# NOTE we don't append `item1` to `stmt` here so that we don't serialize
# `Core.Compiler` data structure into the global cache
Expand Down
11 changes: 11 additions & 0 deletions test/compiler/inline.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1522,3 +1522,14 @@ let src = code_typed1(fvarargN_inline, (Tuple{Vararg{Int}},))
count(iscall((src, Core._svec_ref)), src.code) == 0 &&
count(iscall((src, Core.nfields)), src.code) == 1
end

# Test effect annotation of declined inline unionsplit
f_union_unmatched(x::Union{Nothing, Type{T}}) where {T} = nothing
let src = code_typed1((Any,)) do x
if isa(x, Union{Nothing, Type})
f_union_unmatched(x)
end
nothing
end
@test count(iscall((src, f_union_unmatched)), src.code) == 0
end