diff --git a/base/compiler/ssair/ir.jl b/base/compiler/ssair/ir.jl index a1a6bf3b15546..3377e0c5cbde8 100644 --- a/base/compiler/ssair/ir.jl +++ b/base/compiler/ssair/ir.jl @@ -1511,10 +1511,20 @@ function finish_current_bb!(compact::IncrementalCompact, active_bb::Int, return skipped end -function attach_after_stmt_after(compact::IncrementalCompact, idx::Int) - compact.new_nodes_idx > length(compact.perm) && return false - entry = compact.ir.new_nodes.info[compact.perm[compact.new_nodes_idx]] - return entry.pos == idx && entry.attach_after +""" + stmts_awaiting_insertion(compact::IncrementalCompact, idx::Int) + +Returns true if there are new/pending instructions enqueued for insertion into +`compact` on any instruction in the range `1:idx`. Otherwise, returns false. +""" +function stmts_awaiting_insertion(compact::IncrementalCompact, idx::Int) + + new_node_waiting = compact.new_nodes_idx <= length(compact.perm) && + compact.ir.new_nodes.info[compact.perm[compact.new_nodes_idx]].pos <= idx + pending_node_waiting = !isempty(compact.pending_perm) && + compact.pending_nodes.info[compact.pending_perm[1]].pos <= idx + + return new_node_waiting || pending_node_waiting end function process_newnode!(compact::IncrementalCompact, new_idx::Int, new_node_entry::Instruction, new_node_info::NewNodeInfo, idx::Int, active_bb::Int, do_rename_ssa::Bool) @@ -1526,7 +1536,7 @@ function process_newnode!(compact::IncrementalCompact, new_idx::Int, new_node_en compact.result_idx = result_idx # If this instruction has reverse affinity and we were at the end of a basic block, # finish it now. - if new_node_info.attach_after && idx == last(bb.stmts)+1 && !attach_after_stmt_after(compact, idx-1) + if new_node_info.attach_after && idx == last(bb.stmts)+1 && !stmts_awaiting_insertion(compact, idx-1) active_bb += 1 finish_current_bb!(compact, active_bb, old_result_idx) end @@ -1656,7 +1666,7 @@ function iterate_compact(compact::IncrementalCompact) compact.result[old_result_idx] = compact.ir.stmts[idx] result_idx = process_node!(compact, old_result_idx, compact.ir.stmts[idx], idx, idx, active_bb, true) compact.result_idx = result_idx - if idx == last(bb.stmts) && !attach_after_stmt_after(compact, idx) + if idx == last(bb.stmts) && !stmts_awaiting_insertion(compact, idx) finish_current_bb!(compact, active_bb, old_result_idx) active_bb += 1 end diff --git a/test/compiler/ssair.jl b/test/compiler/ssair.jl index 43f17d4ad69f2..98cab349b46ee 100644 --- a/test/compiler/ssair.jl +++ b/test/compiler/ssair.jl @@ -566,6 +566,33 @@ let ir = Base.code_ircode((Int,Int); optimize_until="inlining") do a, b @test call2.args[2] === SSAValue(2) end +# Issue #50379 - insert_node!(::IncrementalCompact, ...) at end of basic block +let ci = make_ci([ + # block 1 + #= %1: =# Core.Compiler.GotoIfNot(Expr(:boundscheck), 3), + # block 2 + #= %2: =# Expr(:call, println, Argument(1)), + # block 3 + #= %3: =# Core.PhiNode(), + #= %4: =# Core.Compiler.ReturnNode(), + ]) + ir = Core.Compiler.inflate_ir(ci) + + # Insert another call at end of "block 2" + compact = Core.Compiler.IncrementalCompact(ir) + new_inst = NewInstruction(Expr(:call, println, Argument(1)), Nothing) + insert_node!(compact, SSAValue(2), new_inst, #= attach_after =# true) + + # Complete iteration + x = Core.Compiler.iterate(compact) + while x !== nothing + x = Core.Compiler.iterate(compact, x[2]) + end + ir = Core.Compiler.complete(compact) + + @test Core.Compiler.verify_ir(ir) === nothing +end + # insert_node! with new instruction with flag computed let ir = Base.code_ircode((Int,Int); optimize_until="inlining") do a, b a^b