{name: "opt", fn: opt, required: true}, // TODO: split required rules and optimizing rules
{name: "zero arg cse", fn: zcse, required: true}, // required to merge OpSB values
{name: "opt deadcode", fn: deadcode, required: true}, // remove any blocks orphaned during opt
- {name: "generic cse", fn: cse},
{name: "generic domtree", fn: domTree},
+ {name: "generic cse", fn: cse},
{name: "phiopt", fn: phiopt},
{name: "nilcheckelim", fn: nilcheckelim},
{name: "prove", fn: prove},
{"opt", "nilcheckelim"},
// tighten should happen before lowering to avoid splitting naturally paired instructions such as CMP/SET
{"tighten", "lower"},
- // nilcheckelim, prove and loopbce share idom.
+ // cse, nilcheckelim, prove and loopbce share idom.
+ {"generic domtree", "generic cse"},
{"generic domtree", "nilcheckelim"},
{"generic domtree", "prove"},
{"generic domtree", "loopbce"},
}
}
- // Compute dominator tree
- idom := dominators(f)
- sdom := newSparseTree(f, idom)
+ // Dominator tree (f.sdom) is computed by the generic domtree pass.
// Compute substitutions we would like to do. We substitute v for w
// if v and w are in the same equivalence class and v dominates w.
// Find a maximal dominant element in e
v := e[0]
for _, w := range e[1:] {
- if sdom.isAncestorEq(w.Block, v.Block) {
+ if f.sdom.isAncestorEq(w.Block, v.Block) {
v = w
}
}
w := e[i]
if w == v {
e, e[i] = e[:len(e)-1], e[len(e)-1]
- } else if sdom.isAncestorEq(v.Block, w.Block) {
+ } else if f.sdom.isAncestorEq(v.Block, w.Block) {
rewrite[w.ID] = v
e, e[i] = e[:len(e)-1], e[len(e)-1]
} else {