}
// Add flag spill and recomputation where they are needed.
- // TODO: Remove original instructions if they are never used.
+ var remove []*Value // values that should be checked for possible removal
var oldSched []*Value
for _, b := range f.Blocks {
oldSched = append(oldSched[:0], b.Values...)
// If v will be spilled, and v uses memory, then we must split it
// into a load + a flag generator.
if spill[v.ID] && v.MemoryArg() != nil {
+ remove = append(remove, v)
if !f.Config.splitLoad(v) {
f.Fatalf("can't split flag generator: %s", v.LongString())
}
for i, v := range b.ControlValues() {
if v != flag && v.Type.IsFlags() {
// Recalculate control value.
+ remove = append(remove, v)
c := copyFlags(v, b)
b.ReplaceControl(i, c)
flag = v
if v := end[b.ID]; v != nil && v != flag {
// Need to reissue flag generator for use by
// subsequent blocks.
+ remove = append(remove, v)
copyFlags(v, b)
// Note: this flag generator is not properly linked up
// with the flag users. This breaks the SSA representation.
// We could fix up the users with another pass, but for now
- // we'll just leave it. (Regalloc has the same issue for
+ // we'll just leave it. (Regalloc has the same issue for
// standard regs, and it runs next.)
+ // For this reason, take care not to add this flag
+ // generator to the remove list.
}
}
for _, b := range f.Blocks {
b.FlagsLiveAtEnd = end[b.ID] != nil
}
+
+ const go115flagallocdeadcode = true
+ if !go115flagallocdeadcode {
+ return
+ }
+
+ // Remove any now-dead values.
+ // The number of values to remove is likely small,
+ // and removing them requires processing all values in a block,
+ // so minimize the number of blocks that we touch.
+
+ // Shrink remove to contain only dead values, and clobber those dead values.
+ for i := 0; i < len(remove); i++ {
+ v := remove[i]
+ if v.Uses == 0 {
+ v.reset(OpInvalid)
+ continue
+ }
+ // Remove v.
+ last := len(remove) - 1
+ remove[i] = remove[last]
+ remove[last] = nil
+ remove = remove[:last]
+ i-- // reprocess value at i
+ }
+
+ if len(remove) == 0 {
+ return
+ }
+
+ removeBlocks := f.newSparseSet(f.NumBlocks())
+ defer f.retSparseSet(removeBlocks)
+ for _, v := range remove {
+ removeBlocks.add(v.Block.ID)
+ }
+
+ // Process affected blocks, preserving value order.
+ for _, b := range f.Blocks {
+ if !removeBlocks.contains(b.ID) {
+ continue
+ }
+ i := 0
+ for j := 0; j < len(b.Values); j++ {
+ v := b.Values[j]
+ if v.Op == OpInvalid {
+ continue
+ }
+ b.Values[i] = v
+ i++
+ }
+ b.truncateValues(i)
+ }
}
func (v *Value) clobbersFlags() bool {