github.com/corona10/go@v0.0.0-20180224231303-7a218942be57/src/cmd/compile/internal/gc/asm_test.go (about)

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