Skip to content

Commit 38b26f2

Browse files
committed
cmd/compile: remove stores to unread parameters
Currently, we remove stores to local variables that are not read. We don't do that for arguments. But arguments and locals are essentially the same. Arguments are passed by value, and are not expected to be read in the caller's frame. So we can remove the writes to them as well. One exception is the cgo_unsafe_arg directive, which makes all the arguments effectively address-taken. cgo_unsafe_arg implies ABI0, so we just skip ABI0 functions' arguments. Cherry-picked from the dev.simd branch. This CL is not necessarily SIMD specific. Apply early to reduce risk. Change-Id: I8999fc50da6a87f22c1ec23e9a0c15483b6f7df8 Reviewed-on: https://go-review.googlesource.com/c/go/+/705815 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: David Chase <[email protected]> Reviewed-by: Junyang Shao <[email protected]> Reviewed-on: https://go-review.googlesource.com/c/go/+/708865
1 parent 003b5ce commit 38b26f2

File tree

3 files changed

+26
-4
lines changed

3 files changed

+26
-4
lines changed

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

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ package ssa
77
import (
88
"cmd/compile/internal/ir"
99
"cmd/compile/internal/types"
10+
"cmd/internal/obj"
1011
)
1112

1213
// dse does dead-store elimination on the Function.
@@ -213,7 +214,7 @@ func elimDeadAutosGeneric(f *Func) {
213214
case OpAddr, OpLocalAddr:
214215
// Propagate the address if it points to an auto.
215216
n, ok := v.Aux.(*ir.Name)
216-
if !ok || n.Class != ir.PAUTO {
217+
if !ok || (n.Class != ir.PAUTO && !isABIInternalParam(f, n)) {
217218
return
218219
}
219220
if addr[v] == nil {
@@ -224,7 +225,7 @@ func elimDeadAutosGeneric(f *Func) {
224225
case OpVarDef:
225226
// v should be eliminated if we eliminate the auto.
226227
n, ok := v.Aux.(*ir.Name)
227-
if !ok || n.Class != ir.PAUTO {
228+
if !ok || (n.Class != ir.PAUTO && !isABIInternalParam(f, n)) {
228229
return
229230
}
230231
if elim[v] == nil {
@@ -240,7 +241,7 @@ func elimDeadAutosGeneric(f *Func) {
240241
// may not be used by the inline code, but will be used by
241242
// panic processing).
242243
n, ok := v.Aux.(*ir.Name)
243-
if !ok || n.Class != ir.PAUTO {
244+
if !ok || (n.Class != ir.PAUTO && !isABIInternalParam(f, n)) {
244245
return
245246
}
246247
if !used.Has(n) {
@@ -373,7 +374,7 @@ func elimUnreadAutos(f *Func) {
373374
if !ok {
374375
continue
375376
}
376-
if n.Class != ir.PAUTO {
377+
if n.Class != ir.PAUTO && !isABIInternalParam(f, n) {
377378
continue
378379
}
379380

@@ -413,3 +414,16 @@ func elimUnreadAutos(f *Func) {
413414
store.Op = OpCopy
414415
}
415416
}
417+
418+
// isABIInternalParam returns whether n is a parameter of an ABIInternal
419+
// function. For dead store elimination, we can treat parameters the same
420+
// way as autos. Storing to a parameter can be removed if it is not read
421+
// or address-taken.
422+
//
423+
// We check ABI here because for a cgo_unsafe_arg function (which is ABI0),
424+
// all the args are effectively address-taken, but not necessarily have
425+
// an Addr or LocalAddr op. We could probably just check for cgo_unsafe_arg,
426+
// but ABIInternal is mostly what matters.
427+
func isABIInternalParam(f *Func, n *ir.Name) bool {
428+
return n.Class == ir.PPARAM && f.ABISelf.Which() == obj.ABIInternal
429+
}

src/runtime/testdata/testprog/badtraceback.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ func badLR2(arg int) {
4444
lrPtr := (*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&arg)) - lrOff))
4545
*lrPtr = 0xbad
4646

47+
runtime.KeepAlive(lrPtr) // prevent dead store elimination
48+
4749
// Print a backtrace. This should include diagnostics for the
4850
// bad return PC and a hex dump.
4951
panic("backtrace")

test/codegen/stack.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,9 @@ func getp1() *[4]int {
168168
func getp2() *[4]int {
169169
return nil
170170
}
171+
172+
// Store to an argument without read can be removed.
173+
func storeArg(a [2]int) {
174+
// amd64:-`MOVQ\t\$123,.*\.a\+\d+\(SP\)`
175+
a[1] = 123
176+
}

0 commit comments

Comments
 (0)