@@ -1564,10 +1564,12 @@ end
15641564
15651565is_nothrow (ir:: IRCode , ssa:: SSAValue ) = has_flag (ir[ssa], IR_FLAG_NOTHROW)
15661566
1567- function reachable_blocks (cfg:: CFG , from_bb:: Int , to_bb:: Union{Nothing, Int} = nothing )
1567+ function reachable_blocks (cfg:: CFG , from_bb:: Int , to_bb:: Int )
15681568 worklist = Int[from_bb]
15691569 visited = BitSet (from_bb)
1570- if to_bb != = nothing
1570+ if to_bb == from_bb
1571+ return visited
1572+ else
15711573 push! (visited, to_bb)
15721574 end
15731575 function visit! (bb:: Int )
@@ -1582,100 +1584,78 @@ function reachable_blocks(cfg::CFG, from_bb::Int, to_bb::Union{Nothing,Int} = no
15821584 return visited
15831585end
15841586
1585- function try_resolve_finalizer! (ir:: IRCode , idx :: Int , finalizer_idx:: Int , defuse:: SSADefUse ,
1587+ function try_resolve_finalizer! (ir:: IRCode , alloc_idx :: Int , finalizer_idx:: Int , defuse:: SSADefUse ,
15861588 inlining:: InliningState , lazydomtree:: LazyDomtree ,
15871589 lazypostdomtree:: LazyPostDomtree , @nospecialize (info:: CallInfo ))
15881590 # For now, require that:
15891591 # 1. The allocation dominates the finalizer registration
1590- # 2. The finalizer registration dominates all uses reachable from the
1591- # finalizer registration.
1592- # 3. The insertion block for the finalizer is the post-dominator of all
1593- # uses and the finalizer registration block. The insertion block must
1594- # be dominated by the finalizer registration block.
1595- # 4. The path from the finalizer registration to the finalizer inlining
1592+ # 2. The insertion block for the finalizer is the post-dominator of all
1593+ # uses (including the finalizer registration).
1594+ # 3. The path from the finalizer registration to the finalizer inlining
15961595 # location is nothrow
15971596 #
1598- # TODO : We could relax item 3 , by inlining the finalizer multiple times.
1597+ # TODO : We could relax the check 2 , by inlining the finalizer multiple times.
15991598
16001599 # Check #1: The allocation dominates the finalizer registration
16011600 domtree = get! (lazydomtree)
16021601 finalizer_bb = block_for_inst (ir, finalizer_idx)
1603- alloc_bb = block_for_inst (ir, idx )
1602+ alloc_bb = block_for_inst (ir, alloc_idx )
16041603 dominates (domtree, alloc_bb, finalizer_bb) || return nothing
16051604
1606- bb_insert_block:: Int = finalizer_bb
1607- bb_insert_idx:: Union{Int,Nothing} = finalizer_idx
1608- function note_block_use! (usebb:: Int , useidx:: Int )
1609- new_bb_insert_block = nearest_common_dominator (get! (lazypostdomtree),
1610- bb_insert_block, usebb)
1611- if new_bb_insert_block == bb_insert_block && bb_insert_idx != = nothing
1612- bb_insert_idx = max (bb_insert_idx:: Int , useidx)
1613- elseif new_bb_insert_block == usebb
1614- bb_insert_idx = useidx
1605+ # Check #2: The insertion block for the finalizer is the post-dominator of all uses
1606+ insert_bb:: Int = finalizer_bb
1607+ insert_idx:: Union{Int,Nothing} = finalizer_idx
1608+ function note_defuse! (x:: Union{Int,SSAUse} )
1609+ defuse_idx = x isa SSAUse ? x. idx : x
1610+ defuse_idx == finalizer_idx && return nothing
1611+ defuse_bb = block_for_inst (ir, defuse_idx)
1612+ new_insert_bb = nearest_common_dominator (get! (lazypostdomtree),
1613+ insert_bb, defuse_bb)
1614+ if new_insert_bb == insert_bb && insert_idx != = nothing
1615+ insert_idx = max (insert_idx:: Int , defuse_idx)
1616+ elseif new_insert_bb == defuse_bb
1617+ insert_idx = defuse_idx
16151618 else
1616- bb_insert_idx = nothing
1619+ insert_idx = nothing
16171620 end
1618- bb_insert_block = new_bb_insert_block
1621+ insert_bb = new_insert_bb
16191622 nothing
16201623 end
1621-
1622- # Collect all reachable blocks between the finalizer registration and the
1623- # insertion point
1624- blocks = reachable_blocks (ir. cfg, finalizer_bb, alloc_bb)
1625-
1626- # Check #2
1627- function check_defuse (x:: Union{Int,SSAUse} )
1628- duidx = x isa SSAUse ? x. idx : x
1629- duidx == finalizer_idx && return true
1630- bb = block_for_inst (ir, duidx)
1631- # Not reachable from finalizer registration - we're ok
1632- bb ∉ blocks && return true
1633- note_block_use! (bb, duidx)
1634- if dominates (domtree, finalizer_bb, bb)
1635- return true
1636- else
1637- return false
1638- end
1639- end
1640- all (check_defuse, defuse. uses) || return nothing
1641- all (check_defuse, defuse. defs) || return nothing
1642- bb_insert_block != 0 || return nothing # verify post-dominator of all uses exists
1643-
1644- # Check #3
1645- dominates (domtree, finalizer_bb, bb_insert_block) || return nothing
1624+ foreach (note_defuse!, defuse. uses)
1625+ foreach (note_defuse!, defuse. defs)
1626+ insert_bb != 0 || return nothing # verify post-dominator of all uses exists
16461627
16471628 if ! OptimizationParams (inlining. interp). assume_fatal_throw
16481629 # Collect all reachable blocks between the finalizer registration and the
16491630 # insertion point
1650- blocks = finalizer_bb == bb_insert_block ? Int[finalizer_bb] :
1651- reachable_blocks (ir. cfg, finalizer_bb, bb_insert_block)
1631+ blocks = reachable_blocks (ir. cfg, finalizer_bb, insert_bb)
16521632
1653- # Check #4
1654- function check_range_nothrow (ir :: IRCode , s:: Int , e:: Int )
1633+ # Check #3
1634+ function check_range_nothrow (s:: Int , e:: Int )
16551635 return all (s: e) do sidx:: Int
16561636 sidx == finalizer_idx && return true
1657- sidx == idx && return true
1637+ sidx == alloc_idx && return true
16581638 return is_nothrow (ir, SSAValue (sidx))
16591639 end
16601640 end
16611641 for bb in blocks
16621642 range = ir. cfg. blocks[bb]. stmts
16631643 s, e = first (range), last (range)
1664- if bb == bb_insert_block
1665- bb_insert_idx === nothing && continue
1666- e = bb_insert_idx
1644+ if bb == insert_bb
1645+ insert_idx === nothing && continue
1646+ e = insert_idx
16671647 end
16681648 if bb == finalizer_bb
16691649 s = finalizer_idx
16701650 end
1671- check_range_nothrow (ir, s, e) || return nothing
1651+ check_range_nothrow (s, e) || return nothing
16721652 end
16731653 end
16741654
16751655 # Ok, legality check complete. Figure out the exact statement where we're
16761656 # going to inline the finalizer.
1677- loc = bb_insert_idx === nothing ? first (ir. cfg. blocks[bb_insert_block ]. stmts) : bb_insert_idx :: Int
1678- attach_after = bb_insert_idx != = nothing
1657+ loc = insert_idx === nothing ? first (ir. cfg. blocks[insert_bb ]. stmts) : insert_idx :: Int
1658+ attach_after = insert_idx != = nothing
16791659
16801660 finalizer_stmt = ir[SSAValue (finalizer_idx)][:stmt ]
16811661 argexprs = Any[finalizer_stmt. args[2 ], finalizer_stmt. args[3 ]]
@@ -1702,11 +1682,10 @@ function try_resolve_finalizer!(ir::IRCode, idx::Int, finalizer_idx::Int, defuse
17021682 return nothing
17031683end
17041684
1705- function sroa_mutables! (ir:: IRCode , defuses:: IdDict{Int, Tuple{SPCSet, SSADefUse}} , used_ssas:: Vector{Int} , lazydomtree:: LazyDomtree , inlining:: Union{Nothing, InliningState} )
1685+ function sroa_mutables! (ir:: IRCode , defuses:: IdDict{Int,Tuple{SPCSet,SSADefUse}} , used_ssas:: Vector{Int} , lazydomtree:: LazyDomtree , inlining:: Union{Nothing,InliningState} )
17061686 𝕃ₒ = inlining === nothing ? SimpleInferenceLattice. instance : optimizer_lattice (inlining. interp)
17071687 lazypostdomtree = LazyPostDomtree (ir)
17081688 for (defidx, (intermediaries, defuse)) in defuses
1709- intermediaries = collect (intermediaries)
17101689 # Check if there are any uses we did not account for. If so, the variable
17111690 # escapes and we cannot eliminate the allocation. This works, because we're guaranteed
17121691 # not to include any intermediaries that have dead uses. As a result, missing uses will only ever
@@ -1906,7 +1885,7 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse
19061885 end
19071886end
19081887
1909- function form_new_preserves (origex:: Expr , intermediates :: Vector{Int} , new_preserves:: Vector{Any} )
1888+ function form_new_preserves (origex:: Expr , intermediaries :: Union{ Vector{Int},SPCSet } , new_preserves:: Vector{Any} )
19101889 newex = Expr (:foreigncall )
19111890 nccallargs = length (origex. args[3 ]:: SimpleVector )
19121891 for i in 1 : (6 + nccallargs- 1 )
@@ -1915,7 +1894,7 @@ function form_new_preserves(origex::Expr, intermediates::Vector{Int}, new_preser
19151894 for i in (6 + nccallargs): length (origex. args)
19161895 x = origex. args[i]
19171896 # don't need to preserve intermediaries
1918- if isa (x, SSAValue) && x. id in intermediates
1897+ if isa (x, SSAValue) && x. id in intermediaries
19191898 continue
19201899 end
19211900 push! (newex. args, x)
0 commit comments