aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/test
diff options
context:
space:
mode:
authorThan McIntosh <thanm@google.com>2021-04-06 16:18:50 -0400
committerThan McIntosh <thanm@google.com>2021-04-12 10:30:24 +0000
commitc26f954a540a99eafac6ee3bb3b996c750aad8a4 (patch)
tree7d1f54018243071e6d165a1d961299b6d67a6cca /src/cmd/compile/internal/test
parent16cd770e0668a410a511680b2ac1412e554bd27b (diff)
downloadgo-c26f954a540a99eafac6ee3bb3b996c750aad8a4.tar.gz
go-c26f954a540a99eafac6ee3bb3b996c750aad8a4.zip
cmd/compile/internal/amd64: follow-on regabi fix for amd64 zerorange
This patch provides a better long-term fix for the compiler's zerorange() helper function to make it generate code friendly to the register ABI. CL 305829 did part of the work, but didn't properly handle the case where the compiler emits a REP.STOSQ sequence; this patch changes the REP code to make sure it doesn't clobber any incoming register parameter values. Also included is a test that is specifically written to trigger the REP emit code in the compiler (prior to this, this code was not being hit on linux/amd64 all.bash). Updates #45372. Updates #40724. Change-Id: Iaf1c4e709e98eda45cd6f3aeebda0fe9160f1f42 Reviewed-on: https://go-review.googlesource.com/c/go/+/307829 Trust: Than McIntosh <thanm@google.com> Run-TryBot: Than McIntosh <thanm@google.com> Reviewed-by: Cherry Zhang <cherryyz@google.com>
Diffstat (limited to 'src/cmd/compile/internal/test')
-rw-r--r--src/cmd/compile/internal/test/zerorange_test.go91
1 files changed, 90 insertions, 1 deletions
diff --git a/src/cmd/compile/internal/test/zerorange_test.go b/src/cmd/compile/internal/test/zerorange_test.go
index cb1a6e04e4..ec87136157 100644
--- a/src/cmd/compile/internal/test/zerorange_test.go
+++ b/src/cmd/compile/internal/test/zerorange_test.go
@@ -4,7 +4,9 @@
package test
-import "testing"
+import (
+ "testing"
+)
var glob = 3
var globp *int64
@@ -94,3 +96,90 @@ func testZeroRange136(t *testing.T) (r, s, t2, u, v, w, x, y, r1, s1, t1, u1, v1
globp = &z1
return
}
+
+type S struct {
+ x [2]uint64
+ p *uint64
+ y [2]uint64
+ q uint64
+}
+
+type M struct {
+ x [8]uint64
+ p *uint64
+ y [8]uint64
+ q uint64
+}
+
+type L struct {
+ x [4096]uint64
+ p *uint64
+ y [4096]uint64
+ q uint64
+}
+
+//go:noinline
+func triggerZerorangeLarge(f, g, h uint64) (rv0 uint64) {
+ ll := L{p: &f}
+ da := f
+ rv0 = f + g + h
+ defer func(dl L, i uint64) {
+ rv0 += dl.q + i
+ }(ll, da)
+ return rv0
+}
+
+//go:noinline
+func triggerZerorangeMedium(f, g, h uint64) (rv0 uint64) {
+ ll := M{p: &f}
+ rv0 = f + g + h
+ defer func(dm M, i uint64) {
+ rv0 += dm.q + i
+ }(ll, f)
+ return rv0
+}
+
+//go:noinline
+func triggerZerorangeSmall(f, g, h uint64) (rv0 uint64) {
+ ll := S{p: &f}
+ rv0 = f + g + h
+ defer func(ds S, i uint64) {
+ rv0 += ds.q + i
+ }(ll, f)
+ return rv0
+}
+
+// This test was created as a follow up to issue #45372, to help
+// improve coverage of the compiler's arch-specific "zerorange"
+// function, which is invoked to zero out ambiguously live portions of
+// the stack frame in certain specific circumstances.
+//
+// In the current compiler implementation, for zerorange to be
+// invoked, we need to have an ambiguously live variable that needs
+// zeroing. One way to trigger this is to have a function with an
+// open-coded defer, where the opendefer function has an argument that
+// contains a pointer (this is what's used below).
+//
+// At the moment this test doesn't do any specific checking for
+// code sequence, or verification that things were properly set to zero,
+// this seems as though it would be too tricky and would result
+// in a "brittle" test.
+//
+// The small/medium/large scenarios below are inspired by the amd64
+// implementation of zerorange, which generates different code
+// depending on the size of the thing that needs to be zeroed out
+// (I've verified at the time of the writing of this test that it
+// exercises the various cases).
+//
+func TestZerorange45372(t *testing.T) {
+ if r := triggerZerorangeLarge(101, 303, 505); r != 1010 {
+ t.Errorf("large: wanted %d got %d", 1010, r)
+ }
+ if r := triggerZerorangeMedium(101, 303, 505); r != 1010 {
+ t.Errorf("medium: wanted %d got %d", 1010, r)
+ }
+ if r := triggerZerorangeSmall(101, 303, 505); r != 1010 {
+ t.Errorf("small: wanted %d got %d", 1010, r)
+ }
+
+}