]> Cypherpunks repositories - gostls13.git/commitdiff
test: move load/store combines into asmcheck
authorGiovanni Bajo <rasky@develer.com>
Sat, 3 Mar 2018 15:00:43 +0000 (16:00 +0100)
committerGiovanni Bajo <rasky@develer.com>
Sun, 4 Mar 2018 16:52:03 +0000 (16:52 +0000)
This CL moves the load/store combining tests into asmcheck.
In addition at being more compact, it's also now easier to
spot what it is missing in each architecture.

While doing so, I think I uncovered a bug in ppc64le and arm64
rules, because they fail to load/store combine in non-trivial
functions. Not sure why, I'll open an issue.

Change-Id: Ia1572d53c0553d9104f3e52b95e4d1768a8440a3
Reviewed-on: https://go-review.googlesource.com/98441
Run-TryBot: Giovanni Bajo <rasky@develer.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/gc/asm_test.go
test/codegen/memcombine.go [new file with mode: 0644]

index 0919eab3070b28ef8b02422572d123ebaf89cbca..b9180dafcb382833cdffc49e440a1032709de8fc 100644 (file)
@@ -224,19 +224,19 @@ var allAsmTests = []*asmTests{
        {
                arch:    "amd64",
                os:      "linux",
-               imports: []string{"encoding/binary", "math", "math/bits", "unsafe", "runtime"},
+               imports: []string{"math", "math/bits", "unsafe", "runtime"},
                tests:   linuxAMD64Tests,
        },
        {
                arch:    "386",
                os:      "linux",
-               imports: []string{"encoding/binary", "math"},
+               imports: []string{"math"},
                tests:   linux386Tests,
        },
        {
                arch:    "s390x",
                os:      "linux",
-               imports: []string{"encoding/binary", "math", "math/bits"},
+               imports: []string{"math", "math/bits"},
                tests:   linuxS390XTests,
        },
        {
@@ -248,7 +248,7 @@ var allAsmTests = []*asmTests{
        {
                arch:    "arm64",
                os:      "linux",
-               imports: []string{"encoding/binary", "math", "math/bits"},
+               imports: []string{"math", "math/bits"},
                tests:   linuxARM64Tests,
        },
        {
@@ -266,7 +266,7 @@ var allAsmTests = []*asmTests{
        {
                arch:    "ppc64le",
                os:      "linux",
-               imports: []string{"encoding/binary", "math", "math/bits"},
+               imports: []string{"math", "math/bits"},
                tests:   linuxPPC64LETests,
        },
        {
@@ -305,183 +305,6 @@ var linuxAMD64Tests = []*asmTest{
                `,
                pos: []string{"\tSHLQ\t\\$5,", "\tLEAQ\t\\(.*\\)\\(.*\\*2\\),"},
        },
-       // Load-combining tests.
-       {
-               fn: `
-               func f2(b []byte) uint64 {
-                       return binary.LittleEndian.Uint64(b)
-               }
-               `,
-               pos: []string{"\tMOVQ\t\\(.*\\),"},
-       },
-       {
-               fn: `
-               func f3(b []byte, i int) uint64 {
-                       return binary.LittleEndian.Uint64(b[i:])
-               }
-               `,
-               pos: []string{"\tMOVQ\t\\(.*\\)\\(.*\\*1\\),"},
-       },
-       {
-               fn: `
-               func f4(b []byte) uint32 {
-                       return binary.LittleEndian.Uint32(b)
-               }
-               `,
-               pos: []string{"\tMOVL\t\\(.*\\),"},
-       },
-       {
-               fn: `
-               func f5(b []byte, i int) uint32 {
-                       return binary.LittleEndian.Uint32(b[i:])
-               }
-               `,
-               pos: []string{"\tMOVL\t\\(.*\\)\\(.*\\*1\\),"},
-       },
-       {
-               fn: `
-               func $(b []byte, v uint64) {
-                       binary.LittleEndian.PutUint64(b, v)
-               }
-               `,
-               neg: []string{"SHRQ"},
-       },
-       {
-               fn: `
-               func $(b []byte, i int, v uint64) {
-                       binary.LittleEndian.PutUint64(b[i:], v)
-               }
-               `,
-               neg: []string{"SHRQ"},
-       },
-       {
-               fn: `
-               func $(b []byte, v uint32) {
-                       binary.LittleEndian.PutUint32(b, v)
-               }
-               `,
-               neg: []string{"SHRL", "SHRQ"},
-       },
-       {
-               fn: `
-               func $(b []byte, i int, v uint32) {
-                       binary.LittleEndian.PutUint32(b[i:], v)
-               }
-               `,
-               neg: []string{"SHRL", "SHRQ"},
-       },
-       {
-               fn: `
-               func $(b []byte, v uint16) {
-                       binary.LittleEndian.PutUint16(b, v)
-               }
-               `,
-               neg: []string{"SHRW", "SHRL", "SHRQ"},
-       },
-       {
-               fn: `
-               func $(b []byte, i int, v uint16) {
-                       binary.LittleEndian.PutUint16(b[i:], v)
-               }
-               `,
-               neg: []string{"SHRW", "SHRL", "SHRQ"},
-       },
-       {
-               fn: `
-               func f6(b []byte) uint64 {
-                       return binary.BigEndian.Uint64(b)
-               }
-               `,
-               pos: []string{"\tBSWAPQ\t"},
-       },
-       {
-               fn: `
-               func f7(b []byte, i int) uint64 {
-                       return binary.BigEndian.Uint64(b[i:])
-               }
-               `,
-               pos: []string{"\tBSWAPQ\t"},
-       },
-       {
-               fn: `
-               func f8(b []byte, v uint64) {
-                       binary.BigEndian.PutUint64(b, v)
-               }
-               `,
-               pos: []string{"\tBSWAPQ\t"},
-       },
-       {
-               fn: `
-               func f9(b []byte, i int, v uint64) {
-                       binary.BigEndian.PutUint64(b[i:], v)
-               }
-               `,
-               pos: []string{"\tBSWAPQ\t"},
-       },
-       {
-               fn: `
-               func f10(b []byte) uint32 {
-                       return binary.BigEndian.Uint32(b)
-               }
-               `,
-               pos: []string{"\tBSWAPL\t"},
-       },
-       {
-               fn: `
-               func f11(b []byte, i int) uint32 {
-                       return binary.BigEndian.Uint32(b[i:])
-               }
-               `,
-               pos: []string{"\tBSWAPL\t"},
-       },
-       {
-               fn: `
-               func f12(b []byte, v uint32) {
-                       binary.BigEndian.PutUint32(b, v)
-               }
-               `,
-               pos: []string{"\tBSWAPL\t"},
-       },
-       {
-               fn: `
-               func f13(b []byte, i int, v uint32) {
-                       binary.BigEndian.PutUint32(b[i:], v)
-               }
-               `,
-               pos: []string{"\tBSWAPL\t"},
-       },
-       {
-               fn: `
-               func f14(b []byte) uint16 {
-                       return binary.BigEndian.Uint16(b)
-               }
-               `,
-               pos: []string{"\tROLW\t\\$8,"},
-       },
-       {
-               fn: `
-               func f15(b []byte, i int) uint16 {
-                       return binary.BigEndian.Uint16(b[i:])
-               }
-               `,
-               pos: []string{"\tROLW\t\\$8,"},
-       },
-       {
-               fn: `
-               func f16(b []byte, v uint16) {
-                       binary.BigEndian.PutUint16(b, v)
-               }
-               `,
-               pos: []string{"\tROLW\t\\$8,"},
-       },
-       {
-               fn: `
-               func f17(b []byte, i int, v uint16) {
-                       binary.BigEndian.PutUint16(b[i:], v)
-               }
-               `,
-               pos: []string{"\tROLW\t\\$8,"},
-       },
        // Structure zeroing.  See issue #18370.
        {
                fn: `
@@ -1336,23 +1159,6 @@ var linuxAMD64Tests = []*asmTest{
 }
 
 var linux386Tests = []*asmTest{
-       {
-               fn: `
-               func f0(b []byte) uint32 {
-                       return binary.LittleEndian.Uint32(b)
-               }
-               `,
-               pos: []string{"\tMOVL\t\\(.*\\),"},
-       },
-       {
-               fn: `
-               func f1(b []byte, i int) uint32 {
-                       return binary.LittleEndian.Uint32(b[i:])
-               }
-               `,
-               pos: []string{"\tMOVL\t\\(.*\\)\\(.*\\*1\\),"},
-       },
-
        // multiplication by powers of two
        {
                fn: `
@@ -1497,70 +1303,6 @@ var linux386Tests = []*asmTest{
 }
 
 var linuxS390XTests = []*asmTest{
-       {
-               fn: `
-               func f0(b []byte) uint32 {
-                       return binary.LittleEndian.Uint32(b)
-               }
-               `,
-               pos: []string{"\tMOVWBR\t\\(.*\\),"},
-       },
-       {
-               fn: `
-               func f1(b []byte, i int) uint32 {
-                       return binary.LittleEndian.Uint32(b[i:])
-               }
-               `,
-               pos: []string{"\tMOVWBR\t\\(.*\\)\\(.*\\*1\\),"},
-       },
-       {
-               fn: `
-               func f2(b []byte) uint64 {
-                       return binary.LittleEndian.Uint64(b)
-               }
-               `,
-               pos: []string{"\tMOVDBR\t\\(.*\\),"},
-       },
-       {
-               fn: `
-               func f3(b []byte, i int) uint64 {
-                       return binary.LittleEndian.Uint64(b[i:])
-               }
-               `,
-               pos: []string{"\tMOVDBR\t\\(.*\\)\\(.*\\*1\\),"},
-       },
-       {
-               fn: `
-               func f4(b []byte) uint32 {
-                       return binary.BigEndian.Uint32(b)
-               }
-               `,
-               pos: []string{"\tMOVWZ\t\\(.*\\),"},
-       },
-       {
-               fn: `
-               func f5(b []byte, i int) uint32 {
-                       return binary.BigEndian.Uint32(b[i:])
-               }
-               `,
-               pos: []string{"\tMOVWZ\t\\(.*\\)\\(.*\\*1\\),"},
-       },
-       {
-               fn: `
-               func f6(b []byte) uint64 {
-                       return binary.BigEndian.Uint64(b)
-               }
-               `,
-               pos: []string{"\tMOVD\t\\(.*\\),"},
-       },
-       {
-               fn: `
-               func f7(b []byte, i int) uint64 {
-                       return binary.BigEndian.Uint64(b[i:])
-               }
-               `,
-               pos: []string{"\tMOVD\t\\(.*\\)\\(.*\\*1\\),"},
-       },
        {
                fn: `
                func f8(x uint64) uint64 {
@@ -2388,70 +2130,6 @@ var linuxARM64Tests = []*asmTest{
                pos: []string{"\tVCNT\t", "\tVUADDLV\t"},
        },
        // Load-combining tests.
-       {
-               fn: `
-               func $(b []byte) uint64 {
-                       return binary.LittleEndian.Uint64(b)
-               }
-               `,
-               pos: []string{"\tMOVD\t\\(R[0-9]+\\)"},
-       },
-       {
-               fn: `
-               func $(b []byte, i int) uint64 {
-                       return binary.LittleEndian.Uint64(b[i:])
-               }
-               `,
-               pos: []string{"\tMOVD\t\\(R[0-9]+\\)"},
-       },
-       {
-               fn: `
-               func $(b []byte) uint32 {
-                       return binary.LittleEndian.Uint32(b)
-               }
-               `,
-               pos: []string{"\tMOVWU\t\\(R[0-9]+\\)"},
-       },
-       {
-               fn: `
-               func $(b []byte, i int) uint32 {
-                       return binary.LittleEndian.Uint32(b[i:])
-               }
-               `,
-               pos: []string{"\tMOVWU\t\\(R[0-9]+\\)"},
-       },
-       {
-               fn: `
-               func $(b []byte) uint64 {
-                       return binary.BigEndian.Uint64(b)
-               }
-               `,
-               pos: []string{"\tREV\t"},
-       },
-       {
-               fn: `
-               func $(b []byte, i int) uint64 {
-                       return binary.BigEndian.Uint64(b[i:])
-               }
-               `,
-               pos: []string{"\tREV\t"},
-       },
-       {
-               fn: `
-               func $(b []byte) uint32 {
-                       return binary.BigEndian.Uint32(b)
-               }
-               `,
-               pos: []string{"\tREVW\t"},
-       },
-       {
-               fn: `
-               func $(b []byte, i int) uint32 {
-                       return binary.BigEndian.Uint32(b[i:])
-               }
-               `,
-               pos: []string{"\tREVW\t"},
-       },
        {
                fn: `
                func $(s []byte) uint16 {
@@ -2759,61 +2437,6 @@ var linuxARM64Tests = []*asmTest{
                pos: []string{"STP"},
                neg: []string{"MOVB", "MOVH", "MOVW"},
        },
-       // Check that stores are combine into larger stores
-       {
-               fn: `
-               func $(b []byte, v uint16) {
-                       binary.LittleEndian.PutUint16(b, v)
-               }
-               `,
-               pos: []string{"MOVH"},
-               neg: []string{"MOVB"},
-       },
-       {
-               fn: `
-               func $(b []byte, v uint32) {
-                       binary.LittleEndian.PutUint32(b, v)
-               }
-               `,
-               pos: []string{"MOVW"},
-               neg: []string{"MOVB", "MOVH"},
-       },
-       {
-               fn: `
-               func $(b []byte, v uint64) {
-                       binary.LittleEndian.PutUint64(b, v)
-               }
-               `,
-               pos: []string{"MOVD"},
-               neg: []string{"MOVB", "MOVH", "MOVW"},
-       },
-       {
-               fn: `
-               func $(b []byte, v uint16) {
-                       binary.BigEndian.PutUint16(b, v)
-               }
-               `,
-               pos: []string{"MOVH"},
-               neg: []string{"MOVB"},
-       },
-       {
-               fn: `
-               func $(b []byte, v uint32) {
-                       binary.BigEndian.PutUint32(b, v)
-               }
-               `,
-               pos: []string{"MOVW"},
-               neg: []string{"MOVB", "MOVH"},
-       },
-       {
-               fn: `
-               func $(b []byte, v uint64) {
-                       binary.BigEndian.PutUint64(b, v)
-               }
-               `,
-               pos: []string{"MOVD"},
-               neg: []string{"MOVB", "MOVH", "MOVW"},
-       },
 }
 
 var linuxMIPSTests = []*asmTest{
@@ -3058,61 +2681,6 @@ var linuxPPC64LETests = []*asmTest{
                pos: []string{"\tFABS\t"},
        },
 
-       {
-               fn: `
-               func f14(b []byte) uint16 {
-                       return binary.LittleEndian.Uint16(b)
-       }
-               `,
-               pos: []string{"\tMOVHZ\t"},
-       },
-       {
-               fn: `
-               func f15(b []byte) uint32 {
-                       return binary.LittleEndian.Uint32(b)
-               }
-               `,
-               pos: []string{"\tMOVWZ\t"},
-       },
-
-       {
-               fn: `
-               func f16(b []byte) uint64 {
-                       return binary.LittleEndian.Uint64(b)
-               }
-               `,
-               pos: []string{"\tMOVD\t"},
-               neg: []string{"MOVBZ", "MOVHZ", "MOVWZ"},
-       },
-
-       {
-               fn: `
-               func f17(b []byte, v uint16) {
-                       binary.LittleEndian.PutUint16(b, v)
-               }
-               `,
-               pos: []string{"\tMOVH\t"},
-       },
-
-       {
-               fn: `
-               func f18(b []byte, v uint32) {
-                       binary.LittleEndian.PutUint32(b, v)
-               }
-               `,
-               pos: []string{"\tMOVW\t"},
-       },
-
-       {
-               fn: `
-               func f19(b []byte, v uint64) {
-                       binary.LittleEndian.PutUint64(b, v)
-               }
-               `,
-               pos: []string{"\tMOVD\t"},
-               neg: []string{"MOVB", "MOVH", "MOVW"},
-       },
-
        {
                // check that stack store is optimized away
                fn: `
diff --git a/test/codegen/memcombine.go b/test/codegen/memcombine.go
new file mode 100644 (file)
index 0000000..d08fabf
--- /dev/null
@@ -0,0 +1,173 @@
+// asmcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package codegen
+
+import "encoding/binary"
+
+var sink64 uint64
+var sink32 uint32
+var sink16 uint16
+
+func load_le64(b []byte) {
+       // amd64:`MOVQ\s\(.*\),`
+       // s390x:`MOVDBR\s\(.*\),`
+       // arm64:`MOVD\s\(R[0-9]+\),`
+       // ppc64le:`MOVD\s`,-`MOV[BHW]Z`
+       sink64 = binary.LittleEndian.Uint64(b)
+}
+
+func load_le64_idx(b []byte, idx int) {
+       // amd64:`MOVQ\s\(.*\)\(.*\*1\),`
+       // s390x:`MOVDBR\s\(.*\)\(.*\*1\),`
+       // arm64:`MOVD\s\(R[0-9]+\),`
+       // ppc64le:`MOVD\s`,-`MOV[BHW]Z\s`
+       sink64 = binary.LittleEndian.Uint64(b[idx:])
+}
+
+func load_le32(b []byte) {
+       // amd64:`MOVL\s\(.*\),`           386:`MOVL\s\(.*\),`
+       // s390x:`MOVWBR\s\(.*\),`
+       // arm64:`MOVWU\s\(R[0-9]+\),`
+       // ppc64le:`MOVWZ\s`
+       sink32 = binary.LittleEndian.Uint32(b)
+}
+
+func load_le32_idx(b []byte, idx int) {
+       // amd64:`MOVL\s\(.*\)\(.*\*1\),`  386:`MOVL\s\(.*\)\(.*\*1\),`
+       // s390x:`MOVWBR\s\(.*\)\(.*\*1\),`
+       // arm64:`MOVWU\s\(R[0-9]+\),`
+       // ppc64le:`MOVWZ\s`
+       sink32 = binary.LittleEndian.Uint32(b[idx:])
+}
+
+func load_le16(b []byte) {
+       // amd64:`MOVWLZX\s\(.*\),`
+       // ppc64le:`MOVHZ\s`
+       sink16 = binary.LittleEndian.Uint16(b)
+}
+
+func load_le16_idx(b []byte, idx int) {
+       // amd64:`MOVWLZX\s\(.*\),`
+       // ppc64le:`MOVHZ\s`
+       sink16 = binary.LittleEndian.Uint16(b[idx:])
+}
+
+func load_be64(b []byte) {
+       // amd64:`BSWAPQ`
+       // s390x:`MOVD\s\(.*\),`
+       // arm64:`REV`
+       sink64 = binary.BigEndian.Uint64(b)
+}
+
+func load_be64_idx(b []byte, idx int) {
+       // amd64:`BSWAPQ`
+       // s390x:`MOVD\s\(.*\)\(.*\*1\),`
+       // arm64:`REV`
+       sink64 = binary.BigEndian.Uint64(b[idx:])
+}
+
+func load_be32(b []byte) {
+       // amd64:`BSWAPL`
+       // s390x:`MOVWZ\s\(.*\),`
+       // arm64:`REVW`
+       sink32 = binary.BigEndian.Uint32(b)
+}
+
+func load_be32_idx(b []byte, idx int) {
+       // amd64:`BSWAPL`
+       // s390x:`MOVWZ\s\(.*\)\(.*\*1\),`
+       // arm64:`REVW`
+       sink32 = binary.BigEndian.Uint32(b[idx:])
+}
+
+func load_be16(b []byte) {
+       // amd64:`ROLW\s\$8`
+       sink16 = binary.BigEndian.Uint16(b)
+}
+
+func load_be16_idx(b []byte, idx int) {
+       // amd64:`ROLW\s\$8`
+       sink16 = binary.BigEndian.Uint16(b[idx:])
+}
+
+func store_le64(b []byte) {
+       // amd64:`MOVQ\s.*\(.*\)$`,-`SHR.`
+       // arm64:`MOVD`,-`MOV[WBH]`
+       // ppc64le:`MOVD\s`,-`MOV[BHW]\s`
+       binary.LittleEndian.PutUint64(b, sink64)
+}
+
+func store_le64_idx(b []byte, idx int) {
+       // amd64:`MOVQ\s.*\(.*\)\(.*\*1\)$`,-`SHR.`
+       // arm64:`MOVD`,-`MOV[WBH]`
+       // ppc64le:`MOVD\s`,-`MOV[BHW]\s`
+       binary.LittleEndian.PutUint64(b[idx:], sink64)
+}
+
+func store_le32(b []byte) {
+       // amd64:`MOVL\s`
+       // arm64(DISABLED):`MOVW`,-`MOV[BH]`
+       // ppc64le:`MOVW\s`
+       binary.LittleEndian.PutUint32(b, sink32)
+}
+
+func store_le32_idx(b []byte, idx int) {
+       // amd64:`MOVL\s`
+       // arm64(DISABLED):`MOVW`,-`MOV[BH]`
+       // ppc64le:`MOVW\s`
+       binary.LittleEndian.PutUint32(b[idx:], sink32)
+}
+
+func store_le16(b []byte) {
+       // amd64:`MOVW\s`
+       // arm64(DISABLED):`MOVH`,-`MOVB`
+       // ppc64le(DISABLED):`MOVH\s`
+       binary.LittleEndian.PutUint16(b, sink16)
+}
+
+func store_le16_idx(b []byte, idx int) {
+       // amd64:`MOVW\s`
+       // arm64(DISABLED):`MOVH`,-`MOVB`
+       // ppc64le(DISABLED):`MOVH\s`
+       binary.LittleEndian.PutUint16(b[idx:], sink16)
+}
+
+func store_be64(b []byte) {
+       // amd64:`BSWAPQ`,-`SHR.`
+       // arm64:`MOVD`,`REV`,-`MOV[WBH]`
+       binary.BigEndian.PutUint64(b, sink64)
+}
+
+func store_be64_idx(b []byte, idx int) {
+       // amd64:`BSWAPQ`,-`SHR.`
+       // arm64:`MOVD`,`REV`,-`MOV[WBH]`
+       binary.BigEndian.PutUint64(b[idx:], sink64)
+}
+
+func store_be32(b []byte) {
+       // amd64:`BSWAPL`,-`SHR.`
+       // arm64(DISABLED):`MOVW`,`REVW`,-`MOV[BH]`
+       binary.BigEndian.PutUint32(b, sink32)
+}
+
+func store_be32_idx(b []byte, idx int) {
+       // amd64:`BSWAPL`,-`SHR.`
+       // arm64(DISABLED):`MOVW`,`REVW`,-`MOV[BH]`
+       binary.BigEndian.PutUint32(b[idx:], sink32)
+}
+
+func store_be16(b []byte) {
+       // amd64:`ROLW\s\$8`,-`SHR.`
+       // arm64(DISABLED):`MOVH`,`REV16W`,-`MOVB`
+       binary.BigEndian.PutUint16(b, sink16)
+}
+
+func store_be16_idx(b []byte, idx int) {
+       // amd64:`ROLW\s\$8`,-`SHR.`
+       // arm64(DISABLED):`MOVH`,`REV16W`,-`MOVB`
+       binary.BigEndian.PutUint16(b[idx:], sink16)
+}