f.Fatalf("used value v%d in free list", id)
}
}
+
+ // Check to make sure all args dominate uses.
+ if f.RegAlloc == nil {
+ // Note: regalloc introduces non-dominating args.
+ // See TODO in regalloc.go.
+ idom := dominators(f)
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ for i, arg := range v.Args {
+ x := arg.Block
+ y := b
+ if v.Op == OpPhi {
+ y = b.Preds[i]
+ }
+ if !domCheck(f, idom, x, y) {
+ f.Fatalf("arg %d of value %s does not dominate", i, v.LongString())
+ }
+ }
+ }
+ if b.Control != nil && !domCheck(f, idom, b.Control.Block, b) {
+ f.Fatalf("control value %s for %s doesn't dominate", b.Control, b)
+ }
+ }
+ }
+}
+
+// domCheck reports whether x dominates y (including x==y).
+func domCheck(f *Func, idom []*Block, x, y *Block) bool {
+ if y != f.Entry && idom[y.ID] == nil {
+ // unreachable - ignore
+ return true
+ }
+ for {
+ if x == y {
+ return true
+ }
+ y = idom[y.ID]
+ if y == nil {
+ return false
+ }
+ }
}
// v = phi(x,x,x)
// v = phi(x,v,x,v)
func phielim(f *Func) {
- args := newSparseSet(f.NumValues())
+ argSet := newSparseSet(f.NumValues())
+ var args []*Value
for _, b := range f.Blocks {
for _, v := range b.Values {
if v.Op != OpPhi {
continue
}
- args.clear()
+ argSet.clear()
+ args = args[:0]
for _, x := range v.Args {
for x.Op == OpCopy {
x = x.Args[0]
}
- args.add(x.ID)
- }
- switch {
- case args.size() == 1:
- v.Op = OpCopy
- v.SetArgs1(v.Args[0])
- case args.size() == 2 && args.contains(v.ID):
- var w *Value
- for _, x := range v.Args {
- if x.ID != v.ID {
- w = x
- break
- }
+ if x != v && !argSet.contains(x.ID) {
+ argSet.add(x.ID)
+ args = append(args, x)
}
+ }
+ if len(args) == 1 {
v.Op = OpCopy
- v.SetArgs1(w)
+ v.SetArgs1(args[0])
}
}
}