aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/cmd/compile/internal/ssa/deadstore.go22
-rw-r--r--src/runtime/testdata/testprog/badtraceback.go2
2 files changed, 20 insertions, 4 deletions
diff --git a/src/cmd/compile/internal/ssa/deadstore.go b/src/cmd/compile/internal/ssa/deadstore.go
index 9e67e83399..d0adff788c 100644
--- a/src/cmd/compile/internal/ssa/deadstore.go
+++ b/src/cmd/compile/internal/ssa/deadstore.go
@@ -7,6 +7,7 @@ package ssa
import (
"cmd/compile/internal/ir"
"cmd/compile/internal/types"
+ "cmd/internal/obj"
)
// dse does dead-store elimination on the Function.
@@ -213,7 +214,7 @@ func elimDeadAutosGeneric(f *Func) {
case OpAddr, OpLocalAddr:
// Propagate the address if it points to an auto.
n, ok := v.Aux.(*ir.Name)
- if !ok || n.Class != ir.PAUTO {
+ if !ok || (n.Class != ir.PAUTO && !isABIInternalParam(f, n)) {
return
}
if addr[v] == nil {
@@ -224,7 +225,7 @@ func elimDeadAutosGeneric(f *Func) {
case OpVarDef:
// v should be eliminated if we eliminate the auto.
n, ok := v.Aux.(*ir.Name)
- if !ok || n.Class != ir.PAUTO {
+ if !ok || (n.Class != ir.PAUTO && !isABIInternalParam(f, n)) {
return
}
if elim[v] == nil {
@@ -240,7 +241,7 @@ func elimDeadAutosGeneric(f *Func) {
// may not be used by the inline code, but will be used by
// panic processing).
n, ok := v.Aux.(*ir.Name)
- if !ok || n.Class != ir.PAUTO {
+ if !ok || (n.Class != ir.PAUTO && !isABIInternalParam(f, n)) {
return
}
if !used.Has(n) {
@@ -373,7 +374,7 @@ func elimUnreadAutos(f *Func) {
if !ok {
continue
}
- if n.Class != ir.PAUTO {
+ if n.Class != ir.PAUTO && !isABIInternalParam(f, n) {
continue
}
@@ -413,3 +414,16 @@ func elimUnreadAutos(f *Func) {
store.Op = OpCopy
}
}
+
+// isABIInternalParam returns whether n is a parameter of an ABIInternal
+// function. For dead store elimination, we can treat parameters the same
+// way as autos. Storing to a parameter can be removed if it is not read
+// or address-taken.
+//
+// We check ABI here because for a cgo_unsafe_arg function (which is ABI0),
+// all the args are effectively address-taken, but not necessarily have
+// an Addr or LocalAddr op. We could probably just check for cgo_unsafe_arg,
+// but ABIInternal is mostly what matters.
+func isABIInternalParam(f *Func, n *ir.Name) bool {
+ return n.Class == ir.PPARAM && f.ABISelf.Which() == obj.ABIInternal
+}
diff --git a/src/runtime/testdata/testprog/badtraceback.go b/src/runtime/testdata/testprog/badtraceback.go
index 09aa2b877e..455118a543 100644
--- a/src/runtime/testdata/testprog/badtraceback.go
+++ b/src/runtime/testdata/testprog/badtraceback.go
@@ -44,6 +44,8 @@ func badLR2(arg int) {
lrPtr := (*uintptr)(unsafe.Pointer(uintptr(unsafe.Pointer(&arg)) - lrOff))
*lrPtr = 0xbad
+ runtime.KeepAlive(lrPtr) // prevent dead store elimination
+
// Print a backtrace. This should include diagnostics for the
// bad return PC and a hex dump.
panic("backtrace")