Skip to content

Commit 140f560

Browse files
committed
convert to full CodeInstance edge list on the Julia side
1 parent 6b1b0c1 commit 140f560

File tree

7 files changed

+90
-70
lines changed

7 files changed

+90
-70
lines changed

base/compiler/ssair/inlining.jl

+41-42
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,8 @@ end
2828

2929
struct ConstantCase
3030
val::Any
31-
ConstantCase(@nospecialize val) = new(val)
31+
edge::CodeInstance
32+
ConstantCase(@nospecialize(val), edge::CodeInstance) = new(val, edge)
3233
end
3334

3435
struct SomeCase
@@ -68,12 +69,12 @@ struct InliningEdgeTracker
6869
new(state.edges, invokesig)
6970
end
7071

71-
function add_inlining_edge!(et::InliningEdgeTracker, mi::MethodInstance)
72+
function add_inlining_edge!(et::InliningEdgeTracker, edge::CodeInstance)
7273
(; edges, invokesig) = et
7374
if invokesig === nothing
74-
add_one_edge!(edges, mi)
75+
add_one_edge!(edges, edge)
7576
else # invoke backedge
76-
add_invoke_edge!(edges, invoke_signature(invokesig), mi)
77+
add_invoke_edge!(edges, invoke_signature(invokesig), edge)
7778
end
7879
return nothing
7980
end
@@ -784,11 +785,11 @@ function rewrite_apply_exprargs!(todo::Vector{Pair{Int,Any}},
784785
return new_argtypes
785786
end
786787

787-
function compileable_specialization(mi::MethodInstance, effects::Effects,
788-
et::InliningEdgeTracker, @nospecialize(info::CallInfo); compilesig_invokes::Bool=true)
789-
mi_invoke = mi
788+
function compileable_specialization(edge::CodeInstance, effects::Effects,
789+
et::InliningEdgeTracker, @nospecialize(info::CallInfo), state::InliningState)
790+
mi_invoke = mi = edge.def
790791
method, atype, sparams = mi.def::Method, mi.specTypes, mi.sparam_vals
791-
if compilesig_invokes
792+
if OptimizationParams(state.interp).compilesig_invokes
792793
new_atype = get_compileable_sig(method, atype, sparams)
793794
new_atype === nothing && return nothing
794795
if atype !== new_atype
@@ -806,43 +807,42 @@ function compileable_specialization(mi::MethodInstance, effects::Effects,
806807
return nothing
807808
end
808809
end
809-
add_inlining_edge!(et, mi) # to the dispatch lookup
810-
mi_invoke !== mi && add_invoke_edge!(et.edges, method.sig, mi_invoke) # add_inlining_edge to the invoke call, if that is different
810+
add_inlining_edge!(et, edge) # to the dispatch lookup
811+
if mi_invoke !== mi
812+
edge_invoke = codeinst_as_invoke_edge(state.interp, mi_invoke)
813+
add_invoke_edge!(et.edges, method.sig, edge_invoke) # add_inlining_edge to the invoke call, if that is different
814+
end
811815
return InvokeCase(mi_invoke, effects, info)
812816
end
813817

814-
function compileable_specialization(match::MethodMatch, effects::Effects,
815-
et::InliningEdgeTracker, @nospecialize(info::CallInfo); compilesig_invokes::Bool=true)
816-
mi = specialize_method(match)
817-
return compileable_specialization(mi, effects, et, info; compilesig_invokes)
818-
end
819-
820818
struct InferredResult
821819
src::Any # CodeInfo or IRCode
822820
effects::Effects
823-
InferredResult(@nospecialize(src), effects::Effects) = new(src, effects)
821+
edge::CodeInstance
822+
InferredResult(@nospecialize(src), effects::Effects, edge::CodeInstance) = new(src, effects, edge)
824823
end
825824
@inline function get_cached_result(state::InliningState, mi::MethodInstance)
826825
code = get(code_cache(state), mi, nothing)
827826
if code isa CodeInstance
828827
if use_const_api(code)
829828
# in this case function can be inlined to a constant
830-
return ConstantCase(quoted(code.rettype_const))
829+
return ConstantCase(quoted(code.rettype_const), code)
831830
end
832831
return code
833832
end
834833
return nothing
835834
end
836835
@inline function get_local_result(inf_result::InferenceResult)
836+
@assert isdefined(inf_result, :ci_as_edge) "InferenceResult without ci_as_edge"
837837
effects = inf_result.ipo_effects
838838
if is_foldable_nothrow(effects)
839839
res = inf_result.result
840840
if isa(res, Const) && is_inlineable_constant(res.val)
841841
# use constant calling convention
842-
return ConstantCase(quoted(res.val))
842+
return ConstantCase(quoted(res.val), inf_result.ci_as_edge)
843843
end
844844
end
845-
return InferredResult(inf_result.src, effects)
845+
return InferredResult(inf_result.src, effects, inf_result.ci_as_edge)
846846
end
847847

848848
# the general resolver for usual and const-prop'ed calls
@@ -862,30 +862,29 @@ function resolve_todo(mi::MethodInstance, result::Union{Nothing,InferenceResult,
862862
inferred_result = get_cached_result(state, mi)
863863
end
864864
if inferred_result isa ConstantCase
865-
add_inlining_edge!(et, mi)
865+
add_inlining_edge!(et, inferred_result.edge)
866866
return inferred_result
867867
elseif inferred_result isa InferredResult
868-
(; src, effects) = inferred_result
868+
(; src, effects, edge) = inferred_result
869869
elseif inferred_result isa CodeInstance
870870
src = @atomic :monotonic inferred_result.inferred
871871
effects = decode_effects(inferred_result.ipo_purity_bits)
872+
edge = inferred_result
872873
else # there is no cached source available, bail out
873-
return compileable_specialization(mi, Effects(), et, info;
874-
compilesig_invokes=OptimizationParams(state.interp).compilesig_invokes)
874+
edge = codeinst_as_invoke_edge(state.interp, mi)
875+
return compileable_specialization(edge, Effects(), et, info, state)
875876
end
876877

877878
# the duplicated check might have been done already within `analyze_method!`, but still
878879
# we need it here too since we may come here directly using a constant-prop' result
879880
if !OptimizationParams(state.interp).inlining || is_stmt_noinline(flag)
880-
return compileable_specialization(mi, effects, et, info;
881-
compilesig_invokes=OptimizationParams(state.interp).compilesig_invokes)
881+
return compileable_specialization(edge, effects, et, info, state)
882882
end
883883

884884
src_inlining_policy(state.interp, src, info, flag) ||
885-
return compileable_specialization(mi, effects, et, info;
886-
compilesig_invokes=OptimizationParams(state.interp).compilesig_invokes)
885+
return compileable_specialization(edge, effects, et, info, state)
887886

888-
add_inlining_edge!(et, mi)
887+
add_inlining_edge!(et, edge)
889888
if inferred_result isa CodeInstance
890889
ir, spec_info, debuginfo = retrieve_ir_for_inlining(inferred_result, src)
891890
else
@@ -905,7 +904,7 @@ function resolve_todo(mi::MethodInstance, @nospecialize(info::CallInfo), flag::U
905904

906905
cached_result = get_cached_result(state, mi)
907906
if cached_result isa ConstantCase
908-
add_inlining_edge!(et, mi)
907+
add_inlining_edge!(et, cached_result.edge)
909908
return cached_result
910909
elseif cached_result isa CodeInstance
911910
src = @atomic :monotonic cached_result.inferred
@@ -916,7 +915,7 @@ function resolve_todo(mi::MethodInstance, @nospecialize(info::CallInfo), flag::U
916915

917916
src_inlining_policy(state.interp, src, info, flag) || return nothing
918917
ir, spec_info, debuginfo = retrieve_ir_for_inlining(cached_result, src)
919-
add_inlining_edge!(et, mi)
918+
add_inlining_edge!(et, cached_result)
920919
return InliningTodo(mi, ir, spec_info, debuginfo, effects)
921920
end
922921

@@ -1464,14 +1463,12 @@ function semiconcrete_result_item(result::SemiConcreteResult,
14641463
# a `@noinline`-declared method when it's marked as `@constprop :aggressive`.
14651464
# Suppress the inlining here (unless inlining is requested at the callsite).
14661465
(is_declared_noinline(mi.def::Method) && !is_stmt_inline(flag)))
1467-
return compileable_specialization(mi, result.effects, et, info;
1468-
compilesig_invokes=OptimizationParams(state.interp).compilesig_invokes)
1466+
return compileable_specialization(result.edge, result.effects, et, info, state)
14691467
end
14701468
src_inlining_policy(state.interp, result.ir, info, flag) ||
1471-
return compileable_specialization(mi, result.effects, et, info;
1472-
compilesig_invokes=OptimizationParams(state.interp).compilesig_invokes)
1469+
return compileable_specialization(result.edge, result.effects, et, info, state)
14731470

1474-
add_inlining_edge!(et, mi)
1471+
add_inlining_edge!(et, result.edge)
14751472
preserve_local_sources = OptimizationParams(state.interp).preserve_local_sources
14761473
ir, _, debuginfo = retrieve_ir_for_inlining(mi, result.ir, preserve_local_sources)
14771474
return InliningTodo(mi, ir, result.spec_info, debuginfo, result.effects)
@@ -1503,11 +1500,10 @@ function concrete_result_item(result::ConcreteResult, @nospecialize(info::CallIn
15031500
invokesig::Union{Nothing,Vector{Any}}=nothing)
15041501
if !may_inline_concrete_result(result)
15051502
et = InliningEdgeTracker(state, invokesig)
1506-
return compileable_specialization(result.edge.def, result.effects, et, info;
1507-
compilesig_invokes=OptimizationParams(state.interp).compilesig_invokes)
1503+
return compileable_specialization(result.edge, result.effects, et, info, state)
15081504
end
15091505
@assert result.effects === EFFECTS_TOTAL
1510-
return ConstantCase(quoted(result.result))
1506+
return ConstantCase(quoted(result.result), result.edge)
15111507
end
15121508

15131509
function handle_cases!(todo::Vector{Pair{Int,Any}}, ir::IRCode, idx::Int, stmt::Expr,
@@ -1556,11 +1552,14 @@ function handle_modifyop!_call!(ir::IRCode, idx::Int, stmt::Expr, info::ModifyOp
15561552
info isa MethodResultPure && (info = info.info)
15571553
info isa ConstCallInfo && (info = info.call)
15581554
info isa MethodMatchInfo || return nothing
1559-
length(info.results) == 1 || return nothing
1555+
length(info.edges) == length(info.results) == 1 || return nothing
15601556
match = info.results[1]::MethodMatch
15611557
match.fully_covers || return nothing
1562-
case = compileable_specialization(match, Effects(), InliningEdgeTracker(state), info;
1563-
compilesig_invokes=OptimizationParams(state.interp).compilesig_invokes)
1558+
edge = info.edges[1]
1559+
if edge === nothing
1560+
edge = codeinst_as_invoke_edge(state.interp, specialize_method(match))
1561+
end
1562+
case = compileable_specialization(edge, Effects(), InliningEdgeTracker(state), info, state)
15641563
case === nothing && return nothing
15651564
stmt.head = :invoke_modify
15661565
pushfirst!(stmt.args, case.invoke)

base/compiler/ssair/passes.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -1529,7 +1529,7 @@ function try_inline_finalizer!(ir::IRCode, argexprs::Vector{Any}, idx::Int,
15291529
if code isa CodeInstance
15301530
if use_const_api(code)
15311531
# No code in the function - Nothing to do
1532-
add_inlining_edge!(et, mi)
1532+
add_inlining_edge!(et, code)
15331533
return true
15341534
end
15351535
src = @atomic :monotonic code.inferred
@@ -1544,7 +1544,7 @@ function try_inline_finalizer!(ir::IRCode, argexprs::Vector{Any}, idx::Int,
15441544
length(src.cfg.blocks) == 1 || return false
15451545

15461546
# Ok, we're committed to inlining the finalizer
1547-
add_inlining_edge!(et, mi)
1547+
add_inlining_edge!(et, code)
15481548

15491549
# TODO: Should there be a special line number node for inlined finalizers?
15501550
inline_at = ir[SSAValue(idx)][:line]

base/compiler/stmtinfo.jl

+14-10
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ function add_edges_impl(edges::Vector{Any}, info::MethodMatchInfo)
6666
# if this doesn't succeed, the backedge will be less precise,
6767
# but the forward edge will maintain the precision
6868
if edge.def.specTypes === info.results[1].spec_types
69-
add_one_edge!(edges, edge.def) # TODO CodeInstance as edge
69+
add_one_edge!(edges, edge)
7070
return nothing
7171
end
7272
end
@@ -81,18 +81,20 @@ function add_edges_impl(edges::Vector{Any}, info::MethodMatchInfo)
8181
for i = 1:nmatches
8282
edge = info.edges[i]
8383
if edge !== nothing
84-
push!(edges, edge.def) # TODO CodeInstance as edge
84+
push!(edges, edge)
8585
end
8686
end
8787
nothing
8888
end
89-
function add_one_edge!(edges::Vector{Any}, mi::MethodInstance)
89+
function add_one_edge!(edges::Vector{Any}, edge::CodeInstance)
9090
for i in 1:length(edges)
91-
if edges[i] === mi && !(i > 1 && edges[i-1] isa Type)
91+
edgeᵢ = edges[i]
92+
# XXX compare `CodeInstance` identify?
93+
if edgeᵢ isa CodeInstance && edgeᵢ.def === edge.def && !(i > 1 && edges[i-1] isa Type)
9294
return
9395
end
9496
end
95-
push!(edges, mi)
97+
push!(edges, edge)
9698
nothing
9799
end
98100
nsplit_impl(info::MethodMatchInfo) = 1
@@ -264,19 +266,21 @@ end
264266
function add_edges_impl(edges::Vector{Any}, info::InvokeCallInfo)
265267
edge = info.edge
266268
if edge !== nothing
267-
add_invoke_edge!(edges, info.atype, edge.def) # TODO CodeInstance as edge
269+
add_invoke_edge!(edges, info.atype, edge)
268270
end
271+
nothing
269272
end
270-
function add_invoke_edge!(edges::Vector{Any}, @nospecialize(atype), mi::MethodInstance)
273+
function add_invoke_edge!(edges::Vector{Any}, @nospecialize(atype), edge::CodeInstance)
271274
for i in 2:length(edges)
272-
if edges[i] === mi
275+
edgeᵢ = edges[i]
276+
if edgeᵢ isa CodeInstance && edgeᵢ.def === edge.def # XXX compare `CodeInstance` identify?
273277
edge_minus_1 = edges[i-1]
274278
if edge_minus_1 isa Type && edge_minus_1 == atype
275279
return nothing
276280
end
277281
end
278282
end
279-
push!(edges, atype, mi)
283+
push!(edges, atype, edge)
280284
nothing
281285
end
282286

@@ -295,7 +299,7 @@ end
295299
function add_edges_impl(edges::Vector{Any}, info::OpaqueClosureCallInfo)
296300
edge = info.edge
297301
if edge !== nothing
298-
add_one_edge!(edges, edge.def) # TODO CodeInstance as edge
302+
add_one_edge!(edges, edge)
299303
end
300304
end
301305

base/compiler/tfuncs.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -1432,7 +1432,7 @@ end
14321432
return Future{CallMeta}(callinfo, interp, sv) do callinfo, interp, sv
14331433
TF = TF.contents
14341434
RT = RT.contents
1435-
TF2 = tmeet(callinfo.rt, widenconst(TF))
1435+
TF2 = tmeet(ipo_lattice(interp), callinfo.rt, widenconst(TF))
14361436
if TF2 === Bottom
14371437
RT = Bottom
14381438
elseif isconcretetype(RT) && has_nontrivial_extended_info(𝕃ᵢ, TF2) # isconcrete condition required to form a PartialStruct
@@ -3012,7 +3012,7 @@ function abstract_applicable(interp::AbstractInterpreter, argtypes::Vector{Any},
30123012
if rt !== Bool
30133013
for i = 1:napplicable
30143014
(; match, edges, edge_idx) = applicable[i]
3015-
edges[edge_idx] = codeinst_as_method_match_edge(interp, specialize_method(match))
3015+
edges[edge_idx] = codeinst_as_invoke_edge(interp, specialize_method(match))
30163016
end
30173017
info = VirtualMethodMatchInfo(matches.info)
30183018
end
@@ -3055,7 +3055,7 @@ function _hasmethod_tfunc(interp::AbstractInterpreter, argtypes::Vector{Any}, sv
30553055
vinfo = MethodMatchInfo(vresults, mt, types, false) # XXX: this should actually be an info with invoke-type edge
30563056
else
30573057
rt = Const(true)
3058-
edge = codeinst_as_method_match_edge(interp, specialize_method(match))
3058+
edge = codeinst_as_invoke_edge(interp, specialize_method(match))
30593059
vinfo = InvokeCallInfo(edge, match, nothing, types)
30603060
end
30613061
info = VirtualMethodMatchInfo(vinfo)

0 commit comments

Comments
 (0)