diff --git a/base/compiler/ssair/passes.jl b/base/compiler/ssair/passes.jl index d291e85a661b8b..4edf4bcfc0ba5e 100644 --- a/base/compiler/ssair/passes.jl +++ b/base/compiler/ssair/passes.jl @@ -191,7 +191,7 @@ function walk_to_defs(compact::IncrementalCompact, @nospecialize(defssa), @nospe collect(Iterators.filter(1:length(def.edges)) do n isassigned(def.values, n) || return false val = def.values[n] - if isa(defssa, OldSSAValue) && isa(val, SSAValue) + if is_old(compact, defssa) && isa(val, SSAValue) val = OldSSAValue(val.id) end edge_typ = widenconst(compact_exprtype(compact, val)) @@ -201,7 +201,7 @@ function walk_to_defs(compact::IncrementalCompact, @nospecialize(defssa), @nospe for n in possible_predecessors pred = def.edges[n] val = def.values[n] - if isa(defssa, OldSSAValue) && isa(val, SSAValue) + if is_old(compact, defssa) && isa(val, SSAValue) val = OldSSAValue(val.id) end if isa(val, AnySSAValue) @@ -425,6 +425,12 @@ struct LiftedPhi need_argupdate::Bool end +function is_old(compact, @nospecialize(old_node_ssa)) + isa(old_node_ssa, OldSSAValue) && + !is_pending(compact, old_node_ssa) && + !already_inserted(compact, old_node_ssa) +end + function perform_lifting!(compact::IncrementalCompact, visited_phinodes::Vector{Any}, @nospecialize(cache_key), lifting_cache::IdDict{Pair{AnySSAValue, Any}, AnySSAValue}, @@ -455,7 +461,7 @@ function perform_lifting!(compact::IncrementalCompact, isassigned(old_node.values, i) || continue val = old_node.values[i] orig_val = val - if isa(old_node_ssa, OldSSAValue) && !is_pending(compact, old_node_ssa) && !already_inserted(compact, old_node_ssa) && isa(val, SSAValue) + if is_old(compact, old_node_ssa) && isa(val, SSAValue) val = OldSSAValue(val.id) end if isa(val, Union{NewSSAValue, SSAValue, OldSSAValue}) diff --git a/test/compiler/irpasses.jl b/test/compiler/irpasses.jl index 77f75958fd8376..870f33a9b938b8 100644 --- a/test/compiler/irpasses.jl +++ b/test/compiler/irpasses.jl @@ -37,3 +37,31 @@ let m = Meta.@lower 1 + 1 Core.Compiler.verify_ir(ir) @test isa(ir.stmts[3], Core.PhiNode) && length(ir.stmts[3].edges) == 1 end + +# SROA + +# Issue #29983 +# This one is a bit hard to trigger, but the key is to create a case +# where SROA needs to introduce an intermediate type-unstable phi node +struct Foo29983{T} + x::Tuple{T} +end +struct Bar29983{S} + x::S +end +Base.:+(a::T, b::Bar29983{S}) where {T, S} = Bar29983(a + b.x) +Base.:+(a::Bar29983{S}, b::T) where {T, S} = b + a +Base.:+(a::Bar29983{S}, b::Bar29983{T}) where {T, S} = Bar29983(a.x + b.x) +Base.:+(a::Foo29983, b::Foo29983) = Foo29983((a.x[1] + b.x[1],)) + +function f(x::Vector{T}) where {T} + x1 = Foo29983((x[1],)) + la1 = Foo29983((x[1],)) + f1 = Foo29983((0,)) + for _ in 1:2 + f1 += la1 + end + return f1 +end + +@test f([Bar29983(1.0)]).x[1].x == 2.0