Skip to content

Commit cdc6355

Browse files
committed
cmd/compile: invalidate zero-use values during rewrite
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Josh Bleecher Snyder <[email protected]>
1 parent 8247da3 commit cdc6355

File tree

6 files changed

+49
-7
lines changed

6 files changed

+49
-7
lines changed

src/cmd/compile/internal/ssa/decompose.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,11 @@ func decomposeBuiltIn(f *Func) {
2323
}
2424

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

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

217219
func decomposeArgs(f *Func) {
218-
applyRewrite(f, rewriteBlockdecArgs, rewriteValuedecArgs)
220+
applyRewrite(f, rewriteBlockdecArgs, rewriteValuedecArgs, removeDeadValues)
219221
}
220222

221223
func decomposeUser(f *Func) {

src/cmd/compile/internal/ssa/lower.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ package ssa
77
// convert to machine-dependent ops
88
func lower(f *Func) {
99
// repeat rewrites until we find no more rewrites
10-
applyRewrite(f, f.Config.lowerBlock, f.Config.lowerValue)
10+
applyRewrite(f, f.Config.lowerBlock, f.Config.lowerValue, removeDeadValues)
1111
}
1212

1313
// checkLower checks for unlowered opcodes and fails if we find one.

src/cmd/compile/internal/ssa/opt.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ package ssa
66

77
// machine-independent optimization
88
func opt(f *Func) {
9-
applyRewrite(f, rewriteBlockgeneric, rewriteValuegeneric)
9+
applyRewrite(f, rewriteBlockgeneric, rewriteValuegeneric, removeDeadValues)
1010
}

src/cmd/compile/internal/ssa/rewrite.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,15 @@ import (
2020
"path/filepath"
2121
)
2222

23-
func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter) {
23+
type deadValueChoice bool
24+
25+
const (
26+
leaveDeadValues deadValueChoice = false
27+
removeDeadValues = true
28+
)
29+
30+
// deadcode indicates that rewrite should try to remove any values that become dead.
31+
func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter, deadcode deadValueChoice) {
2432
// repeat rewrites until we find no more rewrites
2533
pendingLines := f.cachedLineStarts // Holds statement boundaries that need to be moved to a new value/block
2634
pendingLines.clear()
@@ -56,6 +64,18 @@ func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter) {
5664
*v0 = *v
5765
v0.Args = append([]*Value{}, v.Args...) // make a new copy, not aliasing
5866
}
67+
if v.Uses == 0 && v.removeable() {
68+
if v.Op != OpInvalid && deadcode == removeDeadValues {
69+
// Reset any values that are now unused, so that we decrement
70+
// the use count of all of its arguments.
71+
// Not quite a deadcode pass, because it does not handle cycles.
72+
// But it should help Uses==1 rules to fire.
73+
v.reset(OpInvalid)
74+
change = true
75+
}
76+
// No point rewriting values which aren't used.
77+
continue
78+
}
5979

6080
vchange := phielimValue(v)
6181
if vchange && debug > 1 {

src/cmd/compile/internal/ssa/softfloat.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ func softfloat(f *Func) {
7272
if newInt64 && f.Config.RegSize == 4 {
7373
// On 32bit arch, decompose Uint64 introduced in the switch above.
7474
decomposeBuiltIn(f)
75-
applyRewrite(f, rewriteBlockdec64, rewriteValuedec64)
75+
applyRewrite(f, rewriteBlockdec64, rewriteValuedec64, removeDeadValues)
7676
}
7777

7878
}

src/cmd/compile/internal/ssa/value.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,3 +460,23 @@ func (v *Value) LackingPos() bool {
460460
return v.Op == OpVarDef || v.Op == OpVarKill || v.Op == OpVarLive || v.Op == OpPhi ||
461461
(v.Op == OpFwdRef || v.Op == OpCopy) && v.Type == types.TypeMem
462462
}
463+
464+
// removeable reports whether the value v can be removed from the SSA graph entirely
465+
// if its use count drops to 0.
466+
func (v *Value) removeable() bool {
467+
if v.Type.IsVoid() {
468+
// Void ops, like nil pointer checks, must stay.
469+
return false
470+
}
471+
if v.Type.IsMemory() {
472+
// All memory ops aren't needed here, but we do need
473+
// to keep calls at least (because they might have
474+
// syncronization operations we can't see).
475+
return false
476+
}
477+
if v.Op.HasSideEffects() {
478+
// These are mostly synchronization operations.
479+
return false
480+
}
481+
return true
482+
}

0 commit comments

Comments
 (0)