Skip to content

Commit c476d84

Browse files
authored
slot2ssa: consider liveness when inserting PiNodes (#51406)
1 parent 9f0676c commit c476d84

File tree

2 files changed

+52
-1
lines changed

2 files changed

+52
-1
lines changed

base/compiler/ssair/slot2ssa.jl

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,7 @@ function construct_ssa!(ci::CodeInfo, ir::IRCode, sv::OptimizationState,
587587
handler_at = compute_trycatch(code, BitSet())
588588

589589
phi_slots = Vector{Int}[Int[] for _ = 1:length(ir.cfg.blocks)]
590+
live_slots = Vector{Int}[Int[] for _ = 1:length(ir.cfg.blocks)]
590591
new_phi_nodes = Vector{NewPhiNode2}[NewPhiNode2[] for _ = 1:length(cfg.blocks)]
591592
new_phic_nodes = IdDict{Int, Vector{NewPhiCNode2}}()
592593
for (; leave_block) in catch_entry_blocks
@@ -617,8 +618,10 @@ function construct_ssa!(ci::CodeInfo, ir::IRCode, sv::OptimizationState,
617618
end
618619
continue
619620
end
621+
620622
@timeit "liveness" (live = compute_live_ins(cfg, slot))
621623
for li in live.live_in_bbs
624+
push!(live_slots[li], idx)
622625
cidx = findfirst(x::TryCatchRegion->x.leave_block==li, catch_entry_blocks)
623626
if cidx !== nothing
624627
# The slot is live-in into this block. We need to
@@ -735,7 +738,7 @@ function construct_ssa!(ci::CodeInfo, ir::IRCode, sv::OptimizationState,
735738
end
736739
# Record Pi nodes if necessary
737740
has_pinode = fill(false, length(sv.slottypes))
738-
for slot in 1:length(sv.slottypes)
741+
for slot in live_slots[item]
739742
(ival, idef) = incoming_vals[slot]
740743
(ival === SSAValue(-1)) && continue
741744
(ival === SSAValue(-2)) && continue

test/compiler/irpasses.jl

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1519,3 +1519,51 @@ let ir = first(only(Base.code_ircode(f_with_early_try_catch_exit, (); optimize_u
15191519
end
15201520

15211521
@test isnothing(f_with_early_try_catch_exit())
1522+
1523+
# Issue #51144 - UndefRefError during compaction
1524+
let m = Meta.@lower 1 + 1
1525+
@assert Meta.isexpr(m, :thunk)
1526+
src = m.args[1]::CodeInfo
1527+
src.code = Any[
1528+
# block 1 → 2, 3
1529+
#= %1: =# Expr(:(=), Core.SlotNumber(4), Core.Argument(2)),
1530+
#= %2: =# Expr(:call, :(===), Core.SlotNumber(4), nothing),
1531+
#= %3: =# GotoIfNot(Core.SSAValue(1), 5),
1532+
# block 2
1533+
#= %4: =# ReturnNode(nothing),
1534+
# block 3 → 4, 5
1535+
#= %5: =# Expr(:(=), Core.SlotNumber(4), false),
1536+
#= %6: =# GotoIfNot(Core.Argument(2), 8),
1537+
# block 4 → 5
1538+
#= %7: =# Expr(:(=), Core.SlotNumber(4), true),
1539+
# block 5
1540+
#= %8: =# ReturnNode(nothing), # Must not insert a π-node here
1541+
]
1542+
nstmts = length(src.code)
1543+
nslots = 4
1544+
src.ssavaluetypes = nstmts
1545+
src.codelocs = fill(Int32(1), nstmts)
1546+
src.ssaflags = fill(Int32(0), nstmts)
1547+
src.slotflags = fill(0, nslots)
1548+
src.slottypes = Any[Any, Union{Bool, Nothing}, Bool, Union{Bool, Nothing}]
1549+
ir = Core.Compiler.inflate_ir(src)
1550+
1551+
mi = ccall(:jl_new_method_instance_uninit, Ref{Core.MethodInstance}, ());
1552+
mi.specTypes = Tuple{}
1553+
mi.def = Module()
1554+
1555+
# Simulate the important results from inference
1556+
interp = Core.Compiler.NativeInterpreter()
1557+
sv = Core.Compiler.OptimizationState(mi, src, interp)
1558+
slot_id = 4
1559+
for block_id = 3:5
1560+
# (_4 !== nothing) conditional narrows the type, triggering PiNodes
1561+
sv.bb_vartables[block_id][slot_id] = VarState(Bool, #= maybe_undef =# false)
1562+
end
1563+
1564+
ir = Core.Compiler.convert_to_ircode(src, sv)
1565+
ir = Core.Compiler.slot2reg(ir, src, sv)
1566+
ir = Core.Compiler.compact!(ir)
1567+
1568+
Core.Compiler.verify_ir(ir)
1569+
end

0 commit comments

Comments
 (0)