From 9c2324abba27e48712ec439ff922576402107489 Mon Sep 17 00:00:00 2001 From: gbaraldi Date: Mon, 9 Jun 2025 22:07:45 -0300 Subject: [PATCH 1/2] Add 0 predecessor to entry basic block and handle it in inlining --- Compiler/src/ssair/inlining.jl | 16 ++++++++-------- Compiler/src/ssair/ir.jl | 3 +++ Compiler/test/ssair.jl | 20 ++++++++++++++++++++ 3 files changed, 31 insertions(+), 8 deletions(-) diff --git a/Compiler/src/ssair/inlining.jl b/Compiler/src/ssair/inlining.jl index ec3879e27357f..9db5e08a216f2 100644 --- a/Compiler/src/ssair/inlining.jl +++ b/Compiler/src/ssair/inlining.jl @@ -126,10 +126,11 @@ function cfg_inline_item!(ir::IRCode, idx::Int, todo::InliningTodo, state::CFGIn block = block_for_inst(ir, idx) inline_into_block!(state, block) - if !isempty(inlinee_cfg.blocks[1].preds) + if length(inlinee_cfg.blocks[1].preds) > 1 need_split_before = true + else + @assert inlinee_cfg.blocks[1].preds[1] == 0 end - last_block_idx = last(state.cfg.blocks[block].stmts) if false # TODO: ((idx+1) == last_block_idx && isa(ir[SSAValue(last_block_idx)], GotoNode)) need_split = false @@ -166,12 +167,15 @@ function cfg_inline_item!(ir::IRCode, idx::Int, todo::InliningTodo, state::CFGIn end new_block_range = (length(state.new_cfg_blocks)-length(inlinee_cfg.blocks)+1):length(state.new_cfg_blocks) - # Fixup the edges of the newely added blocks + # Fixup the edges of the newly added blocks for (old_block, new_block) in enumerate(bb_rename_range) if old_block != 1 || need_split_before p = state.new_cfg_blocks[new_block].preds let bb_rename_range = bb_rename_range map!(p, p) do old_pred_block + if old_block == 1 && old_pred_block == 0 + return first(bb_rename_range) - 1 + end return old_pred_block == 0 ? 0 : bb_rename_range[old_pred_block] end end @@ -186,10 +190,6 @@ function cfg_inline_item!(ir::IRCode, idx::Int, todo::InliningTodo, state::CFGIn end end - if need_split_before - push!(state.new_cfg_blocks[first(bb_rename_range)].preds, first(bb_rename_range)-1) - end - any_edges = false for (old_block, new_block) in enumerate(bb_rename_range) if (length(state.new_cfg_blocks[new_block].succs) == 0) @@ -399,7 +399,7 @@ function ir_inline_item!(compact::IncrementalCompact, idx::Int, argexprs::Vector else bb_offset, post_bb_id = popfirst!(todo_bbs) # This implements the need_split_before flag above - need_split_before = !isempty(item.ir.cfg.blocks[1].preds) + need_split_before = length(item.ir.cfg.blocks[1].preds) > 1 if need_split_before finish_current_bb!(compact, 0) end diff --git a/Compiler/src/ssair/ir.jl b/Compiler/src/ssair/ir.jl index 87c8e7f0bc00d..e6a8ffe6d539e 100644 --- a/Compiler/src/ssair/ir.jl +++ b/Compiler/src/ssair/ir.jl @@ -105,6 +105,9 @@ function compute_basic_blocks(stmts::Vector{Any}) end # Compute successors/predecessors for (num, b) in enumerate(blocks) + if b.stmts.start == 1 + push!(b.preds, 0) # the entry block has a virtual predecessor + end terminator = stmts[last(b.stmts)] if isa(terminator, ReturnNode) # return never has any successors diff --git a/Compiler/test/ssair.jl b/Compiler/test/ssair.jl index a855439877f1b..7aca2b8977a4e 100644 --- a/Compiler/test/ssair.jl +++ b/Compiler/test/ssair.jl @@ -825,3 +825,23 @@ end @test_throws ErrorException Base.code_ircode(+, (Float64, Float64); optimize_until = "nonexisting pass name") @test_throws ErrorException Base.code_ircode(+, (Float64, Float64); optimize_until = typemax(Int)) + +#57153 check that the CFG has a #0 block predecessor and that we don't fail to compile code that observes that +function _worker_task57153() + while true + r = let + try + if @noinline rand(Bool) + return nothing + end + q, m + finally + missing + end + end + r[1]::Bool + end +end +let ir = Base.code_ircode(_worker_task57153, (), optimize_until="CC: COMPACT_2")[1].first + @test findfirst(x->x==0, ir.cfg.blocks[1].preds) !== nothing +end From 7ecfe592c541344dc075620ad6fd1334080310e0 Mon Sep 17 00:00:00 2001 From: gbaraldi Date: Tue, 10 Jun 2025 11:41:08 -0300 Subject: [PATCH 2/2] Add comments --- Compiler/src/ssair/inlining.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Compiler/src/ssair/inlining.jl b/Compiler/src/ssair/inlining.jl index 9db5e08a216f2..251767d577157 100644 --- a/Compiler/src/ssair/inlining.jl +++ b/Compiler/src/ssair/inlining.jl @@ -173,9 +173,12 @@ function cfg_inline_item!(ir::IRCode, idx::Int, todo::InliningTodo, state::CFGIn p = state.new_cfg_blocks[new_block].preds let bb_rename_range = bb_rename_range map!(p, p) do old_pred_block + # the meaning of predecessor 0 depends on the block we encounter it: + # - in the first block, it represents the function entry and so needs to be re-mapped if old_block == 1 && old_pred_block == 0 return first(bb_rename_range) - 1 end + # - elsewhere, it represents external control-flow from a caught exception which is un-affected by inlining return old_pred_block == 0 ? 0 : bb_rename_range[old_pred_block] end end