}
}
}
+
+ // Check that after scheduling, phis are always first in the block.
+ if f.scheduled {
+ for _, b := range f.Blocks {
+ seenNonPhi := false
+ for _, v := range b.Values {
+ if v.Op == OpPhi {
+ if seenNonPhi {
+ f.Fatalf("phi after non-phi @ %s: %s", b, v)
+ }
+ } else {
+ seenNonPhi = true
+ }
+ }
+ }
+ }
}
// domCheck reports whether x dominates y (including x==y).
}
// walk to previous store
if v.Op == OpPhi {
- continue // At start of block. Move on to next block.
+ // At start of block. Move on to next block.
+ // The memory phi, if it exists, is always
+ // the first logical store in the block.
+ // (Even if it isn't the first in the current b.Values order.)
+ continue
}
for _, a := range v.Args {
if a.Block == b && a.Type.IsMemory() {
}
if v.Op == OpPhi {
// A Phi implies we have reached the top of the block.
+ // The memory phi, if it exists, is always
+ // the first logical store in the block.
continue search
}
if v.Type.IsTuple() && v.Type.FieldType(1).IsMemory() {
const limit = 50
for i := 0; i < limit; i++ {
if m.Op == OpPhi {
+ // The memory phi, if it exists, is always
+ // the first logical store in the block.
break
}
if m.Block.ID != target.Block.ID {