diff --git a/base/compiler/ssair/passes.jl b/base/compiler/ssair/passes.jl index d291e85a661b8..68b7424f8a676 100644 --- a/base/compiler/ssair/passes.jl +++ b/base/compiler/ssair/passes.jl @@ -688,10 +688,14 @@ function getfield_elim_pass!(ir::IRCode, domtree::DomTree) compact[idx] = val === nothing ? nothing : val.x end - # Copy the use count, `finish` may modify it and for our predicate - # below we need it consistent with the state of the IR here. + + non_dce_finish!(compact) + # Copy the use count, `simple_dce!` may modify it and for our predicate + # below we need it consistent with the state of the IR here (after tracking + # phi node arguments, but before dce). used_ssas = copy(compact.used_ssas) - ir = finish(compact) + simple_dce!(compact) + ir = complete(compact) # Now go through any mutable structs and see which ones we can eliminate for (idx, (intermediaries, defuse)) in defuses intermediaries = collect(intermediaries) diff --git a/test/compiler/irpasses.jl b/test/compiler/irpasses.jl index 77f75958fd837..d7b1ec172936c 100644 --- a/test/compiler/irpasses.jl +++ b/test/compiler/irpasses.jl @@ -37,3 +37,29 @@ 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 + +# Tests for SROA + +mutable struct Foo30594; x::Float64; end +Base.copy(x::Foo30594) = Foo30594(x.x) +function add!(p::Foo30594, off::Foo30594) + p.x += off.x + return p +end +Base.:(+)(a::Foo30594, b::Foo30594) = add!(copy(a), b) + +let results = Float64[] + @noinline use30594(x) = push!(results, x.x); nothing + function foo30594(cnt::Int, dx::Int) + step = Foo30594(dx) + curr = step + Foo30594(1) + for i in 1:cnt + use30594(curr) + curr = curr + step + end + nothing + end + + foo30594(4, -1) + @test results == [0.0, -1.0, -2.0, -3.0] +end