Skip to content

Commit 3025e36

Browse files
vtjnashaviatesk
authored andcommitted
inference: compute edges more precisely in post-inference
Start computing edges from stmt_info later (after CodeInstance is able to have been allocated for recursion) instead of immediately.
1 parent 365a2b8 commit 3025e36

File tree

5 files changed

+102
-9
lines changed

5 files changed

+102
-9
lines changed

base/compiler/abstractinterpretation.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -352,7 +352,7 @@ function find_union_split_method_matches(interp::AbstractInterpreter, argtypes::
352352
end
353353
valid_worlds = intersect(valid_worlds, thismatches.valid_worlds)
354354
thisfullmatch = any(match::MethodMatch->match.fully_covers, thismatches)
355-
thisinfo = MethodMatchInfo(thismatches, mt, thisfullmatch)
355+
thisinfo = MethodMatchInfo(thismatches, mt, sig_n, thisfullmatch)
356356
push!(infos, thisinfo)
357357
end
358358
info = UnionSplitInfo(infos)
@@ -373,7 +373,7 @@ function find_simple_method_matches(interp::AbstractInterpreter, @nospecialize(a
373373
return FailedMethodMatch("Too many methods matched")
374374
end
375375
fullmatch = any(match::MethodMatch->match.fully_covers, matches)
376-
info = MethodMatchInfo(matches, mt, fullmatch)
376+
info = MethodMatchInfo(matches, mt, atype, fullmatch)
377377
return MethodMatches(matches.matches, info, matches.valid_worlds)
378378
end
379379

@@ -2188,7 +2188,7 @@ function abstract_invoke(interp::AbstractInterpreter, arginfo::ArgInfo, si::Stmt
21882188
end
21892189
end
21902190
rt = from_interprocedural!(interp, rt, sv, arginfo, sig)
2191-
info = InvokeCallInfo(match, const_result)
2191+
info = InvokeCallInfo(match, const_result, lookupsig)
21922192
edge !== nothing && add_invoke_backedge!(sv, lookupsig, edge)
21932193
if !match.fully_covers
21942194
effects = Effects(effects; nothrow=false)

base/compiler/stmtinfo.jl

+6-4
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,15 @@ struct NoCallInfo <: CallInfo end
2626
"""
2727
info::MethodMatchInfo <: CallInfo
2828
29-
Captures the result of a `:jl_matching_methods` lookup for the given call (`info.results`).
30-
This info may then be used by the optimizer to inline the matches, without having
31-
to re-consult the method table. This info is illegal on any statement that is
32-
not a call to a generic function.
29+
Captures the essential arguments and result of a `:jl_matching_methods` lookup
30+
for the given call (`info.results`). This info may then be used by the
31+
optimizer, without having to re-consult the method table.
32+
This info is illegal on any statement that is not a call to a generic function.
3333
"""
3434
struct MethodMatchInfo <: CallInfo
3535
results::MethodLookupResult
3636
mt::MethodTable
37+
atype
3738
fullmatch::Bool
3839
end
3940
nsplit_impl(info::MethodMatchInfo) = 1
@@ -185,6 +186,7 @@ Optionally keeps `info.result::InferenceResult` that keeps constant information.
185186
struct InvokeCallInfo <: CallInfo
186187
match::MethodMatch
187188
result::Union{Nothing,ConstResult}
189+
atype # ::Type
188190
end
189191

190192
"""

base/compiler/tfuncs.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -2940,7 +2940,7 @@ function return_type_tfunc(interp::AbstractInterpreter, argtypes::Vector{Any}, s
29402940
else
29412941
call = abstract_call(interp, ArgInfo(nothing, argtypes_vec), si, sv, #=max_methods=#-1)
29422942
end
2943-
info = verbose_stmt_info(interp) ? MethodResultPure(ReturnTypeCallInfo(call.info)) : MethodResultPure()
2943+
info = MethodResultPure(ReturnTypeCallInfo(call.info))
29442944
rt = widenslotwrapper(call.rt)
29452945
if isa(rt, Const)
29462946
# output was computed to be constant

base/compiler/typeinfer.jl

+92
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,12 @@ function finishinfer!(me::InferenceState, interp::AbstractInterpreter)
536536
append!(s_edges, edges)
537537
empty!(edges)
538538
end
539+
#s_edges_new = compute_edges(me)
540+
#println(Any[z isa MethodTable ? z.name : z for z in s_edges_new])
541+
#if length(s_edges) != length(s_edges_new) || !all(i -> isassigned(s_edges, i) ? isassigned(s_edges_new, i) && s_edges_new[i] === s_edges[i] : !isassigned(s_edges_new, i), length(s_edges))
542+
# println(sizehint!(s_edges, length(s_edges)))
543+
# println(sizehint!(s_edges_new, length(s_edges_new)))
544+
#end
539545
if me.src.edges !== nothing && me.src.edges !== Core.svec()
540546
append!(s_edges, me.src.edges::Vector)
541547
end
@@ -653,6 +659,92 @@ function store_backedges(caller::MethodInstance, edges::Vector{Any})
653659
return nothing
654660
end
655661

662+
add_edges!(edges::Vector{Any}, info::MethodResultPure) = add_edges!(edges, info.info)
663+
add_edges!(edges::Vector{Any}, info::ConstCallInfo) = add_edges!(edges, info.call)
664+
add_edges!(edges::Vector{Any}, info::OpaqueClosureCreateInfo) = nothing # TODO(jwn)
665+
add_edges!(edges::Vector{Any}, info::ReturnTypeCallInfo) = add_edges!(edges, info.info)
666+
function add_edges!(edges::Vector{Any}, info::ApplyCallInfo)
667+
add_edges!(edges, info.call)
668+
for arg in info.arginfo
669+
arg === nothing && continue
670+
for edge in arg.each
671+
add_edges!(edges, edge.info)
672+
end
673+
end
674+
end
675+
add_edges!(edges::Vector{Any}, info::ModifyOpInfo) = add_edges!(edges, info.call)
676+
add_edges!(edges::Vector{Any}, info::UnionSplitInfo) = for split in info.matches; add_edges!(edges, split); end
677+
add_edges!(edges::Vector{Any}, info::UnionSplitApplyCallInfo) = for split in info.infos; add_edges!(edges, split); end
678+
add_edges!(edges::Vector{Any}, info::FinalizerInfo) = nothing
679+
add_edges!(edges::Vector{Any}, info::NoCallInfo) = nothing
680+
function add_edges!(edges::Vector{Any}, info::MethodMatchInfo)
681+
matches = info.results.matches
682+
#if length(matches) == 1 && !info.results.ambig && (matches[end]::Core.MethodMatch).fully_covers
683+
# push!(edges, specialize_method(matches[1]))
684+
#elseif isempty(matches) || info.results.ambig || !(matches[end]::Core.MethodMatch).fully_covers
685+
#else
686+
# push!(edges, length(matches))
687+
# for m in matches
688+
# push!(edges, specialize_method(m))
689+
# end
690+
#end
691+
if isempty(matches) || !(matches[end]::Core.MethodMatch).fully_covers
692+
exists = false
693+
for i in 1:length(edges)
694+
if edges[i] === info.mt && edges[i + 1] == info.atype
695+
exists = true
696+
break
697+
end
698+
end
699+
if !exists
700+
push!(edges, info.mt)
701+
push!(edges, info.atype)
702+
end
703+
end
704+
for m in matches
705+
mi = specialize_method(m)
706+
exists = false
707+
for i in 1:length(edges)
708+
if edges[i] === mi && !(i > 1 && edges[i - 1] isa Type)
709+
exists = true
710+
break
711+
end
712+
end
713+
exists || push!(edges, mi)
714+
end
715+
end
716+
function add_edges!(edges::Vector{Any}, info::InvokeCallInfo)
717+
#push!(edges, 1)
718+
mi = specialize_method(info.match)
719+
exists = false
720+
for i in 2:length(edges)
721+
if edges[i] === mi && edges[i - 1] isa Type && edges[i - 1] == info.atype
722+
exists = true
723+
break
724+
end
725+
end
726+
if !exists
727+
push!(edges, info.atype)
728+
push!(edges, mi)
729+
end
730+
nothing
731+
end
732+
733+
function compute_edges(sv::InferenceState)
734+
edges = []
735+
for i in 1:length(sv.stmt_info)
736+
info = sv.stmt_info[i]
737+
#rt = sv.ssavaluetypes[i]
738+
#effects = EFFECTS_TOTAL # sv.stmt_effects[i]
739+
#if rt === Any && effects === Effects()
740+
# continue
741+
#end
742+
add_edges!(edges, info)
743+
end
744+
return edges
745+
end
746+
747+
656748
function record_slot_assign!(sv::InferenceState)
657749
# look at all assignments to slots
658750
# and union the set of types stored there

base/compiler/types.jl

-1
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,6 @@ function add_remark! end
403403
may_optimize(::AbstractInterpreter) = true
404404
may_compress(::AbstractInterpreter) = true
405405
may_discard_trees(::AbstractInterpreter) = true
406-
verbose_stmt_info(::AbstractInterpreter) = false
407406

408407
"""
409408
method_table(interp::AbstractInterpreter) -> MethodTableView

0 commit comments

Comments
 (0)