Skip to content

Commit 44a7915

Browse files
Kenomaleadt
andauthored
ir: Fix incorrect renaming of phinode values (#52614)
This fixes #52610. The underlying issue is a left over OldSSAValue after the adce_pass! (introduced by compaction, it being during adce is incidental). Compaction introduces `OldSSAValue` when it compacts in PhiNodes that reference later SSAValues and adds them to a list to revisit at the end of compaction to fill in the actual renamed result. There are two separate fixes here: 1. If the result of the final revisit is yet another `OldSSAValue`, rename it again. I don't this ordinarily happens at all, but I suppose it is possible in theory during sroa beacuse of the rename-shortcut optimization [1]. However, this is not not what happened here. Instead compaction incorrectly used an OldSSAValue for an already-inserted node, which then ends up in the rename list because we deleted one of the predecessor edges [2]. To fix that we: 2. Fix an issue where we weren't accounting for the possibility of previously pending nodes (which have SSAValues beyond the numbering range of the ordinary statements) in the special already_inserted query in phinode value processing. To fix this, unify the logic with the ordinary `already_inserted` query, which handles this case correctly. [1] https://github.com/JuliaLang/julia/blob/9443c761871c4db9c3213a1e01804286292c3f4d/base/compiler/ssair/passes.jl#L1385 [2] https://github.com/JuliaLang/julia/blob/9443c761871c4db9c3213a1e01804286292c3f4d/base/compiler/ssair/ir.jl#L1556 Co-authored-by: Tim Besard <[email protected]>
1 parent 4975a78 commit 44a7915

File tree

4 files changed

+39
-14
lines changed

4 files changed

+39
-14
lines changed

base/compiler/ssair/ir.jl

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1359,7 +1359,7 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr
13591359
(; result, ssa_rename, late_fixup, used_ssas, new_new_used_ssas) = compact
13601360
(; cfg_transforms_enabled, fold_constant_branches, bb_rename_succ, bb_rename_pred, result_bbs) = compact.cfg_transform
13611361
mark_refined! = Refiner(result.flag, result_idx)
1362-
already_inserted = (::Int, ssa::OldSSAValue)->ssa.id <= processed_idx
1362+
already_inserted_phi_arg = already_inserted_ssa(compact, processed_idx)
13631363
if stmt === nothing
13641364
ssa_rename[idx] = stmt
13651365
elseif isa(stmt, OldSSAValue)
@@ -1535,7 +1535,7 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr
15351535
values = stmt.values
15361536
end
15371537

1538-
values = process_phinode_values(values, late_fixup, already_inserted, result_idx, ssa_rename, used_ssas, new_new_used_ssas, do_rename_ssa, mark_refined!)
1538+
values = process_phinode_values(values, late_fixup, already_inserted_phi_arg, result_idx, ssa_rename, used_ssas, new_new_used_ssas, do_rename_ssa, mark_refined!)
15391539
# Don't remove the phi node if it is before the definition of its value
15401540
# because doing so can create forward references. This should only
15411541
# happen with dead loops, but can cause problems when optimization
@@ -1574,7 +1574,7 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr
15741574
push!(values, value)
15751575
end
15761576
end
1577-
result[result_idx][:stmt] = PhiCNode(process_phinode_values(values, late_fixup, already_inserted, result_idx, ssa_rename, used_ssas, new_new_used_ssas, do_rename_ssa, mark_refined!))
1577+
result[result_idx][:stmt] = PhiCNode(process_phinode_values(values, late_fixup, already_inserted_phi_arg, result_idx, ssa_rename, used_ssas, new_new_used_ssas, do_rename_ssa, mark_refined!))
15781578
result_idx += 1
15791579
else
15801580
if isa(stmt, SSAValue)
@@ -1883,6 +1883,8 @@ function fixup_node(compact::IncrementalCompact, @nospecialize(stmt), reify_new_
18831883
compact.used_ssas[node.id] += 1
18841884
elseif isa(node, NewSSAValue)
18851885
compact.new_new_used_ssas[-node.id] += 1
1886+
elseif isa(node, OldSSAValue)
1887+
return fixup_node(compact, node, reify_new_nodes)
18861888
end
18871889
return FixedNode(node, needs_fixup)
18881890
else

base/compiler/ssair/passes.jl

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -348,17 +348,23 @@ function record_immutable_preserve!(new_preserves::Vector{Any}, def::Expr, compa
348348
end
349349

350350
function already_inserted(compact::IncrementalCompact, old::OldSSAValue)
351-
id = old.id
352-
if id < length(compact.ir.stmts)
353-
return id < compact.idx
354-
end
355-
id -= length(compact.ir.stmts)
356-
if id < length(compact.ir.new_nodes)
357-
return already_inserted(compact, OldSSAValue(compact.ir.new_nodes.info[id].pos))
351+
already_inserted_ssa(compact, compact.idx-1)(0, old)
352+
end
353+
354+
function already_inserted_ssa(compact::IncrementalCompact, processed_idx::Int)
355+
return function did_already_insert(phi_arg::Int, old::OldSSAValue)
356+
id = old.id
357+
if id <= length(compact.ir.stmts)
358+
return id <= processed_idx
359+
end
360+
id -= length(compact.ir.stmts)
361+
if id <= length(compact.ir.new_nodes)
362+
return did_already_insert(phi_arg, OldSSAValue(compact.ir.new_nodes.info[id].pos))
363+
end
364+
id -= length(compact.ir.new_nodes)
365+
@assert id <= length(compact.pending_nodes)
366+
return !(id in compact.pending_perm)
358367
end
359-
id -= length(compact.ir.new_nodes)
360-
@assert id <= length(compact.pending_nodes)
361-
return !(id in compact.pending_perm)
362368
end
363369

364370
function is_pending(compact::IncrementalCompact, old::OldSSAValue)
@@ -2079,6 +2085,7 @@ function adce_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing)
20792085
end
20802086
end
20812087
end
2088+
20822089
return Pair{IRCode, Bool}(complete(compact), made_changes)
20832090
end
20842091

base/compiler/ssair/verify.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ function check_op(ir::IRCode, domtree::DomTree, @nospecialize(op), use_bb::Int,
7272
end
7373
end
7474
elseif isa(op, Union{OldSSAValue, NewSSAValue})
75-
@verify_error "Left over SSA marker"
75+
@verify_error "At statement %$use_idx: Left over SSA marker ($op)"
7676
error("")
7777
elseif isa(op, SlotNumber)
7878
@verify_error "Left over slot detected in converted IR"

test/compiler/irpasses.jl

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1709,3 +1709,19 @@ end
17091709
@test scope_folding_opt() == 1
17101710
@test_broken fully_eliminated(scope_folding)
17111711
@test_broken fully_eliminated(scope_folding_opt)
1712+
1713+
# Function that happened to have lots of sroa that
1714+
# happened to trigger a bad case in the renamer. We
1715+
# just want to check this doesn't crash in inference.
1716+
function f52610()
1717+
slots_dict = IdDict()
1718+
for () in Base.inferencebarrier(1)
1719+
for x in 1
1720+
if Base.inferencebarrier(true)
1721+
slots_dict[x] = 0
1722+
end
1723+
end
1724+
end
1725+
return nothing
1726+
end
1727+
@test code_typed(f52610)[1][2] === Nothing

0 commit comments

Comments
 (0)