diff options
author | Russ Cox <rsc@golang.org> | 2014-04-01 13:31:38 -0400 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2014-04-01 13:31:38 -0400 |
commit | 3765e1185802d58f12697f3a0d6b5da94f16c6b8 (patch) | |
tree | c1b8205e3d9db618be292b5660302a11bf0bb101 /test/live.go | |
parent | 0e00206e5a0cda367ba0d98286aa25d533f1c589 (diff) | |
download | go-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.go | 118 |
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]+$" +} |