// TestAssembly checks to make sure the assembly generated for
// functions contains certain expected instructions.
func TestAssembly(t *testing.T) {
- if testing.Short() {
- t.Skip("slow test; skipping")
- }
testenv.MustHaveGoBuild(t)
if runtime.GOOS == "windows" {
// TODO: remove if we can get "go tool compile -S" to work on windows.
}
defer os.RemoveAll(dir)
- for _, test := range asmTests {
- asm := compileToAsm(t, dir, test.arch, test.os, fmt.Sprintf(template, test.function))
- // Get rid of code for "".init. Also gets rid of type algorithms & other junk.
- if i := strings.Index(asm, "\n\"\".init "); i >= 0 {
- asm = asm[:i+1]
+ t.Run("platform", func(t *testing.T) {
+ for _, ats := range allAsmTests {
+ ats := ats
+ t.Run(ats.os+"/"+ats.arch, func(tt *testing.T) {
+ tt.Parallel()
+
+ asm := ats.compileToAsm(tt, dir)
+
+ for i, at := range ats.tests {
+ fa := funcAsm(asm, i)
+
+ at.verifyAsm(tt, fa)
+ }
+ })
}
- for _, r := range test.regexps {
- if b, err := regexp.MatchString(r, asm); !b || err != nil {
- t.Errorf("%s/%s: expected:%s\ngo:%s\nasm:%s\n", test.os, test.arch, r, test.function, asm)
- }
+ })
+}
+
+// funcAsm returns the assembly listing for f{funcIndex}
+func funcAsm(asm string, funcIndex int) string {
+ if i := strings.Index(asm, fmt.Sprintf("TEXT\t\"\".f%d(SB)", funcIndex)); i >= 0 {
+ asm = asm[i:]
+ }
+
+ if i := strings.Index(asm, fmt.Sprintf("TEXT\t\"\".f%d(SB)", funcIndex+1)); i >= 0 {
+ asm = asm[:i+1]
+ }
+
+ return asm
+}
+
+type asmTest struct {
+ // function to compile, must be named fX,
+ // where X is this test's index in asmTests.tests.
+ function string
+ // regexps that must match the generated assembly
+ regexps []string
+}
+
+func (at asmTest) verifyAsm(t *testing.T, fa string) {
+ for _, r := range at.regexps {
+ if b, err := regexp.MatchString(r, fa); !b || err != nil {
+ t.Errorf("expected:%s\ngo:%s\nasm:%s\n", r, at.function, fa)
}
}
}
+type asmTests struct {
+ arch string
+ os string
+ imports []string
+ tests []*asmTest
+}
+
+func (ats *asmTests) generateCode() []byte {
+ var buf bytes.Buffer
+ fmt.Fprintln(&buf, "package main")
+ for _, s := range ats.imports {
+ fmt.Fprintf(&buf, "import %q\n", s)
+ }
+
+ for _, t := range ats.tests {
+ fmt.Fprintln(&buf, t.function)
+ }
+
+ return buf.Bytes()
+}
+
// compile compiles the package pkg for architecture arch and
// returns the generated assembly. dir is a scratch directory.
-func compileToAsm(t *testing.T, dir, goarch, goos, pkg string) string {
+func (ats *asmTests) compileToAsm(t *testing.T, dir string) string {
+ // create test directory
+ testDir := filepath.Join(dir, fmt.Sprintf("%s_%s", ats.arch, ats.os))
+ err := os.Mkdir(testDir, 0700)
+ if err != nil {
+ t.Fatalf("could not create directory: %v", err)
+ }
+
// Create source.
- src := filepath.Join(dir, "test.go")
- f, err := os.Create(src)
+ src := filepath.Join(testDir, "test.go")
+ err = ioutil.WriteFile(src, ats.generateCode(), 0600)
if err != nil {
- panic(err)
+ t.Fatalf("error writing code: %v", err)
}
- f.Write([]byte(pkg))
- f.Close()
// First, install any dependencies we need. This builds the required export data
// for any packages that are imported.
- // TODO: extract dependencies automatically?
- var stdout, stderr bytes.Buffer
- cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", filepath.Join(dir, "encoding/binary.a"), "encoding/binary")
- cmd.Env = mergeEnvLists([]string{"GOARCH=" + goarch, "GOOS=" + goos}, os.Environ())
- cmd.Stdout = &stdout
- cmd.Stderr = &stderr
- if err := cmd.Run(); err != nil {
- panic(err)
- }
- if s := stdout.String(); s != "" {
- panic(fmt.Errorf("Stdout = %s\nWant empty", s))
- }
- if s := stderr.String(); s != "" {
- panic(fmt.Errorf("Stderr = %s\nWant empty", s))
+ for _, i := range ats.imports {
+ out := filepath.Join(testDir, i+".a")
+
+ if s := ats.runGo(t, "build", "-o", out, "-gcflags=-dolinkobj", i); s != "" {
+ t.Fatalf("Stdout = %s\nWant empty", s)
+ }
}
// Now, compile the individual file for which we want to see the generated assembly.
- cmd = exec.Command(testenv.GoToolPath(t), "tool", "compile", "-I", dir, "-S", "-o", filepath.Join(dir, "out.o"), src)
- cmd.Env = mergeEnvLists([]string{"GOARCH=" + goarch, "GOOS=" + goos}, os.Environ())
+ asm := ats.runGo(t, "tool", "compile", "-I", testDir, "-S", "-o", filepath.Join(testDir, "out.o"), src)
+
+ // Get rid of code for "".init. Also gets rid of type algorithms & other junk.
+ if i := strings.Index(asm, "\n\"\".init "); i >= 0 {
+ asm = asm[:i+1]
+ }
+
+ return asm
+}
+
+// runGo runs go command with the given args and returns stdout string.
+// go is run with GOARCH and GOOS set as ats.arch and ats.os respectively
+func (ats *asmTests) runGo(t *testing.T, args ...string) string {
+ var stdout, stderr bytes.Buffer
+ cmd := exec.Command(testenv.GoToolPath(t), args...)
+ cmd.Env = mergeEnvLists([]string{"GOARCH=" + ats.arch, "GOOS=" + ats.os}, os.Environ())
cmd.Stdout = &stdout
cmd.Stderr = &stderr
+
if err := cmd.Run(); err != nil {
- panic(err)
+ t.Fatalf("error running cmd: %v", err)
}
+
if s := stderr.String(); s != "" {
- panic(fmt.Errorf("Stderr = %s\nWant empty", s))
+ t.Fatalf("Stderr = %s\nWant empty", s)
}
+
return stdout.String()
}
-// template to convert a function to a full file
-const template = `
-package main
-%s
-`
-
-type asmTest struct {
- // architecture to compile to
- arch string
- // os to compile to
- os string
- // function to compile
- function string
- // regexps that must match the generated assembly
- regexps []string
+var allAsmTests = []*asmTests{
+ {
+ arch: "amd64",
+ os: "linux",
+ imports: []string{"encoding/binary"},
+ tests: linuxAMD64Tests,
+ },
+ {
+ arch: "386",
+ os: "linux",
+ imports: []string{"encoding/binary"},
+ tests: linux386Tests,
+ },
+ {
+ arch: "s390x",
+ os: "linux",
+ imports: []string{"encoding/binary"},
+ tests: linuxS390XTests,
+ },
+ {
+ arch: "arm",
+ os: "linux",
+ tests: linuxARMTests,
+ },
+ {
+ arch: "arm64",
+ os: "linux",
+ tests: linuxARM64Tests,
+ },
}
-var asmTests = [...]asmTest{
- {"amd64", "linux", `
-func f(x int) int {
- return x * 64
-}
-`,
+var linuxAMD64Tests = []*asmTest{
+ {
+ `
+ func f0(x int) int {
+ return x * 64
+ }
+ `,
[]string{"\tSHLQ\t\\$6,"},
},
- {"amd64", "linux", `
-func f(x int) int {
- return x * 96
-}`,
+ {
+ `
+ func f1(x int) int {
+ return x * 96
+ }
+ `,
[]string{"\tSHLQ\t\\$5,", "\tLEAQ\t\\(.*\\)\\(.*\\*2\\),"},
},
// Load-combining tests.
- {"amd64", "linux", `
-import "encoding/binary"
-func f(b []byte) uint64 {
- return binary.LittleEndian.Uint64(b)
-}
-`,
+ {
+ `
+ func f2(b []byte) uint64 {
+ return binary.LittleEndian.Uint64(b)
+ }
+ `,
[]string{"\tMOVQ\t\\(.*\\),"},
},
- {"amd64", "linux", `
-import "encoding/binary"
-func f(b []byte, i int) uint64 {
- return binary.LittleEndian.Uint64(b[i:])
-}
-`,
+ {
+ `
+ func f3(b []byte, i int) uint64 {
+ return binary.LittleEndian.Uint64(b[i:])
+ }
+ `,
[]string{"\tMOVQ\t\\(.*\\)\\(.*\\*1\\),"},
},
- {"amd64", "linux", `
-import "encoding/binary"
-func f(b []byte) uint32 {
- return binary.LittleEndian.Uint32(b)
-}
-`,
+ {
+ `
+ func f4(b []byte) uint32 {
+ return binary.LittleEndian.Uint32(b)
+ }
+ `,
[]string{"\tMOVL\t\\(.*\\),"},
},
- {"amd64", "linux", `
-import "encoding/binary"
-func f(b []byte, i int) uint32 {
- return binary.LittleEndian.Uint32(b[i:])
-}
-`,
+ {
+ `
+ func f5(b []byte, i int) uint32 {
+ return binary.LittleEndian.Uint32(b[i:])
+ }
+ `,
[]string{"\tMOVL\t\\(.*\\)\\(.*\\*1\\),"},
},
- {"amd64", "linux", `
-import "encoding/binary"
-func f(b []byte) uint64 {
- return binary.BigEndian.Uint64(b)
-}
-`,
+ {
+ `
+ func f6(b []byte) uint64 {
+ return binary.BigEndian.Uint64(b)
+ }
+ `,
[]string{"\tBSWAPQ\t"},
},
- {"amd64", "linux", `
-import "encoding/binary"
-func f(b []byte, i int) uint64 {
- return binary.BigEndian.Uint64(b[i:])
-}
-`,
+ {
+ `
+ func f7(b []byte, i int) uint64 {
+ return binary.BigEndian.Uint64(b[i:])
+ }
+ `,
[]string{"\tBSWAPQ\t"},
},
- {"amd64", "linux", `
-import "encoding/binary"
-func f(b []byte, v uint64) {
- binary.BigEndian.PutUint64(b, v)
-}
-`,
+ {
+ `
+ func f8(b []byte, v uint64) {
+ binary.BigEndian.PutUint64(b, v)
+ }
+ `,
[]string{"\tBSWAPQ\t"},
},
- {"amd64", "linux", `
-import "encoding/binary"
-func f(b []byte, i int, v uint64) {
- binary.BigEndian.PutUint64(b[i:], v)
-}
-`,
+ {
+ `
+ func f9(b []byte, i int, v uint64) {
+ binary.BigEndian.PutUint64(b[i:], v)
+ }
+ `,
[]string{"\tBSWAPQ\t"},
},
- {"amd64", "linux", `
-import "encoding/binary"
-func f(b []byte) uint32 {
- return binary.BigEndian.Uint32(b)
-}
-`,
+ {
+ `
+ func f10(b []byte) uint32 {
+ return binary.BigEndian.Uint32(b)
+ }
+ `,
[]string{"\tBSWAPL\t"},
},
- {"amd64", "linux", `
-import "encoding/binary"
-func f(b []byte, i int) uint32 {
- return binary.BigEndian.Uint32(b[i:])
-}
-`,
+ {
+ `
+ func f11(b []byte, i int) uint32 {
+ return binary.BigEndian.Uint32(b[i:])
+ }
+ `,
[]string{"\tBSWAPL\t"},
},
- {"amd64", "linux", `
-import "encoding/binary"
-func f(b []byte, v uint32) {
- binary.BigEndian.PutUint32(b, v)
-}
-`,
+ {
+ `
+ func f12(b []byte, v uint32) {
+ binary.BigEndian.PutUint32(b, v)
+ }
+ `,
[]string{"\tBSWAPL\t"},
},
- {"amd64", "linux", `
-import "encoding/binary"
-func f(b []byte, i int, v uint32) {
- binary.BigEndian.PutUint32(b[i:], v)
-}
-`,
+ {
+ `
+ func f13(b []byte, i int, v uint32) {
+ binary.BigEndian.PutUint32(b[i:], v)
+ }
+ `,
[]string{"\tBSWAPL\t"},
},
- {"amd64", "linux", `
-import "encoding/binary"
-func f(b []byte) uint16 {
- return binary.BigEndian.Uint16(b)
-}
-`,
+ {
+ `
+ func f14(b []byte) uint16 {
+ return binary.BigEndian.Uint16(b)
+ }
+ `,
[]string{"\tROLW\t\\$8,"},
},
- {"amd64", "linux", `
-import "encoding/binary"
-func f(b []byte, i int) uint16 {
- return binary.BigEndian.Uint16(b[i:])
-}
-`,
+ {
+ `
+ func f15(b []byte, i int) uint16 {
+ return binary.BigEndian.Uint16(b[i:])
+ }
+ `,
[]string{"\tROLW\t\\$8,"},
},
- {"amd64", "linux", `
-import "encoding/binary"
-func f(b []byte, v uint16) {
- binary.BigEndian.PutUint16(b, v)
-}
-`,
+ {
+ `
+ func f16(b []byte, v uint16) {
+ binary.BigEndian.PutUint16(b, v)
+ }
+ `,
[]string{"\tROLW\t\\$8,"},
},
- {"amd64", "linux", `
-import "encoding/binary"
-func f(b []byte, i int, v uint16) {
- binary.BigEndian.PutUint16(b[i:], v)
-}
-`,
+ {
+ `
+ func f17(b []byte, i int, v uint16) {
+ binary.BigEndian.PutUint16(b[i:], v)
+ }
+ `,
[]string{"\tROLW\t\\$8,"},
},
- {"386", "linux", `
-import "encoding/binary"
-func f(b []byte) uint32 {
- return binary.LittleEndian.Uint32(b)
-}
-`,
- []string{"\tMOVL\t\\(.*\\),"},
- },
- {"386", "linux", `
-import "encoding/binary"
-func f(b []byte, i int) uint32 {
- return binary.LittleEndian.Uint32(b[i:])
-}
-`,
- []string{"\tMOVL\t\\(.*\\)\\(.*\\*1\\),"},
- },
- {"s390x", "linux", `
-import "encoding/binary"
-func f(b []byte) uint32 {
- return binary.LittleEndian.Uint32(b)
-}
-`,
- []string{"\tMOVWBR\t\\(.*\\),"},
- },
- {"s390x", "linux", `
-import "encoding/binary"
-func f(b []byte, i int) uint32 {
- return binary.LittleEndian.Uint32(b[i:])
-}
-`,
- []string{"\tMOVWBR\t\\(.*\\)\\(.*\\*1\\),"},
- },
- {"s390x", "linux", `
-import "encoding/binary"
-func f(b []byte) uint64 {
- return binary.LittleEndian.Uint64(b)
-}
-`,
- []string{"\tMOVDBR\t\\(.*\\),"},
- },
- {"s390x", "linux", `
-import "encoding/binary"
-func f(b []byte, i int) uint64 {
- return binary.LittleEndian.Uint64(b[i:])
-}
-`,
- []string{"\tMOVDBR\t\\(.*\\)\\(.*\\*1\\),"},
- },
- {"s390x", "linux", `
-import "encoding/binary"
-func f(b []byte) uint32 {
- return binary.BigEndian.Uint32(b)
-}
-`,
- []string{"\tMOVWZ\t\\(.*\\),"},
- },
- {"s390x", "linux", `
-import "encoding/binary"
-func f(b []byte, i int) uint32 {
- return binary.BigEndian.Uint32(b[i:])
-}
-`,
- []string{"\tMOVWZ\t\\(.*\\)\\(.*\\*1\\),"},
- },
- {"s390x", "linux", `
-import "encoding/binary"
-func f(b []byte) uint64 {
- return binary.BigEndian.Uint64(b)
-}
-`,
- []string{"\tMOVD\t\\(.*\\),"},
- },
- {"s390x", "linux", `
-import "encoding/binary"
-func f(b []byte, i int) uint64 {
- return binary.BigEndian.Uint64(b[i:])
-}
-`,
- []string{"\tMOVD\t\\(.*\\)\\(.*\\*1\\),"},
- },
-
// Structure zeroing. See issue #18370.
- {"amd64", "linux", `
-type T struct {
- a, b, c int
-}
-func f(t *T) {
- *t = T{}
-}
-`,
+ {
+ `
+ type T1 struct {
+ a, b, c int
+ }
+ func f18(t *T1) {
+ *t = T1{}
+ }
+ `,
[]string{"\tMOVQ\t\\$0, \\(.*\\)", "\tMOVQ\t\\$0, 8\\(.*\\)", "\tMOVQ\t\\$0, 16\\(.*\\)"},
},
// TODO: add a test for *t = T{3,4,5} when we fix that.
// Also test struct containing pointers (this was special because of write barriers).
- {"amd64", "linux", `
-type T struct {
- a, b, c *int
-}
-func f(t *T) {
- *t = T{}
-}
-`,
+ {
+ `
+ type T2 struct {
+ a, b, c *int
+ }
+ func f19(t *T2) {
+ *t = T2{}
+ }
+ `,
[]string{"\tMOVQ\t\\$0, \\(.*\\)", "\tMOVQ\t\\$0, 8\\(.*\\)", "\tMOVQ\t\\$0, 16\\(.*\\)", "\tCALL\truntime\\.writebarrierptr\\(SB\\)"},
},
-
// Rotate tests
- {"amd64", "linux", `
- func f(x uint64) uint64 {
- return x<<7 | x>>57
- }
-`,
+ {
+ `
+ func f20(x uint64) uint64 {
+ return x<<7 | x>>57
+ }
+ `,
[]string{"\tROLQ\t[$]7,"},
},
- {"amd64", "linux", `
- func f(x uint64) uint64 {
- return x<<7 + x>>57
- }
-`,
+ {
+ `
+ func f21(x uint64) uint64 {
+ return x<<7 + x>>57
+ }
+ `,
[]string{"\tROLQ\t[$]7,"},
},
- {"amd64", "linux", `
- func f(x uint64) uint64 {
- return x<<7 ^ x>>57
- }
-`,
+ {
+ `
+ func f22(x uint64) uint64 {
+ return x<<7 ^ x>>57
+ }
+ `,
[]string{"\tROLQ\t[$]7,"},
},
- {"amd64", "linux", `
- func f(x uint32) uint32 {
- return x<<7 + x>>25
- }
-`,
+ {
+ `
+ func f23(x uint32) uint32 {
+ return x<<7 + x>>25
+ }
+ `,
[]string{"\tROLL\t[$]7,"},
},
- {"amd64", "linux", `
- func f(x uint32) uint32 {
- return x<<7 | x>>25
- }
-`,
+ {
+ `
+ func f24(x uint32) uint32 {
+ return x<<7 | x>>25
+ }
+ `,
[]string{"\tROLL\t[$]7,"},
},
- {"amd64", "linux", `
- func f(x uint32) uint32 {
- return x<<7 ^ x>>25
- }
-`,
+ {
+ `
+ func f25(x uint32) uint32 {
+ return x<<7 ^ x>>25
+ }
+ `,
[]string{"\tROLL\t[$]7,"},
},
- {"amd64", "linux", `
- func f(x uint16) uint16 {
- return x<<7 + x>>9
- }
-`,
+ {
+ `
+ func f26(x uint16) uint16 {
+ return x<<7 + x>>9
+ }
+ `,
[]string{"\tROLW\t[$]7,"},
},
- {"amd64", "linux", `
- func f(x uint16) uint16 {
- return x<<7 | x>>9
- }
-`,
+ {
+ `
+ func f27(x uint16) uint16 {
+ return x<<7 | x>>9
+ }
+ `,
[]string{"\tROLW\t[$]7,"},
},
- {"amd64", "linux", `
- func f(x uint16) uint16 {
- return x<<7 ^ x>>9
- }
-`,
+ {
+ `
+ func f28(x uint16) uint16 {
+ return x<<7 ^ x>>9
+ }
+ `,
[]string{"\tROLW\t[$]7,"},
},
- {"amd64", "linux", `
- func f(x uint8) uint8 {
- return x<<7 + x>>1
- }
-`,
+ {
+ `
+ func f29(x uint8) uint8 {
+ return x<<7 + x>>1
+ }
+ `,
[]string{"\tROLB\t[$]7,"},
},
- {"amd64", "linux", `
- func f(x uint8) uint8 {
- return x<<7 | x>>1
- }
-`,
+ {
+ `
+ func f30(x uint8) uint8 {
+ return x<<7 | x>>1
+ }
+ `,
[]string{"\tROLB\t[$]7,"},
},
- {"amd64", "linux", `
- func f(x uint8) uint8 {
- return x<<7 ^ x>>1
- }
-`,
+ {
+ `
+ func f31(x uint8) uint8 {
+ return x<<7 ^ x>>1
+ }
+ `,
[]string{"\tROLB\t[$]7,"},
},
-
- {"arm", "linux", `
- func f(x uint32) uint32 {
- return x<<7 + x>>25
- }
-`,
- []string{"\tMOVW\tR[0-9]+@>25,"},
+ // Rotate after inlining (see issue 18254).
+ {
+ `
+ func g(x uint32, k uint) uint32 {
+ return x<<k | x>>(32-k)
+ }
+ func f32(x uint32) uint32 {
+ return g(x, 7)
+ }
+ `,
+ []string{"\tROLL\t[$]7,"},
},
- {"arm", "linux", `
- func f(x uint32) uint32 {
- return x<<7 | x>>25
- }
-`,
- []string{"\tMOVW\tR[0-9]+@>25,"},
+ {
+ `
+ func f33(m map[int]int) int {
+ return m[5]
+ }
+ `,
+ []string{"\tMOVQ\t[$]5,"},
},
- {"arm", "linux", `
- func f(x uint32) uint32 {
- return x<<7 ^ x>>25
- }
-`,
- []string{"\tMOVW\tR[0-9]+@>25,"},
+ // Direct use of constants in fast map access calls. Issue 19015.
+ {
+ `
+ func f34(m map[int]int) bool {
+ _, ok := m[5]
+ return ok
+ }
+ `,
+ []string{"\tMOVQ\t[$]5,"},
},
+ {
+ `
+ func f35(m map[string]int) int {
+ return m["abc"]
+ }
+ `,
+ []string{"\"abc\""},
+ },
+ {
+ `
+ func f36(m map[string]int) bool {
+ _, ok := m["abc"]
+ return ok
+ }
+ `,
+ []string{"\"abc\""},
+ },
+}
- {"arm64", "linux", `
- func f(x uint64) uint64 {
- return x<<7 + x>>57
- }
-`,
- []string{"\tROR\t[$]57,"},
+var linux386Tests = []*asmTest{
+ {
+ `
+ func f0(b []byte) uint32 {
+ return binary.LittleEndian.Uint32(b)
+ }
+ `,
+ []string{"\tMOVL\t\\(.*\\),"},
},
- {"arm64", "linux", `
- func f(x uint64) uint64 {
- return x<<7 | x>>57
- }
-`,
- []string{"\tROR\t[$]57,"},
+ {
+ `
+ func f1(b []byte, i int) uint32 {
+ return binary.LittleEndian.Uint32(b[i:])
+ }
+ `,
+ []string{"\tMOVL\t\\(.*\\)\\(.*\\*1\\),"},
},
- {"arm64", "linux", `
- func f(x uint64) uint64 {
- return x<<7 ^ x>>57
- }
-`,
- []string{"\tROR\t[$]57,"},
+}
+
+var linuxS390XTests = []*asmTest{
+ {
+ `
+ func f0(b []byte) uint32 {
+ return binary.LittleEndian.Uint32(b)
+ }
+ `,
+ []string{"\tMOVWBR\t\\(.*\\),"},
},
- {"arm64", "linux", `
- func f(x uint32) uint32 {
- return x<<7 + x>>25
- }
-`,
- []string{"\tRORW\t[$]25,"},
+ {
+ `
+ func f1(b []byte, i int) uint32 {
+ return binary.LittleEndian.Uint32(b[i:])
+ }
+ `,
+ []string{"\tMOVWBR\t\\(.*\\)\\(.*\\*1\\),"},
},
- {"arm64", "linux", `
- func f(x uint32) uint32 {
- return x<<7 | x>>25
- }
-`,
- []string{"\tRORW\t[$]25,"},
+ {
+ `
+ func f2(b []byte) uint64 {
+ return binary.LittleEndian.Uint64(b)
+ }
+ `,
+ []string{"\tMOVDBR\t\\(.*\\),"},
},
- {"arm64", "linux", `
- func f(x uint32) uint32 {
- return x<<7 ^ x>>25
- }
-`,
- []string{"\tRORW\t[$]25,"},
+ {
+ `
+ func f3(b []byte, i int) uint64 {
+ return binary.LittleEndian.Uint64(b[i:])
+ }
+ `,
+ []string{"\tMOVDBR\t\\(.*\\)\\(.*\\*1\\),"},
},
-
- {"s390x", "linux", `
- func f(x uint64) uint64 {
- return x<<7 + x>>57
- }
-`,
+ {
+ `
+ func f4(b []byte) uint32 {
+ return binary.BigEndian.Uint32(b)
+ }
+ `,
+ []string{"\tMOVWZ\t\\(.*\\),"},
+ },
+ {
+ `
+ func f5(b []byte, i int) uint32 {
+ return binary.BigEndian.Uint32(b[i:])
+ }
+ `,
+ []string{"\tMOVWZ\t\\(.*\\)\\(.*\\*1\\),"},
+ },
+ {
+ `
+ func f6(b []byte) uint64 {
+ return binary.BigEndian.Uint64(b)
+ }
+ `,
+ []string{"\tMOVD\t\\(.*\\),"},
+ },
+ {
+ `
+ func f7(b []byte, i int) uint64 {
+ return binary.BigEndian.Uint64(b[i:])
+ }
+ `,
+ []string{"\tMOVD\t\\(.*\\)\\(.*\\*1\\),"},
+ },
+ {
+ `
+ func f8(x uint64) uint64 {
+ return x<<7 + x>>57
+ }
+ `,
[]string{"\tRLLG\t[$]7,"},
},
- {"s390x", "linux", `
- func f(x uint64) uint64 {
- return x<<7 | x>>57
- }
-`,
+ {
+ `
+ func f9(x uint64) uint64 {
+ return x<<7 | x>>57
+ }
+ `,
[]string{"\tRLLG\t[$]7,"},
},
- {"s390x", "linux", `
- func f(x uint64) uint64 {
- return x<<7 ^ x>>57
- }
-`,
+ {
+ `
+ func f10(x uint64) uint64 {
+ return x<<7 ^ x>>57
+ }
+ `,
[]string{"\tRLLG\t[$]7,"},
},
- {"s390x", "linux", `
- func f(x uint32) uint32 {
- return x<<7 + x>>25
- }
-`,
+ {
+ `
+ func f11(x uint32) uint32 {
+ return x<<7 + x>>25
+ }
+ `,
[]string{"\tRLL\t[$]7,"},
},
- {"s390x", "linux", `
- func f(x uint32) uint32 {
- return x<<7 | x>>25
- }
-`,
+ {
+ `
+ func f12(x uint32) uint32 {
+ return x<<7 | x>>25
+ }
+ `,
[]string{"\tRLL\t[$]7,"},
},
- {"s390x", "linux", `
- func f(x uint32) uint32 {
- return x<<7 ^ x>>25
- }
-`,
+ {
+ `
+ func f13(x uint32) uint32 {
+ return x<<7 ^ x>>25
+ }
+ `,
[]string{"\tRLL\t[$]7,"},
},
+}
- // Rotate after inlining (see issue 18254).
- {"amd64", "linux", `
- func f(x uint32, k uint) uint32 {
- return x<<k | x>>(32-k)
- }
- func g(x uint32) uint32 {
- return f(x, 7)
- }
-`,
- []string{"\tROLL\t[$]7,"},
+var linuxARMTests = []*asmTest{
+ {
+ `
+ func f0(x uint32) uint32 {
+ return x<<7 + x>>25
+ }
+ `,
+ []string{"\tMOVW\tR[0-9]+@>25,"},
+ },
+ {
+ `
+ func f1(x uint32) uint32 {
+ return x<<7 | x>>25
+ }
+ `,
+ []string{"\tMOVW\tR[0-9]+@>25,"},
+ },
+ {
+ `
+ func f2(x uint32) uint32 {
+ return x<<7 ^ x>>25
+ }
+ `,
+ []string{"\tMOVW\tR[0-9]+@>25,"},
},
+}
- // Direct use of constants in fast map access calls. Issue 19015.
- {"amd64", "linux", `
- func f(m map[int]int) int {
- return m[5]
- }
-`,
- []string{"\tMOVQ\t[$]5,"},
+var linuxARM64Tests = []*asmTest{
+ {
+ `
+ func f0(x uint64) uint64 {
+ return x<<7 + x>>57
+ }
+ `,
+ []string{"\tROR\t[$]57,"},
},
- {"amd64", "linux", `
- func f(m map[int]int) bool {
- _, ok := m[5]
- return ok
- }
-`,
- []string{"\tMOVQ\t[$]5,"},
+ {
+ `
+ func f1(x uint64) uint64 {
+ return x<<7 | x>>57
+ }
+ `,
+ []string{"\tROR\t[$]57,"},
},
- {"amd64", "linux", `
- func f(m map[string]int) int {
- return m["abc"]
- }
-`,
- []string{"\"abc\""},
+ {
+ `
+ func f2(x uint64) uint64 {
+ return x<<7 ^ x>>57
+ }
+ `,
+ []string{"\tROR\t[$]57,"},
},
- {"amd64", "linux", `
- func f(m map[string]int) bool {
- _, ok := m["abc"]
- return ok
- }
-`,
- []string{"\"abc\""},
+ {
+ `
+ func f3(x uint32) uint32 {
+ return x<<7 + x>>25
+ }
+ `,
+ []string{"\tRORW\t[$]25,"},
+ },
+ {
+ `
+ func f4(x uint32) uint32 {
+ return x<<7 | x>>25
+ }
+ `,
+ []string{"\tRORW\t[$]25,"},
+ },
+ {
+ `
+ func f5(x uint32) uint32 {
+ return x<<7 ^ x>>25
+ }
+ `,
+ []string{"\tRORW\t[$]25,"},
},
}