Skip to content

Commit

Permalink
cmd/compile: invalidate zero-use values during rewrite
Browse files Browse the repository at this point in the history
This helps remove uses that aren't needed any more.
That in turn helps other rules with Uses==1 conditions fire.

Update #39918

Change-Id: I68635b675472f1d59e59604e4d34b949a0016533
Reviewed-on: https://go-review.googlesource.com/c/go/+/249463
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
  • Loading branch information
randall77 committed Aug 27, 2020
1 parent 8247da3 commit cdc6355
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 7 deletions.
8 changes: 5 additions & 3 deletions src/cmd/compile/internal/ssa/decompose.go
Expand Up @@ -23,9 +23,11 @@ func decomposeBuiltIn(f *Func) {
}

// Decompose other values
applyRewrite(f, rewriteBlockdec, rewriteValuedec)
// Note: deadcode is false because we need to keep the original
// values around so the name component resolution below can still work.
applyRewrite(f, rewriteBlockdec, rewriteValuedec, leaveDeadValues)
if f.Config.RegSize == 4 {
applyRewrite(f, rewriteBlockdec64, rewriteValuedec64)
applyRewrite(f, rewriteBlockdec64, rewriteValuedec64, leaveDeadValues)
}

// Split up named values into their components.
Expand Down Expand Up @@ -215,7 +217,7 @@ func decomposeInterfacePhi(v *Value) {
}

func decomposeArgs(f *Func) {
applyRewrite(f, rewriteBlockdecArgs, rewriteValuedecArgs)
applyRewrite(f, rewriteBlockdecArgs, rewriteValuedecArgs, removeDeadValues)
}

func decomposeUser(f *Func) {
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/ssa/lower.go
Expand Up @@ -7,7 +7,7 @@ package ssa
// convert to machine-dependent ops
func lower(f *Func) {
// repeat rewrites until we find no more rewrites
applyRewrite(f, f.Config.lowerBlock, f.Config.lowerValue)
applyRewrite(f, f.Config.lowerBlock, f.Config.lowerValue, removeDeadValues)
}

// checkLower checks for unlowered opcodes and fails if we find one.
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/ssa/opt.go
Expand Up @@ -6,5 +6,5 @@ package ssa

// machine-independent optimization
func opt(f *Func) {
applyRewrite(f, rewriteBlockgeneric, rewriteValuegeneric)
applyRewrite(f, rewriteBlockgeneric, rewriteValuegeneric, removeDeadValues)
}
22 changes: 21 additions & 1 deletion src/cmd/compile/internal/ssa/rewrite.go
Expand Up @@ -20,7 +20,15 @@ import (
"path/filepath"
)

func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter) {
type deadValueChoice bool

const (
leaveDeadValues deadValueChoice = false
removeDeadValues = true
)

// deadcode indicates that rewrite should try to remove any values that become dead.
func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter, deadcode deadValueChoice) {
// repeat rewrites until we find no more rewrites
pendingLines := f.cachedLineStarts // Holds statement boundaries that need to be moved to a new value/block
pendingLines.clear()
Expand Down Expand Up @@ -56,6 +64,18 @@ func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter) {
*v0 = *v
v0.Args = append([]*Value{}, v.Args...) // make a new copy, not aliasing
}
if v.Uses == 0 && v.removeable() {
if v.Op != OpInvalid && deadcode == removeDeadValues {
// Reset any values that are now unused, so that we decrement
// the use count of all of its arguments.
// Not quite a deadcode pass, because it does not handle cycles.
// But it should help Uses==1 rules to fire.
v.reset(OpInvalid)
change = true
}
// No point rewriting values which aren't used.
continue
}

vchange := phielimValue(v)
if vchange && debug > 1 {
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/ssa/softfloat.go
Expand Up @@ -72,7 +72,7 @@ func softfloat(f *Func) {
if newInt64 && f.Config.RegSize == 4 {
// On 32bit arch, decompose Uint64 introduced in the switch above.
decomposeBuiltIn(f)
applyRewrite(f, rewriteBlockdec64, rewriteValuedec64)
applyRewrite(f, rewriteBlockdec64, rewriteValuedec64, removeDeadValues)
}

}
20 changes: 20 additions & 0 deletions src/cmd/compile/internal/ssa/value.go
Expand Up @@ -460,3 +460,23 @@ func (v *Value) LackingPos() bool {
return v.Op == OpVarDef || v.Op == OpVarKill || v.Op == OpVarLive || v.Op == OpPhi ||
(v.Op == OpFwdRef || v.Op == OpCopy) && v.Type == types.TypeMem
}

// removeable reports whether the value v can be removed from the SSA graph entirely
// if its use count drops to 0.
func (v *Value) removeable() bool {
if v.Type.IsVoid() {
// Void ops, like nil pointer checks, must stay.
return false
}
if v.Type.IsMemory() {
// All memory ops aren't needed here, but we do need
// to keep calls at least (because they might have
// syncronization operations we can't see).
return false
}
if v.Op.HasSideEffects() {
// These are mostly synchronization operations.
return false
}
return true
}

0 comments on commit cdc6355

Please sign in to comment.