Skip to content

Commit b6b5528

Browse files
authored
optimizer: fix up the inlining algorithm to use correct nargs/isva (#55976)
It appears that inlining.jl was not updated in #54341. Specifically, using `nargs`/`isva` from `mi.def::Method` in `ir_prepare_inlining!` causes the following error to occur: ```julia function generate_lambda_ex(world::UInt, source::LineNumberNode, argnames, spnames, @nospecialize body) stub = Core.GeneratedFunctionStub(identity, Core.svec(argnames...), Core.svec(spnames...)) return stub(world, source, body) end function overdubbee54341(a, b) return a + b end const overdubee_codeinfo54341 = code_lowered(overdubbee54341, Tuple{Any, Any})[1] function overdub_generator54341(world::UInt, source::LineNumberNode, selftype, fargtypes) if length(fargtypes) != 2 return generate_lambda_ex(world, source, (:overdub54341, :args), (), :(error("Wrong number of arguments"))) else return copy(overdubee_codeinfo54341) end end @eval function overdub54341(args...) $(Expr(:meta, :generated, overdub_generator54341)) $(Expr(:meta, :generated_only)) end topfunc(x) = overdub54341(x, 2) ``` ```julia julia> topfunc(1) Internal error: during type inference of topfunc(Int64) Encountered unexpected error in runtime: BoundsError(a=Array{Any, 1}(dims=(2,), mem=Memory{Any}(8, 0x10632e780)[SSAValue(2), SSAValue(3), #<null>, #<null>, #<null>, #<null>, #<null>, #<null>]), i=(3,)) throw_boundserror at ./essentials.jl:14 getindex at ./essentials.jl:909 [inlined] ssa_substitute_op! at ./compiler/ssair/inlining.jl:1798 ssa_substitute_op! at ./compiler/ssair/inlining.jl:1852 ir_inline_item! at ./compiler/ssair/inlining.jl:386 ... ``` This commit updates the abstract interpretation and inlining algorithm to use the `nargs`/`isva` values held by `CodeInfo`. Similar modifications have also been made to EscapeAnalysis.jl. @nanosoldier `runbenchmarks("inference", vs=":master")`
1 parent 42737f7 commit b6b5528

File tree

10 files changed

+81
-67
lines changed

10 files changed

+81
-67
lines changed

base/compiler/abstractinterpretation.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1282,7 +1282,7 @@ function semi_concrete_eval_call(interp::AbstractInterpreter,
12821282
effects = Effects(effects; noub=ALWAYS_TRUE)
12831283
end
12841284
exct = refine_exception_type(result.exct, effects)
1285-
return ConstCallResults(rt, exct, SemiConcreteResult(mi, ir, effects), effects, mi)
1285+
return ConstCallResults(rt, exct, SemiConcreteResult(mi, ir, effects, spec_info(irsv)), effects, mi)
12861286
end
12871287
end
12881288
end

base/compiler/inferencestate.jl

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ mutable struct InferenceState
236236
slottypes::Vector{Any}
237237
src::CodeInfo
238238
cfg::CFG
239-
method_info::MethodInfo
239+
spec_info::SpecInfo
240240

241241
#= intermediate states for local abstract interpretation =#
242242
currbb::Int
@@ -294,7 +294,7 @@ mutable struct InferenceState
294294
sptypes = sptypes_from_meth_instance(mi)
295295
code = src.code::Vector{Any}
296296
cfg = compute_basic_blocks(code)
297-
method_info = MethodInfo(src)
297+
spec_info = SpecInfo(src)
298298

299299
currbb = currpc = 1
300300
ip = BitSet(1) # TODO BitSetBoundedMinPrioritySet(1)
@@ -351,7 +351,7 @@ mutable struct InferenceState
351351
restrict_abstract_call_sites = isa(def, Module)
352352

353353
this = new(
354-
mi, world, mod, sptypes, slottypes, src, cfg, method_info,
354+
mi, world, mod, sptypes, slottypes, src, cfg, spec_info,
355355
currbb, currpc, ip, handler_info, ssavalue_uses, bb_vartables, ssavaluetypes, stmt_edges, stmt_info,
356356
tasks, pclimitations, limitations, cycle_backedges, callstack, 0, 0, 0,
357357
result, unreachable, valid_worlds, bestguess, exc_bestguess, ipo_effects,
@@ -791,7 +791,7 @@ end
791791

792792
# TODO add `result::InferenceResult` and put the irinterp result into the inference cache?
793793
mutable struct IRInterpretationState
794-
const method_info::MethodInfo
794+
const spec_info::SpecInfo
795795
const ir::IRCode
796796
const mi::MethodInstance
797797
const world::UInt
@@ -809,7 +809,7 @@ mutable struct IRInterpretationState
809809
parentid::Int
810810

811811
function IRInterpretationState(interp::AbstractInterpreter,
812-
method_info::MethodInfo, ir::IRCode, mi::MethodInstance, argtypes::Vector{Any},
812+
spec_info::SpecInfo, ir::IRCode, mi::MethodInstance, argtypes::Vector{Any},
813813
world::UInt, min_world::UInt, max_world::UInt)
814814
curridx = 1
815815
given_argtypes = Vector{Any}(undef, length(argtypes))
@@ -831,7 +831,7 @@ mutable struct IRInterpretationState
831831
tasks = WorkThunk[]
832832
edges = Any[]
833833
callstack = AbsIntState[]
834-
return new(method_info, ir, mi, world, curridx, argtypes_refined, ir.sptypes, tpdum,
834+
return new(spec_info, ir, mi, world, curridx, argtypes_refined, ir.sptypes, tpdum,
835835
ssa_refined, lazyreachability, valid_worlds, tasks, edges, callstack, 0, 0)
836836
end
837837
end
@@ -845,14 +845,13 @@ function IRInterpretationState(interp::AbstractInterpreter,
845845
else
846846
isa(src, CodeInfo) || return nothing
847847
end
848-
method_info = MethodInfo(src)
848+
spec_info = SpecInfo(src)
849849
ir = inflate_ir(src, mi)
850850
argtypes = va_process_argtypes(optimizer_lattice(interp), argtypes, src.nargs, src.isva)
851-
return IRInterpretationState(interp, method_info, ir, mi, argtypes, world,
851+
return IRInterpretationState(interp, spec_info, ir, mi, argtypes, world,
852852
codeinst.min_world, codeinst.max_world)
853853
end
854854

855-
856855
# AbsIntState
857856
# ===========
858857

@@ -927,11 +926,11 @@ is_constproped(::IRInterpretationState) = true
927926
is_cached(sv::InferenceState) = !iszero(sv.cache_mode & CACHE_MODE_GLOBAL)
928927
is_cached(::IRInterpretationState) = false
929928

930-
method_info(sv::InferenceState) = sv.method_info
931-
method_info(sv::IRInterpretationState) = sv.method_info
929+
spec_info(sv::InferenceState) = sv.spec_info
930+
spec_info(sv::IRInterpretationState) = sv.spec_info
932931

933-
propagate_inbounds(sv::AbsIntState) = method_info(sv).propagate_inbounds
934-
method_for_inference_limit_heuristics(sv::AbsIntState) = method_info(sv).method_for_inference_limit_heuristics
932+
propagate_inbounds(sv::AbsIntState) = spec_info(sv).propagate_inbounds
933+
method_for_inference_limit_heuristics(sv::AbsIntState) = spec_info(sv).method_for_inference_limit_heuristics
935934

936935
frame_world(sv::InferenceState) = sv.world
937936
frame_world(sv::IRInterpretationState) = sv.world

base/compiler/optimize.jl

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -644,10 +644,10 @@ function ((; code_cache)::GetNativeEscapeCache)(mi::MethodInstance)
644644
return false
645645
end
646646

647-
function refine_effects!(interp::AbstractInterpreter, sv::PostOptAnalysisState)
647+
function refine_effects!(interp::AbstractInterpreter, opt::OptimizationState, sv::PostOptAnalysisState)
648648
if !is_effect_free(sv.result.ipo_effects) && sv.all_effect_free && !isempty(sv.ea_analysis_pending)
649649
ir = sv.ir
650-
nargs = let def = sv.result.linfo.def; isa(def, Method) ? Int(def.nargs) : 0; end
650+
nargs = Int(opt.src.nargs)
651651
estate = EscapeAnalysis.analyze_escapes(ir, nargs, optimizer_lattice(interp), GetNativeEscapeCache(interp))
652652
argescapes = EscapeAnalysis.ArgEscapeCache(estate)
653653
stack_analysis_result!(sv.result, argescapes)
@@ -939,7 +939,8 @@ function check_inconsistentcy!(sv::PostOptAnalysisState, scanner::BBScanner)
939939
end
940940
end
941941

942-
function ipo_dataflow_analysis!(interp::AbstractInterpreter, ir::IRCode, result::InferenceResult)
942+
function ipo_dataflow_analysis!(interp::AbstractInterpreter, opt::OptimizationState,
943+
ir::IRCode, result::InferenceResult)
943944
if !is_ipo_dataflow_analysis_profitable(result.ipo_effects)
944945
return false
945946
end
@@ -967,13 +968,13 @@ function ipo_dataflow_analysis!(interp::AbstractInterpreter, ir::IRCode, result:
967968
end
968969
end
969970

970-
return refine_effects!(interp, sv)
971+
return refine_effects!(interp, opt, sv)
971972
end
972973

973974
# run the optimization work
974975
function optimize(interp::AbstractInterpreter, opt::OptimizationState, caller::InferenceResult)
975-
@timeit "optimizer" ir = run_passes_ipo_safe(opt.src, opt, caller)
976-
ipo_dataflow_analysis!(interp, ir, caller)
976+
@timeit "optimizer" ir = run_passes_ipo_safe(opt.src, opt)
977+
ipo_dataflow_analysis!(interp, opt, ir, caller)
977978
return finish(interp, opt, ir, caller)
978979
end
979980

@@ -995,7 +996,6 @@ matchpass(::Nothing, _, _) = false
995996
function run_passes_ipo_safe(
996997
ci::CodeInfo,
997998
sv::OptimizationState,
998-
caller::InferenceResult,
999999
optimize_until = nothing, # run all passes by default
10001000
)
10011001
__stage__ = 0 # used by @pass

base/compiler/ssair/inlining.jl

Lines changed: 37 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ struct InliningTodo
1212
mi::MethodInstance
1313
# The IR of the inlinee
1414
ir::IRCode
15+
# The SpecInfo for the inlinee
16+
spec_info::SpecInfo
1517
# The DebugInfo table for the inlinee
1618
di::DebugInfo
1719
# If the function being inlined is a single basic block we can use a
@@ -20,8 +22,8 @@ struct InliningTodo
2022
# Effects of the call statement
2123
effects::Effects
2224
end
23-
function InliningTodo(mi::MethodInstance, (ir, di)::Tuple{IRCode, DebugInfo}, effects::Effects)
24-
return InliningTodo(mi, ir, di, linear_inline_eligible(ir), effects)
25+
function InliningTodo(mi::MethodInstance, ir::IRCode, spec_info::SpecInfo, di::DebugInfo, effects::Effects)
26+
return InliningTodo(mi, ir, spec_info, di, linear_inline_eligible(ir), effects)
2527
end
2628

2729
struct ConstantCase
@@ -321,7 +323,8 @@ function ir_inline_linetable!(debuginfo::DebugInfoStream, inlinee_debuginfo::Deb
321323
end
322324

323325
function ir_prepare_inlining!(insert_node!::Inserter, inline_target::Union{IRCode, IncrementalCompact},
324-
ir::IRCode, di::DebugInfo, mi::MethodInstance, inlined_at::NTuple{3,Int32}, argexprs::Vector{Any})
326+
ir::IRCode, spec_info::SpecInfo, di::DebugInfo, mi::MethodInstance,
327+
inlined_at::NTuple{3,Int32}, argexprs::Vector{Any})
325328
def = mi.def::Method
326329
debuginfo = inline_target isa IRCode ? inline_target.debuginfo : inline_target.ir.debuginfo
327330
topline = new_inlined_at = ir_inline_linetable!(debuginfo, di, inlined_at)
@@ -334,8 +337,8 @@ function ir_prepare_inlining!(insert_node!::Inserter, inline_target::Union{IRCod
334337
spvals_ssa = insert_node!(
335338
removable_if_unused(NewInstruction(Expr(:call, Core._compute_sparams, def, argexprs...), SimpleVector, topline)))
336339
end
337-
if def.isva
338-
nargs_def = Int(def.nargs::Int32)
340+
if spec_info.isva
341+
nargs_def = spec_info.nargs
339342
if nargs_def > 0
340343
argexprs = fix_va_argexprs!(insert_node!, inline_target, argexprs, nargs_def, topline)
341344
end
@@ -362,7 +365,7 @@ function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector
362365
item::InliningTodo, boundscheck::Symbol, todo_bbs::Vector{Tuple{Int, Int}})
363366
# Ok, do the inlining here
364367
inlined_at = compact.result[idx][:line]
365-
ssa_substitute = ir_prepare_inlining!(InsertHere(compact), compact, item.ir, item.di, item.mi, inlined_at, argexprs)
368+
ssa_substitute = ir_prepare_inlining!(InsertHere(compact), compact, item.ir, item.spec_info, item.di, item.mi, inlined_at, argexprs)
366369
boundscheck = has_flag(compact.result[idx], IR_FLAG_INBOUNDS) ? :off : boundscheck
367370

368371
# If the iterator already moved on to the next basic block,
@@ -860,15 +863,14 @@ function resolve_todo(mi::MethodInstance, result::Union{Nothing,InferenceResult,
860863
if inferred_result isa ConstantCase
861864
add_inlining_backedge!(et, mi)
862865
return inferred_result
863-
end
864-
if inferred_result isa InferredResult
866+
elseif inferred_result isa InferredResult
865867
(; src, effects) = inferred_result
866868
elseif inferred_result isa CodeInstance
867869
src = @atomic :monotonic inferred_result.inferred
868870
effects = decode_effects(inferred_result.ipo_purity_bits)
869-
else
870-
src = nothing
871-
effects = Effects()
871+
else # there is no cached source available, bail out
872+
return compileable_specialization(mi, Effects(), et, info;
873+
compilesig_invokes=OptimizationParams(state.interp).compilesig_invokes)
872874
end
873875

874876
# the duplicated check might have been done already within `analyze_method!`, but still
@@ -883,9 +885,12 @@ function resolve_todo(mi::MethodInstance, result::Union{Nothing,InferenceResult,
883885
compilesig_invokes=OptimizationParams(state.interp).compilesig_invokes)
884886

885887
add_inlining_backedge!(et, mi)
886-
ir = inferred_result isa CodeInstance ? retrieve_ir_for_inlining(inferred_result, src) :
887-
retrieve_ir_for_inlining(mi, src, preserve_local_sources)
888-
return InliningTodo(mi, ir, effects)
888+
if inferred_result isa CodeInstance
889+
ir, spec_info, debuginfo = retrieve_ir_for_inlining(inferred_result, src)
890+
else
891+
ir, spec_info, debuginfo = retrieve_ir_for_inlining(mi, src, preserve_local_sources)
892+
end
893+
return InliningTodo(mi, ir, spec_info, debuginfo, effects)
889894
end
890895

891896
# the special resolver for :invoke-d call
@@ -901,23 +906,17 @@ function resolve_todo(mi::MethodInstance, @nospecialize(info::CallInfo), flag::U
901906
if cached_result isa ConstantCase
902907
add_inlining_backedge!(et, mi)
903908
return cached_result
904-
end
905-
if cached_result isa InferredResult
906-
(; src, effects) = cached_result
907909
elseif cached_result isa CodeInstance
908910
src = @atomic :monotonic cached_result.inferred
909911
effects = decode_effects(cached_result.ipo_purity_bits)
910-
else
911-
src = nothing
912-
effects = Effects()
912+
else # there is no cached source available, bail out
913+
return nothing
913914
end
914915

915-
preserve_local_sources = true
916916
src_inlining_policy(state.interp, src, info, flag) || return nothing
917-
ir = cached_result isa CodeInstance ? retrieve_ir_for_inlining(cached_result, src) :
918-
retrieve_ir_for_inlining(mi, src, preserve_local_sources)
917+
ir, spec_info, debuginfo = retrieve_ir_for_inlining(cached_result, src)
919918
add_inlining_backedge!(et, mi)
920-
return InliningTodo(mi, ir, effects)
919+
return InliningTodo(mi, ir, spec_info, debuginfo, effects)
921920
end
922921

923922
function validate_sparams(sparams::SimpleVector)
@@ -971,22 +970,29 @@ function analyze_method!(match::MethodMatch, argtypes::Vector{Any},
971970
return resolve_todo(mi, volatile_inf_result, info, flag, state; invokesig)
972971
end
973972

974-
function retrieve_ir_for_inlining(cached_result::CodeInstance, src::MaybeCompressed)
975-
src = _uncompressed_ir(cached_result, src)::CodeInfo
976-
return inflate_ir!(src, cached_result.def), src.debuginfo
973+
function retrieve_ir_for_inlining(cached_result::CodeInstance, src::String)
974+
src = _uncompressed_ir(cached_result, src)
975+
return inflate_ir!(src, cached_result.def), SpecInfo(src), src.debuginfo
976+
end
977+
function retrieve_ir_for_inlining(cached_result::CodeInstance, src::CodeInfo)
978+
return inflate_ir!(copy(src), cached_result.def), SpecInfo(src), src.debuginfo
977979
end
978980
function retrieve_ir_for_inlining(mi::MethodInstance, src::CodeInfo, preserve_local_sources::Bool)
979981
if preserve_local_sources
980982
src = copy(src)
981983
end
982-
return inflate_ir!(src, mi), src.debuginfo
984+
return inflate_ir!(src, mi), SpecInfo(src), src.debuginfo
983985
end
984986
function retrieve_ir_for_inlining(mi::MethodInstance, ir::IRCode, preserve_local_sources::Bool)
985987
if preserve_local_sources
986988
ir = copy(ir)
987989
end
990+
# COMBAK this is not correct, we should make `InferenceResult` propagate `SpecInfo`
991+
spec_info = let m = mi.def::Method
992+
SpecInfo(Int(m.nargs), m.isva, false, nothing)
993+
end
988994
ir.debuginfo.def = mi
989-
return ir, DebugInfo(ir.debuginfo, length(ir.stmts))
995+
return ir, spec_info, DebugInfo(ir.debuginfo, length(ir.stmts))
990996
end
991997

992998
function handle_single_case!(todo::Vector{Pair{Int,Any}},
@@ -1466,8 +1472,8 @@ function semiconcrete_result_item(result::SemiConcreteResult,
14661472

14671473
add_inlining_backedge!(et, mi)
14681474
preserve_local_sources = OptimizationParams(state.interp).preserve_local_sources
1469-
ir = retrieve_ir_for_inlining(mi, result.ir, preserve_local_sources)
1470-
return InliningTodo(mi, ir, result.effects)
1475+
ir, _, debuginfo = retrieve_ir_for_inlining(mi, result.ir, preserve_local_sources)
1476+
return InliningTodo(mi, ir, result.spec_info, debuginfo, result.effects)
14711477
end
14721478

14731479
function handle_semi_concrete_result!(cases::Vector{InliningCase}, result::SemiConcreteResult,

base/compiler/ssair/passes.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,7 +1532,7 @@ function try_inline_finalizer!(ir::IRCode, argexprs::Vector{Any}, idx::Int,
15321532
end
15331533

15341534
src_inlining_policy(inlining.interp, src, info, IR_FLAG_NULL) || return false
1535-
src, di = retrieve_ir_for_inlining(code, src)
1535+
src, spec_info, di = retrieve_ir_for_inlining(code, src)
15361536

15371537
# For now: Require finalizer to only have one basic block
15381538
length(src.cfg.blocks) == 1 || return false
@@ -1542,7 +1542,7 @@ function try_inline_finalizer!(ir::IRCode, argexprs::Vector{Any}, idx::Int,
15421542

15431543
# TODO: Should there be a special line number node for inlined finalizers?
15441544
inline_at = ir[SSAValue(idx)][:line]
1545-
ssa_substitute = ir_prepare_inlining!(InsertBefore(ir, SSAValue(idx)), ir, src, di, mi, inline_at, argexprs)
1545+
ssa_substitute = ir_prepare_inlining!(InsertBefore(ir, SSAValue(idx)), ir, src, spec_info, di, mi, inline_at, argexprs)
15461546

15471547
# TODO: Use the actual inliner here rather than open coding this special purpose inliner.
15481548
ssa_rename = Vector{Any}(undef, length(src.stmts))

base/compiler/stmtinfo.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ struct SemiConcreteResult <: ConstResult
9494
mi::MethodInstance
9595
ir::IRCode
9696
effects::Effects
97+
spec_info::SpecInfo
9798
end
9899

99100
# XXX Technically this does not represent a result of constant inference, but rather that of

base/compiler/typeinfer.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -941,7 +941,7 @@ function typeinf_ircode(interp::AbstractInterpreter, mi::MethodInstance,
941941
end
942942
(; result) = frame
943943
opt = OptimizationState(frame, interp)
944-
ir = run_passes_ipo_safe(opt.src, opt, result, optimize_until)
944+
ir = run_passes_ipo_safe(opt.src, opt, optimize_until)
945945
rt = widenconst(ignorelimited(result.result))
946946
return ir, rt
947947
end

base/compiler/types.jl

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,14 @@ struct StmtInfo
4141
used::Bool
4242
end
4343

44-
struct MethodInfo
44+
struct SpecInfo
45+
nargs::Int
46+
isva::Bool
4547
propagate_inbounds::Bool
4648
method_for_inference_limit_heuristics::Union{Nothing,Method}
4749
end
48-
MethodInfo(src::CodeInfo) = MethodInfo(
50+
SpecInfo(src::CodeInfo) = SpecInfo(
51+
Int(src.nargs), src.isva,
4952
src.propagate_inbounds,
5053
src.method_for_inference_limit_heuristics::Union{Nothing,Method})
5154

test/compiler/EscapeAnalysis/EAUtils.jl

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,12 +116,14 @@ CC.get_inference_world(interp::EscapeAnalyzer) = interp.world
116116
CC.get_inference_cache(interp::EscapeAnalyzer) = interp.inf_cache
117117
CC.cache_owner(::EscapeAnalyzer) = EAToken()
118118

119-
function CC.ipo_dataflow_analysis!(interp::EscapeAnalyzer, ir::IRCode, caller::InferenceResult)
119+
function CC.ipo_dataflow_analysis!(interp::EscapeAnalyzer, opt::OptimizationState,
120+
ir::IRCode, caller::InferenceResult)
120121
# run EA on all frames that have been optimized
121-
nargs = let def = caller.linfo.def; isa(def, Method) ? Int(def.nargs) : 0; end
122+
nargs = Int(opt.src.nargs)
123+
𝕃ₒ = CC.optimizer_lattice(interp)
122124
get_escape_cache = GetEscapeCache(interp)
123125
estate = try
124-
analyze_escapes(ir, nargs, CC.optimizer_lattice(interp), get_escape_cache)
126+
analyze_escapes(ir, nargs, 𝕃ₒ, get_escape_cache)
125127
catch err
126128
@error "error happened within EA, inspect `Main.failed_escapeanalysis`"
127129
Main.failed_escapeanalysis = FailedAnalysis(ir, nargs, get_escape_cache)
@@ -133,7 +135,8 @@ function CC.ipo_dataflow_analysis!(interp::EscapeAnalyzer, ir::IRCode, caller::I
133135
end
134136
record_escapes!(interp, caller, estate, ir)
135137

136-
@invoke CC.ipo_dataflow_analysis!(interp::AbstractInterpreter, ir::IRCode, caller::InferenceResult)
138+
@invoke CC.ipo_dataflow_analysis!(interp::AbstractInterpreter, opt::OptimizationState,
139+
ir::IRCode, caller::InferenceResult)
137140
end
138141

139142
function record_escapes!(interp::EscapeAnalyzer,

0 commit comments

Comments
 (0)