Skip to content

Commit dec7072

Browse files
serenity4aviatesk
authored andcommitted
Optimizer: Update SROA def-uses after DCE (#57201)
Fixes #57141. Given the function ```julia julia> function _f() ref = Ref{Any}() ref[] = 3 @Assert isdefined(ref, :x) inner = Returns(ref) x = inner() (x, ref[]) end _f (generic function with 1 method) julia> f() = first(_f()) f (generic function with 1 method) ``` Here is before: ```julia julia> @code_typed f() CodeInfo( 1 ─ %1 = %new(Base.RefValue{Any})::Base.RefValue{Any} └── goto #3 2 ─ unreachable 3 ─ return %1 ) => Base.RefValue{Any} ``` Here is after this PR: ```julia julia> @code_typed f() CodeInfo( 1 ─ %1 = %new(Base.RefValue{Any})::Base.RefValue{Any} │ builtin Base.setfield!(%1, :x, 3)::Int64 │ %3 = builtin Main.isdefined(%1, :x)::Bool └── goto #3 if not %3 2 ─ goto #4 3 ─ %6 = invoke Base.AssertionError("isdefined(ref, :x)"::String)::AssertionError │ builtin Base.throw(%6)::Union{} └── unreachable 4 ─ return %1 ) => Base.RefValue{Any} ``` The elimination of `setfield!` was due to a use still being recorded for `ref[]` in the def-use data while DCE eliminated this `getindex` call (by virtue of not using the second tuple element in the result). --------- Co-authored-by: Cédric Belmant <[email protected]> Co-authored-by: Shuhei Kadowaki <[email protected]> (cherry picked from commit fea26dd)
1 parent c28dc85 commit dec7072

File tree

2 files changed

+16
-0
lines changed

2 files changed

+16
-0
lines changed

base/compiler/ssair/passes.jl

+4
Original file line numberDiff line numberDiff line change
@@ -1480,6 +1480,10 @@ function sroa_pass!(ir::IRCode, inlining::Union{Nothing,InliningState}=nothing)
14801480
used_ssas[x.id] -= 1
14811481
end
14821482
ir = complete(compact)
1483+
# remove any use that has been optimized away by the DCE
1484+
for (intermediaries, defuse) in values(defuses)
1485+
filter!(x -> ir[SSAValue(x.idx)][:stmt] !== nothing, defuse.uses)
1486+
end
14831487
sroa_mutables!(ir, defuses, used_ssas, lazydomtree, inlining)
14841488
return ir
14851489
else

test/compiler/irpasses.jl

+12
Original file line numberDiff line numberDiff line change
@@ -1841,3 +1841,15 @@ let f = (x)->nothing, mi = Base.method_instance(f, (Base.RefValue{Nothing},)), c
18411841
ir = Core.Compiler.sroa_pass!(ir, inlining)
18421842
Core.Compiler.verify_ir(ir)
18431843
end
1844+
1845+
# https://github.com/JuliaLang/julia/issues/57141
1846+
# don't eliminate `setfield!` when the field is to be used
1847+
let src = code_typed1(()) do
1848+
ref = Ref{Any}()
1849+
ref[] = 0
1850+
@assert isdefined(ref, :x)
1851+
inner() = ref[] + 1
1852+
(inner(), ref[])
1853+
end
1854+
@test count(iscall((src, setfield!)), src.code) == 1
1855+
end

0 commit comments

Comments
 (0)