github.com/yukk001/go1.10.8@v0.0.0-20190813125351-6df2d3982e20/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"},
   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  `