summaryrefslogtreecommitdiff
path: root/test/live.go
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-04-01 13:31:38 -0400
committerRuss Cox <rsc@golang.org>2014-04-01 13:31:38 -0400
commit3765e1185802d58f12697f3a0d6b5da94f16c6b8 (patch)
treec1b8205e3d9db618be292b5660302a11bf0bb101 /test/live.go
parent0e00206e5a0cda367ba0d98286aa25d533f1c589 (diff)
downloadgo-3765e1185802d58f12697f3a0d6b5da94f16c6b8.tar.gz
cmd/gc: shorten temporary lifetimes when possible
The new channel and map runtime routines take pointers to values, typically temporaries. Without help, the compiler cannot tell when those temporaries stop being needed, because it isn't sure what happened to the pointer. Arrange to insert explicit VARKILL instructions for these temporaries so that the liveness analysis can avoid seeing them as "ambiguously live". The change is made in order.c, which was already in charge of introducing temporaries to preserve the order-of-evaluation guarantees. Now its job has expanded to include introducing temporaries as needed by runtime routines, and then also inserting the VARKILL annotations for all these temporaries, so that their lifetimes can be shortened. In order to do its job for the map runtime routines, order.c arranges that all map lookups or map assignments have the form: x = m[k] x, y = m[k] m[k] = x where x, y, and k are simple variables (often temporaries). Likewise, receiving from a channel is now always: x = <-c In order to provide the map guarantee, order.c is responsible for rewriting x op= y into x = x op y, so that m[k] += z becomes t = m[k] t2 = t + z m[k] = t2 While here, fix a few bugs in order.c's traversal: it was failing to walk into select and switch case bodies, so order of evaluation guarantees were not preserved in those situations. Added tests to test/reorder2.go. Fixes issue 7671. In gc/popt's temporary-merging optimization, allow merging of temporaries with their address taken as long as the liveness ranges do not intersect. (There is a good chance of that now that we have VARKILL annotations to limit the liveness range.) Explicitly killing temporaries cuts the number of ambiguously live temporaries that must be zeroed in the godoc binary from 860 to 711, or -17%. There is more work to be done, but this is a good checkpoint. Update issue 7345 LGTM=khr R=khr CC=golang-codereviews https://codereview.appspot.com/81940043
Diffstat (limited to 'test/live.go')
-rw-r--r--test/live.go118
1 files changed, 118 insertions, 0 deletions
diff --git a/test/live.go b/test/live.go
index f0d7c9045..5a03bf031 100644
--- a/test/live.go
+++ b/test/live.go
@@ -212,3 +212,121 @@ func f15() {
}
func g15() string
+
+// Checking that various temporaries do not persist or cause
+// ambiguously live values that must be zeroed.
+// The exact temporary names are inconsequential but we are
+// trying to check that there is only one at any given site,
+// and also that none show up in "ambiguously live" messages.
+
+var m map[string]int
+
+func f16() {
+ if b {
+ delete(m, "hi") // ERROR "live at call to mapdelete: autotmp_[0-9]+$"
+ }
+ delete(m, "hi") // ERROR "live at call to mapdelete: autotmp_[0-9]+$"
+ delete(m, "hi") // ERROR "live at call to mapdelete: autotmp_[0-9]+$"
+}
+
+var m2s map[string]*byte
+var m2 map[[2]string]*byte
+var x2 [2]string
+var bp *byte
+
+func f17a() {
+ // value temporary only
+ if b {
+ m2[x2] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+$"
+ }
+ m2[x2] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+$"
+ m2[x2] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+$"
+}
+
+func f17b() {
+ // key temporary only
+ if b {
+ m2s["x"] = bp // ERROR "live at call to mapassign1: autotmp_[0-9]+$"
+ }
+ m2s["x"] = bp // ERROR "live at call to mapassign1: autotmp_[0-9]+$"
+ m2s["x"] = bp // ERROR "live at call to mapassign1: autotmp_[0-9]+$"
+}
+
+func f17c() {
+ // key and value temporaries
+ if b {
+ m2s["x"] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$"
+ }
+ m2s["x"] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$"
+ m2s["x"] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$"
+}
+
+func g18() [2]string
+
+func f18() {
+ // key temporary for mapaccess.
+ // temporary introduced by orderexpr.
+ var z *byte
+ if b {
+ z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
+ }
+ z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
+ z = m2[g18()] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
+ print(z)
+}
+
+var ch chan *byte
+
+func f19() {
+ // dest temporary for channel receive.
+ var z *byte
+
+ if b {
+ z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$"
+ }
+ z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$"
+ z = <-ch // ERROR "live at call to chanrecv1: autotmp_[0-9]+$"
+ print(z)
+}
+
+func f20() {
+ // src temporary for channel send
+ if b {
+ ch <- nil // ERROR "live at call to chansend1: autotmp_[0-9]+$"
+ }
+ ch <- nil // ERROR "live at call to chansend1: autotmp_[0-9]+$"
+ ch <- nil // ERROR "live at call to chansend1: autotmp_[0-9]+$"
+}
+
+func f21() {
+ // key temporary for mapaccess using array literal key.
+ var z *byte
+ if b {
+ z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
+ }
+ z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
+ z = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess1: autotmp_[0-9]+$"
+ print(z)
+}
+
+func f23() {
+ // key temporary for two-result map access using array literal key.
+ var z *byte
+ var ok bool
+ if b {
+ z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$"
+ }
+ z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$"
+ z, ok = m2[[2]string{"x", "y"}] // ERROR "live at call to mapaccess2: autotmp_[0-9]+$"
+ print(z, ok)
+}
+
+func f24() {
+ // key temporary for map access using array literal key.
+ // value temporary too.
+ if b {
+ m2[[2]string{"x", "y"}] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$"
+ }
+ m2[[2]string{"x", "y"}] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$"
+ m2[[2]string{"x", "y"}] = nil // ERROR "live at call to mapassign1: autotmp_[0-9]+ autotmp_[0-9]+$"
+}