Home | History | Annotate | Download | only in gc
      1 // Copyright 2016 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package gc
      6 
      7 import (
      8 	"bytes"
      9 	"fmt"
     10 	"internal/testenv"
     11 	"io/ioutil"
     12 	"os"
     13 	"os/exec"
     14 	"path/filepath"
     15 	"regexp"
     16 	"runtime"
     17 	"strings"
     18 	"testing"
     19 )
     20 
     21 // This file contains code generation tests.
     22 //
     23 // Each test is defined in a variable of type asmTest. Tests are
     24 // architecture-specific, and they are grouped in arrays of tests, one
     25 // for each architecture.
     26 //
     27 // Each asmTest consists of a function to compile, an array of
     28 // positive regexps that must match the generated assembly and
     29 // an array of negative regexps that must not match generated assembly.
     30 // For example, the following amd64 test
     31 //
     32 //   {
     33 // 	  fn: `
     34 // 	  func f0(x int) int {
     35 // 		  return x * 64
     36 // 	  }
     37 // 	  `,
     38 // 	  pos: []string{"\tSHLQ\t[$]6,"},
     39 //	  neg: []string{"MULQ"}
     40 //   }
     41 //
     42 // verifies that the code the compiler generates for a multiplication
     43 // by 64 contains a 'SHLQ' instruction and does not contain a MULQ.
     44 //
     45 // Since all the tests for a given architecture are dumped in the same
     46 // file, the function names must be unique. As a workaround for this
     47 // restriction, the test harness supports the use of a '$' placeholder
     48 // for function names. The func f0 above can be also written as
     49 //
     50 //   {
     51 // 	  fn: `
     52 // 	  func $(x int) int {
     53 // 		  return x * 64
     54 // 	  }
     55 // 	  `,
     56 // 	  pos: []string{"\tSHLQ\t[$]6,"},
     57 //	  neg: []string{"MULQ"}
     58 //   }
     59 //
     60 // Each '$'-function will be given a unique name of form f<N>_<arch>,
     61 // where <N> is the test index in the test array, and <arch> is the
     62 // test's architecture.
     63 //
     64 // It is allowed to mix named and unnamed functions in the same test
     65 // array; the named functions will retain their original names.
     66 
     67 // TestAssembly checks to make sure the assembly generated for
     68 // functions contains certain expected instructions.
     69 func TestAssembly(t *testing.T) {
     70 	testenv.MustHaveGoBuild(t)
     71 	if runtime.GOOS == "windows" {
     72 		// TODO: remove if we can get "go tool compile -S" to work on windows.
     73 		t.Skipf("skipping test: recursive windows compile not working")
     74 	}
     75 	dir, err := ioutil.TempDir("", "TestAssembly")
     76 	if err != nil {
     77 		t.Fatalf("could not create directory: %v", err)
     78 	}
     79 	defer os.RemoveAll(dir)
     80 
     81 	nameRegexp := regexp.MustCompile("func \\w+")
     82 	t.Run("platform", func(t *testing.T) {
     83 		for _, ats := range allAsmTests {
     84 			ats := ats
     85 			t.Run(ats.os+"/"+ats.arch, func(tt *testing.T) {
     86 				tt.Parallel()
     87 
     88 				asm := ats.compileToAsm(tt, dir)
     89 
     90 				for i, at := range ats.tests {
     91 					var funcName string
     92 					if strings.Contains(at.fn, "func $") {
     93 						funcName = fmt.Sprintf("f%d_%s", i, ats.arch)
     94 					} else {
     95 						funcName = nameRegexp.FindString(at.fn)[len("func "):]
     96 					}
     97 					fa := funcAsm(tt, asm, funcName)
     98 					if fa != "" {
     99 						at.verifyAsm(tt, fa)
    100 					}
    101 				}
    102 			})
    103 		}
    104 	})
    105 }
    106 
    107 var nextTextRegexp = regexp.MustCompile(`\n\S`)
    108 
    109 // funcAsm returns the assembly listing for the given function name.
    110 func funcAsm(t *testing.T, asm string, funcName string) string {
    111 	if i := strings.Index(asm, fmt.Sprintf("TEXT\t\"\".%s(SB)", funcName)); i >= 0 {
    112 		asm = asm[i:]
    113 	} else {
    114 		t.Errorf("could not find assembly for function %v", funcName)
    115 		return ""
    116 	}
    117 
    118 	// Find the next line that doesn't begin with whitespace.
    119 	loc := nextTextRegexp.FindStringIndex(asm)
    120 	if loc != nil {
    121 		asm = asm[:loc[0]]
    122 	}
    123 
    124 	return asm
    125 }
    126 
    127 type asmTest struct {
    128 	// function to compile
    129 	fn string
    130 	// regular expressions that must match the generated assembly
    131 	pos []string
    132 	// regular expressions that must not match the generated assembly
    133 	neg []string
    134 }
    135 
    136 func (at asmTest) verifyAsm(t *testing.T, fa string) {
    137 	for _, r := range at.pos {
    138 		if b, err := regexp.MatchString(r, fa); !b || err != nil {
    139 			t.Errorf("expected:%s\ngo:%s\nasm:%s\n", r, at.fn, fa)
    140 		}
    141 	}
    142 	for _, r := range at.neg {
    143 		if b, err := regexp.MatchString(r, fa); b || err != nil {
    144 			t.Errorf("not expected:%s\ngo:%s\nasm:%s\n", r, at.fn, fa)
    145 		}
    146 	}
    147 }
    148 
    149 type asmTests struct {
    150 	arch    string
    151 	os      string
    152 	imports []string
    153 	tests   []*asmTest
    154 }
    155 
    156 func (ats *asmTests) generateCode() []byte {
    157 	var buf bytes.Buffer
    158 	fmt.Fprintln(&buf, "package main")
    159 	for _, s := range ats.imports {
    160 		fmt.Fprintf(&buf, "import %q\n", s)
    161 	}
    162 
    163 	for i, t := range ats.tests {
    164 		function := strings.Replace(t.fn, "func $", fmt.Sprintf("func f%d_%s", i, ats.arch), 1)
    165 		fmt.Fprintln(&buf, function)
    166 	}
    167 
    168 	return buf.Bytes()
    169 }
    170 
    171 // compile compiles the package pkg for architecture arch and
    172 // returns the generated assembly.  dir is a scratch directory.
    173 func (ats *asmTests) compileToAsm(t *testing.T, dir string) string {
    174 	// create test directory
    175 	testDir := filepath.Join(dir, fmt.Sprintf("%s_%s", ats.arch, ats.os))
    176 	err := os.Mkdir(testDir, 0700)
    177 	if err != nil {
    178 		t.Fatalf("could not create directory: %v", err)
    179 	}
    180 
    181 	// Create source.
    182 	src := filepath.Join(testDir, "test.go")
    183 	err = ioutil.WriteFile(src, ats.generateCode(), 0600)
    184 	if err != nil {
    185 		t.Fatalf("error writing code: %v", err)
    186 	}
    187 
    188 	// First, install any dependencies we need.  This builds the required export data
    189 	// for any packages that are imported.
    190 	for _, i := range ats.imports {
    191 		out := filepath.Join(testDir, i+".a")
    192 
    193 		if s := ats.runGo(t, "build", "-o", out, "-gcflags=-dolinkobj=false", i); s != "" {
    194 			t.Fatalf("Stdout = %s\nWant empty", s)
    195 		}
    196 	}
    197 
    198 	// Now, compile the individual file for which we want to see the generated assembly.
    199 	asm := ats.runGo(t, "tool", "compile", "-I", testDir, "-S", "-o", filepath.Join(testDir, "out.o"), src)
    200 	return asm
    201 }
    202 
    203 // runGo runs go command with the given args and returns stdout string.
    204 // go is run with GOARCH and GOOS set as ats.arch and ats.os respectively
    205 func (ats *asmTests) runGo(t *testing.T, args ...string) string {
    206 	var stdout, stderr bytes.Buffer
    207 	cmd := exec.Command(testenv.GoToolPath(t), args...)
    208 	cmd.Env = append(os.Environ(), "GOARCH="+ats.arch, "GOOS="+ats.os)
    209 	cmd.Stdout = &stdout
    210 	cmd.Stderr = &stderr
    211 
    212 	if err := cmd.Run(); err != nil {
    213 		t.Fatalf("error running cmd: %v\nstdout:\n%sstderr:\n%s\n", err, stdout.String(), stderr.String())
    214 	}
    215 
    216 	if s := stderr.String(); s != "" {
    217 		t.Fatalf("Stderr = %s\nWant empty", s)
    218 	}
    219 
    220 	return stdout.String()
    221 }
    222 
    223 var allAsmTests = []*asmTests{
    224 	{
    225 		arch:    "amd64",
    226 		os:      "linux",
    227 		imports: []string{"encoding/binary", "math", "math/bits", "unsafe", "runtime"},
    228 		tests:   linuxAMD64Tests,
    229 	},
    230 	{
    231 		arch:    "386",
    232 		os:      "linux",
    233 		imports: []string{"encoding/binary"},
    234 		tests:   linux386Tests,
    235 	},
    236 	{
    237 		arch:    "s390x",
    238 		os:      "linux",
    239 		imports: []string{"encoding/binary", "math", "math/bits"},
    240 		tests:   linuxS390XTests,
    241 	},
    242 	{
    243 		arch:    "arm",
    244 		os:      "linux",
    245 		imports: []string{"math/bits", "runtime"},
    246 		tests:   linuxARMTests,
    247 	},
    248 	{
    249 		arch:    "arm64",
    250 		os:      "linux",
    251 		imports: []string{"math/bits"},
    252 		tests:   linuxARM64Tests,
    253 	},
    254 	{
    255 		arch:    "mips",
    256 		os:      "linux",
    257 		imports: []string{"math/bits"},
    258 		tests:   linuxMIPSTests,
    259 	},
    260 	{
    261 		arch:  "mips64",
    262 		os:    "linux",
    263 		tests: linuxMIPS64Tests,
    264 	},
    265 	{
    266 		arch:    "ppc64le",
    267 		os:      "linux",
    268 		imports: []string{"encoding/binary", "math", "math/bits"},
    269 		tests:   linuxPPC64LETests,
    270 	},
    271 	{
    272 		arch:  "amd64",
    273 		os:    "plan9",
    274 		tests: plan9AMD64Tests,
    275 	},
    276 }
    277 
    278 var linuxAMD64Tests = []*asmTest{
    279 	// multiplication by powers of two
    280 	{
    281 		fn: `
    282 		func $(n int) int {
    283 			return n * 64
    284 		}
    285 		`,
    286 		pos: []string{"\tSHLQ\t\\$6,"},
    287 		neg: []string{"IMULQ"},
    288 	},
    289 	{
    290 		fn: `
    291 		func $(n int) int {
    292 			return -128*n
    293 		}
    294 		`,
    295 		pos: []string{"SHLQ"},
    296 		neg: []string{"IMULQ"},
    297 	},
    298 
    299 	{
    300 		fn: `
    301 		func $(x int) int {
    302 			return x * 96
    303 		}
    304 		`,
    305 		pos: []string{"\tSHLQ\t\\$5,", "\tLEAQ\t\\(.*\\)\\(.*\\*2\\),"},
    306 	},
    307 	// Load-combining tests.
    308 	{
    309 		fn: `
    310 		func f2(b []byte) uint64 {
    311 			return binary.LittleEndian.Uint64(b)
    312 		}
    313 		`,
    314 		pos: []string{"\tMOVQ\t\\(.*\\),"},
    315 	},
    316 	{
    317 		fn: `
    318 		func f3(b []byte, i int) uint64 {
    319 			return binary.LittleEndian.Uint64(b[i:])
    320 		}
    321 		`,
    322 		pos: []string{"\tMOVQ\t\\(.*\\)\\(.*\\*1\\),"},
    323 	},
    324 	{
    325 		fn: `
    326 		func f4(b []byte) uint32 {
    327 			return binary.LittleEndian.Uint32(b)
    328 		}
    329 		`,
    330 		pos: []string{"\tMOVL\t\\(.*\\),"},
    331 	},
    332 	{
    333 		fn: `
    334 		func f5(b []byte, i int) uint32 {
    335 			return binary.LittleEndian.Uint32(b[i:])
    336 		}
    337 		`,
    338 		pos: []string{"\tMOVL\t\\(.*\\)\\(.*\\*1\\),"},
    339 	},
    340 	{
    341 		fn: `
    342 		func f6(b []byte) uint64 {
    343 			return binary.BigEndian.Uint64(b)
    344 		}
    345 		`,
    346 		pos: []string{"\tBSWAPQ\t"},
    347 	},
    348 	{
    349 		fn: `
    350 		func f7(b []byte, i int) uint64 {
    351 			return binary.BigEndian.Uint64(b[i:])
    352 		}
    353 		`,
    354 		pos: []string{"\tBSWAPQ\t"},
    355 	},
    356 	{
    357 		fn: `
    358 		func f8(b []byte, v uint64) {
    359 			binary.BigEndian.PutUint64(b, v)
    360 		}
    361 		`,
    362 		pos: []string{"\tBSWAPQ\t"},
    363 	},
    364 	{
    365 		fn: `
    366 		func f9(b []byte, i int, v uint64) {
    367 			binary.BigEndian.PutUint64(b[i:], v)
    368 		}
    369 		`,
    370 		pos: []string{"\tBSWAPQ\t"},
    371 	},
    372 	{
    373 		fn: `
    374 		func f10(b []byte) uint32 {
    375 			return binary.BigEndian.Uint32(b)
    376 		}
    377 		`,
    378 		pos: []string{"\tBSWAPL\t"},
    379 	},
    380 	{
    381 		fn: `
    382 		func f11(b []byte, i int) uint32 {
    383 			return binary.BigEndian.Uint32(b[i:])
    384 		}
    385 		`,
    386 		pos: []string{"\tBSWAPL\t"},
    387 	},
    388 	{
    389 		fn: `
    390 		func f12(b []byte, v uint32) {
    391 			binary.BigEndian.PutUint32(b, v)
    392 		}
    393 		`,
    394 		pos: []string{"\tBSWAPL\t"},
    395 	},
    396 	{
    397 		fn: `
    398 		func f13(b []byte, i int, v uint32) {
    399 			binary.BigEndian.PutUint32(b[i:], v)
    400 		}
    401 		`,
    402 		pos: []string{"\tBSWAPL\t"},
    403 	},
    404 	{
    405 		fn: `
    406 		func f14(b []byte) uint16 {
    407 			return binary.BigEndian.Uint16(b)
    408 		}
    409 		`,
    410 		pos: []string{"\tROLW\t\\$8,"},
    411 	},
    412 	{
    413 		fn: `
    414 		func f15(b []byte, i int) uint16 {
    415 			return binary.BigEndian.Uint16(b[i:])
    416 		}
    417 		`,
    418 		pos: []string{"\tROLW\t\\$8,"},
    419 	},
    420 	{
    421 		fn: `
    422 		func f16(b []byte, v uint16) {
    423 			binary.BigEndian.PutUint16(b, v)
    424 		}
    425 		`,
    426 		pos: []string{"\tROLW\t\\$8,"},
    427 	},
    428 	{
    429 		fn: `
    430 		func f17(b []byte, i int, v uint16) {
    431 			binary.BigEndian.PutUint16(b[i:], v)
    432 		}
    433 		`,
    434 		pos: []string{"\tROLW\t\\$8,"},
    435 	},
    436 	// Structure zeroing.  See issue #18370.
    437 	{
    438 		fn: `
    439 		type T1 struct {
    440 			a, b, c int
    441 		}
    442 		func $(t *T1) {
    443 			*t = T1{}
    444 		}
    445 		`,
    446 		pos: []string{"\tXORPS\tX., X", "\tMOVUPS\tX., \\(.*\\)", "\tMOVQ\t\\$0, 16\\(.*\\)"},
    447 	},
    448 	// SSA-able composite literal initialization. Issue 18872.
    449 	{
    450 		fn: `
    451 		type T18872 struct {
    452 			a, b, c, d int
    453 		}
    454 
    455 		func f18872(p *T18872) {
    456 			*p = T18872{1, 2, 3, 4}
    457 		}
    458 		`,
    459 		pos: []string{"\tMOVQ\t[$]1", "\tMOVQ\t[$]2", "\tMOVQ\t[$]3", "\tMOVQ\t[$]4"},
    460 	},
    461 	// Also test struct containing pointers (this was special because of write barriers).
    462 	{
    463 		fn: `
    464 		type T2 struct {
    465 			a, b, c *int
    466 		}
    467 		func f19(t *T2) {
    468 			*t = T2{}
    469 		}
    470 		`,
    471 		pos: []string{"\tXORPS\tX., X", "\tMOVUPS\tX., \\(.*\\)", "\tMOVQ\t\\$0, 16\\(.*\\)", "\tCALL\truntime\\.(writebarrierptr|gcWriteBarrier)\\(SB\\)"},
    472 	},
    473 	// Rotate tests
    474 	{
    475 		fn: `
    476 		func f20(x uint64) uint64 {
    477 			return x<<7 | x>>57
    478 		}
    479 		`,
    480 		pos: []string{"\tROLQ\t[$]7,"},
    481 	},
    482 	{
    483 		fn: `
    484 		func f21(x uint64) uint64 {
    485 			return x<<7 + x>>57
    486 		}
    487 		`,
    488 		pos: []string{"\tROLQ\t[$]7,"},
    489 	},
    490 	{
    491 		fn: `
    492 		func f22(x uint64) uint64 {
    493 			return x<<7 ^ x>>57
    494 		}
    495 		`,
    496 		pos: []string{"\tROLQ\t[$]7,"},
    497 	},
    498 	{
    499 		fn: `
    500 		func f23(x uint32) uint32 {
    501 			return x<<7 + x>>25
    502 		}
    503 		`,
    504 		pos: []string{"\tROLL\t[$]7,"},
    505 	},
    506 	{
    507 		fn: `
    508 		func f24(x uint32) uint32 {
    509 			return x<<7 | x>>25
    510 		}
    511 		`,
    512 		pos: []string{"\tROLL\t[$]7,"},
    513 	},
    514 	{
    515 		fn: `
    516 		func f25(x uint32) uint32 {
    517 			return x<<7 ^ x>>25
    518 		}
    519 		`,
    520 		pos: []string{"\tROLL\t[$]7,"},
    521 	},
    522 	{
    523 		fn: `
    524 		func f26(x uint16) uint16 {
    525 			return x<<7 + x>>9
    526 		}
    527 		`,
    528 		pos: []string{"\tROLW\t[$]7,"},
    529 	},
    530 	{
    531 		fn: `
    532 		func f27(x uint16) uint16 {
    533 			return x<<7 | x>>9
    534 		}
    535 		`,
    536 		pos: []string{"\tROLW\t[$]7,"},
    537 	},
    538 	{
    539 		fn: `
    540 		func f28(x uint16) uint16 {
    541 			return x<<7 ^ x>>9
    542 		}
    543 		`,
    544 		pos: []string{"\tROLW\t[$]7,"},
    545 	},
    546 	{
    547 		fn: `
    548 		func f29(x uint8) uint8 {
    549 			return x<<7 + x>>1
    550 		}
    551 		`,
    552 		pos: []string{"\tROLB\t[$]7,"},
    553 	},
    554 	{
    555 		fn: `
    556 		func f30(x uint8) uint8 {
    557 			return x<<7 | x>>1
    558 		}
    559 		`,
    560 		pos: []string{"\tROLB\t[$]7,"},
    561 	},
    562 	{
    563 		fn: `
    564 		func f31(x uint8) uint8 {
    565 			return x<<7 ^ x>>1
    566 		}
    567 		`,
    568 		pos: []string{"\tROLB\t[$]7,"},
    569 	},
    570 	// Rotate after inlining (see issue 18254).
    571 	{
    572 		fn: `
    573 		func f32(x uint32) uint32 {
    574 			return g(x, 7)
    575 		}
    576 		func g(x uint32, k uint) uint32 {
    577 			return x<<k | x>>(32-k)
    578 		}
    579 		`,
    580 		pos: []string{"\tROLL\t[$]7,"},
    581 	},
    582 	{
    583 		fn: `
    584 		func f33(m map[int]int) int {
    585 			return m[5]
    586 		}
    587 		`,
    588 		pos: []string{"\tMOVQ\t[$]5,"},
    589 	},
    590 	// Direct use of constants in fast map access calls. Issue 19015.
    591 	{
    592 		fn: `
    593 		func f34(m map[int]int) bool {
    594 			_, ok := m[5]
    595 			return ok
    596 		}
    597 		`,
    598 		pos: []string{"\tMOVQ\t[$]5,"},
    599 	},
    600 	{
    601 		fn: `
    602 		func f35(m map[string]int) int {
    603 			return m["abc"]
    604 		}
    605 		`,
    606 		pos: []string{"\"abc\""},
    607 	},
    608 	{
    609 		fn: `
    610 		func f36(m map[string]int) bool {
    611 			_, ok := m["abc"]
    612 			return ok
    613 		}
    614 		`,
    615 		pos: []string{"\"abc\""},
    616 	},
    617 	// Bit test ops on amd64, issue 18943.
    618 	{
    619 		fn: `
    620 		func f37(a, b uint64) int {
    621 			if a&(1<<(b&63)) != 0 {
    622 				return 1
    623 			}
    624 			return -1
    625 		}
    626 		`,
    627 		pos: []string{"\tBTQ\t"},
    628 	},
    629 	{
    630 		fn: `
    631 		func f38(a, b uint64) bool {
    632 			return a&(1<<(b&63)) != 0
    633 		}
    634 		`,
    635 		pos: []string{"\tBTQ\t"},
    636 	},
    637 	{
    638 		fn: `
    639 		func f39(a uint64) int {
    640 			if a&(1<<60) != 0 {
    641 				return 1
    642 			}
    643 			return -1
    644 		}
    645 		`,
    646 		pos: []string{"\tBTQ\t\\$60"},
    647 	},
    648 	{
    649 		fn: `
    650 		func f40(a uint64) bool {
    651 			return a&(1<<60) != 0
    652 		}
    653 		`,
    654 		pos: []string{"\tBTQ\t\\$60"},
    655 	},
    656 	// Intrinsic tests for math/bits
    657 	{
    658 		fn: `
    659 		func f41(a uint64) int {
    660 			return bits.TrailingZeros64(a)
    661 		}
    662 		`,
    663 		pos: []string{"\tBSFQ\t", "\tMOVL\t\\$64,", "\tCMOVQEQ\t"},
    664 	},
    665 	{
    666 		fn: `
    667 		func f42(a uint32) int {
    668 			return bits.TrailingZeros32(a)
    669 		}
    670 		`,
    671 		pos: []string{"\tBSFQ\t", "\tORQ\t[^$]", "\tMOVQ\t\\$4294967296,"},
    672 	},
    673 	{
    674 		fn: `
    675 		func f43(a uint16) int {
    676 			return bits.TrailingZeros16(a)
    677 		}
    678 		`,
    679 		pos: []string{"\tBSFQ\t", "\tORQ\t\\$65536,"},
    680 	},
    681 	{
    682 		fn: `
    683 		func f44(a uint8) int {
    684 			return bits.TrailingZeros8(a)
    685 		}
    686 		`,
    687 		pos: []string{"\tBSFQ\t", "\tORQ\t\\$256,"},
    688 	},
    689 	{
    690 		fn: `
    691 		func f45(a uint64) uint64 {
    692 			return bits.ReverseBytes64(a)
    693 		}
    694 		`,
    695 		pos: []string{"\tBSWAPQ\t"},
    696 	},
    697 	{
    698 		fn: `
    699 		func f46(a uint32) uint32 {
    700 			return bits.ReverseBytes32(a)
    701 		}
    702 		`,
    703 		pos: []string{"\tBSWAPL\t"},
    704 	},
    705 	{
    706 		fn: `
    707 		func f47(a uint16) uint16 {
    708 			return bits.ReverseBytes16(a)
    709 		}
    710 		`,
    711 		pos: []string{"\tROLW\t\\$8,"},
    712 	},
    713 	{
    714 		fn: `
    715 		func f48(a uint64) int {
    716 			return bits.Len64(a)
    717 		}
    718 		`,
    719 		pos: []string{"\tBSRQ\t"},
    720 	},
    721 	{
    722 		fn: `
    723 		func f49(a uint32) int {
    724 			return bits.Len32(a)
    725 		}
    726 		`,
    727 		pos: []string{"\tBSRQ\t"},
    728 	},
    729 	{
    730 		fn: `
    731 		func f50(a uint16) int {
    732 			return bits.Len16(a)
    733 		}
    734 		`,
    735 		pos: []string{"\tBSRQ\t"},
    736 	},
    737 	/* see ssa.go
    738 	{
    739 		fn:`
    740 		func f51(a uint8) int {
    741 			return bits.Len8(a)
    742 		}
    743 		`,
    744 		pos:[]string{"\tBSRQ\t"},
    745 	},
    746 	*/
    747 	{
    748 		fn: `
    749 		func f52(a uint) int {
    750 			return bits.Len(a)
    751 		}
    752 		`,
    753 		pos: []string{"\tBSRQ\t"},
    754 	},
    755 	{
    756 		fn: `
    757 		func f53(a uint64) int {
    758 			return bits.LeadingZeros64(a)
    759 		}
    760 		`,
    761 		pos: []string{"\tBSRQ\t"},
    762 	},
    763 	{
    764 		fn: `
    765 		func f54(a uint32) int {
    766 			return bits.LeadingZeros32(a)
    767 		}
    768 		`,
    769 		pos: []string{"\tBSRQ\t"},
    770 	},
    771 	{
    772 		fn: `
    773 		func f55(a uint16) int {
    774 			return bits.LeadingZeros16(a)
    775 		}
    776 		`,
    777 		pos: []string{"\tBSRQ\t"},
    778 	},
    779 	/* see ssa.go
    780 	{
    781 		fn:`
    782 		func f56(a uint8) int {
    783 			return bits.LeadingZeros8(a)
    784 		}
    785 		`,
    786 		pos:[]string{"\tBSRQ\t"},
    787 	},
    788 	*/
    789 	{
    790 		fn: `
    791 		func f57(a uint) int {
    792 			return bits.LeadingZeros(a)
    793 		}
    794 		`,
    795 		pos: []string{"\tBSRQ\t"},
    796 	},
    797 	{
    798 		fn: `
    799 		func pop1(x uint64) int {
    800 			return bits.OnesCount64(x)
    801 		}`,
    802 		pos: []string{"\tPOPCNTQ\t", "support_popcnt"},
    803 	},
    804 	{
    805 		fn: `
    806 		func pop2(x uint32) int {
    807 			return bits.OnesCount32(x)
    808 		}`,
    809 		pos: []string{"\tPOPCNTL\t", "support_popcnt"},
    810 	},
    811 	{
    812 		fn: `
    813 		func pop3(x uint16) int {
    814 			return bits.OnesCount16(x)
    815 		}`,
    816 		pos: []string{"\tPOPCNTL\t", "support_popcnt"},
    817 	},
    818 	{
    819 		fn: `
    820 		func pop4(x uint) int {
    821 			return bits.OnesCount(x)
    822 		}`,
    823 		pos: []string{"\tPOPCNTQ\t", "support_popcnt"},
    824 	},
    825 	// multiplication merging tests
    826 	{
    827 		fn: `
    828 		func mul1(n int) int {
    829 			return 15*n + 31*n
    830 		}`,
    831 		pos: []string{"\tIMULQ\t[$]46"}, // 46*n
    832 	},
    833 	{
    834 		fn: `
    835 		func mul2(n int) int {
    836 			return 5*n + 7*(n+1) + 11*(n+2)
    837 		}`,
    838 		pos: []string{"\tIMULQ\t[$]23", "\tADDQ\t[$]29"}, // 23*n + 29
    839 	},
    840 	{
    841 		fn: `
    842 		func mul3(a, n int) int {
    843 			return a*n + 19*n
    844 		}`,
    845 		pos: []string{"\tADDQ\t[$]19", "\tIMULQ"}, // (a+19)*n
    846 	},
    847 	{
    848 		fn: `
    849 		func mul4(n int) int {
    850 			return 23*n - 9*n
    851 		}`,
    852 		pos: []string{"\tIMULQ\t[$]14"}, // 14*n
    853 	},
    854 	{
    855 		fn: `
    856 		func mul5(a, n int) int {
    857 			return a*n - 19*n
    858 		}`,
    859 		pos: []string{"\tADDQ\t[$]-19", "\tIMULQ"}, // (a-19)*n
    860 	},
    861 
    862 	// see issue 19595.
    863 	// We want to merge load+op in f58, but not in f59.
    864 	{
    865 		fn: `
    866 		func f58(p, q *int) {
    867 			x := *p
    868 			*q += x
    869 		}`,
    870 		pos: []string{"\tADDQ\t\\("},
    871 	},
    872 	{
    873 		fn: `
    874 		func f59(p, q *int) {
    875 			x := *p
    876 			for i := 0; i < 10; i++ {
    877 				*q += x
    878 			}
    879 		}`,
    880 		pos: []string{"\tADDQ\t[A-Z]"},
    881 	},
    882 	// Floating-point strength reduction
    883 	{
    884 		fn: `
    885 		func f60(f float64) float64 {
    886 			return f * 2.0
    887 		}`,
    888 		pos: []string{"\tADDSD\t"},
    889 	},
    890 	{
    891 		fn: `
    892 		func f62(f float64) float64 {
    893 			return f / 16.0
    894 		}`,
    895 		pos: []string{"\tMULSD\t"},
    896 	},
    897 	{
    898 		fn: `
    899 		func f63(f float64) float64 {
    900 			return f / 0.125
    901 		}`,
    902 		pos: []string{"\tMULSD\t"},
    903 	},
    904 	{
    905 		fn: `
    906 		func f64(f float64) float64 {
    907 			return f / 0.5
    908 		}`,
    909 		pos: []string{"\tADDSD\t"},
    910 	},
    911 	// Check that compare to constant string uses 2/4/8 byte compares
    912 	{
    913 		fn: `
    914 		func f65(a string) bool {
    915 		    return a == "xx"
    916 		}`,
    917 		pos: []string{"\tCMPW\t[A-Z]"},
    918 	},
    919 	{
    920 		fn: `
    921 		func f66(a string) bool {
    922 		    return a == "xxxx"
    923 		}`,
    924 		pos: []string{"\tCMPL\t[A-Z]"},
    925 	},
    926 	{
    927 		fn: `
    928 		func f67(a string) bool {
    929 		    return a == "xxxxxxxx"
    930 		}`,
    931 		pos: []string{"\tCMPQ\t[A-Z]"},
    932 	},
    933 	// Non-constant rotate
    934 	{
    935 		fn: `func rot64l(x uint64, y int) uint64 {
    936 			z := uint(y & 63)
    937 			return x << z | x >> (64-z)
    938 		}`,
    939 		pos: []string{"\tROLQ\t"},
    940 	},
    941 	{
    942 		fn: `func rot64r(x uint64, y int) uint64 {
    943 			z := uint(y & 63)
    944 			return x >> z | x << (64-z)
    945 		}`,
    946 		pos: []string{"\tRORQ\t"},
    947 	},
    948 	{
    949 		fn: `func rot32l(x uint32, y int) uint32 {
    950 			z := uint(y & 31)
    951 			return x << z | x >> (32-z)
    952 		}`,
    953 		pos: []string{"\tROLL\t"},
    954 	},
    955 	{
    956 		fn: `func rot32r(x uint32, y int) uint32 {
    957 			z := uint(y & 31)
    958 			return x >> z | x << (32-z)
    959 		}`,
    960 		pos: []string{"\tRORL\t"},
    961 	},
    962 	{
    963 		fn: `func rot16l(x uint16, y int) uint16 {
    964 			z := uint(y & 15)
    965 			return x << z | x >> (16-z)
    966 		}`,
    967 		pos: []string{"\tROLW\t"},
    968 	},
    969 	{
    970 		fn: `func rot16r(x uint16, y int) uint16 {
    971 			z := uint(y & 15)
    972 			return x >> z | x << (16-z)
    973 		}`,
    974 		pos: []string{"\tRORW\t"},
    975 	},
    976 	{
    977 		fn: `func rot8l(x uint8, y int) uint8 {
    978 			z := uint(y & 7)
    979 			return x << z | x >> (8-z)
    980 		}`,
    981 		pos: []string{"\tROLB\t"},
    982 	},
    983 	{
    984 		fn: `func rot8r(x uint8, y int) uint8 {
    985 			z := uint(y & 7)
    986 			return x >> z | x << (8-z)
    987 		}`,
    988 		pos: []string{"\tRORB\t"},
    989 	},
    990 	// Check that array compare uses 2/4/8 byte compares
    991 	{
    992 		fn: `
    993 		func f68(a,b [2]byte) bool {
    994 		    return a == b
    995 		}`,
    996 		pos: []string{"\tCMPW\t[A-Z]"},
    997 	},
    998 	{
    999 		fn: `
   1000 		func f69(a,b [3]uint16) bool {
   1001 		    return a == b
   1002 		}`,
   1003 		pos: []string{"\tCMPL\t[A-Z]"},
   1004 	},
   1005 	{
   1006 		fn: `
   1007 		func $(a,b [3]int16) bool {
   1008 		    return a == b
   1009 		}`,
   1010 		pos: []string{"\tCMPL\t[A-Z]"},
   1011 	},
   1012 	{
   1013 		fn: `
   1014 		func $(a,b [12]int8) bool {
   1015 		    return a == b
   1016 		}`,
   1017 		pos: []string{"\tCMPQ\t[A-Z]", "\tCMPL\t[A-Z]"},
   1018 	},
   1019 	{
   1020 		fn: `
   1021 		func f70(a,b [15]byte) bool {
   1022 		    return a == b
   1023 		}`,
   1024 		pos: []string{"\tCMPQ\t[A-Z]"},
   1025 	},
   1026 	{
   1027 		fn: `
   1028 		func f71(a,b unsafe.Pointer) bool { // This was a TODO in mapaccess1_faststr
   1029 		    return *((*[4]byte)(a)) != *((*[4]byte)(b))
   1030 		}`,
   1031 		pos: []string{"\tCMPL\t[A-Z]"},
   1032 	},
   1033 	{
   1034 		// make sure assembly output has matching offset and base register.
   1035 		fn: `
   1036 		func f72(a, b int) int {
   1037 			runtime.GC() // use some frame
   1038 			return b
   1039 		}
   1040 		`,
   1041 		pos: []string{"b\\+24\\(SP\\)"},
   1042 	},
   1043 	{
   1044 		// check load combining
   1045 		fn: `
   1046 		func f73(a, b byte) (byte,byte) {
   1047 		    return f73(f73(a,b))
   1048 		}
   1049 		`,
   1050 		pos: []string{"\tMOVW\t"},
   1051 	},
   1052 	{
   1053 		fn: `
   1054 		func f74(a, b uint16) (uint16,uint16) {
   1055 		    return f74(f74(a,b))
   1056 		}
   1057 		`,
   1058 		pos: []string{"\tMOVL\t"},
   1059 	},
   1060 	{
   1061 		fn: `
   1062 		func f75(a, b uint32) (uint32,uint32) {
   1063 		    return f75(f75(a,b))
   1064 		}
   1065 		`,
   1066 		pos: []string{"\tMOVQ\t"},
   1067 	},
   1068 	// Make sure we don't put pointers in SSE registers across safe points.
   1069 	{
   1070 		fn: `
   1071 		func $(p, q *[2]*int)  {
   1072 		    a, b := p[0], p[1]
   1073 		    runtime.GC()
   1074 		    q[0], q[1] = a, b
   1075 		}
   1076 		`,
   1077 		neg: []string{"MOVUPS"},
   1078 	},
   1079 	{
   1080 		// check that stack store is optimized away
   1081 		fn: `
   1082 		func $() int {
   1083 			var x int
   1084 			return *(&x)
   1085 		}
   1086 		`,
   1087 		pos: []string{"TEXT\t.*, [$]0-8"},
   1088 	},
   1089 	// math.Abs using integer registers
   1090 	{
   1091 		fn: `
   1092 		func $(x float64) float64 {
   1093 			return math.Abs(x)
   1094 		}
   1095 		`,
   1096 		pos: []string{"\tSHLQ\t[$]1,", "\tSHRQ\t[$]1,"},
   1097 	},
   1098 	// math.Copysign using integer registers
   1099 	{
   1100 		fn: `
   1101 		func $(x, y float64) float64 {
   1102 			return math.Copysign(x, y)
   1103 		}
   1104 		`,
   1105 		pos: []string{"\tSHLQ\t[$]1,", "\tSHRQ\t[$]1,", "\tSHRQ\t[$]63,", "\tSHLQ\t[$]63,", "\tORQ\t"},
   1106 	},
   1107 	// int <-> fp moves
   1108 	{
   1109 		fn: `
   1110 		func $(x float64) uint64 {
   1111 			return math.Float64bits(x+1) + 1
   1112 		}
   1113 		`,
   1114 		pos: []string{"\tMOVQ\tX.*, [^X].*"},
   1115 	},
   1116 	{
   1117 		fn: `
   1118 		func $(x float32) uint32 {
   1119 			return math.Float32bits(x+1) + 1
   1120 		}
   1121 		`,
   1122 		pos: []string{"\tMOVL\tX.*, [^X].*"},
   1123 	},
   1124 	{
   1125 		fn: `
   1126 		func $(x uint64) float64 {
   1127 			return math.Float64frombits(x+1) + 1
   1128 		}
   1129 		`,
   1130 		pos: []string{"\tMOVQ\t[^X].*, X.*"},
   1131 	},
   1132 	{
   1133 		fn: `
   1134 		func $(x uint32) float32 {
   1135 			return math.Float32frombits(x+1) + 1
   1136 		}
   1137 		`,
   1138 		pos: []string{"\tMOVL\t[^X].*, X.*"},
   1139 	},
   1140 	{
   1141 		fn: `
   1142 		func $(x uint32) bool {
   1143 			return x > 4
   1144 		}
   1145 		`,
   1146 		pos: []string{"\tSETHI\t\\("},
   1147 	},
   1148 	// Check that len() and cap() div by a constant power of two
   1149 	// are compiled into SHRQ.
   1150 	{
   1151 		fn: `
   1152 		func $(a []int) int {
   1153 			return len(a) / 1024
   1154 		}
   1155 		`,
   1156 		pos: []string{"\tSHRQ\t\\$10,"},
   1157 	},
   1158 	{
   1159 		fn: `
   1160 		func $(s string) int {
   1161 			return len(s) / (4097 >> 1)
   1162 		}
   1163 		`,
   1164 		pos: []string{"\tSHRQ\t\\$11,"},
   1165 	},
   1166 	{
   1167 		fn: `
   1168 		func $(a []int) int {
   1169 			return cap(a) / ((1 << 11) + 2048)
   1170 		}
   1171 		`,
   1172 		pos: []string{"\tSHRQ\t\\$12,"},
   1173 	},
   1174 	// Check that len() and cap() mod by a constant power of two
   1175 	// are compiled into ANDQ.
   1176 	{
   1177 		fn: `
   1178 		func $(a []int) int {
   1179 			return len(a) % 1024
   1180 		}
   1181 		`,
   1182 		pos: []string{"\tANDQ\t\\$1023,"},
   1183 	},
   1184 	{
   1185 		fn: `
   1186 		func $(s string) int {
   1187 			return len(s) % (4097 >> 1)
   1188 		}
   1189 		`,
   1190 		pos: []string{"\tANDQ\t\\$2047,"},
   1191 	},
   1192 	{
   1193 		fn: `
   1194 		func $(a []int) int {
   1195 			return cap(a) % ((1 << 11) + 2048)
   1196 		}
   1197 		`,
   1198 		pos: []string{"\tANDQ\t\\$4095,"},
   1199 	},
   1200 	{
   1201 		// Test that small memmove was replaced with direct movs
   1202 		fn: `
   1203                 func $() {
   1204                        x := [...]byte{1, 2, 3, 4, 5, 6, 7}
   1205                        copy(x[1:], x[:])
   1206                 }
   1207 		`,
   1208 		neg: []string{"memmove"},
   1209 	},
   1210 	{
   1211 		// Same as above but with different size
   1212 		fn: `
   1213                 func $() {
   1214                        x := [...]byte{1, 2, 3, 4}
   1215                        copy(x[1:], x[:])
   1216                 }
   1217 		`,
   1218 		neg: []string{"memmove"},
   1219 	},
   1220 	{
   1221 		// Same as above but with different size
   1222 		fn: `
   1223                 func $() {
   1224                        x := [...]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
   1225                        copy(x[1:], x[:])
   1226                 }
   1227 		`,
   1228 		neg: []string{"memmove"},
   1229 	},
   1230 	// Nil checks before calling interface methods
   1231 	{
   1232 		fn: `
   1233 		type I interface {
   1234 			foo000()
   1235 			foo001()
   1236 			foo002()
   1237 			foo003()
   1238 			foo004()
   1239 			foo005()
   1240 			foo006()
   1241 			foo007()
   1242 			foo008()
   1243 			foo009()
   1244 			foo010()
   1245 			foo011()
   1246 			foo012()
   1247 			foo013()
   1248 			foo014()
   1249 			foo015()
   1250 			foo016()
   1251 			foo017()
   1252 			foo018()
   1253 			foo019()
   1254 			foo020()
   1255 			foo021()
   1256 			foo022()
   1257 			foo023()
   1258 			foo024()
   1259 			foo025()
   1260 			foo026()
   1261 			foo027()
   1262 			foo028()
   1263 			foo029()
   1264 			foo030()
   1265 			foo031()
   1266 			foo032()
   1267 			foo033()
   1268 			foo034()
   1269 			foo035()
   1270 			foo036()
   1271 			foo037()
   1272 			foo038()
   1273 			foo039()
   1274 			foo040()
   1275 			foo041()
   1276 			foo042()
   1277 			foo043()
   1278 			foo044()
   1279 			foo045()
   1280 			foo046()
   1281 			foo047()
   1282 			foo048()
   1283 			foo049()
   1284 			foo050()
   1285 			foo051()
   1286 			foo052()
   1287 			foo053()
   1288 			foo054()
   1289 			foo055()
   1290 			foo056()
   1291 			foo057()
   1292 			foo058()
   1293 			foo059()
   1294 			foo060()
   1295 			foo061()
   1296 			foo062()
   1297 			foo063()
   1298 			foo064()
   1299 			foo065()
   1300 			foo066()
   1301 			foo067()
   1302 			foo068()
   1303 			foo069()
   1304 			foo070()
   1305 			foo071()
   1306 			foo072()
   1307 			foo073()
   1308 			foo074()
   1309 			foo075()
   1310 			foo076()
   1311 			foo077()
   1312 			foo078()
   1313 			foo079()
   1314 			foo080()
   1315 			foo081()
   1316 			foo082()
   1317 			foo083()
   1318 			foo084()
   1319 			foo085()
   1320 			foo086()
   1321 			foo087()
   1322 			foo088()
   1323 			foo089()
   1324 			foo090()
   1325 			foo091()
   1326 			foo092()
   1327 			foo093()
   1328 			foo094()
   1329 			foo095()
   1330 			foo096()
   1331 			foo097()
   1332 			foo098()
   1333 			foo099()
   1334 			foo100()
   1335 			foo101()
   1336 			foo102()
   1337 			foo103()
   1338 			foo104()
   1339 			foo105()
   1340 			foo106()
   1341 			foo107()
   1342 			foo108()
   1343 			foo109()
   1344 			foo110()
   1345 			foo111()
   1346 			foo112()
   1347 			foo113()
   1348 			foo114()
   1349 			foo115()
   1350 			foo116()
   1351 			foo117()
   1352 			foo118()
   1353 			foo119()
   1354 			foo120()
   1355 			foo121()
   1356 			foo122()
   1357 			foo123()
   1358 			foo124()
   1359 			foo125()
   1360 			foo126()
   1361 			foo127()
   1362 			foo128()
   1363 			foo129()
   1364 			foo130()
   1365 			foo131()
   1366 			foo132()
   1367 			foo133()
   1368 			foo134()
   1369 			foo135()
   1370 			foo136()
   1371 			foo137()
   1372 			foo138()
   1373 			foo139()
   1374 			foo140()
   1375 			foo141()
   1376 			foo142()
   1377 			foo143()
   1378 			foo144()
   1379 			foo145()
   1380 			foo146()
   1381 			foo147()
   1382 			foo148()
   1383 			foo149()
   1384 			foo150()
   1385 			foo151()
   1386 			foo152()
   1387 			foo153()
   1388 			foo154()
   1389 			foo155()
   1390 			foo156()
   1391 			foo157()
   1392 			foo158()
   1393 			foo159()
   1394 			foo160()
   1395 			foo161()
   1396 			foo162()
   1397 			foo163()
   1398 			foo164()
   1399 			foo165()
   1400 			foo166()
   1401 			foo167()
   1402 			foo168()
   1403 			foo169()
   1404 			foo170()
   1405 			foo171()
   1406 			foo172()
   1407 			foo173()
   1408 			foo174()
   1409 			foo175()
   1410 			foo176()
   1411 			foo177()
   1412 			foo178()
   1413 			foo179()
   1414 			foo180()
   1415 			foo181()
   1416 			foo182()
   1417 			foo183()
   1418 			foo184()
   1419 			foo185()
   1420 			foo186()
   1421 			foo187()
   1422 			foo188()
   1423 			foo189()
   1424 			foo190()
   1425 			foo191()
   1426 			foo192()
   1427 			foo193()
   1428 			foo194()
   1429 			foo195()
   1430 			foo196()
   1431 			foo197()
   1432 			foo198()
   1433 			foo199()
   1434 			foo200()
   1435 			foo201()
   1436 			foo202()
   1437 			foo203()
   1438 			foo204()
   1439 			foo205()
   1440 			foo206()
   1441 			foo207()
   1442 			foo208()
   1443 			foo209()
   1444 			foo210()
   1445 			foo211()
   1446 			foo212()
   1447 			foo213()
   1448 			foo214()
   1449 			foo215()
   1450 			foo216()
   1451 			foo217()
   1452 			foo218()
   1453 			foo219()
   1454 			foo220()
   1455 			foo221()
   1456 			foo222()
   1457 			foo223()
   1458 			foo224()
   1459 			foo225()
   1460 			foo226()
   1461 			foo227()
   1462 			foo228()
   1463 			foo229()
   1464 			foo230()
   1465 			foo231()
   1466 			foo232()
   1467 			foo233()
   1468 			foo234()
   1469 			foo235()
   1470 			foo236()
   1471 			foo237()
   1472 			foo238()
   1473 			foo239()
   1474 			foo240()
   1475 			foo241()
   1476 			foo242()
   1477 			foo243()
   1478 			foo244()
   1479 			foo245()
   1480 			foo246()
   1481 			foo247()
   1482 			foo248()
   1483 			foo249()
   1484 			foo250()
   1485 			foo251()
   1486 			foo252()
   1487 			foo253()
   1488 			foo254()
   1489 			foo255()
   1490 			foo256()
   1491 			foo257()
   1492 			foo258()
   1493 			foo259()
   1494 			foo260()
   1495 			foo261()
   1496 			foo262()
   1497 			foo263()
   1498 			foo264()
   1499 			foo265()
   1500 			foo266()
   1501 			foo267()
   1502 			foo268()
   1503 			foo269()
   1504 			foo270()
   1505 			foo271()
   1506 			foo272()
   1507 			foo273()
   1508 			foo274()
   1509 			foo275()
   1510 			foo276()
   1511 			foo277()
   1512 			foo278()
   1513 			foo279()
   1514 			foo280()
   1515 			foo281()
   1516 			foo282()
   1517 			foo283()
   1518 			foo284()
   1519 			foo285()
   1520 			foo286()
   1521 			foo287()
   1522 			foo288()
   1523 			foo289()
   1524 			foo290()
   1525 			foo291()
   1526 			foo292()
   1527 			foo293()
   1528 			foo294()
   1529 			foo295()
   1530 			foo296()
   1531 			foo297()
   1532 			foo298()
   1533 			foo299()
   1534 			foo300()
   1535 			foo301()
   1536 			foo302()
   1537 			foo303()
   1538 			foo304()
   1539 			foo305()
   1540 			foo306()
   1541 			foo307()
   1542 			foo308()
   1543 			foo309()
   1544 			foo310()
   1545 			foo311()
   1546 			foo312()
   1547 			foo313()
   1548 			foo314()
   1549 			foo315()
   1550 			foo316()
   1551 			foo317()
   1552 			foo318()
   1553 			foo319()
   1554 			foo320()
   1555 			foo321()
   1556 			foo322()
   1557 			foo323()
   1558 			foo324()
   1559 			foo325()
   1560 			foo326()
   1561 			foo327()
   1562 			foo328()
   1563 			foo329()
   1564 			foo330()
   1565 			foo331()
   1566 			foo332()
   1567 			foo333()
   1568 			foo334()
   1569 			foo335()
   1570 			foo336()
   1571 			foo337()
   1572 			foo338()
   1573 			foo339()
   1574 			foo340()
   1575 			foo341()
   1576 			foo342()
   1577 			foo343()
   1578 			foo344()
   1579 			foo345()
   1580 			foo346()
   1581 			foo347()
   1582 			foo348()
   1583 			foo349()
   1584 			foo350()
   1585 			foo351()
   1586 			foo352()
   1587 			foo353()
   1588 			foo354()
   1589 			foo355()
   1590 			foo356()
   1591 			foo357()
   1592 			foo358()
   1593 			foo359()
   1594 			foo360()
   1595 			foo361()
   1596 			foo362()
   1597 			foo363()
   1598 			foo364()
   1599 			foo365()
   1600 			foo366()
   1601 			foo367()
   1602 			foo368()
   1603 			foo369()
   1604 			foo370()
   1605 			foo371()
   1606 			foo372()
   1607 			foo373()
   1608 			foo374()
   1609 			foo375()
   1610 			foo376()
   1611 			foo377()
   1612 			foo378()
   1613 			foo379()
   1614 			foo380()
   1615 			foo381()
   1616 			foo382()
   1617 			foo383()
   1618 			foo384()
   1619 			foo385()
   1620 			foo386()
   1621 			foo387()
   1622 			foo388()
   1623 			foo389()
   1624 			foo390()
   1625 			foo391()
   1626 			foo392()
   1627 			foo393()
   1628 			foo394()
   1629 			foo395()
   1630 			foo396()
   1631 			foo397()
   1632 			foo398()
   1633 			foo399()
   1634 			foo400()
   1635 			foo401()
   1636 			foo402()
   1637 			foo403()
   1638 			foo404()
   1639 			foo405()
   1640 			foo406()
   1641 			foo407()
   1642 			foo408()
   1643 			foo409()
   1644 			foo410()
   1645 			foo411()
   1646 			foo412()
   1647 			foo413()
   1648 			foo414()
   1649 			foo415()
   1650 			foo416()
   1651 			foo417()
   1652 			foo418()
   1653 			foo419()
   1654 			foo420()
   1655 			foo421()
   1656 			foo422()
   1657 			foo423()
   1658 			foo424()
   1659 			foo425()
   1660 			foo426()
   1661 			foo427()
   1662 			foo428()
   1663 			foo429()
   1664 			foo430()
   1665 			foo431()
   1666 			foo432()
   1667 			foo433()
   1668 			foo434()
   1669 			foo435()
   1670 			foo436()
   1671 			foo437()
   1672 			foo438()
   1673 			foo439()
   1674 			foo440()
   1675 			foo441()
   1676 			foo442()
   1677 			foo443()
   1678 			foo444()
   1679 			foo445()
   1680 			foo446()
   1681 			foo447()
   1682 			foo448()
   1683 			foo449()
   1684 			foo450()
   1685 			foo451()
   1686 			foo452()
   1687 			foo453()
   1688 			foo454()
   1689 			foo455()
   1690 			foo456()
   1691 			foo457()
   1692 			foo458()
   1693 			foo459()
   1694 			foo460()
   1695 			foo461()
   1696 			foo462()
   1697 			foo463()
   1698 			foo464()
   1699 			foo465()
   1700 			foo466()
   1701 			foo467()
   1702 			foo468()
   1703 			foo469()
   1704 			foo470()
   1705 			foo471()
   1706 			foo472()
   1707 			foo473()
   1708 			foo474()
   1709 			foo475()
   1710 			foo476()
   1711 			foo477()
   1712 			foo478()
   1713 			foo479()
   1714 			foo480()
   1715 			foo481()
   1716 			foo482()
   1717 			foo483()
   1718 			foo484()
   1719 			foo485()
   1720 			foo486()
   1721 			foo487()
   1722 			foo488()
   1723 			foo489()
   1724 			foo490()
   1725 			foo491()
   1726 			foo492()
   1727 			foo493()
   1728 			foo494()
   1729 			foo495()
   1730 			foo496()
   1731 			foo497()
   1732 			foo498()
   1733 			foo499()
   1734 			foo500()
   1735 			foo501()
   1736 			foo502()
   1737 			foo503()
   1738 			foo504()
   1739 			foo505()
   1740 			foo506()
   1741 			foo507()
   1742 			foo508()
   1743 			foo509()
   1744 			foo510()
   1745 			foo511()
   1746 		}
   1747 		func $(i I) {
   1748 			i.foo511()
   1749 		}
   1750 		`,
   1751 		pos: []string{"TESTB"},
   1752 	},
   1753 	{
   1754 		fn: `
   1755 		func $(i I) {
   1756 			i.foo001()
   1757 		}
   1758 		`,
   1759 		neg: []string{"TESTB"},
   1760 	},
   1761 }
   1762 
   1763 var linux386Tests = []*asmTest{
   1764 	{
   1765 		fn: `
   1766 		func f0(b []byte) uint32 {
   1767 			return binary.LittleEndian.Uint32(b)
   1768 		}
   1769 		`,
   1770 		pos: []string{"\tMOVL\t\\(.*\\),"},
   1771 	},
   1772 	{
   1773 		fn: `
   1774 		func f1(b []byte, i int) uint32 {
   1775 			return binary.LittleEndian.Uint32(b[i:])
   1776 		}
   1777 		`,
   1778 		pos: []string{"\tMOVL\t\\(.*\\)\\(.*\\*1\\),"},
   1779 	},
   1780 
   1781 	// multiplication by powers of two
   1782 	{
   1783 		fn: `
   1784 		func $(n int) int {
   1785 			return 32*n
   1786 		}
   1787 		`,
   1788 		pos: []string{"SHLL"},
   1789 		neg: []string{"IMULL"},
   1790 	},
   1791 	{
   1792 		fn: `
   1793 		func $(n int) int {
   1794 			return -64*n
   1795 		}
   1796 		`,
   1797 		pos: []string{"SHLL"},
   1798 		neg: []string{"IMULL"},
   1799 	},
   1800 
   1801 	// multiplication merging tests
   1802 	{
   1803 		fn: `
   1804 		func $(n int) int {
   1805 			return 9*n + 14*n
   1806 		}`,
   1807 		pos: []string{"\tIMULL\t[$]23"}, // 23*n
   1808 	},
   1809 	{
   1810 		fn: `
   1811 		func $(a, n int) int {
   1812 			return 19*a + a*n
   1813 		}`,
   1814 		pos: []string{"\tADDL\t[$]19", "\tIMULL"}, // (n+19)*a
   1815 	},
   1816 	{
   1817 		// check that stack store is optimized away
   1818 		fn: `
   1819 		func $() int {
   1820 			var x int
   1821 			return *(&x)
   1822 		}
   1823 		`,
   1824 		pos: []string{"TEXT\t.*, [$]0-4"},
   1825 	},
   1826 	{
   1827 		fn: `
   1828 		func mul3(n int) int {
   1829 			return 23*n - 9*n
   1830 		}`,
   1831 		pos: []string{"\tIMULL\t[$]14"}, // 14*n
   1832 	},
   1833 	{
   1834 		fn: `
   1835 		func mul4(a, n int) int {
   1836 			return n*a - a*19
   1837 		}`,
   1838 		pos: []string{"\tADDL\t[$]-19", "\tIMULL"}, // (n-19)*a
   1839 	},
   1840 	// Check that len() and cap() div by a constant power of two
   1841 	// are compiled into SHRL.
   1842 	{
   1843 		fn: `
   1844 		func $(a []int) int {
   1845 			return len(a) / 1024
   1846 		}
   1847 		`,
   1848 		pos: []string{"\tSHRL\t\\$10,"},
   1849 	},
   1850 	{
   1851 		fn: `
   1852 		func $(s string) int {
   1853 			return len(s) / (4097 >> 1)
   1854 		}
   1855 		`,
   1856 		pos: []string{"\tSHRL\t\\$11,"},
   1857 	},
   1858 	{
   1859 		fn: `
   1860 		func $(a []int) int {
   1861 			return cap(a) / ((1 << 11) + 2048)
   1862 		}
   1863 		`,
   1864 		pos: []string{"\tSHRL\t\\$12,"},
   1865 	},
   1866 	// Check that len() and cap() mod by a constant power of two
   1867 	// are compiled into ANDL.
   1868 	{
   1869 		fn: `
   1870 		func $(a []int) int {
   1871 			return len(a) % 1024
   1872 		}
   1873 		`,
   1874 		pos: []string{"\tANDL\t\\$1023,"},
   1875 	},
   1876 	{
   1877 		fn: `
   1878 		func $(s string) int {
   1879 			return len(s) % (4097 >> 1)
   1880 		}
   1881 		`,
   1882 		pos: []string{"\tANDL\t\\$2047,"},
   1883 	},
   1884 	{
   1885 		fn: `
   1886 		func $(a []int) int {
   1887 			return cap(a) % ((1 << 11) + 2048)
   1888 		}
   1889 		`,
   1890 		pos: []string{"\tANDL\t\\$4095,"},
   1891 	},
   1892 	{
   1893 		// Test that small memmove was replaced with direct movs
   1894 		fn: `
   1895                 func $() {
   1896                        x := [...]byte{1, 2, 3, 4, 5, 6, 7}
   1897                        copy(x[1:], x[:])
   1898                 }
   1899 		`,
   1900 		neg: []string{"memmove"},
   1901 	},
   1902 	{
   1903 		// Same as above but with different size
   1904 		fn: `
   1905                 func $() {
   1906                        x := [...]byte{1, 2, 3, 4}
   1907                        copy(x[1:], x[:])
   1908                 }
   1909 		`,
   1910 		neg: []string{"memmove"},
   1911 	},
   1912 }
   1913 
   1914 var linuxS390XTests = []*asmTest{
   1915 	{
   1916 		fn: `
   1917 		func f0(b []byte) uint32 {
   1918 			return binary.LittleEndian.Uint32(b)
   1919 		}
   1920 		`,
   1921 		pos: []string{"\tMOVWBR\t\\(.*\\),"},
   1922 	},
   1923 	{
   1924 		fn: `
   1925 		func f1(b []byte, i int) uint32 {
   1926 			return binary.LittleEndian.Uint32(b[i:])
   1927 		}
   1928 		`,
   1929 		pos: []string{"\tMOVWBR\t\\(.*\\)\\(.*\\*1\\),"},
   1930 	},
   1931 	{
   1932 		fn: `
   1933 		func f2(b []byte) uint64 {
   1934 			return binary.LittleEndian.Uint64(b)
   1935 		}
   1936 		`,
   1937 		pos: []string{"\tMOVDBR\t\\(.*\\),"},
   1938 	},
   1939 	{
   1940 		fn: `
   1941 		func f3(b []byte, i int) uint64 {
   1942 			return binary.LittleEndian.Uint64(b[i:])
   1943 		}
   1944 		`,
   1945 		pos: []string{"\tMOVDBR\t\\(.*\\)\\(.*\\*1\\),"},
   1946 	},
   1947 	{
   1948 		fn: `
   1949 		func f4(b []byte) uint32 {
   1950 			return binary.BigEndian.Uint32(b)
   1951 		}
   1952 		`,
   1953 		pos: []string{"\tMOVWZ\t\\(.*\\),"},
   1954 	},
   1955 	{
   1956 		fn: `
   1957 		func f5(b []byte, i int) uint32 {
   1958 			return binary.BigEndian.Uint32(b[i:])
   1959 		}
   1960 		`,
   1961 		pos: []string{"\tMOVWZ\t\\(.*\\)\\(.*\\*1\\),"},
   1962 	},
   1963 	{
   1964 		fn: `
   1965 		func f6(b []byte) uint64 {
   1966 			return binary.BigEndian.Uint64(b)
   1967 		}
   1968 		`,
   1969 		pos: []string{"\tMOVD\t\\(.*\\),"},
   1970 	},
   1971 	{
   1972 		fn: `
   1973 		func f7(b []byte, i int) uint64 {
   1974 			return binary.BigEndian.Uint64(b[i:])
   1975 		}
   1976 		`,
   1977 		pos: []string{"\tMOVD\t\\(.*\\)\\(.*\\*1\\),"},
   1978 	},
   1979 	{
   1980 		fn: `
   1981 		func f8(x uint64) uint64 {
   1982 			return x<<7 + x>>57
   1983 		}
   1984 		`,
   1985 		pos: []string{"\tRLLG\t[$]7,"},
   1986 	},
   1987 	{
   1988 		fn: `
   1989 		func f9(x uint64) uint64 {
   1990 			return x<<7 | x>>57
   1991 		}
   1992 		`,
   1993 		pos: []string{"\tRLLG\t[$]7,"},
   1994 	},
   1995 	{
   1996 		fn: `
   1997 		func f10(x uint64) uint64 {
   1998 			return x<<7 ^ x>>57
   1999 		}
   2000 		`,
   2001 		pos: []string{"\tRLLG\t[$]7,"},
   2002 	},
   2003 	{
   2004 		fn: `
   2005 		func f11(x uint32) uint32 {
   2006 			return x<<7 + x>>25
   2007 		}
   2008 		`,
   2009 		pos: []string{"\tRLL\t[$]7,"},
   2010 	},
   2011 	{
   2012 		fn: `
   2013 		func f12(x uint32) uint32 {
   2014 			return x<<7 | x>>25
   2015 		}
   2016 		`,
   2017 		pos: []string{"\tRLL\t[$]7,"},
   2018 	},
   2019 	{
   2020 		fn: `
   2021 		func f13(x uint32) uint32 {
   2022 			return x<<7 ^ x>>25
   2023 		}
   2024 		`,
   2025 		pos: []string{"\tRLL\t[$]7,"},
   2026 	},
   2027 	// Fused multiply-add/sub instructions.
   2028 	{
   2029 		fn: `
   2030 		func f14(x, y, z float64) float64 {
   2031 			return x * y + z
   2032 		}
   2033 		`,
   2034 		pos: []string{"\tFMADD\t"},
   2035 	},
   2036 	{
   2037 		fn: `
   2038 		func f15(x, y, z float64) float64 {
   2039 			return x * y - z
   2040 		}
   2041 		`,
   2042 		pos: []string{"\tFMSUB\t"},
   2043 	},
   2044 	{
   2045 		fn: `
   2046 		func f16(x, y, z float32) float32 {
   2047 			return x * y + z
   2048 		}
   2049 		`,
   2050 		pos: []string{"\tFMADDS\t"},
   2051 	},
   2052 	{
   2053 		fn: `
   2054 		func f17(x, y, z float32) float32 {
   2055 			return x * y - z
   2056 		}
   2057 		`,
   2058 		pos: []string{"\tFMSUBS\t"},
   2059 	},
   2060 	// Intrinsic tests for math/bits
   2061 	{
   2062 		fn: `
   2063 		func f18(a uint64) int {
   2064 			return bits.TrailingZeros64(a)
   2065 		}
   2066 		`,
   2067 		pos: []string{"\tFLOGR\t"},
   2068 	},
   2069 	{
   2070 		fn: `
   2071 		func f19(a uint32) int {
   2072 			return bits.TrailingZeros32(a)
   2073 		}
   2074 		`,
   2075 		pos: []string{"\tFLOGR\t", "\tMOVWZ\t"},
   2076 	},
   2077 	{
   2078 		fn: `
   2079 		func f20(a uint16) int {
   2080 			return bits.TrailingZeros16(a)
   2081 		}
   2082 		`,
   2083 		pos: []string{"\tFLOGR\t", "\tOR\t\\$65536,"},
   2084 	},
   2085 	{
   2086 		fn: `
   2087 		func f21(a uint8) int {
   2088 			return bits.TrailingZeros8(a)
   2089 		}
   2090 		`,
   2091 		pos: []string{"\tFLOGR\t", "\tOR\t\\$256,"},
   2092 	},
   2093 	// Intrinsic tests for math/bits
   2094 	{
   2095 		fn: `
   2096 		func f22(a uint64) uint64 {
   2097 			return bits.ReverseBytes64(a)
   2098 		}
   2099 		`,
   2100 		pos: []string{"\tMOVDBR\t"},
   2101 	},
   2102 	{
   2103 		fn: `
   2104 		func f23(a uint32) uint32 {
   2105 			return bits.ReverseBytes32(a)
   2106 		}
   2107 		`,
   2108 		pos: []string{"\tMOVWBR\t"},
   2109 	},
   2110 	{
   2111 		fn: `
   2112 		func f24(a uint64) int {
   2113 			return bits.Len64(a)
   2114 		}
   2115 		`,
   2116 		pos: []string{"\tFLOGR\t"},
   2117 	},
   2118 	{
   2119 		fn: `
   2120 		func f25(a uint32) int {
   2121 			return bits.Len32(a)
   2122 		}
   2123 		`,
   2124 		pos: []string{"\tFLOGR\t"},
   2125 	},
   2126 	{
   2127 		fn: `
   2128 		func f26(a uint16) int {
   2129 			return bits.Len16(a)
   2130 		}
   2131 		`,
   2132 		pos: []string{"\tFLOGR\t"},
   2133 	},
   2134 	{
   2135 		fn: `
   2136 		func f27(a uint8) int {
   2137 			return bits.Len8(a)
   2138 		}
   2139 		`,
   2140 		pos: []string{"\tFLOGR\t"},
   2141 	},
   2142 	{
   2143 		fn: `
   2144 		func f28(a uint) int {
   2145 			return bits.Len(a)
   2146 		}
   2147 		`,
   2148 		pos: []string{"\tFLOGR\t"},
   2149 	},
   2150 	{
   2151 		fn: `
   2152 		func f29(a uint64) int {
   2153 			return bits.LeadingZeros64(a)
   2154 		}
   2155 		`,
   2156 		pos: []string{"\tFLOGR\t"},
   2157 	},
   2158 	{
   2159 		fn: `
   2160 		func f30(a uint32) int {
   2161 			return bits.LeadingZeros32(a)
   2162 		}
   2163 		`,
   2164 		pos: []string{"\tFLOGR\t"},
   2165 	},
   2166 	{
   2167 		fn: `
   2168 		func f31(a uint16) int {
   2169 			return bits.LeadingZeros16(a)
   2170 		}
   2171 		`,
   2172 		pos: []string{"\tFLOGR\t"},
   2173 	},
   2174 	{
   2175 		fn: `
   2176 		func f32(a uint8) int {
   2177 			return bits.LeadingZeros8(a)
   2178 		}
   2179 		`,
   2180 		pos: []string{"\tFLOGR\t"},
   2181 	},
   2182 	{
   2183 		fn: `
   2184 		func f33(a uint) int {
   2185 			return bits.LeadingZeros(a)
   2186 		}
   2187 		`,
   2188 		pos: []string{"\tFLOGR\t"},
   2189 	},
   2190 	// Intrinsic tests for math.
   2191 	{
   2192 		fn: `
   2193 		func ceil(x float64) float64 {
   2194 			return math.Ceil(x)
   2195 		}
   2196 		`,
   2197 		pos: []string{"\tFIDBR\t[$]6"},
   2198 	},
   2199 	{
   2200 		fn: `
   2201 		func floor(x float64) float64 {
   2202 			return math.Floor(x)
   2203 		}
   2204 		`,
   2205 		pos: []string{"\tFIDBR\t[$]7"},
   2206 	},
   2207 	{
   2208 		fn: `
   2209 		func round(x float64) float64 {
   2210 			return math.Round(x)
   2211 		}
   2212 		`,
   2213 		pos: []string{"\tFIDBR\t[$]1"},
   2214 	},
   2215 	{
   2216 		fn: `
   2217 		func trunc(x float64) float64 {
   2218 			return math.Trunc(x)
   2219 		}
   2220 		`,
   2221 		pos: []string{"\tFIDBR\t[$]5"},
   2222 	},
   2223 	{
   2224 		fn: `
   2225 		func roundToEven(x float64) float64 {
   2226 			return math.RoundToEven(x)
   2227 		}
   2228 		`,
   2229 		pos: []string{"\tFIDBR\t[$]4"},
   2230 	},
   2231 	{
   2232 		// check that stack store is optimized away
   2233 		fn: `
   2234 		func $() int {
   2235 			var x int
   2236 			return *(&x)
   2237 		}
   2238 		`,
   2239 		pos: []string{"TEXT\t.*, [$]0-8"},
   2240 	},
   2241 	// Constant propagation through raw bits conversions.
   2242 	{
   2243 		// uint32 constant converted to float32 constant
   2244 		fn: `
   2245 		func $(x float32) float32 {
   2246 			if x > math.Float32frombits(0x3f800000) {
   2247 				return -x
   2248 			}
   2249 			return x
   2250 		}
   2251 		`,
   2252 		pos: []string{"\tFMOVS\t[$]f32.3f800000\\(SB\\)"},
   2253 	},
   2254 	{
   2255 		// float32 constant converted to uint32 constant
   2256 		fn: `
   2257 		func $(x uint32) uint32 {
   2258 			if x > math.Float32bits(1) {
   2259 				return -x
   2260 			}
   2261 			return x
   2262 		}
   2263 		`,
   2264 		neg: []string{"\tFMOVS\t"},
   2265 	},
   2266 	// Constant propagation through float comparisons.
   2267 	{
   2268 		fn: `
   2269 		func $() bool {
   2270 			return 0.5 == float64(uint32(1)) ||
   2271 				1.5 > float64(uint64(1<<63)) ||
   2272 				math.NaN() == math.NaN()
   2273 		}
   2274 		`,
   2275 		pos: []string{"\tMOV(B|BZ|D)\t[$]0,"},
   2276 		neg: []string{"\tFCMPU\t", "\tMOV(B|BZ|D)\t[$]1,"},
   2277 	},
   2278 	{
   2279 		fn: `
   2280 		func $() bool {
   2281 			return float32(0.5) <= float32(int64(1)) &&
   2282 				float32(1.5) >= float32(int32(-1<<31)) &&
   2283 				float32(math.NaN()) != float32(math.NaN())
   2284 		}
   2285 		`,
   2286 		pos: []string{"\tMOV(B|BZ|D)\t[$]1,"},
   2287 		neg: []string{"\tCEBR\t", "\tMOV(B|BZ|D)\t[$]0,"},
   2288 	},
   2289 	// math tests
   2290 	{
   2291 		fn: `
   2292 		func $(x float64) float64 {
   2293 			return math.Abs(x)
   2294 		}
   2295 		`,
   2296 		pos: []string{"\tLPDFR\t"},
   2297 		neg: []string{"\tMOVD\t"}, // no integer loads/stores
   2298 	},
   2299 	{
   2300 		fn: `
   2301 		func $(x float32) float32 {
   2302 			return float32(math.Abs(float64(x)))
   2303 		}
   2304 		`,
   2305 		pos: []string{"\tLPDFR\t"},
   2306 		neg: []string{"\tLDEBR\t", "\tLEDBR\t"}, // no float64 conversion
   2307 	},
   2308 	{
   2309 		fn: `
   2310 		func $(x float64) float64 {
   2311 			return math.Float64frombits(math.Float64bits(x)|1<<63)
   2312 		}
   2313 		`,
   2314 		pos: []string{"\tLNDFR\t"},
   2315 		neg: []string{"\tMOVD\t"}, // no integer loads/stores
   2316 	},
   2317 	{
   2318 		fn: `
   2319 		func $(x float64) float64 {
   2320 			return -math.Abs(x)
   2321 		}
   2322 		`,
   2323 		pos: []string{"\tLNDFR\t"},
   2324 		neg: []string{"\tMOVD\t"}, // no integer loads/stores
   2325 	},
   2326 	{
   2327 		fn: `
   2328 		func $(x, y float64) float64 {
   2329 			return math.Copysign(x, y)
   2330 		}
   2331 		`,
   2332 		pos: []string{"\tCPSDR\t"},
   2333 		neg: []string{"\tMOVD\t"}, // no integer loads/stores
   2334 	},
   2335 	{
   2336 		fn: `
   2337 		func $(x float64) float64 {
   2338 			return math.Copysign(x, -1)
   2339 		}
   2340 		`,
   2341 		pos: []string{"\tLNDFR\t"},
   2342 		neg: []string{"\tMOVD\t"}, // no integer loads/stores
   2343 	},
   2344 	{
   2345 		fn: `
   2346 		func $(x float64) float64 {
   2347 			return math.Copysign(-1, x)
   2348 		}
   2349 		`,
   2350 		pos: []string{"\tCPSDR\t"},
   2351 		neg: []string{"\tMOVD\t"}, // no integer loads/stores
   2352 	},
   2353 }
   2354 
   2355 var linuxARMTests = []*asmTest{
   2356 	// multiplication by powers of two
   2357 	{
   2358 		fn: `
   2359 		func $(n int) int {
   2360 			return 16*n
   2361 		}
   2362 		`,
   2363 		pos: []string{"\tSLL\t[$]4"},
   2364 		neg: []string{"\tMUL\t"},
   2365 	},
   2366 	{
   2367 		fn: `
   2368 		func $(n int) int {
   2369 			return -32*n
   2370 		}
   2371 		`,
   2372 		pos: []string{"\tSLL\t[$]5"},
   2373 		neg: []string{"\tMUL\t"},
   2374 	},
   2375 
   2376 	{
   2377 		fn: `
   2378 		func f0(x uint32) uint32 {
   2379 			return x<<7 + x>>25
   2380 		}
   2381 		`,
   2382 		pos: []string{"\tMOVW\tR[0-9]+@>25,"},
   2383 	},
   2384 	{
   2385 		fn: `
   2386 		func f1(x uint32) uint32 {
   2387 			return x<<7 | x>>25
   2388 		}
   2389 		`,
   2390 		pos: []string{"\tMOVW\tR[0-9]+@>25,"},
   2391 	},
   2392 	{
   2393 		fn: `
   2394 		func f2(x uint32) uint32 {
   2395 			return x<<7 ^ x>>25
   2396 		}
   2397 		`,
   2398 		pos: []string{"\tMOVW\tR[0-9]+@>25,"},
   2399 	},
   2400 	{
   2401 		fn: `
   2402 		func f3(a uint64) int {
   2403 			return bits.Len64(a)
   2404 		}
   2405 		`,
   2406 		pos: []string{"\tCLZ\t"},
   2407 	},
   2408 	{
   2409 		fn: `
   2410 		func f4(a uint32) int {
   2411 			return bits.Len32(a)
   2412 		}
   2413 		`,
   2414 		pos: []string{"\tCLZ\t"},
   2415 	},
   2416 	{
   2417 		fn: `
   2418 		func f5(a uint16) int {
   2419 			return bits.Len16(a)
   2420 		}
   2421 		`,
   2422 		pos: []string{"\tCLZ\t"},
   2423 	},
   2424 	{
   2425 		fn: `
   2426 		func f6(a uint8) int {
   2427 			return bits.Len8(a)
   2428 		}
   2429 		`,
   2430 		pos: []string{"\tCLZ\t"},
   2431 	},
   2432 	{
   2433 		fn: `
   2434 		func f7(a uint) int {
   2435 			return bits.Len(a)
   2436 		}
   2437 		`,
   2438 		pos: []string{"\tCLZ\t"},
   2439 	},
   2440 	{
   2441 		fn: `
   2442 		func f8(a uint64) int {
   2443 			return bits.LeadingZeros64(a)
   2444 		}
   2445 		`,
   2446 		pos: []string{"\tCLZ\t"},
   2447 	},
   2448 	{
   2449 		fn: `
   2450 		func f9(a uint32) int {
   2451 			return bits.LeadingZeros32(a)
   2452 		}
   2453 		`,
   2454 		pos: []string{"\tCLZ\t"},
   2455 	},
   2456 	{
   2457 		fn: `
   2458 		func f10(a uint16) int {
   2459 			return bits.LeadingZeros16(a)
   2460 		}
   2461 		`,
   2462 		pos: []string{"\tCLZ\t"},
   2463 	},
   2464 	{
   2465 		fn: `
   2466 		func f11(a uint8) int {
   2467 			return bits.LeadingZeros8(a)
   2468 		}
   2469 		`,
   2470 		pos: []string{"\tCLZ\t"},
   2471 	},
   2472 	{
   2473 		fn: `
   2474 		func f12(a uint) int {
   2475 			return bits.LeadingZeros(a)
   2476 		}
   2477 		`,
   2478 		pos: []string{"\tCLZ\t"},
   2479 	},
   2480 	{
   2481 		// make sure assembly output has matching offset and base register.
   2482 		fn: `
   2483 		func f13(a, b int) int {
   2484 			runtime.GC() // use some frame
   2485 			return b
   2486 		}
   2487 		`,
   2488 		pos: []string{"b\\+4\\(FP\\)"},
   2489 	},
   2490 	{
   2491 		// check that stack store is optimized away
   2492 		fn: `
   2493 		func $() int {
   2494 			var x int
   2495 			return *(&x)
   2496 		}
   2497 		`,
   2498 		pos: []string{"TEXT\t.*, [$]-4-4"},
   2499 	},
   2500 }
   2501 
   2502 var linuxARM64Tests = []*asmTest{
   2503 	// multiplication by powers of two
   2504 	{
   2505 		fn: `
   2506 		func $(n int) int {
   2507 			return 64*n
   2508 		}
   2509 		`,
   2510 		pos: []string{"\tLSL\t[$]6"},
   2511 		neg: []string{"\tMUL\t"},
   2512 	},
   2513 	{
   2514 		fn: `
   2515 		func $(n int) int {
   2516 			return -128*n
   2517 		}
   2518 		`,
   2519 		pos: []string{"\tLSL\t[$]7"},
   2520 		neg: []string{"\tMUL\t"},
   2521 	},
   2522 
   2523 	{
   2524 		fn: `
   2525 		func f0(x uint64) uint64 {
   2526 			return x<<7 + x>>57
   2527 		}
   2528 		`,
   2529 		pos: []string{"\tROR\t[$]57,"},
   2530 	},
   2531 	{
   2532 		fn: `
   2533 		func f1(x uint64) uint64 {
   2534 			return x<<7 | x>>57
   2535 		}
   2536 		`,
   2537 		pos: []string{"\tROR\t[$]57,"},
   2538 	},
   2539 	{
   2540 		fn: `
   2541 		func f2(x uint64) uint64 {
   2542 			return x<<7 ^ x>>57
   2543 		}
   2544 		`,
   2545 		pos: []string{"\tROR\t[$]57,"},
   2546 	},
   2547 	{
   2548 		fn: `
   2549 		func f3(x uint32) uint32 {
   2550 			return x<<7 + x>>25
   2551 		}
   2552 		`,
   2553 		pos: []string{"\tRORW\t[$]25,"},
   2554 	},
   2555 	{
   2556 		fn: `
   2557 		func f4(x uint32) uint32 {
   2558 			return x<<7 | x>>25
   2559 		}
   2560 		`,
   2561 		pos: []string{"\tRORW\t[$]25,"},
   2562 	},
   2563 	{
   2564 		fn: `
   2565 		func f5(x uint32) uint32 {
   2566 			return x<<7 ^ x>>25
   2567 		}
   2568 		`,
   2569 		pos: []string{"\tRORW\t[$]25,"},
   2570 	},
   2571 	{
   2572 		fn: `
   2573 		func f22(a uint64) uint64 {
   2574 			return bits.ReverseBytes64(a)
   2575 		}
   2576 		`,
   2577 		pos: []string{"\tREV\t"},
   2578 	},
   2579 	{
   2580 		fn: `
   2581 		func f23(a uint32) uint32 {
   2582 			return bits.ReverseBytes32(a)
   2583 		}
   2584 		`,
   2585 		pos: []string{"\tREVW\t"},
   2586 	},
   2587 	{
   2588 		fn: `
   2589 		func f24(a uint64) int {
   2590 			return bits.Len64(a)
   2591 		}
   2592 		`,
   2593 		pos: []string{"\tCLZ\t"},
   2594 	},
   2595 	{
   2596 		fn: `
   2597 		func f25(a uint32) int {
   2598 			return bits.Len32(a)
   2599 		}
   2600 		`,
   2601 		pos: []string{"\tCLZ\t"},
   2602 	},
   2603 	{
   2604 		fn: `
   2605 		func f26(a uint16) int {
   2606 			return bits.Len16(a)
   2607 		}
   2608 		`,
   2609 		pos: []string{"\tCLZ\t"},
   2610 	},
   2611 	{
   2612 		fn: `
   2613 		func f27(a uint8) int {
   2614 			return bits.Len8(a)
   2615 		}
   2616 		`,
   2617 		pos: []string{"\tCLZ\t"},
   2618 	},
   2619 	{
   2620 		fn: `
   2621 		func f28(a uint) int {
   2622 			return bits.Len(a)
   2623 		}
   2624 		`,
   2625 		pos: []string{"\tCLZ\t"},
   2626 	},
   2627 	{
   2628 		fn: `
   2629 		func f29(a uint64) int {
   2630 			return bits.LeadingZeros64(a)
   2631 		}
   2632 		`,
   2633 		pos: []string{"\tCLZ\t"},
   2634 	},
   2635 	{
   2636 		fn: `
   2637 		func f30(a uint32) int {
   2638 			return bits.LeadingZeros32(a)
   2639 		}
   2640 		`,
   2641 		pos: []string{"\tCLZ\t"},
   2642 	},
   2643 	{
   2644 		fn: `
   2645 		func f31(a uint16) int {
   2646 			return bits.LeadingZeros16(a)
   2647 		}
   2648 		`,
   2649 		pos: []string{"\tCLZ\t"},
   2650 	},
   2651 	{
   2652 		fn: `
   2653 		func f32(a uint8) int {
   2654 			return bits.LeadingZeros8(a)
   2655 		}
   2656 		`,
   2657 		pos: []string{"\tCLZ\t"},
   2658 	},
   2659 	{
   2660 		fn: `
   2661 		func f33(a uint) int {
   2662 			return bits.LeadingZeros(a)
   2663 		}
   2664 		`,
   2665 		pos: []string{"\tCLZ\t"},
   2666 	},
   2667 	{
   2668 		fn: `
   2669 		func f34(a uint64) uint64 {
   2670 			return a & ((1<<63)-1)
   2671 		}
   2672 		`,
   2673 		pos: []string{"\tAND\t"},
   2674 	},
   2675 	{
   2676 		fn: `
   2677 		func f35(a uint64) uint64 {
   2678 			return a & (1<<63)
   2679 		}
   2680 		`,
   2681 		pos: []string{"\tAND\t"},
   2682 	},
   2683 	{
   2684 		// make sure offsets are folded into load and store.
   2685 		fn: `
   2686 		func f36(_, a [20]byte) (b [20]byte) {
   2687 			b = a
   2688 			return
   2689 		}
   2690 		`,
   2691 		pos: []string{"\tMOVD\t\"\"\\.a\\+[0-9]+\\(FP\\), R[0-9]+", "\tMOVD\tR[0-9]+, \"\"\\.b\\+[0-9]+\\(FP\\)"},
   2692 	},
   2693 	{
   2694 		// check that stack store is optimized away
   2695 		fn: `
   2696 		func $() int {
   2697 			var x int
   2698 			return *(&x)
   2699 		}
   2700 		`,
   2701 		pos: []string{"TEXT\t.*, [$]-8-8"},
   2702 	},
   2703 	{
   2704 		// check that we don't emit comparisons for constant shift
   2705 		fn: `
   2706 //go:nosplit
   2707 		func $(x int) int {
   2708 			return x << 17
   2709 		}
   2710 		`,
   2711 		pos: []string{"LSL\t\\$17"},
   2712 		neg: []string{"CMP"},
   2713 	},
   2714 }
   2715 
   2716 var linuxMIPSTests = []*asmTest{
   2717 	{
   2718 		fn: `
   2719 		func f0(a uint64) int {
   2720 			return bits.Len64(a)
   2721 		}
   2722 		`,
   2723 		pos: []string{"\tCLZ\t"},
   2724 	},
   2725 	{
   2726 		fn: `
   2727 		func f1(a uint32) int {
   2728 			return bits.Len32(a)
   2729 		}
   2730 		`,
   2731 		pos: []string{"\tCLZ\t"},
   2732 	},
   2733 	{
   2734 		fn: `
   2735 		func f2(a uint16) int {
   2736 			return bits.Len16(a)
   2737 		}
   2738 		`,
   2739 		pos: []string{"\tCLZ\t"},
   2740 	},
   2741 	{
   2742 		fn: `
   2743 		func f3(a uint8) int {
   2744 			return bits.Len8(a)
   2745 		}
   2746 		`,
   2747 		pos: []string{"\tCLZ\t"},
   2748 	},
   2749 	{
   2750 		fn: `
   2751 		func f4(a uint) int {
   2752 			return bits.Len(a)
   2753 		}
   2754 		`,
   2755 		pos: []string{"\tCLZ\t"},
   2756 	},
   2757 	{
   2758 		fn: `
   2759 		func f5(a uint64) int {
   2760 			return bits.LeadingZeros64(a)
   2761 		}
   2762 		`,
   2763 		pos: []string{"\tCLZ\t"},
   2764 	},
   2765 	{
   2766 		fn: `
   2767 		func f6(a uint32) int {
   2768 			return bits.LeadingZeros32(a)
   2769 		}
   2770 		`,
   2771 		pos: []string{"\tCLZ\t"},
   2772 	},
   2773 	{
   2774 		fn: `
   2775 		func f7(a uint16) int {
   2776 			return bits.LeadingZeros16(a)
   2777 		}
   2778 		`,
   2779 		pos: []string{"\tCLZ\t"},
   2780 	},
   2781 	{
   2782 		fn: `
   2783 		func f8(a uint8) int {
   2784 			return bits.LeadingZeros8(a)
   2785 		}
   2786 		`,
   2787 		pos: []string{"\tCLZ\t"},
   2788 	},
   2789 	{
   2790 		fn: `
   2791 		func f9(a uint) int {
   2792 			return bits.LeadingZeros(a)
   2793 		}
   2794 		`,
   2795 		pos: []string{"\tCLZ\t"},
   2796 	},
   2797 	{
   2798 		// check that stack store is optimized away
   2799 		fn: `
   2800 		func $() int {
   2801 			var x int
   2802 			return *(&x)
   2803 		}
   2804 		`,
   2805 		pos: []string{"TEXT\t.*, [$]-4-4"},
   2806 	},
   2807 }
   2808 
   2809 var linuxMIPS64Tests = []*asmTest{
   2810 	{
   2811 		// check that we don't emit comparisons for constant shift
   2812 		fn: `
   2813 		func $(x int) int {
   2814 			return x << 17
   2815 		}
   2816 		`,
   2817 		pos: []string{"SLLV\t\\$17"},
   2818 		neg: []string{"SGT"},
   2819 	},
   2820 }
   2821 
   2822 var linuxPPC64LETests = []*asmTest{
   2823 	// Fused multiply-add/sub instructions.
   2824 	{
   2825 		fn: `
   2826 		func f0(x, y, z float64) float64 {
   2827 			return x * y + z
   2828 		}
   2829 		`,
   2830 		pos: []string{"\tFMADD\t"},
   2831 	},
   2832 	{
   2833 		fn: `
   2834 		func f1(x, y, z float64) float64 {
   2835 			return x * y - z
   2836 		}
   2837 		`,
   2838 		pos: []string{"\tFMSUB\t"},
   2839 	},
   2840 	{
   2841 		fn: `
   2842 		func f2(x, y, z float32) float32 {
   2843 			return x * y + z
   2844 		}
   2845 		`,
   2846 		pos: []string{"\tFMADDS\t"},
   2847 	},
   2848 	{
   2849 		fn: `
   2850 		func f3(x, y, z float32) float32 {
   2851 			return x * y - z
   2852 		}
   2853 		`,
   2854 		pos: []string{"\tFMSUBS\t"},
   2855 	},
   2856 	{
   2857 		fn: `
   2858 		func f4(x uint32) uint32 {
   2859 			return x<<7 | x>>25
   2860 		}
   2861 		`,
   2862 		pos: []string{"\tROTLW\t"},
   2863 	},
   2864 	{
   2865 		fn: `
   2866 		func f5(x uint32) uint32 {
   2867 			return x<<7 + x>>25
   2868 		}
   2869 		`,
   2870 		pos: []string{"\tROTLW\t"},
   2871 	},
   2872 	{
   2873 		fn: `
   2874 		func f6(x uint32) uint32 {
   2875 			return x<<7 ^ x>>25
   2876 		}
   2877 		`,
   2878 		pos: []string{"\tROTLW\t"},
   2879 	},
   2880 	{
   2881 		fn: `
   2882 		func f7(x uint64) uint64 {
   2883 			return x<<7 | x>>57
   2884 		}
   2885 		`,
   2886 		pos: []string{"\tROTL\t"},
   2887 	},
   2888 	{
   2889 		fn: `
   2890 		func f8(x uint64) uint64 {
   2891 			return x<<7 + x>>57
   2892 		}
   2893 		`,
   2894 		pos: []string{"\tROTL\t"},
   2895 	},
   2896 	{
   2897 		fn: `
   2898 		func f9(x uint64) uint64 {
   2899 			return x<<7 ^ x>>57
   2900 		}
   2901 		`,
   2902 		pos: []string{"\tROTL\t"},
   2903 	},
   2904 	{
   2905 		fn: `
   2906 		func f10(a uint32) uint32 {
   2907 			return bits.RotateLeft32(a, 9)
   2908 		}
   2909 		`,
   2910 		pos: []string{"\tROTLW\t"},
   2911 	},
   2912 	{
   2913 		fn: `
   2914 		func f11(a uint64) uint64 {
   2915 			return bits.RotateLeft64(a, 37)
   2916 		}
   2917 		`,
   2918 		pos: []string{"\tROTL\t"},
   2919 	},
   2920 
   2921 	{
   2922 		fn: `
   2923                 func f12(a, b float64) float64 {
   2924                         return math.Copysign(a, b)
   2925                 }
   2926                 `,
   2927 		pos: []string{"\tFCPSGN\t"},
   2928 	},
   2929 
   2930 	{
   2931 		fn: `
   2932                 func f13(a float64) float64 {
   2933                         return math.Abs(a)
   2934                 }
   2935                 `,
   2936 		pos: []string{"\tFABS\t"},
   2937 	},
   2938 
   2939 	{
   2940 		fn: `
   2941 		func f14(b []byte) uint16 {
   2942 			return binary.LittleEndian.Uint16(b)
   2943 	}
   2944 		`,
   2945 		pos: []string{"\tMOVHZ\t"},
   2946 	},
   2947 	{
   2948 		fn: `
   2949 		func f15(b []byte) uint32 {
   2950 			return binary.LittleEndian.Uint32(b)
   2951 		}
   2952 		`,
   2953 		pos: []string{"\tMOVWZ\t"},
   2954 	},
   2955 
   2956 	{
   2957 		fn: `
   2958 		func f16(b []byte) uint64 {
   2959 			return binary.LittleEndian.Uint64(b)
   2960 		}
   2961 		`,
   2962 		pos: []string{"\tMOVD\t"},
   2963 		neg: []string{"MOVBZ", "MOVHZ", "MOVWZ"},
   2964 	},
   2965 
   2966 	{
   2967 		fn: `
   2968 		func f17(b []byte, v uint16) {
   2969 			binary.LittleEndian.PutUint16(b, v)
   2970 		}
   2971 		`,
   2972 		pos: []string{"\tMOVH\t"},
   2973 	},
   2974 
   2975 	{
   2976 		fn: `
   2977 		func f18(b []byte, v uint32) {
   2978 			binary.LittleEndian.PutUint32(b, v)
   2979 		}
   2980 		`,
   2981 		pos: []string{"\tMOVW\t"},
   2982 	},
   2983 
   2984 	{
   2985 		fn: `
   2986 		func f19(b []byte, v uint64) {
   2987 			binary.LittleEndian.PutUint64(b, v)
   2988 		}
   2989 		`,
   2990 		pos: []string{"\tMOVD\t"},
   2991 		neg: []string{"MOVB", "MOVH", "MOVW"},
   2992 	},
   2993 
   2994 	{
   2995 		// check that stack store is optimized away
   2996 		fn: `
   2997 		func $() int {
   2998 			var x int
   2999 			return *(&x)
   3000 		}
   3001 		`,
   3002 		pos: []string{"TEXT\t.*, [$]0-8"},
   3003 	},
   3004 	// Constant propagation through raw bits conversions.
   3005 	{
   3006 		// uint32 constant converted to float32 constant
   3007 		fn: `
   3008 		func $(x float32) float32 {
   3009 			if x > math.Float32frombits(0x3f800000) {
   3010 				return -x
   3011 			}
   3012 			return x
   3013 		}
   3014 		`,
   3015 		pos: []string{"\tFMOVS\t[$]f32.3f800000\\(SB\\)"},
   3016 	},
   3017 	{
   3018 		// float32 constant converted to uint32 constant
   3019 		fn: `
   3020 		func $(x uint32) uint32 {
   3021 			if x > math.Float32bits(1) {
   3022 				return -x
   3023 			}
   3024 			return x
   3025 		}
   3026 		`,
   3027 		neg: []string{"\tFMOVS\t"},
   3028 	},
   3029 }
   3030 
   3031 var plan9AMD64Tests = []*asmTest{
   3032 	// We should make sure that the compiler doesn't generate floating point
   3033 	// instructions for non-float operations on Plan 9, because floating point
   3034 	// operations are not allowed in the note handler.
   3035 	// Array zeroing.
   3036 	{
   3037 		fn: `
   3038 		func $() [16]byte {
   3039 			var a [16]byte
   3040 			return a
   3041 		}
   3042 		`,
   3043 		pos: []string{"\tMOVQ\t\\$0, \"\""},
   3044 	},
   3045 	// Array copy.
   3046 	{
   3047 		fn: `
   3048 		func $(a [16]byte) (b [16]byte) {
   3049 			b = a
   3050 			return
   3051 		}
   3052 		`,
   3053 		pos: []string{"\tMOVQ\t\"\"\\.a\\+[0-9]+\\(SP\\), (AX|CX)", "\tMOVQ\t(AX|CX), \"\"\\.b\\+[0-9]+\\(SP\\)"},
   3054 	},
   3055 }
   3056 
   3057 // TestLineNumber checks to make sure the generated assembly has line numbers
   3058 // see issue #16214
   3059 func TestLineNumber(t *testing.T) {
   3060 	testenv.MustHaveGoBuild(t)
   3061 	dir, err := ioutil.TempDir("", "TestLineNumber")
   3062 	if err != nil {
   3063 		t.Fatalf("could not create directory: %v", err)
   3064 	}
   3065 	defer os.RemoveAll(dir)
   3066 
   3067 	src := filepath.Join(dir, "x.go")
   3068 	err = ioutil.WriteFile(src, []byte(issue16214src), 0644)
   3069 	if err != nil {
   3070 		t.Fatalf("could not write file: %v", err)
   3071 	}
   3072 
   3073 	cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-S", "-o", filepath.Join(dir, "out.o"), src)
   3074 	out, err := cmd.CombinedOutput()
   3075 	if err != nil {
   3076 		t.Fatalf("fail to run go tool compile: %v", err)
   3077 	}
   3078 
   3079 	if strings.Contains(string(out), "unknown line number") {
   3080 		t.Errorf("line number missing in assembly:\n%s", out)
   3081 	}
   3082 }
   3083 
   3084 var issue16214src = `
   3085 package main
   3086 
   3087 func Mod32(x uint32) uint32 {
   3088 	return x % 3 // frontend rewrites it as HMUL with 2863311531, the LITERAL node has unknown Pos
   3089 }
   3090 `
   3091