From: Giovanni Bajo Date: Sat, 3 Mar 2018 15:00:43 +0000 (+0100) Subject: test: move load/store combines into asmcheck X-Git-Tag: go1.11beta1~1355 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=fad31e513d721a36f2d881d99de54def805a8648;p=gostls13.git test: move load/store combines into asmcheck 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 TryBot-Result: Gobot Gobot Reviewed-by: Keith Randall --- diff --git a/src/cmd/compile/internal/gc/asm_test.go b/src/cmd/compile/internal/gc/asm_test.go index 0919eab307..b9180dafcb 100644 --- a/src/cmd/compile/internal/gc/asm_test.go +++ b/src/cmd/compile/internal/gc/asm_test.go @@ -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 index 0000000000..d08fabf846 --- /dev/null +++ b/test/codegen/memcombine.go @@ -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) +}