summaryrefslogtreecommitdiff
path: root/test/reorder2.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/reorder2.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/reorder2.go')
-rw-r--r--test/reorder2.go169
1 files changed, 169 insertions, 0 deletions
diff --git a/test/reorder2.go b/test/reorder2.go
index d91f1d895..e56be2bc8 100644
--- a/test/reorder2.go
+++ b/test/reorder2.go
@@ -167,6 +167,175 @@ func main() {
err++
}
log = ""
+
+ x := 0
+ switch x {
+ case 0:
+ if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
+ println("in switch, expecting a(1)a(2)a(3) , got ", log)
+ err++
+ }
+ log = ""
+
+ if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
+ println("in switch, expecting a(1)b(2)a(2), got ", log)
+ err++
+ }
+ log = ""
+ if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
+ println("in switch, expecting a(3)b(4)a(4)b(5)a(5), got ", log)
+ err++
+ }
+ log = ""
+ var i I = T1(0)
+ if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
+ println("in switch, expecting a(6)ba(7)ba(8)ba(9), got", log)
+ err++
+ }
+ log = ""
+ }
+
+ c := make(chan int, 1)
+ c <- 1
+ select {
+ case c <- 0:
+ case c <- 1:
+ case <-c:
+ if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
+ println("in select1, expecting a(1)a(2)a(3) , got ", log)
+ err++
+ }
+ log = ""
+
+ if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
+ println("in select1, expecting a(1)b(2)a(2), got ", log)
+ err++
+ }
+ log = ""
+ if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
+ println("in select1, expecting a(3)b(4)a(4)b(5)a(5), got ", log)
+ err++
+ }
+ log = ""
+ var i I = T1(0)
+ if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
+ println("in select1, expecting a(6)ba(7)ba(8)ba(9), got", log)
+ err++
+ }
+ log = ""
+ }
+
+ c <- 1
+ select {
+ case <-c:
+ if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
+ println("in select2, expecting a(1)a(2)a(3) , got ", log)
+ err++
+ }
+ log = ""
+
+ if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
+ println("in select2, expecting a(1)b(2)a(2), got ", log)
+ err++
+ }
+ log = ""
+ if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
+ println("in select2, expecting a(3)b(4)a(4)b(5)a(5), got ", log)
+ err++
+ }
+ log = ""
+ var i I = T1(0)
+ if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
+ println("in select2, expecting a(6)ba(7)ba(8)ba(9), got", log)
+ err++
+ }
+ log = ""
+ }
+
+ c <- 1
+ select {
+ default:
+ case c<-1:
+ case <-c:
+ if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
+ println("in select3, expecting a(1)a(2)a(3) , got ", log)
+ err++
+ }
+ log = ""
+
+ if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
+ println("in select3, expecting a(1)b(2)a(2), got ", log)
+ err++
+ }
+ log = ""
+ if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
+ println("in select3, expecting a(3)b(4)a(4)b(5)a(5), got ", log)
+ err++
+ }
+ log = ""
+ var i I = T1(0)
+ if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
+ println("in select3, expecting a(6)ba(7)ba(8)ba(9), got", log)
+ err++
+ }
+ log = ""
+ }
+
+ c <- 1
+ select {
+ default:
+ case <-c:
+ if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
+ println("in select4, expecting a(1)a(2)a(3) , got ", log)
+ err++
+ }
+ log = ""
+
+ if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
+ println("in select4, expecting a(1)b(2)a(2), got ", log)
+ err++
+ }
+ log = ""
+ if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
+ println("in select4, expecting a(3)b(4)a(4)b(5)a(5), got ", log)
+ err++
+ }
+ log = ""
+ var i I = T1(0)
+ if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
+ println("in select4, expecting a(6)ba(7)ba(8)ba(9), got", log)
+ err++
+ }
+ log = ""
+ }
+
+ select {
+ case <-c:
+ case <-c:
+ default:
+ if a("1")("2")("3"); log != "a(1)a(2)a(3)" {
+ println("in select5, expecting a(1)a(2)a(3) , got ", log)
+ err++
+ }
+ log = ""
+
+ if t.a("1").a(t.b("2")); log != "a(1)b(2)a(2)" {
+ println("in select5, expecting a(1)b(2)a(2), got ", log)
+ err++
+ }
+ log = ""
+ if a("3")(b("4"))(b("5")); log != "a(3)b(4)a(4)b(5)a(5)" {
+ println("in select5, expecting a(3)b(4)a(4)b(5)a(5), got ", log)
+ err++
+ }
+ log = ""
+ var i I = T1(0)
+ if i.a("6").a(i.b("7")).a(i.b("8")).a(i.b("9")); log != "a(6)b(7)a(7)b(8)a(8)b(9)a(9)" {
+ println("in select5, expecting a(6)ba(7)ba(8)ba(9), got", log)
+ err++
+ }
+ log = ""
+ }
if err > 0 {
panic("fail")