Skip to content

Commit f14bf29

Browse files
authored
sroa: Fix affinity of inserted undef check (#52864)
There is a bit of complexity here making sure that this instruction ends up in the correct basic block because there's a fair number of corner cases (e.g. whether we're deleting the first instruction of a basic block or the last or both). Side-step all that by never doing the delete-then-insert dance and instead doing regular instruction replacement if necessary. Fixes #52857.
1 parent 6f73806 commit f14bf29

File tree

2 files changed

+27
-7
lines changed

2 files changed

+27
-7
lines changed

base/compiler/ssair/passes.jl

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,7 +1403,7 @@ function sroa_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing)
14031403
(lifted_val, nest) = perform_lifting!(compact,
14041404
visited_philikes, field, result_t, lifted_leaves, val, lazydomtree)
14051405

1406-
node_was_deleted = false
1406+
should_delete_node = false
14071407
line = compact[SSAValue(idx)][:line]
14081408
if lifted_val !== nothing && !(𝕃ₒ, compact[SSAValue(idx)][:type], result_t)
14091409
compact[idx] = lifted_val === nothing ? nothing : lifted_val.val
@@ -1412,9 +1412,8 @@ function sroa_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing)
14121412
# Save some work in a later compaction, by inserting this into the renamer now,
14131413
# but only do this if we didn't set the REFINED flag, to save work for irinterp
14141414
# in revisiting only the renamings that came through *this* idx.
1415-
delete_inst_here!(compact)
14161415
compact.ssa_rename[old_idx] = lifted_val === nothing ? nothing : lifted_val.val
1417-
node_was_deleted = true
1416+
should_delete_node = true
14181417
else
14191418
compact[idx] = lifted_val === nothing ? nothing : lifted_val.val
14201419
end
@@ -1435,17 +1434,24 @@ function sroa_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing)
14351434
def_val = (def_val::LiftedValue).val
14361435
finish_phi_nest!(compact, nest)
14371436
end
1438-
ni = NewInstruction(
1439-
Expr(:throw_undef_if_not, Symbol("##getfield##"), def_val), Nothing, line)
1440-
if node_was_deleted
1441-
insert_node_here!(compact, ni, true)
1437+
throw_expr = Expr(:throw_undef_if_not, Symbol("##getfield##"), def_val)
1438+
if should_delete_node
1439+
# Replace the node we already have rather than deleting/re-inserting.
1440+
# This way it is easier to handle BB boundary corner cases.
1441+
compact[SSAValue(idx)] = throw_expr
1442+
compact[SSAValue(idx)][:type] = Nothing
1443+
compact[SSAValue(idx)][:flag] = IR_FLAG_EFFECT_FREE | IR_FLAG_CONSISTENT | IR_FLAG_NOUB
1444+
should_delete_node = false
14421445
else
1446+
ni = NewInstruction(throw_expr, Nothing, line)
14431447
insert_node!(compact, SSAValue(idx), ni)
14441448
end
14451449
else
14461450
# val must be defined
14471451
@assert lifted_val !== nothing
14481452
end
1453+
1454+
should_delete_node && delete_inst_here!(compact)
14491455
end
14501456

14511457
non_dce_finish!(compact)

test/compiler/irpasses.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1764,3 +1764,17 @@ let code = Any[
17641764
@test Core.Compiler.verify_ir(ir) === nothing
17651765
@test count(x->isa(x, GotoIfNot), ir.stmts.stmt) == 1
17661766
end
1767+
1768+
# Issue #52857 - Affinity of sroa definedness check
1769+
let code = Any[
1770+
Expr(:new, ImmutableRef{Any}),
1771+
GotoIfNot(Argument(1), 4),
1772+
Expr(:call, GlobalRef(Base, :getfield), SSAValue(1), 1), # Will throw
1773+
ReturnNode(1)
1774+
]
1775+
ir = make_ircode(code; ssavaluetypes = Any[ImmutableRef{Any}, Any, Any, Any], slottypes=Any[Bool], verify=true)
1776+
ir = Core.Compiler.sroa_pass!(ir)
1777+
@test Core.Compiler.verify_ir(ir) === nothing
1778+
@test !any(iscall((ir, getfield)), ir.stmts.stmt)
1779+
@test length(ir.cfg.blocks[end].stmts) == 1
1780+
end

0 commit comments

Comments
 (0)