Skip to content

Commit 72dbbdb

Browse files
authored
cfg_simplify: Handle various corner cases with try/catch blocks (#52323)
Mostly long-standing bugs related to not handling the virtual predecessor to catch blocks, but also one recent regression from the EnterNode change.
1 parent 5b2fcb6 commit 72dbbdb

File tree

2 files changed

+67
-3
lines changed

2 files changed

+67
-3
lines changed

base/compiler/ssair/passes.jl

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2011,6 +2011,7 @@ function follow_map(map::Vector{Int}, idx::Int)
20112011
end
20122012

20132013
function ascend_eliminated_preds(bbs::Vector{BasicBlock}, pred::Int)
2014+
pred == 0 && return pred
20142015
while pred != 1 && length(bbs[pred].preds) == 1 && length(bbs[pred].succs) == 1
20152016
pred = bbs[pred].preds[1]
20162017
end
@@ -2048,6 +2049,10 @@ function add_preds!(all_new_preds::Vector{Int32}, bbs::Vector{BasicBlock}, bb_re
20482049
preds = copy(bbs[old_edge].preds)
20492050
while !isempty(preds)
20502051
old_edge′ = popfirst!(preds)
2052+
if old_edge′ == 0
2053+
push!(all_new_preds, old_edge′)
2054+
continue
2055+
end
20512056
new_edge = bb_rename_pred[old_edge′]
20522057
if new_edge > 0 && new_edge all_new_preds
20532058
push!(all_new_preds, Int32(new_edge))
@@ -2147,9 +2152,9 @@ function cfg_simplify!(ir::IRCode)
21472152
push!(worklist, terminator.dest)
21482153
end
21492154
elseif isa(terminator, EnterNode)
2150-
enteridx = terminator.args[1]::Int
2151-
if bb_rename_succ[enteridx] == 0
2152-
push!(worklist, enteridx)
2155+
catchbb = terminator.catch_dest
2156+
if bb_rename_succ[catchbb] == 0
2157+
push!(worklist, catchbb)
21532158
end
21542159
end
21552160
ncurr = curr + 1
@@ -2329,6 +2334,12 @@ function cfg_simplify!(ir::IRCode)
23292334
else
23302335
resize!(values, length(values)+1)
23312336
end
2337+
elseif new_edge == -1
2338+
@assert length(phi.edges) == 1
2339+
if isassigned(phi.values, old_index)
2340+
push!(edges, -1)
2341+
push!(values, phi.values[old_index])
2342+
end
23322343
elseif new_edge == -3
23332344
# Multiple predecessors, we need to expand out this phi
23342345
all_new_preds = Int32[]

test/compiler/irpasses.jl

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1626,3 +1626,56 @@ end
16261626
# but currently this would require an extra round of constprop
16271627
@test_broken fully_eliminated(persistent_dict_elim)
16281628
@test code_typed(persistent_dict_elim)[1][1].code[end] == Core.ReturnNode(1)
1629+
1630+
# Test CFG simplify with try/catch blocks
1631+
let m = Meta.@lower 1 + 1
1632+
@assert Meta.isexpr(m, :thunk)
1633+
src = m.args[1]::CodeInfo
1634+
src.code = Any[
1635+
# Block 1
1636+
GotoIfNot(Argument(1), 5),
1637+
# Block 2
1638+
EnterNode(4),
1639+
# Block 3
1640+
Expr(:leave),
1641+
# Block 4
1642+
GotoNode(5),
1643+
# Block 5
1644+
ReturnNode(1)
1645+
]
1646+
nstmts = length(src.code)
1647+
src.ssavaluetypes = nstmts
1648+
src.codelocs = fill(Int32(1), nstmts)
1649+
src.ssaflags = fill(Int32(0), nstmts)
1650+
ir = Core.Compiler.inflate_ir(src)
1651+
Core.Compiler.verify_ir(ir)
1652+
ir = Core.Compiler.cfg_simplify!(ir)
1653+
Core.Compiler.verify_ir(ir)
1654+
@test length(ir.cfg.blocks) == 4
1655+
end
1656+
1657+
# Test CFG simplify with single predecessor phi node
1658+
let m = Meta.@lower 1 + 1
1659+
@assert Meta.isexpr(m, :thunk)
1660+
src = m.args[1]::CodeInfo
1661+
src.code = Any[
1662+
# Block 1
1663+
Expr(:call, Base.inferencebarrier, 1),
1664+
GotoNode(3),
1665+
# Block 2
1666+
PhiNode(Int32[1], Any[SSAValue(1)]),
1667+
ReturnNode(SSAValue(3))
1668+
]
1669+
nstmts = length(src.code)
1670+
src.ssavaluetypes = nstmts
1671+
src.codelocs = fill(Int32(1), nstmts)
1672+
src.ssaflags = fill(Int32(0), nstmts)
1673+
ir = Core.Compiler.inflate_ir(src)
1674+
Core.Compiler.verify_ir(ir)
1675+
ir = Core.Compiler.cfg_simplify!(ir)
1676+
Core.Compiler.verify_ir(ir)
1677+
@test length(ir.cfg.blocks) == 1
1678+
ir = Core.Compiler.compact!(ir)
1679+
@test length(ir.stmts) == 2
1680+
@test (ir[SSAValue(2)][:stmt]::ReturnNode).val == SSAValue(1)
1681+
end

0 commit comments

Comments
 (0)