aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/ssa/regalloc_test.go
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2017-06-14 13:53:57 -0400
committerRuss Cox <rsc@golang.org>2017-06-14 13:53:57 -0400
commit8a5ef1501dee0715093e87cdc1c9b6becb81c882 (patch)
tree85a4b4d1e5633edb79567d9deb3bbbf02ee9383e /src/cmd/compile/internal/ssa/regalloc_test.go
parent1ba29926f3bfd245d46cf1f287716290bc2f1034 (diff)
parent352996a381701cfa0c16e8de29cbde8f3922182f (diff)
downloadgo-dev.typealias.tar.gz
go-dev.typealias.zip
[dev.typealias] all: merge go1.8.3 into dev.typealiasdev.typealias
352996a381 (tag: go1.8.3) [release-branch.go1.8] go1.8.3 bb5055d6f1 [release-branch.go1.8] doc: document go1.8.3 439c0c8be8 [release-branch.go1.8] cmd/compile: don't move spills to loop exits where the spill is dead e396667ba3 [release-branch.go1.8] cmd/compile: zero ambiguously live variables at VARKILLs daf6706f37 [release-branch.go1.8] runtime: use pselect6 for usleep on linux/386 958c64bbab [release-branch.go1.8] runtime: use pselect6 for usleep on linux/amd64 and linux/arm 195e20a976 [release-branch.go1.8] cmd/compile: ignore types when considering tuple select for CSE f55bc1c4eb [release-branch.go1.8] net/http: update bundled http2 for gracefulShutdownCh lock contention slowdown 51f508bb4a [release-branch.go1.8] cmd/compile: fix s390x unsigned comparison constant merging rules 243dee1737 [release-branch.go1.8] cmd/go: if we get a C compiler dwarf2 warning, try without -g a43c0d2dc8 [release-branch.go1.8] runtime: don't corrupt arena bounds on low mmap 1054085dcf [release-branch.go1.8] cmd/compile: fix store chain in schedule pass 18a13d373a [release-branch.go1.8] runtime: doubly fix "double wakeup" panic 6efa2f22ac [release-branch.go1.8] database/sql: ensure releaseConn is defined before a possible close fb9770f09b [release-branch.go1.8] runtime: print debug info on "base out of range" b6a8fc8d8c [release-branch.go1.8] doc: remove mentions of yacc tool 59870f9e19 (tag: go1.8.2) [release-branch.go1.8] go1.8.2 c9688ddb6b [release-branch.go1.8] doc: document go1.8.2 and go1.7.6 38d35f49e7 [release-branch.go1.8] crypto/elliptic: fix carry bug in x86-64 P-256 implementation. Change-Id: I2aa0eab7a990d24e25809fb13ce6cb031104f474
Diffstat (limited to 'src/cmd/compile/internal/ssa/regalloc_test.go')
-rw-r--r--src/cmd/compile/internal/ssa/regalloc_test.go65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/regalloc_test.go b/src/cmd/compile/internal/ssa/regalloc_test.go
index cf8f452d12..d3d1891bcd 100644
--- a/src/cmd/compile/internal/ssa/regalloc_test.go
+++ b/src/cmd/compile/internal/ssa/regalloc_test.go
@@ -31,3 +31,68 @@ func TestLiveControlOps(t *testing.T) {
regalloc(f.f)
checkFunc(f.f)
}
+
+func TestSpillMove(t *testing.T) {
+ // Test for issue 20472. We shouldn't move a spill out to exit blocks
+ // if there is an exit block where the spill is dead but the pre-spill
+ // value is live.
+ c := testConfig(t)
+ ptrType := &TypeImpl{Size_: 8, Ptr: true, Name: "testptr"} // dummy for testing
+ arg1Aux := c.fe.Auto(TypeInt64)
+ arg2Aux := c.fe.Auto(ptrType)
+ f := Fun(c, "entry",
+ Bloc("entry",
+ Valu("mem", OpInitMem, TypeMem, 0, nil),
+ Valu("x", OpArg, TypeInt64, 0, arg1Aux),
+ Valu("p", OpArg, ptrType, 0, arg2Aux),
+ Valu("a", OpAMD64TESTQ, TypeFlags, 0, nil, "x", "x"),
+ Goto("loop1"),
+ ),
+ Bloc("loop1",
+ Valu("y", OpAMD64MULQ, TypeInt64, 0, nil, "x", "x"),
+ Eq("a", "loop2", "exit1"),
+ ),
+ Bloc("loop2",
+ Eq("a", "loop1", "exit2"),
+ ),
+ Bloc("exit1",
+ // store before call, y is available in a register
+ Valu("mem2", OpAMD64MOVQstore, TypeMem, 0, nil, "p", "y", "mem"),
+ Valu("mem3", OpAMD64CALLstatic, TypeMem, 0, nil, "mem2"),
+ Exit("mem3"),
+ ),
+ Bloc("exit2",
+ // store after call, y must be loaded from a spill location
+ Valu("mem4", OpAMD64CALLstatic, TypeMem, 0, nil, "mem"),
+ Valu("mem5", OpAMD64MOVQstore, TypeMem, 0, nil, "p", "y", "mem4"),
+ Exit("mem5"),
+ ),
+ )
+ flagalloc(f.f)
+ regalloc(f.f)
+ checkFunc(f.f)
+ // There should still be a spill in Loop1, and nowhere else.
+ if numSpills(f.blocks["loop1"]) != 1 {
+ t.Errorf("spill missing from loop1")
+ }
+ if numSpills(f.blocks["loop2"]) != 0 {
+ t.Errorf("spill present in loop2")
+ }
+ if numSpills(f.blocks["exit1"]) != 0 {
+ t.Errorf("spill present in exit1")
+ }
+ if numSpills(f.blocks["exit2"]) != 0 {
+ t.Errorf("spill present in exit2")
+ }
+
+}
+
+func numSpills(b *Block) int {
+ n := 0
+ for _, v := range b.Values {
+ if v.Op == OpStoreReg {
+ n++
+ }
+ }
+ return n
+}