Skip to content

Commit 83b3550

Browse files
committed
Fix #29983
SROA was accidentally treating a pending node as old and thus getting the wrong type when querying the predecessor. As a result it thought one of the paths was unreachable causing udefined data to be introduced on that bath (generally the 1.0 that happened to already be in register).
1 parent 5290bba commit 83b3550

File tree

2 files changed

+37
-3
lines changed

2 files changed

+37
-3
lines changed

base/compiler/ssair/passes.jl

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ function walk_to_defs(compact::IncrementalCompact, @nospecialize(defssa), @nospe
191191
collect(Iterators.filter(1:length(def.edges)) do n
192192
isassigned(def.values, n) || return false
193193
val = def.values[n]
194-
if isa(defssa, OldSSAValue) && isa(val, SSAValue)
194+
if is_old(compact, defssa) && isa(val, SSAValue)
195195
val = OldSSAValue(val.id)
196196
end
197197
edge_typ = widenconst(compact_exprtype(compact, val))
@@ -201,7 +201,7 @@ function walk_to_defs(compact::IncrementalCompact, @nospecialize(defssa), @nospe
201201
for n in possible_predecessors
202202
pred = def.edges[n]
203203
val = def.values[n]
204-
if isa(defssa, OldSSAValue) && isa(val, SSAValue)
204+
if is_old(compact, defssa) && isa(val, SSAValue)
205205
val = OldSSAValue(val.id)
206206
end
207207
if isa(val, AnySSAValue)
@@ -425,6 +425,12 @@ struct LiftedPhi
425425
need_argupdate::Bool
426426
end
427427

428+
function is_old(compact, @nospecialize(old_node_ssa))
429+
isa(old_node_ssa, OldSSAValue) &&
430+
!is_pending(compact, old_node_ssa) &&
431+
!already_inserted(compact, old_node_ssa)
432+
end
433+
428434
function perform_lifting!(compact::IncrementalCompact,
429435
visited_phinodes::Vector{Any}, @nospecialize(cache_key),
430436
lifting_cache::IdDict{Pair{AnySSAValue, Any}, AnySSAValue},
@@ -455,7 +461,7 @@ function perform_lifting!(compact::IncrementalCompact,
455461
isassigned(old_node.values, i) || continue
456462
val = old_node.values[i]
457463
orig_val = val
458-
if isa(old_node_ssa, OldSSAValue) && !is_pending(compact, old_node_ssa) && !already_inserted(compact, old_node_ssa) && isa(val, SSAValue)
464+
if is_old(compact, old_node_ssa) && isa(val, SSAValue)
459465
val = OldSSAValue(val.id)
460466
end
461467
if isa(val, Union{NewSSAValue, SSAValue, OldSSAValue})

test/compiler/irpasses.jl

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,31 @@ let m = Meta.@lower 1 + 1
3737
Core.Compiler.verify_ir(ir)
3838
@test isa(ir.stmts[3], Core.PhiNode) && length(ir.stmts[3].edges) == 1
3939
end
40+
41+
# SROA
42+
43+
# Issue #29983
44+
# This one is a bit hard to trigger, but the key is to create a case
45+
# where SROA needs to introduce an intermediate type-unstable phi node
46+
struct Foo29983{T}
47+
x::Tuple{T}
48+
end
49+
struct Bar29983{S}
50+
x::S
51+
end
52+
Base.:+(a::T, b::Bar29983{S}) where {T, S} = Bar29983(a + b.x)
53+
Base.:+(a::Bar29983{S}, b::T) where {T, S} = b + a
54+
Base.:+(a::Bar29983{S}, b::Bar29983{T}) where {T, S} = Bar29983(a.x + b.x)
55+
Base.:+(a::Foo29983, b::Foo29983) = Foo29983((a.x[1] + b.x[1],))
56+
57+
function f(x::Vector{T}) where {T}
58+
x1 = Foo29983((x[1],))
59+
la1 = Foo29983((x[1],))
60+
f1 = Foo29983((0,))
61+
for _ in 1:2
62+
f1 += la1
63+
end
64+
return f1
65+
end
66+
67+
@test f([Bar29983(1.0)]).x[1].x == 2.0

0 commit comments

Comments
 (0)