diff --git a/base/compiler/ssair/ir.jl b/base/compiler/ssair/ir.jl index 039d557b2e9e8..e0ac4b5d61cfc 100644 --- a/base/compiler/ssair/ir.jl +++ b/base/compiler/ssair/ir.jl @@ -31,6 +31,11 @@ end function block_for_inst(index::Vector{Int}, inst::Int) return searchsortedfirst(index, inst, lt=(<=)) end + +function block_for_inst(index::Vector{BasicBlock}, inst::Int) + return searchsortedfirst(index, BasicBlock(StmtRange(inst, inst)), by=x->first(x.stmts), lt=(<=))-1 +end + block_for_inst(cfg::CFG, inst::Int) = block_for_inst(cfg.index, inst) function basic_blocks_starts(stmts::Vector{Any}) @@ -553,6 +558,7 @@ mutable struct IncrementalCompact new_nodes_idx::Int # This supports insertion while compacting new_new_nodes::NewNodeStream # New nodes that were before the compaction point at insertion time + new_new_used_ssas::Vector{Int} # TODO: Switch these two to a min-heap of some sort pending_nodes::NewNodeStream # New nodes that were after the compaction point at insertion time pending_perm::Vector{Int} @@ -573,6 +579,7 @@ mutable struct IncrementalCompact new_len = length(code.stmts) + length(code.new_nodes) result = InstructionStream(new_len) used_ssas = fill(0, new_len) + new_new_used_ssas = Vector{Int}() blocks = code.cfg.blocks if allow_cfg_transforms bb_rename = Vector{Int}(undef, length(blocks)) @@ -615,7 +622,7 @@ mutable struct IncrementalCompact pending_nodes = NewNodeStream() pending_perm = Int[] return new(code, result, result_bbs, ssa_rename, bb_rename, bb_rename, used_ssas, late_fixup, perm, 1, - new_new_nodes, pending_nodes, pending_perm, + new_new_nodes, new_new_used_ssas, pending_nodes, pending_perm, 1, 1, 1, false, allow_cfg_transforms, allow_cfg_transforms) end @@ -625,6 +632,7 @@ mutable struct IncrementalCompact new_len = length(code.stmts) + length(code.new_nodes) ssa_rename = Any[SSAValue(i) for i = 1:new_len] used_ssas = fill(0, new_len) + new_new_used_ssas = Vector{Int}() late_fixup = Vector{Int}() bb_rename = Vector{Int}() new_new_nodes = NewNodeStream() @@ -633,7 +641,7 @@ mutable struct IncrementalCompact return new(code, parent.result, parent.result_bbs, ssa_rename, bb_rename, bb_rename, parent.used_ssas, late_fixup, perm, 1, - new_new_nodes, pending_nodes, pending_perm, + new_new_nodes, new_new_used_ssas, pending_nodes, pending_perm, 1, result_offset, parent.active_result_bb, false, false, false) end end @@ -673,16 +681,27 @@ function getindex(compact::IncrementalCompact, ssa::NewSSAValue) return compact.new_new_nodes.stmts[ssa.id][:inst] end +function block_for_inst(compact::IncrementalCompact, idx::SSAValue) + if idx.id < compact.result_idx + return block_for_inst(compact.result_bbs, idx.id) + else + return block_for_inst(compact.ir.cfg, idx.idx) + end +end + function count_added_node!(compact::IncrementalCompact, @nospecialize(v)) needs_late_fixup = isa(v, NewSSAValue) if isa(v, SSAValue) compact.used_ssas[v.id] += 1 + elseif isa(v, NewSSAValue) + compact.new_new_used_ssas[v.id] += 1 else for ops in userefs(v) val = ops[] if isa(val, SSAValue) compact.used_ssas[val.id] += 1 elseif isa(val, NewSSAValue) + compact.new_new_used_ssas[val.id] += 1 needs_late_fixup = true end end @@ -705,6 +724,7 @@ function insert_node!(compact::IncrementalCompact, before, inst::NewInstruction, count_added_node!(compact, inst.stmt) line = something(inst.line, compact.result[before.id][:line]) node = add!(compact.new_new_nodes, before.id, attach_after) + push!(compact.new_new_used_ssas, 0) node[:inst], node[:type], node[:line], node[:flag] = inst.stmt, inst.type, line, inst.flag return NewSSAValue(node.idx) else @@ -723,6 +743,7 @@ function insert_node!(compact::IncrementalCompact, before, inst::NewInstruction, count_added_node!(compact, inst.stmt) line = something(inst.line, compact.result[renamed.id][:line]) node = add!(compact.new_new_nodes, renamed.id, attach_after) + push!(compact.new_new_used_ssas, 0) node[:inst], node[:type], node[:line], node[:flag] = inst.stmt, inst.type, line, inst.flag return NewSSAValue(node.idx) else @@ -744,6 +765,7 @@ function insert_node!(compact::IncrementalCompact, before, inst::NewInstruction, line = something(inst.line, compact.new_new_nodes.stmts[before.id][:line]) new_entry = add!(compact.new_new_nodes, before_entry.pos, attach_after) new_entry[:inst], new_entry[:type], new_entry[:line], new_entry[:flag] = inst.stmt, inst.type, line, inst.flag + push!(compact.new_new_used_ssas, 0) return NewSSAValue(new_entry.idx) else error("Unsupported") @@ -803,6 +825,9 @@ function setindex!(compact::IncrementalCompact, @nospecialize(v), idx::SSAValue) if isa(val, SSAValue) @assert compact.used_ssas[val.id] >= 1 compact.used_ssas[val.id] -= 1 + elseif isa(val, NewSSAValue) + @assert compact.new_new_used_ssas[val.id] >= 1 + compact.new_new_used_ssas[val.id] -= 1 end end compact.result[idx.id][:inst] = v @@ -853,6 +878,7 @@ end function process_phinode_values(old_values::Vector{Any}, late_fixup::Vector{Int}, processed_idx::Int, result_idx::Int, ssa_rename::Vector{Any}, used_ssas::Vector{Int}, + new_new_used_ssas::Vector{Int}, do_rename_ssa::Bool) values = Vector{Any}(undef, length(old_values)) for i = 1:length(old_values) @@ -864,7 +890,7 @@ function process_phinode_values(old_values::Vector{Any}, late_fixup::Vector{Int} push!(late_fixup, result_idx) val = OldSSAValue(val.id) else - val = renumber_ssa2(val, ssa_rename, used_ssas, do_rename_ssa) + val = renumber_ssa2(val, ssa_rename, used_ssas, new_new_used_ssas, do_rename_ssa) end else used_ssas[val.id] += 1 @@ -874,17 +900,19 @@ function process_phinode_values(old_values::Vector{Any}, late_fixup::Vector{Int} push!(late_fixup, result_idx) else # Always renumber these. do_rename_ssa applies only to actual SSAValues - val = renumber_ssa2(SSAValue(val.id), ssa_rename, used_ssas, true) + val = renumber_ssa2(SSAValue(val.id), ssa_rename, used_ssas, new_new_used_ssas, true) end elseif isa(val, NewSSAValue) push!(late_fixup, result_idx) + new_new_used_ssas[val.id] += 1 end values[i] = val end return values end -function renumber_ssa2(val::SSAValue, ssanums::Vector{Any}, used_ssas::Vector{Int}, do_rename_ssa::Bool) +function renumber_ssa2(val::SSAValue, ssanums::Vector{Any}, used_ssas::Vector{Int}, + new_new_used_ssas::Vector{Int}, do_rename_ssa::Bool) id = val.id if id > length(ssanums) return val @@ -893,22 +921,26 @@ function renumber_ssa2(val::SSAValue, ssanums::Vector{Any}, used_ssas::Vector{In val = ssanums[id] end if isa(val, SSAValue) - if used_ssas !== nothing - used_ssas[val.id] += 1 - end + used_ssas[val.id] += 1 end return val end -function renumber_ssa2!(@nospecialize(stmt), ssanums::Vector{Any}, used_ssas::Vector{Int}, late_fixup::Vector{Int}, result_idx::Int, do_rename_ssa::Bool) +function renumber_ssa2(val::NewSSAValue, ssanums::Vector{Any}, used_ssas::Vector{Int}, + new_new_used_ssas::Vector{Int}, do_rename_ssa::Bool) + new_new_used_ssas[val.id] += 1 + return val +end + +function renumber_ssa2!(@nospecialize(stmt), ssanums::Vector{Any}, used_ssas::Vector{Int}, new_new_used_ssas::Vector{Int}, late_fixup::Vector{Int}, result_idx::Int, do_rename_ssa::Bool) urs = userefs(stmt) for op in urs val = op[] if isa(val, OldSSAValue) || isa(val, NewSSAValue) push!(late_fixup, result_idx) end - if isa(val, SSAValue) - val = renumber_ssa2(val, ssanums, used_ssas, do_rename_ssa) + if isa(val, Union{SSAValue, NewSSAValue}) + val = renumber_ssa2(val, ssanums, used_ssas, new_new_used_ssas, do_rename_ssa) end if isa(val, OldSSAValue) || isa(val, NewSSAValue) push!(late_fixup, result_idx) @@ -992,6 +1024,7 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr ssa_rename = compact.ssa_rename late_fixup = compact.late_fixup used_ssas = compact.used_ssas + new_new_used_ssas = compact.new_new_used_ssas ssa_rename[idx] = SSAValue(result_idx) if stmt === nothing ssa_rename[idx] = stmt @@ -1008,7 +1041,7 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr result[result_idx][:inst] = stmt result_idx += 1 elseif isa(stmt, GotoIfNot) && compact.cfg_transforms_enabled - stmt = renumber_ssa2!(stmt, ssa_rename, used_ssas, late_fixup, result_idx, do_rename_ssa)::GotoIfNot + stmt = renumber_ssa2!(stmt, ssa_rename, used_ssas, new_new_used_ssas, late_fixup, result_idx, do_rename_ssa)::GotoIfNot result[result_idx][:inst] = stmt cond = stmt.cond if compact.fold_constant_branches @@ -1033,7 +1066,7 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr result_idx += 1 end elseif isa(stmt, Expr) - stmt = renumber_ssa2!(stmt, ssa_rename, used_ssas, late_fixup, result_idx, do_rename_ssa)::Expr + stmt = renumber_ssa2!(stmt, ssa_rename, used_ssas, new_new_used_ssas, late_fixup, result_idx, do_rename_ssa)::Expr if compact.cfg_transforms_enabled && isexpr(stmt, :enter) stmt.args[1] = compact.bb_rename_succ[stmt.args[1]::Int] end @@ -1043,7 +1076,7 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr # As an optimization, we eliminate any trivial pinodes. For performance, we use === # type equality. We may want to consider using == in either a separate pass or if # performance turns out ok - stmt = renumber_ssa2!(stmt, ssa_rename, used_ssas, late_fixup, result_idx, do_rename_ssa)::PiNode + stmt = renumber_ssa2!(stmt, ssa_rename, used_ssas, new_new_used_ssas, late_fixup, result_idx, do_rename_ssa)::PiNode pi_val = stmt.val if isa(pi_val, SSAValue) if stmt.typ === compact.result[pi_val.id][:type] @@ -1065,7 +1098,7 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr result[result_idx][:inst] = stmt result_idx += 1 elseif isa(stmt, ReturnNode) || isa(stmt, UpsilonNode) || isa(stmt, GotoIfNot) - result[result_idx][:inst] = renumber_ssa2!(stmt, ssa_rename, used_ssas, late_fixup, result_idx, do_rename_ssa) + result[result_idx][:inst] = renumber_ssa2!(stmt, ssa_rename, used_ssas, new_new_used_ssas, late_fixup, result_idx, do_rename_ssa) result_idx += 1 elseif isa(stmt, PhiNode) if compact.cfg_transforms_enabled @@ -1102,7 +1135,7 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr values = stmt.values end - values = process_phinode_values(values, late_fixup, processed_idx, result_idx, ssa_rename, used_ssas, do_rename_ssa) + values = process_phinode_values(values, late_fixup, processed_idx, result_idx, ssa_rename, used_ssas, new_new_used_ssas, do_rename_ssa) # Don't remove the phi node if it is before the definition of its value # because doing so can create forward references. This should only # happen with dead loops, but can cause problems when optimization @@ -1121,7 +1154,7 @@ function process_node!(compact::IncrementalCompact, result_idx::Int, inst::Instr result_idx += 1 end elseif isa(stmt, PhiCNode) - result[result_idx][:inst] = PhiCNode(process_phinode_values(stmt.values, late_fixup, processed_idx, result_idx, ssa_rename, used_ssas, do_rename_ssa)) + result[result_idx][:inst] = PhiCNode(process_phinode_values(stmt.values, late_fixup, processed_idx, result_idx, ssa_rename, used_ssas, new_new_used_ssas, do_rename_ssa)) result_idx += 1 elseif isa(stmt, SSAValue) # identity assign, replace uses of this ssa value with its result @@ -1323,31 +1356,39 @@ function iterate(compact::IncrementalCompact, (idx, active_bb)::Tuple{Int, Int}= end function maybe_erase_unused!( - extra_worklist::Vector{Int}, compact::IncrementalCompact, idx::Int, + extra_worklist::Vector{Int}, compact::IncrementalCompact, idx::Int, in_worklist::Bool, callback = null_dce_callback) - stmt = compact.result[idx][:inst] + + inst = idx <= length(compact.result) ? compact.result[idx] : + compact.new_new_nodes.stmts[idx - length(compact.result)] + stmt = inst[:inst] stmt === nothing && return false - if argextype(SSAValue(idx), compact) === Bottom + if inst[:type] === Bottom effect_free = false else - effect_free = compact.result[idx][:flag] & IR_FLAG_EFFECT_FREE != 0 + effect_free = inst[:flag] & IR_FLAG_EFFECT_FREE != 0 + end + function kill_ssa_value(val::SSAValue) + if compact.used_ssas[val.id] == 1 + if val.id < idx || in_worklist + push!(extra_worklist, val.id) + end + end + compact.used_ssas[val.id] -= 1 + callback(val) end if effect_free - for ops in userefs(stmt) - val = ops[] - # If the pass we ran inserted new nodes, it's possible for those - # to be outside our used_ssas count. - if isa(val, SSAValue) && val.id <= length(compact.used_ssas) - if compact.used_ssas[val.id] == 1 - if val.id < idx - push!(extra_worklist, val.id) - end + if isa(stmt, SSAValue) + kill_ssa_value(stmt) + else + for ops in userefs(stmt) + val = ops[] + if isa(val, SSAValue) + kill_ssa_value(val) end - compact.used_ssas[val.id] -= 1 - callback(val) end end - compact.result[idx][:inst] = nothing + inst[:inst] = nothing return true end return false @@ -1358,13 +1399,8 @@ function fixup_phinode_values!(compact::IncrementalCompact, old_values::Vector{A for i = 1:length(old_values) isassigned(old_values, i) || continue val = old_values[i] - if isa(val, OldSSAValue) - val = compact.ssa_rename[val.id] - if isa(val, SSAValue) - compact.used_ssas[val.id] += 1 - end - elseif isa(val, NewSSAValue) - val = SSAValue(length(compact.result) + val.id) + if isa(val, Union{OldSSAValue, NewSSAValue}) + val = fixup_node(compact, val) end values[i] = val end @@ -1379,29 +1415,30 @@ function fixup_node(compact::IncrementalCompact, @nospecialize(stmt)) elseif isa(stmt, NewSSAValue) return SSAValue(length(compact.result) + stmt.id) elseif isa(stmt, OldSSAValue) - return compact.ssa_rename[stmt.id] + val = compact.ssa_rename[stmt.id] + if isa(val, SSAValue) + # If `val.id` is greater than the length of `compact.result` or + # `compact.used_ssas`, this SSA value is in `new_new_nodes`, so + # don't count the use + compact.used_ssas[val.id] += 1 + end + return val else urs = userefs(stmt) for ur in urs val = ur[] - if isa(val, NewSSAValue) - val = SSAValue(length(compact.result) + val.id) - elseif isa(val, OldSSAValue) - val = compact.ssa_rename[val.id] - end - if isa(val, SSAValue) && val.id <= length(compact.used_ssas) - # If `val.id` is greater than the length of `compact.result` or - # `compact.used_ssas`, this SSA value is in `new_new_nodes`, so - # don't count the use - compact.used_ssas[val.id] += 1 + if isa(val, Union{NewSSAValue, OldSSAValue}) + ur[] = fixup_node(compact, val) end - ur[] = val end return urs[] end end function just_fixup!(compact::IncrementalCompact) + resize!(compact.used_ssas, length(compact.result)) + append!(compact.used_ssas, compact.new_new_used_ssas) + empty!(compact.new_new_used_ssas) for idx in compact.late_fixup stmt = compact.result[idx][:inst] new_stmt = fixup_node(compact, stmt) @@ -1419,14 +1456,14 @@ end function simple_dce!(compact::IncrementalCompact, callback = null_dce_callback) # Perform simple DCE for unused values + @assert isempty(compact.new_new_used_ssas) # just_fixup! wasn't run? extra_worklist = Int[] for (idx, nused) in Iterators.enumerate(compact.used_ssas) - idx >= compact.result_idx && break nused == 0 || continue - maybe_erase_unused!(extra_worklist, compact, idx, callback) + maybe_erase_unused!(extra_worklist, compact, idx, false, callback) end while !isempty(extra_worklist) - maybe_erase_unused!(extra_worklist, compact, pop!(extra_worklist), callback) + maybe_erase_unused!(extra_worklist, compact, pop!(extra_worklist), true, callback) end end diff --git a/base/compiler/ssair/passes.jl b/base/compiler/ssair/passes.jl index fdc50b3b481cd..96fbc1ba71841 100644 --- a/base/compiler/ssair/passes.jl +++ b/base/compiler/ssair/passes.jl @@ -440,6 +440,9 @@ function lift_arg!( lifted = stmt.args[argidx] if is_old(compact, leaf) && isa(lifted, SSAValue) lifted = OldSSAValue(lifted.id) + if already_inserted(compact, lifted) + lifted = compact.ssa_rename[lifted.id] + end end if isa(lifted, GlobalRef) || isa(lifted, Expr) lifted = insert_node!(compact, leaf, effect_free(NewInstruction(lifted, argextype(lifted, compact)))) @@ -556,7 +559,7 @@ function lift_comparison_leaves!(@specialize(tfunc), # perform lifting lifted_val = perform_lifting!(compact, visited_phinodes, cmp, lifting_cache, Bool, - lifted_leaves::LiftedLeaves, val)::LiftedValue + lifted_leaves::LiftedLeaves, val, ()->nothing, idx)::LiftedValue compact[idx] = lifted_val.x end @@ -576,9 +579,39 @@ end function perform_lifting!(compact::IncrementalCompact, visited_phinodes::Vector{AnySSAValue}, @nospecialize(cache_key), lifting_cache::IdDict{Pair{AnySSAValue, Any}, AnySSAValue}, - @nospecialize(result_t), lifted_leaves::LiftedLeaves, @nospecialize(stmt_val)) + @nospecialize(result_t), lifted_leaves::LiftedLeaves, @nospecialize(stmt_val), get_domtree, idx::Int) reverse_mapping = IdDict{AnySSAValue, Int}(ssa => id for (id, ssa) in enumerate(visited_phinodes)) + # Check if all the lifted leaves are the same + local the_leaf + all_same = true + for (_, val) in lifted_leaves + if !@isdefined(the_leaf) + the_leaf = val + continue + end + if val !== the_leaf + all_same = false + end + end + + if all_same && isa((the_leaf::LiftedValue).x, SSAValue) + domtree = get_domtree() + if domtree !== nothing + lb = compact.active_result_bb + if lb > 1 + if idx <= last(compact.result_bbs[lb-1].stmts) + lb -= 1 + end + end + db = block_for_inst(compact, the_leaf.x) + if dominates(domtree, db, lb) + return the_leaf + end + # TODO: Only insert PhiNodes on the CFG meet path + end + end + # Insert PhiNodes lifted_phis = LiftedPhi[] for item in visited_phinodes @@ -678,6 +711,14 @@ function sroa_pass!(ir::IRCode) compact = IncrementalCompact(ir) defuses = nothing # will be initialized once we encounter mutability in order to reduce dynamic allocations lifting_cache = IdDict{Pair{AnySSAValue, Any}, AnySSAValue}() + # initialization of domtree is delayed to avoid the expensive computation in many cases + local domtree = nothing + function get_domtree() + if domtree === nothing + @timeit "domtree 2" domtree = construct_domtree(ir.cfg.blocks) + end + return domtree + end for ((_, idx), stmt) in compact # check whether this statement is `getfield` / `setfield!` (or other "interesting" statement) isa(stmt, Expr) || continue @@ -819,7 +860,7 @@ function sroa_pass!(ir::IRCode) end val = perform_lifting!(compact, - visited_phinodes, field, lifting_cache, result_t, lifted_leaves, val) + visited_phinodes, field, lifting_cache, result_t, lifted_leaves, val, get_domtree, idx) # Insert the undef check if necessary if any_undef @@ -846,7 +887,7 @@ function sroa_pass!(ir::IRCode) used_ssas = copy(compact.used_ssas) simple_dce!(compact, (x::SSAValue) -> used_ssas[x.id] -= 1) ir = complete(compact) - sroa_mutables!(ir, defuses, used_ssas) + sroa_mutables!(ir, defuses, used_ssas, get_domtree) return ir else simple_dce!(compact) @@ -854,9 +895,7 @@ function sroa_pass!(ir::IRCode) end end -function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse}}, used_ssas::Vector{Int}) - # initialization of domtree is delayed to avoid the expensive computation in many cases - local domtree = nothing +function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse}}, used_ssas::Vector{Int}, get_domtree) for (idx, (intermediaries, defuse)) in defuses intermediaries = collect(intermediaries) # Check if there are any uses we did not account for. If so, the variable @@ -920,15 +959,13 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse if isempty(ldu.live_in_bbs) phiblocks = Int[] else - domtree === nothing && (@timeit "domtree 2" domtree = construct_domtree(ir.cfg.blocks)) - phiblocks = iterated_dominance_frontier(ir.cfg, ldu, domtree) + phiblocks = iterated_dominance_frontier(ir.cfg, ldu, get_domtree()) end allblocks = sort(vcat(phiblocks, ldu.def_bbs)) blocks[fidx] = phiblocks, allblocks if fidx + 1 > length(defexpr.args) for use in du.uses - domtree === nothing && (@timeit "domtree 2" domtree = construct_domtree(ir.cfg.blocks)) - has_safe_def(ir, domtree, allblocks, du, newidx, use) || @goto skip + has_safe_def(ir, get_domtree(), allblocks, du, newidx, use) || @goto skip end end end @@ -936,7 +973,7 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse # Compute domtree now, needed below, now that we have finished compacting the IR. # This needs to be after we iterate through the IR with `IncrementalCompact` # because removing dead blocks can invalidate the domtree. - domtree === nothing && (@timeit "domtree 2" domtree = construct_domtree(ir.cfg.blocks)) + domtree = get_domtree() preserve_uses = isempty(defuse.ccall_preserve_uses) ? nothing : IdDict{Int, Vector{Any}}((idx=>Any[] for idx in SPCSet(defuse.ccall_preserve_uses))) for fidx in 1:ndefuse @@ -1031,12 +1068,12 @@ function canonicalize_typeassert!(compact::IncrementalCompact, idx::Int, stmt::E compact.ssa_rename[compact.idx-1] = pi end -function adce_erase!(phi_uses::Vector{Int}, extra_worklist::Vector{Int}, compact::IncrementalCompact, idx::Int) +function adce_erase!(phi_uses::Vector{Int}, extra_worklist::Vector{Int}, compact::IncrementalCompact, idx::Int, in_worklist::Bool) # return whether this made a change if isa(compact.result[idx][:inst], PhiNode) - return maybe_erase_unused!(extra_worklist, compact, idx, val::SSAValue -> phi_uses[val.id] -= 1) + return maybe_erase_unused!(extra_worklist, compact, idx, in_worklist, val::SSAValue -> phi_uses[val.id] -= 1) else - return maybe_erase_unused!(extra_worklist, compact, idx) + return maybe_erase_unused!(extra_worklist, compact, idx, in_worklist) end end @@ -1189,10 +1226,10 @@ function adce_pass!(ir::IRCode) for (idx, nused) in Iterators.enumerate(compact.used_ssas) idx >= compact.result_idx && break nused == 0 || continue - adce_erase!(phi_uses, extra_worklist, compact, idx) + adce_erase!(phi_uses, extra_worklist, compact, idx, false) end while !isempty(extra_worklist) - adce_erase!(phi_uses, extra_worklist, compact, pop!(extra_worklist)) + adce_erase!(phi_uses, extra_worklist, compact, pop!(extra_worklist), true) end # Go back and erase any phi cycles changed = true @@ -1211,7 +1248,7 @@ function adce_pass!(ir::IRCode) end end while !isempty(extra_worklist) - if adce_erase!(phi_uses, extra_worklist, compact, pop!(extra_worklist)) + if adce_erase!(phi_uses, extra_worklist, compact, pop!(extra_worklist), true) changed = true end end