Skip to content

Commit 7e1431f

Browse files
authored
irinterp: Don't introduce invalid CFGs (#49797)
This is yet another followup to #49692 and #49750. With the introduced change, we kill the CFG edge from the basic block with the discovered error to its successors. However, we have an invariant in the verifier that the CFG should always match the IR. Turns out this is for good reason, as we assume in a number of places (including, ironically in the irinterp) that a GotoNode/GotoIfNot terminator means that the BB has the corresponding number of successors in the IR. Fix all this by killing the rest of the basic block when we discover that it is unreachable and if possible introducing an unreachable node at the end. However, of course if the erroring statement is the fallthrough terminator itself, there is no space for an unreachable node. We fix this by tweaking the verification to allow this case, as its really no worse than the other problems with fall-through terminators (#41476), but of course it would be good to address that as part of a more general IR refactor.
1 parent 0a05a5b commit 7e1431f

File tree

2 files changed

+18
-7
lines changed

2 files changed

+18
-7
lines changed

base/compiler/ssair/irinterp.jl

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -253,14 +253,19 @@ function _ir_abstract_constant_propagation(interp::AbstractInterpreter, irsv::IR
253253
inst = ir.stmts[idx][:inst]
254254
typ = ir.stmts[idx][:type]
255255
end
256-
if idx == lstmt
257-
process_terminator!(ir, inst, idx, bb, all_rets, bb_ip) && @goto residual_scan
258-
(isa(inst, GotoNode) || isa(inst, GotoIfNot) || isa(inst, ReturnNode) || isexpr(inst, :enter)) && continue
259-
end
260-
if typ === Bottom && !isa(inst, PhiNode)
256+
if typ === Bottom && !(isa(inst, PhiNode) || isa(inst, GotoNode) || isa(inst, GotoIfNot) || isa(inst, ReturnNode) || isexpr(inst, :enter))
261257
kill_terminator_edges!(irsv, lstmt, bb)
258+
if idx != lstmt
259+
for idx2 in (idx+1:lstmt-1)
260+
ir[SSAValue(idx2)] = nothing
261+
end
262+
ir[SSAValue(lstmt)][:inst] = ReturnNode()
263+
end
262264
break
263265
end
266+
if idx == lstmt
267+
process_terminator!(ir, inst, idx, bb, all_rets, bb_ip) && @goto residual_scan
268+
end
264269
end
265270
end
266271
@goto compute_rt

base/compiler/ssair/verify.jl

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,8 +174,14 @@ function verify_ir(ir::IRCode, print::Bool=true,
174174
end
175175
isa(stmt, PhiNode) || break
176176
end
177-
@verify_error "Block $idx successors ($(block.succs)), does not match fall-through terminator ($terminator)"
178-
error("")
177+
if isempty(block.succs) && ir.stmts[idx][:type] == Union{}
178+
# Allow fallthrough terminators that are known to error to
179+
# be removed from the CFG. Ideally we'd add an unreachable
180+
# here, but that isn't always possible.
181+
else
182+
@verify_error "Block $idx successors ($(block.succs)), does not match fall-through terminator ($terminator)"
183+
error("")
184+
end
179185
end
180186
end
181187
end

0 commit comments

Comments
 (0)