aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Randall <khr@golang.org>2017-10-28 10:14:08 -0700
committerAndrew Bonventre <andybons@golang.org>2018-01-22 20:25:01 +0000
commit1cca09a8edb777f094026ad3a88111d56454a1b3 (patch)
tree832d08aef5e11109b3c7ecdb04b703780e37bb2f
parent5c08eef8706d56fe9509e9bca63d6a7f9d395036 (diff)
downloadgo-1cca09a8edb777f094026ad3a88111d56454a1b3.tar.gz
go-1cca09a8edb777f094026ad3a88111d56454a1b3.zip
[release-branch.go1.9] cmd/compile: fix runtime.KeepAlive
KeepAlive needs to introduce a use of the spill of the value it is keeping alive. Without that, we don't guarantee that the spill dominates the KeepAlive. This bug was probably introduced with the code to move spills down to the dominator of the restores, instead of always spilling just after the value itself (CL 34822). Fixes #22458. Change-Id: I94955a21960448ffdacc4df775fe1213967b1d4c Reviewed-on: https://go-review.googlesource.com/74210 Reviewed-by: Cherry Zhang <cherryyz@google.com> Reviewed-by: David Chase <drchase@google.com> Reviewed-on: https://go-review.googlesource.com/88318 Run-TryBot: Andrew Bonventre <andybons@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
-rw-r--r--src/cmd/compile/internal/ssa/regalloc.go11
-rw-r--r--test/fixedbugs/issue22458.go26
2 files changed, 33 insertions, 4 deletions
diff --git a/src/cmd/compile/internal/ssa/regalloc.go b/src/cmd/compile/internal/ssa/regalloc.go
index 137e5fc4c2..a0d69bc65c 100644
--- a/src/cmd/compile/internal/ssa/regalloc.go
+++ b/src/cmd/compile/internal/ssa/regalloc.go
@@ -1103,12 +1103,15 @@ func (s *regAllocState) regalloc(f *Func) {
if v.Op == OpKeepAlive {
// Make sure the argument to v is still live here.
s.advanceUses(v)
- vi := &s.values[v.Args[0].ID]
- if vi.spill != nil {
+ a := v.Args[0]
+ vi := &s.values[a.ID]
+ if vi.regs == 0 && !vi.rematerializeable {
// Use the spill location.
- v.SetArg(0, vi.spill)
+ // This forces later liveness analysis to make the
+ // value live at this point.
+ v.SetArg(0, s.makeSpill(a, b))
} else {
- // No need to keep unspilled values live.
+ // In-register and rematerializeable values are already live.
// These are typically rematerializeable constants like nil,
// or values of a variable that were modified since the last call.
v.Op = OpCopy
diff --git a/test/fixedbugs/issue22458.go b/test/fixedbugs/issue22458.go
new file mode 100644
index 0000000000..5c89929577
--- /dev/null
+++ b/test/fixedbugs/issue22458.go
@@ -0,0 +1,26 @@
+// compile
+
+// Copyright 2017 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Make sure KeepAlive introduces a use of the spilled variable.
+
+package main
+
+import "runtime"
+
+type node struct {
+ next *node
+}
+
+var x bool
+
+func main() {
+ var head *node
+ for x {
+ head = &node{head}
+ }
+
+ runtime.KeepAlive(head)
+}