Skip to content

Commit 096c1d2

Browse files
authored
optimizer: enable load forwarding with the finalizer elision (#55991)
When the finalizer elision pass is used, load forwarding is not performed currently, regardless of whether the pass succeeds or not. But this is not necessary, and by keeping the `setfield!` call, we can safely forward `getfield` even if finalizer elision is tried.
1 parent fb77d60 commit 096c1d2

File tree

2 files changed

+35
-7
lines changed

2 files changed

+35
-7
lines changed

base/compiler/ssair/passes.jl

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1707,22 +1707,24 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int,Tuple{SPCSet,SSADefUse}}
17071707
ismutabletype(typ) || continue
17081708
typ = typ::DataType
17091709
# First check for any finalizer calls
1710-
finalizer_idx = nothing
1711-
for use in defuse.uses
1710+
finalizer_useidx = nothing
1711+
for (useidx, use) in enumerate(defuse.uses)
17121712
if use.kind === :finalizer
17131713
# For now: Only allow one finalizer per allocation
1714-
finalizer_idx !== nothing && @goto skip
1715-
finalizer_idx = use.idx
1714+
finalizer_useidx !== nothing && @goto skip
1715+
finalizer_useidx = useidx
17161716
end
17171717
end
1718-
if finalizer_idx !== nothing && inlining !== nothing
1718+
all_eliminated = all_forwarded = true
1719+
if finalizer_useidx !== nothing && inlining !== nothing
1720+
finalizer_idx = defuse.uses[finalizer_useidx].idx
17191721
try_resolve_finalizer!(ir, defidx, finalizer_idx, defuse, inlining,
17201722
lazydomtree, lazypostdomtree, ir[SSAValue(finalizer_idx)][:info])
1721-
continue
1723+
deleteat!(defuse.uses, finalizer_useidx)
1724+
all_eliminated = all_forwarded = false # can't eliminate `setfield!` calls safely
17221725
end
17231726
# Partition defuses by field
17241727
fielddefuse = SSADefUse[SSADefUse() for _ = 1:fieldcount(typ)]
1725-
all_eliminated = all_forwarded = true
17261728
for use in defuse.uses
17271729
if use.kind === :preserve
17281730
for du in fielddefuse

test/compiler/inline.jl

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1596,6 +1596,32 @@ let
15961596
@test get_finalization_count() == 1000
15971597
end
15981598

1599+
# Load forwarding with `finalizer` elision
1600+
let src = code_typed1((Int,)) do x
1601+
xs = finalizer(Ref(x)) do obj
1602+
@noinline
1603+
Base.@assume_effects :nothrow :notaskstate
1604+
Core.println("finalizing: ", obj[])
1605+
end
1606+
Base.@assume_effects :nothrow @noinline println("xs[] = ", @inline xs[])
1607+
return xs[]
1608+
end
1609+
@test count(iscall((src, getfield)), src.code) == 0
1610+
end
1611+
let src = code_typed1((Int,)) do x
1612+
xs = finalizer(Ref(x)) do obj
1613+
@noinline
1614+
Base.@assume_effects :nothrow :notaskstate
1615+
Core.println("finalizing: ", obj[])
1616+
end
1617+
Base.@assume_effects :nothrow @noinline println("xs[] = ", @inline xs[])
1618+
xs[] += 1
1619+
return xs[]
1620+
end
1621+
@test count(iscall((src, getfield)), src.code) == 0
1622+
@test count(iscall((src, setfield!)), src.code) == 1
1623+
end
1624+
15991625
# optimize `[push!|pushfirst!](::Vector{Any}, x...)`
16001626
@testset "optimize `$f(::Vector{Any}, x...)`" for f = Any[push!, pushfirst!]
16011627
@eval begin

0 commit comments

Comments
 (0)