|
97 | 97 | # if this load at `idx` have any "safe" `setfield!` calls that define the field |
98 | 98 | function has_safe_def( |
99 | 99 | ir::IRCode, domtree::DomTree, allblocks::Vector{Int}, du::SSADefUse, |
100 | | - newidx::Int, idx::Int, inclusive::Bool = false) |
101 | | - def = first(find_def_for_use(ir, domtree, allblocks, du, idx, inclusive)) |
102 | | - |
103 | | - # this field is supposed to be defined at the `:new` site (but it's not and thus this load will throw) |
| 100 | + newidx::Int, idx::Int) |
| 101 | + def, _, _ = find_def_for_use(ir, domtree, allblocks, du, idx) |
| 102 | + # will throw since we already checked this `:new` site doesn't define this field |
104 | 103 | def == newidx && return false |
105 | | - |
106 | | - def ≠ 0 && return true # found a "safe" definition |
107 | | - |
108 | | - # we may be able to replace this load with `PhiNode` if all the predecessors have "safe" definitions |
109 | | - idxblock = block_for_inst(ir, idx) |
110 | | - for pred in ir.cfg.blocks[idxblock].preds |
111 | | - lastidx = last(ir.cfg.blocks[pred].stmts) |
112 | | - # NOTE `lastidx` isn't a load, thus we can use inclusive coondition within the `find_def_for_use` |
113 | | - has_safe_def(ir, domtree, allblocks, du, newidx, lastidx, true) || return false |
| 104 | + # found a "safe" definition |
| 105 | + def ≠ 0 && return true |
| 106 | + # we may still be able to replace this load with `PhiNode` |
| 107 | + # examine if all predecessors of `block` have any "safe" definition |
| 108 | + block = block_for_inst(ir, idx) |
| 109 | + seen = BitSet(block) |
| 110 | + worklist = BitSet(ir.cfg.blocks[block].preds) |
| 111 | + isempty(worklist) && return false |
| 112 | + while !isempty(worklist) |
| 113 | + pred = pop!(worklist) |
| 114 | + # if this block has already been examined, bail out to avoid infinite cycles |
| 115 | + pred in seen && return false |
| 116 | + idx = last(ir.cfg.blocks[pred].stmts) |
| 117 | + # NOTE `idx` isn't a load, thus we can use inclusive coondition within the `find_def_for_use` |
| 118 | + def, _, _ = find_def_for_use(ir, domtree, allblocks, du, idx, true) |
| 119 | + # will throw since we already checked this `:new` site doesn't define this field |
| 120 | + def == newidx && return false |
| 121 | + push!(seen, pred) |
| 122 | + # found a "safe" definition for this predecessor |
| 123 | + def ≠ 0 && continue |
| 124 | + # check for the predecessors of this predecessor |
| 125 | + for newpred in ir.cfg.blocks[pred].preds |
| 126 | + push!(worklist, newpred) |
| 127 | + end |
114 | 128 | end |
115 | 129 | return true |
116 | 130 | end |
@@ -599,8 +613,8 @@ function perform_lifting!(compact::IncrementalCompact, |
599 | 613 | return stmt_val # N.B. should never happen |
600 | 614 | end |
601 | 615 |
|
602 | | -# NOTE we use `IdSet{Int}` instead of `BitSet` for `sroa_pass!` since it works on IR after inlining, |
603 | | -# which can be very large sometimes, and analyzed program counters are often very sparse |
| 616 | +# NOTE we use `IdSet{Int}` instead of `BitSet` for in these passes since they work on IR after inlining, |
| 617 | +# which can be very large sometimes, and program counters in question are often very sparse |
604 | 618 | const SPCSet = IdSet{Int} |
605 | 619 |
|
606 | 620 | """ |
@@ -897,8 +911,8 @@ function sroa_mutables!(ir::IRCode, defuses::IdDict{Int, Tuple{SPCSet, SSADefUse |
897 | 911 | end |
898 | 912 | end |
899 | 913 | for b in phiblocks |
| 914 | + n = ir[phinodes[b]]::PhiNode |
900 | 915 | for p in ir.cfg.blocks[b].preds |
901 | | - n = ir[phinodes[b]]::PhiNode |
902 | 916 | push!(n.edges, p) |
903 | 917 | push!(n.values, compute_value_for_block(ir, domtree, |
904 | 918 | allblocks, du, phinodes, fidx, p)) |
@@ -967,7 +981,7 @@ function count_uses(@nospecialize(stmt), uses::Vector{Int}) |
967 | 981 | end |
968 | 982 | end |
969 | 983 |
|
970 | | -function mark_phi_cycles!(compact::IncrementalCompact, safe_phis::BitSet, phi::Int) |
| 984 | +function mark_phi_cycles!(compact::IncrementalCompact, safe_phis::SPCSet, phi::Int) |
971 | 985 | worklist = Int[] |
972 | 986 | push!(worklist, phi) |
973 | 987 | while !isempty(worklist) |
@@ -1037,7 +1051,7 @@ function adce_pass!(ir::IRCode) |
1037 | 1051 | changed = true |
1038 | 1052 | while changed |
1039 | 1053 | changed = false |
1040 | | - safe_phis = BitSet() |
| 1054 | + safe_phis = SPCSet() |
1041 | 1055 | for phi in all_phis |
1042 | 1056 | # Save any phi cycles that have non-phi uses |
1043 | 1057 | if compact.used_ssas[phi] - phi_uses[phi] != 0 |
|
0 commit comments