Skip to content

Commit

Permalink
optimizer: enable load forwarding with the finalizer elision (#55991)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
aviatesk authored Oct 5, 2024
1 parent fb77d60 commit 096c1d2
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 7 deletions.
16 changes: 9 additions & 7 deletions base/compiler/ssair/passes.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1707,22 +1707,24 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int,Tuple{SPCSet,SSADefUse}}
ismutabletype(typ) || continue
typ = typ::DataType
# First check for any finalizer calls
finalizer_idx = nothing
for use in defuse.uses
finalizer_useidx = nothing
for (useidx, use) in enumerate(defuse.uses)
if use.kind === :finalizer
# For now: Only allow one finalizer per allocation
finalizer_idx !== nothing && @goto skip
finalizer_idx = use.idx
finalizer_useidx !== nothing && @goto skip
finalizer_useidx = useidx
end
end
if finalizer_idx !== nothing && inlining !== nothing
all_eliminated = all_forwarded = true
if finalizer_useidx !== nothing && inlining !== nothing
finalizer_idx = defuse.uses[finalizer_useidx].idx
try_resolve_finalizer!(ir, defidx, finalizer_idx, defuse, inlining,
lazydomtree, lazypostdomtree, ir[SSAValue(finalizer_idx)][:info])
continue
deleteat!(defuse.uses, finalizer_useidx)
all_eliminated = all_forwarded = false # can't eliminate `setfield!` calls safely
end
# Partition defuses by field
fielddefuse = SSADefUse[SSADefUse() for _ = 1:fieldcount(typ)]
all_eliminated = all_forwarded = true
for use in defuse.uses
if use.kind === :preserve
for du in fielddefuse
Expand Down
26 changes: 26 additions & 0 deletions test/compiler/inline.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1596,6 +1596,32 @@ let
@test get_finalization_count() == 1000
end

# Load forwarding with `finalizer` elision
let src = code_typed1((Int,)) do x
xs = finalizer(Ref(x)) do obj
@noinline
Base.@assume_effects :nothrow :notaskstate
Core.println("finalizing: ", obj[])
end
Base.@assume_effects :nothrow @noinline println("xs[] = ", @inline xs[])
return xs[]
end
@test count(iscall((src, getfield)), src.code) == 0
end
let src = code_typed1((Int,)) do x
xs = finalizer(Ref(x)) do obj
@noinline
Base.@assume_effects :nothrow :notaskstate
Core.println("finalizing: ", obj[])
end
Base.@assume_effects :nothrow @noinline println("xs[] = ", @inline xs[])
xs[] += 1
return xs[]
end
@test count(iscall((src, getfield)), src.code) == 0
@test count(iscall((src, setfield!)), src.code) == 1
end

# optimize `[push!|pushfirst!](::Vector{Any}, x...)`
@testset "optimize `$f(::Vector{Any}, x...)`" for f = Any[push!, pushfirst!]
@eval begin
Expand Down

0 comments on commit 096c1d2

Please sign in to comment.