Skip to content

Commit

Permalink
cmd/compile: remove dead values after flagalloc
Browse files Browse the repository at this point in the history
Fix a longstanding TODO.

Provides widespread, minor improvements.
Negligible compiler cost.

Because the freeze nears, put in a safety flag to easily disable.

Change-Id: I338812181ab6d806fecf22afd3c3502e2c94f7a0
Reviewed-on: https://go-review.googlesource.com/c/go/+/229600
Run-TryBot: Josh Bleecher Snyder <[email protected]>
TryBot-Result: Gobot Gobot <[email protected]>
Reviewed-by: Keith Randall <[email protected]>
  • Loading branch information
josharian authored and xujianhai666 committed May 21, 2020
1 parent 03d589d commit 677acfe
Showing 1 changed file with 59 additions and 2 deletions.
61 changes: 59 additions & 2 deletions src/cmd/compile/internal/ssa/flagalloc.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ func flagalloc(f *Func) {
}

// 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...)
Expand All @@ -131,6 +131,7 @@ func flagalloc(f *Func) {
// 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())
}
Expand Down Expand Up @@ -164,6 +165,7 @@ func flagalloc(f *Func) {
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
Expand All @@ -172,19 +174,74 @@ func flagalloc(f *Func) {
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.
}
}

// Save live flag state for later.
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 {
Expand Down

0 comments on commit 677acfe

Please sign in to comment.