github.com/kdevb0x/go@v0.0.0-20180115030120-39687051e9e7/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 f70(a,b [15]byte) bool {
  1008  		    return a == b
  1009  		}`,
  1010  		pos: []string{"\tCMPQ\t[A-Z]"},
  1011  	},
  1012  	{
  1013  		fn: `
  1014  		func f71(a,b unsafe.Pointer) bool { // This was a TODO in mapaccess1_faststr
  1015  		    return *((*[4]byte)(a)) != *((*[4]byte)(b))
  1016  		}`,
  1017  		pos: []string{"\tCMPL\t[A-Z]"},
  1018  	},
  1019  	{
  1020  		// make sure assembly output has matching offset and base register.
  1021  		fn: `
  1022  		func f72(a, b int) int {
  1023  			runtime.GC() // use some frame
  1024  			return b
  1025  		}
  1026  		`,
  1027  		pos: []string{"b\\+24\\(SP\\)"},
  1028  	},
  1029  	{
  1030  		// check load combining
  1031  		fn: `
  1032  		func f73(a, b byte) (byte,byte) {
  1033  		    return f73(f73(a,b))
  1034  		}
  1035  		`,
  1036  		pos: []string{"\tMOVW\t"},
  1037  	},
  1038  	{
  1039  		fn: `
  1040  		func f74(a, b uint16) (uint16,uint16) {
  1041  		    return f74(f74(a,b))
  1042  		}
  1043  		`,
  1044  		pos: []string{"\tMOVL\t"},
  1045  	},
  1046  	{
  1047  		fn: `
  1048  		func f75(a, b uint32) (uint32,uint32) {
  1049  		    return f75(f75(a,b))
  1050  		}
  1051  		`,
  1052  		pos: []string{"\tMOVQ\t"},
  1053  	},
  1054  	{
  1055  		fn: `
  1056  		func f76(a, b uint64) (uint64,uint64) {
  1057  		    return f76(f76(a,b))
  1058  		}
  1059  		`,
  1060  		pos: []string{"\tMOVUPS\t"},
  1061  	},
  1062  	// Make sure we don't put pointers in SSE registers across safe points.
  1063  	{
  1064  		fn: `
  1065  		func $(p, q *[2]*int)  {
  1066  		    a, b := p[0], p[1]
  1067  		    runtime.GC()
  1068  		    q[0], q[1] = a, b
  1069  		}
  1070  		`,
  1071  		neg: []string{"MOVUPS"},
  1072  	},
  1073  	{
  1074  		// check that stack store is optimized away
  1075  		fn: `
  1076  		func $() int {
  1077  			var x int
  1078  			return *(&x)
  1079  		}
  1080  		`,
  1081  		pos: []string{"TEXT\t.*, [$]0-8"},
  1082  	},
  1083  	// math.Abs using integer registers
  1084  	{
  1085  		fn: `
  1086  		func $(x float64) float64 {
  1087  			return math.Abs(x)
  1088  		}
  1089  		`,
  1090  		pos: []string{"\tSHLQ\t[$]1,", "\tSHRQ\t[$]1,"},
  1091  	},
  1092  	// math.Copysign using integer registers
  1093  	{
  1094  		fn: `
  1095  		func $(x, y float64) float64 {
  1096  			return math.Copysign(x, y)
  1097  		}
  1098  		`,
  1099  		pos: []string{"\tSHLQ\t[$]1,", "\tSHRQ\t[$]1,", "\tSHRQ\t[$]63,", "\tSHLQ\t[$]63,", "\tORQ\t"},
  1100  	},
  1101  	// int <-> fp moves
  1102  	{
  1103  		fn: `
  1104  		func $(x float64) uint64 {
  1105  			return math.Float64bits(x+1) + 1
  1106  		}
  1107  		`,
  1108  		pos: []string{"\tMOVQ\tX.*, [^X].*"},
  1109  	},
  1110  	{
  1111  		fn: `
  1112  		func $(x float32) uint32 {
  1113  			return math.Float32bits(x+1) + 1
  1114  		}
  1115  		`,
  1116  		pos: []string{"\tMOVL\tX.*, [^X].*"},
  1117  	},
  1118  	{
  1119  		fn: `
  1120  		func $(x uint64) float64 {
  1121  			return math.Float64frombits(x+1) + 1
  1122  		}
  1123  		`,
  1124  		pos: []string{"\tMOVQ\t[^X].*, X.*"},
  1125  	},
  1126  	{
  1127  		fn: `
  1128  		func $(x uint32) float32 {
  1129  			return math.Float32frombits(x+1) + 1
  1130  		}
  1131  		`,
  1132  		pos: []string{"\tMOVL\t[^X].*, X.*"},
  1133  	},
  1134  	{
  1135  		fn: `
  1136  		func $(x uint32) bool {
  1137  			return x > 4
  1138  		}
  1139  		`,
  1140  		pos: []string{"\tSETHI\t\\("},
  1141  	},
  1142  	// Check that len() and cap() div by a constant power of two
  1143  	// are compiled into SHRQ.
  1144  	{
  1145  		fn: `
  1146  		func $(a []int) int {
  1147  			return len(a) / 1024
  1148  		}
  1149  		`,
  1150  		pos: []string{"\tSHRQ\t\\$10,"},
  1151  	},
  1152  	{
  1153  		fn: `
  1154  		func $(s string) int {
  1155  			return len(s) / (4097 >> 1)
  1156  		}
  1157  		`,
  1158  		pos: []string{"\tSHRQ\t\\$11,"},
  1159  	},
  1160  	{
  1161  		fn: `
  1162  		func $(a []int) int {
  1163  			return cap(a) / ((1 << 11) + 2048)
  1164  		}
  1165  		`,
  1166  		pos: []string{"\tSHRQ\t\\$12,"},
  1167  	},
  1168  	// Check that len() and cap() mod by a constant power of two
  1169  	// are compiled into ANDQ.
  1170  	{
  1171  		fn: `
  1172  		func $(a []int) int {
  1173  			return len(a) % 1024
  1174  		}
  1175  		`,
  1176  		pos: []string{"\tANDQ\t\\$1023,"},
  1177  	},
  1178  	{
  1179  		fn: `
  1180  		func $(s string) int {
  1181  			return len(s) % (4097 >> 1)
  1182  		}
  1183  		`,
  1184  		pos: []string{"\tANDQ\t\\$2047,"},
  1185  	},
  1186  	{
  1187  		fn: `
  1188  		func $(a []int) int {
  1189  			return cap(a) % ((1 << 11) + 2048)
  1190  		}
  1191  		`,
  1192  		pos: []string{"\tANDQ\t\\$4095,"},
  1193  	},
  1194  	{
  1195  		// Test that small memmove was replaced with direct movs
  1196  		fn: `
  1197                  func $() {
  1198                         x := [...]byte{1, 2, 3, 4, 5, 6, 7}
  1199                         copy(x[1:], x[:])
  1200                  }
  1201  		`,
  1202  		neg: []string{"memmove"},
  1203  	},
  1204  	{
  1205  		// Same as above but with different size
  1206  		fn: `
  1207                  func $() {
  1208                         x := [...]byte{1, 2, 3, 4}
  1209                         copy(x[1:], x[:])
  1210                  }
  1211  		`,
  1212  		neg: []string{"memmove"},
  1213  	},
  1214  	{
  1215  		// Same as above but with different size
  1216  		fn: `
  1217                  func $() {
  1218                         x := [...]byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}
  1219                         copy(x[1:], x[:])
  1220                  }
  1221  		`,
  1222  		neg: []string{"memmove"},
  1223  	},
  1224  	// Nil checks before calling interface methods
  1225  	{
  1226  		fn: `
  1227  		type I interface {
  1228  			foo000()
  1229  			foo001()
  1230  			foo002()
  1231  			foo003()
  1232  			foo004()
  1233  			foo005()
  1234  			foo006()
  1235  			foo007()
  1236  			foo008()
  1237  			foo009()
  1238  			foo010()
  1239  			foo011()
  1240  			foo012()
  1241  			foo013()
  1242  			foo014()
  1243  			foo015()
  1244  			foo016()
  1245  			foo017()
  1246  			foo018()
  1247  			foo019()
  1248  			foo020()
  1249  			foo021()
  1250  			foo022()
  1251  			foo023()
  1252  			foo024()
  1253  			foo025()
  1254  			foo026()
  1255  			foo027()
  1256  			foo028()
  1257  			foo029()
  1258  			foo030()
  1259  			foo031()
  1260  			foo032()
  1261  			foo033()
  1262  			foo034()
  1263  			foo035()
  1264  			foo036()
  1265  			foo037()
  1266  			foo038()
  1267  			foo039()
  1268  			foo040()
  1269  			foo041()
  1270  			foo042()
  1271  			foo043()
  1272  			foo044()
  1273  			foo045()
  1274  			foo046()
  1275  			foo047()
  1276  			foo048()
  1277  			foo049()
  1278  			foo050()
  1279  			foo051()
  1280  			foo052()
  1281  			foo053()
  1282  			foo054()
  1283  			foo055()
  1284  			foo056()
  1285  			foo057()
  1286  			foo058()
  1287  			foo059()
  1288  			foo060()
  1289  			foo061()
  1290  			foo062()
  1291  			foo063()
  1292  			foo064()
  1293  			foo065()
  1294  			foo066()
  1295  			foo067()
  1296  			foo068()
  1297  			foo069()
  1298  			foo070()
  1299  			foo071()
  1300  			foo072()
  1301  			foo073()
  1302  			foo074()
  1303  			foo075()
  1304  			foo076()
  1305  			foo077()
  1306  			foo078()
  1307  			foo079()
  1308  			foo080()
  1309  			foo081()
  1310  			foo082()
  1311  			foo083()
  1312  			foo084()
  1313  			foo085()
  1314  			foo086()
  1315  			foo087()
  1316  			foo088()
  1317  			foo089()
  1318  			foo090()
  1319  			foo091()
  1320  			foo092()
  1321  			foo093()
  1322  			foo094()
  1323  			foo095()
  1324  			foo096()
  1325  			foo097()
  1326  			foo098()
  1327  			foo099()
  1328  			foo100()
  1329  			foo101()
  1330  			foo102()
  1331  			foo103()
  1332  			foo104()
  1333  			foo105()
  1334  			foo106()
  1335  			foo107()
  1336  			foo108()
  1337  			foo109()
  1338  			foo110()
  1339  			foo111()
  1340  			foo112()
  1341  			foo113()
  1342  			foo114()
  1343  			foo115()
  1344  			foo116()
  1345  			foo117()
  1346  			foo118()
  1347  			foo119()
  1348  			foo120()
  1349  			foo121()
  1350  			foo122()
  1351  			foo123()
  1352  			foo124()
  1353  			foo125()
  1354  			foo126()
  1355  			foo127()
  1356  			foo128()
  1357  			foo129()
  1358  			foo130()
  1359  			foo131()
  1360  			foo132()
  1361  			foo133()
  1362  			foo134()
  1363  			foo135()
  1364  			foo136()
  1365  			foo137()
  1366  			foo138()
  1367  			foo139()
  1368  			foo140()
  1369  			foo141()
  1370  			foo142()
  1371  			foo143()
  1372  			foo144()
  1373  			foo145()
  1374  			foo146()
  1375  			foo147()
  1376  			foo148()
  1377  			foo149()
  1378  			foo150()
  1379  			foo151()
  1380  			foo152()
  1381  			foo153()
  1382  			foo154()
  1383  			foo155()
  1384  			foo156()
  1385  			foo157()
  1386  			foo158()
  1387  			foo159()
  1388  			foo160()
  1389  			foo161()
  1390  			foo162()
  1391  			foo163()
  1392  			foo164()
  1393  			foo165()
  1394  			foo166()
  1395  			foo167()
  1396  			foo168()
  1397  			foo169()
  1398  			foo170()
  1399  			foo171()
  1400  			foo172()
  1401  			foo173()
  1402  			foo174()
  1403  			foo175()
  1404  			foo176()
  1405  			foo177()
  1406  			foo178()
  1407  			foo179()
  1408  			foo180()
  1409  			foo181()
  1410  			foo182()
  1411  			foo183()
  1412  			foo184()
  1413  			foo185()
  1414  			foo186()
  1415  			foo187()
  1416  			foo188()
  1417  			foo189()
  1418  			foo190()
  1419  			foo191()
  1420  			foo192()
  1421  			foo193()
  1422  			foo194()
  1423  			foo195()
  1424  			foo196()
  1425  			foo197()
  1426  			foo198()
  1427  			foo199()
  1428  			foo200()
  1429  			foo201()
  1430  			foo202()
  1431  			foo203()
  1432  			foo204()
  1433  			foo205()
  1434  			foo206()
  1435  			foo207()
  1436  			foo208()
  1437  			foo209()
  1438  			foo210()
  1439  			foo211()
  1440  			foo212()
  1441  			foo213()
  1442  			foo214()
  1443  			foo215()
  1444  			foo216()
  1445  			foo217()
  1446  			foo218()
  1447  			foo219()
  1448  			foo220()
  1449  			foo221()
  1450  			foo222()
  1451  			foo223()
  1452  			foo224()
  1453  			foo225()
  1454  			foo226()
  1455  			foo227()
  1456  			foo228()
  1457  			foo229()
  1458  			foo230()
  1459  			foo231()
  1460  			foo232()
  1461  			foo233()
  1462  			foo234()
  1463  			foo235()
  1464  			foo236()
  1465  			foo237()
  1466  			foo238()
  1467  			foo239()
  1468  			foo240()
  1469  			foo241()
  1470  			foo242()
  1471  			foo243()
  1472  			foo244()
  1473  			foo245()
  1474  			foo246()
  1475  			foo247()
  1476  			foo248()
  1477  			foo249()
  1478  			foo250()
  1479  			foo251()
  1480  			foo252()
  1481  			foo253()
  1482  			foo254()
  1483  			foo255()
  1484  			foo256()
  1485  			foo257()
  1486  			foo258()
  1487  			foo259()
  1488  			foo260()
  1489  			foo261()
  1490  			foo262()
  1491  			foo263()
  1492  			foo264()
  1493  			foo265()
  1494  			foo266()
  1495  			foo267()
  1496  			foo268()
  1497  			foo269()
  1498  			foo270()
  1499  			foo271()
  1500  			foo272()
  1501  			foo273()
  1502  			foo274()
  1503  			foo275()
  1504  			foo276()
  1505  			foo277()
  1506  			foo278()
  1507  			foo279()
  1508  			foo280()
  1509  			foo281()
  1510  			foo282()
  1511  			foo283()
  1512  			foo284()
  1513  			foo285()
  1514  			foo286()
  1515  			foo287()
  1516  			foo288()
  1517  			foo289()
  1518  			foo290()
  1519  			foo291()
  1520  			foo292()
  1521  			foo293()
  1522  			foo294()
  1523  			foo295()
  1524  			foo296()
  1525  			foo297()
  1526  			foo298()
  1527  			foo299()
  1528  			foo300()
  1529  			foo301()
  1530  			foo302()
  1531  			foo303()
  1532  			foo304()
  1533  			foo305()
  1534  			foo306()
  1535  			foo307()
  1536  			foo308()
  1537  			foo309()
  1538  			foo310()
  1539  			foo311()
  1540  			foo312()
  1541  			foo313()
  1542  			foo314()
  1543  			foo315()
  1544  			foo316()
  1545  			foo317()
  1546  			foo318()
  1547  			foo319()
  1548  			foo320()
  1549  			foo321()
  1550  			foo322()
  1551  			foo323()
  1552  			foo324()
  1553  			foo325()
  1554  			foo326()
  1555  			foo327()
  1556  			foo328()
  1557  			foo329()
  1558  			foo330()
  1559  			foo331()
  1560  			foo332()
  1561  			foo333()
  1562  			foo334()
  1563  			foo335()
  1564  			foo336()
  1565  			foo337()
  1566  			foo338()
  1567  			foo339()
  1568  			foo340()
  1569  			foo341()
  1570  			foo342()
  1571  			foo343()
  1572  			foo344()
  1573  			foo345()
  1574  			foo346()
  1575  			foo347()
  1576  			foo348()
  1577  			foo349()
  1578  			foo350()
  1579  			foo351()
  1580  			foo352()
  1581  			foo353()
  1582  			foo354()
  1583  			foo355()
  1584  			foo356()
  1585  			foo357()
  1586  			foo358()
  1587  			foo359()
  1588  			foo360()
  1589  			foo361()
  1590  			foo362()
  1591  			foo363()
  1592  			foo364()
  1593  			foo365()
  1594  			foo366()
  1595  			foo367()
  1596  			foo368()
  1597  			foo369()
  1598  			foo370()
  1599  			foo371()
  1600  			foo372()
  1601  			foo373()
  1602  			foo374()
  1603  			foo375()
  1604  			foo376()
  1605  			foo377()
  1606  			foo378()
  1607  			foo379()
  1608  			foo380()
  1609  			foo381()
  1610  			foo382()
  1611  			foo383()
  1612  			foo384()
  1613  			foo385()
  1614  			foo386()
  1615  			foo387()
  1616  			foo388()
  1617  			foo389()
  1618  			foo390()
  1619  			foo391()
  1620  			foo392()
  1621  			foo393()
  1622  			foo394()
  1623  			foo395()
  1624  			foo396()
  1625  			foo397()
  1626  			foo398()
  1627  			foo399()
  1628  			foo400()
  1629  			foo401()
  1630  			foo402()
  1631  			foo403()
  1632  			foo404()
  1633  			foo405()
  1634  			foo406()
  1635  			foo407()
  1636  			foo408()
  1637  			foo409()
  1638  			foo410()
  1639  			foo411()
  1640  			foo412()
  1641  			foo413()
  1642  			foo414()
  1643  			foo415()
  1644  			foo416()
  1645  			foo417()
  1646  			foo418()
  1647  			foo419()
  1648  			foo420()
  1649  			foo421()
  1650  			foo422()
  1651  			foo423()
  1652  			foo424()
  1653  			foo425()
  1654  			foo426()
  1655  			foo427()
  1656  			foo428()
  1657  			foo429()
  1658  			foo430()
  1659  			foo431()
  1660  			foo432()
  1661  			foo433()
  1662  			foo434()
  1663  			foo435()
  1664  			foo436()
  1665  			foo437()
  1666  			foo438()
  1667  			foo439()
  1668  			foo440()
  1669  			foo441()
  1670  			foo442()
  1671  			foo443()
  1672  			foo444()
  1673  			foo445()
  1674  			foo446()
  1675  			foo447()
  1676  			foo448()
  1677  			foo449()
  1678  			foo450()
  1679  			foo451()
  1680  			foo452()
  1681  			foo453()
  1682  			foo454()
  1683  			foo455()
  1684  			foo456()
  1685  			foo457()
  1686  			foo458()
  1687  			foo459()
  1688  			foo460()
  1689  			foo461()
  1690  			foo462()
  1691  			foo463()
  1692  			foo464()
  1693  			foo465()
  1694  			foo466()
  1695  			foo467()
  1696  			foo468()
  1697  			foo469()
  1698  			foo470()
  1699  			foo471()
  1700  			foo472()
  1701  			foo473()
  1702  			foo474()
  1703  			foo475()
  1704  			foo476()
  1705  			foo477()
  1706  			foo478()
  1707  			foo479()
  1708  			foo480()
  1709  			foo481()
  1710  			foo482()
  1711  			foo483()
  1712  			foo484()
  1713  			foo485()
  1714  			foo486()
  1715  			foo487()
  1716  			foo488()
  1717  			foo489()
  1718  			foo490()
  1719  			foo491()
  1720  			foo492()
  1721  			foo493()
  1722  			foo494()
  1723  			foo495()
  1724  			foo496()
  1725  			foo497()
  1726  			foo498()
  1727  			foo499()
  1728  			foo500()
  1729  			foo501()
  1730  			foo502()
  1731  			foo503()
  1732  			foo504()
  1733  			foo505()
  1734  			foo506()
  1735  			foo507()
  1736  			foo508()
  1737  			foo509()
  1738  			foo510()
  1739  			foo511()
  1740  		}
  1741  		func $(i I) {
  1742  			i.foo511()
  1743  		}
  1744  		`,
  1745  		pos: []string{"TESTB"},
  1746  	},
  1747  	{
  1748  		fn: `
  1749  		func $(i I) {
  1750  			i.foo001()
  1751  		}
  1752  		`,
  1753  		neg: []string{"TESTB"},
  1754  	},
  1755  }
  1756  
  1757  var linux386Tests = []*asmTest{
  1758  	{
  1759  		fn: `
  1760  		func f0(b []byte) uint32 {
  1761  			return binary.LittleEndian.Uint32(b)
  1762  		}
  1763  		`,
  1764  		pos: []string{"\tMOVL\t\\(.*\\),"},
  1765  	},
  1766  	{
  1767  		fn: `
  1768  		func f1(b []byte, i int) uint32 {
  1769  			return binary.LittleEndian.Uint32(b[i:])
  1770  		}
  1771  		`,
  1772  		pos: []string{"\tMOVL\t\\(.*\\)\\(.*\\*1\\),"},
  1773  	},
  1774  
  1775  	// multiplication by powers of two
  1776  	{
  1777  		fn: `
  1778  		func $(n int) int {
  1779  			return 32*n
  1780  		}
  1781  		`,
  1782  		pos: []string{"SHLL"},
  1783  		neg: []string{"IMULL"},
  1784  	},
  1785  	{
  1786  		fn: `
  1787  		func $(n int) int {
  1788  			return -64*n
  1789  		}
  1790  		`,
  1791  		pos: []string{"SHLL"},
  1792  		neg: []string{"IMULL"},
  1793  	},
  1794  
  1795  	// multiplication merging tests
  1796  	{
  1797  		fn: `
  1798  		func $(n int) int {
  1799  			return 9*n + 14*n
  1800  		}`,
  1801  		pos: []string{"\tIMULL\t[$]23"}, // 23*n
  1802  	},
  1803  	{
  1804  		fn: `
  1805  		func $(a, n int) int {
  1806  			return 19*a + a*n
  1807  		}`,
  1808  		pos: []string{"\tADDL\t[$]19", "\tIMULL"}, // (n+19)*a
  1809  	},
  1810  	{
  1811  		// check that stack store is optimized away
  1812  		fn: `
  1813  		func $() int {
  1814  			var x int
  1815  			return *(&x)
  1816  		}
  1817  		`,
  1818  		pos: []string{"TEXT\t.*, [$]0-4"},
  1819  	},
  1820  	{
  1821  		fn: `
  1822  		func mul3(n int) int {
  1823  			return 23*n - 9*n
  1824  		}`,
  1825  		pos: []string{"\tIMULL\t[$]14"}, // 14*n
  1826  	},
  1827  	{
  1828  		fn: `
  1829  		func mul4(a, n int) int {
  1830  			return n*a - a*19
  1831  		}`,
  1832  		pos: []string{"\tADDL\t[$]-19", "\tIMULL"}, // (n-19)*a
  1833  	},
  1834  	// Check that len() and cap() div by a constant power of two
  1835  	// are compiled into SHRL.
  1836  	{
  1837  		fn: `
  1838  		func $(a []int) int {
  1839  			return len(a) / 1024
  1840  		}
  1841  		`,
  1842  		pos: []string{"\tSHRL\t\\$10,"},
  1843  	},
  1844  	{
  1845  		fn: `
  1846  		func $(s string) int {
  1847  			return len(s) / (4097 >> 1)
  1848  		}
  1849  		`,
  1850  		pos: []string{"\tSHRL\t\\$11,"},
  1851  	},
  1852  	{
  1853  		fn: `
  1854  		func $(a []int) int {
  1855  			return cap(a) / ((1 << 11) + 2048)
  1856  		}
  1857  		`,
  1858  		pos: []string{"\tSHRL\t\\$12,"},
  1859  	},
  1860  	// Check that len() and cap() mod by a constant power of two
  1861  	// are compiled into ANDL.
  1862  	{
  1863  		fn: `
  1864  		func $(a []int) int {
  1865  			return len(a) % 1024
  1866  		}
  1867  		`,
  1868  		pos: []string{"\tANDL\t\\$1023,"},
  1869  	},
  1870  	{
  1871  		fn: `
  1872  		func $(s string) int {
  1873  			return len(s) % (4097 >> 1)
  1874  		}
  1875  		`,
  1876  		pos: []string{"\tANDL\t\\$2047,"},
  1877  	},
  1878  	{
  1879  		fn: `
  1880  		func $(a []int) int {
  1881  			return cap(a) % ((1 << 11) + 2048)
  1882  		}
  1883  		`,
  1884  		pos: []string{"\tANDL\t\\$4095,"},
  1885  	},
  1886  	{
  1887  		// Test that small memmove was replaced with direct movs
  1888  		fn: `
  1889                  func $() {
  1890                         x := [...]byte{1, 2, 3, 4, 5, 6, 7}
  1891                         copy(x[1:], x[:])
  1892                  }
  1893  		`,
  1894  		neg: []string{"memmove"},
  1895  	},
  1896  	{
  1897  		// Same as above but with different size
  1898  		fn: `
  1899                  func $() {
  1900                         x := [...]byte{1, 2, 3, 4}
  1901                         copy(x[1:], x[:])
  1902                  }
  1903  		`,
  1904  		neg: []string{"memmove"},
  1905  	},
  1906  }
  1907  
  1908  var linuxS390XTests = []*asmTest{
  1909  	{
  1910  		fn: `
  1911  		func f0(b []byte) uint32 {
  1912  			return binary.LittleEndian.Uint32(b)
  1913  		}
  1914  		`,
  1915  		pos: []string{"\tMOVWBR\t\\(.*\\),"},
  1916  	},
  1917  	{
  1918  		fn: `
  1919  		func f1(b []byte, i int) uint32 {
  1920  			return binary.LittleEndian.Uint32(b[i:])
  1921  		}
  1922  		`,
  1923  		pos: []string{"\tMOVWBR\t\\(.*\\)\\(.*\\*1\\),"},
  1924  	},
  1925  	{
  1926  		fn: `
  1927  		func f2(b []byte) uint64 {
  1928  			return binary.LittleEndian.Uint64(b)
  1929  		}
  1930  		`,
  1931  		pos: []string{"\tMOVDBR\t\\(.*\\),"},
  1932  	},
  1933  	{
  1934  		fn: `
  1935  		func f3(b []byte, i int) uint64 {
  1936  			return binary.LittleEndian.Uint64(b[i:])
  1937  		}
  1938  		`,
  1939  		pos: []string{"\tMOVDBR\t\\(.*\\)\\(.*\\*1\\),"},
  1940  	},
  1941  	{
  1942  		fn: `
  1943  		func f4(b []byte) uint32 {
  1944  			return binary.BigEndian.Uint32(b)
  1945  		}
  1946  		`,
  1947  		pos: []string{"\tMOVWZ\t\\(.*\\),"},
  1948  	},
  1949  	{
  1950  		fn: `
  1951  		func f5(b []byte, i int) uint32 {
  1952  			return binary.BigEndian.Uint32(b[i:])
  1953  		}
  1954  		`,
  1955  		pos: []string{"\tMOVWZ\t\\(.*\\)\\(.*\\*1\\),"},
  1956  	},
  1957  	{
  1958  		fn: `
  1959  		func f6(b []byte) uint64 {
  1960  			return binary.BigEndian.Uint64(b)
  1961  		}
  1962  		`,
  1963  		pos: []string{"\tMOVD\t\\(.*\\),"},
  1964  	},
  1965  	{
  1966  		fn: `
  1967  		func f7(b []byte, i int) uint64 {
  1968  			return binary.BigEndian.Uint64(b[i:])
  1969  		}
  1970  		`,
  1971  		pos: []string{"\tMOVD\t\\(.*\\)\\(.*\\*1\\),"},
  1972  	},
  1973  	{
  1974  		fn: `
  1975  		func f8(x uint64) uint64 {
  1976  			return x<<7 + x>>57
  1977  		}
  1978  		`,
  1979  		pos: []string{"\tRLLG\t[$]7,"},
  1980  	},
  1981  	{
  1982  		fn: `
  1983  		func f9(x uint64) uint64 {
  1984  			return x<<7 | x>>57
  1985  		}
  1986  		`,
  1987  		pos: []string{"\tRLLG\t[$]7,"},
  1988  	},
  1989  	{
  1990  		fn: `
  1991  		func f10(x uint64) uint64 {
  1992  			return x<<7 ^ x>>57
  1993  		}
  1994  		`,
  1995  		pos: []string{"\tRLLG\t[$]7,"},
  1996  	},
  1997  	{
  1998  		fn: `
  1999  		func f11(x uint32) uint32 {
  2000  			return x<<7 + x>>25
  2001  		}
  2002  		`,
  2003  		pos: []string{"\tRLL\t[$]7,"},
  2004  	},
  2005  	{
  2006  		fn: `
  2007  		func f12(x uint32) uint32 {
  2008  			return x<<7 | x>>25
  2009  		}
  2010  		`,
  2011  		pos: []string{"\tRLL\t[$]7,"},
  2012  	},
  2013  	{
  2014  		fn: `
  2015  		func f13(x uint32) uint32 {
  2016  			return x<<7 ^ x>>25
  2017  		}
  2018  		`,
  2019  		pos: []string{"\tRLL\t[$]7,"},
  2020  	},
  2021  	// Fused multiply-add/sub instructions.
  2022  	{
  2023  		fn: `
  2024  		func f14(x, y, z float64) float64 {
  2025  			return x * y + z
  2026  		}
  2027  		`,
  2028  		pos: []string{"\tFMADD\t"},
  2029  	},
  2030  	{
  2031  		fn: `
  2032  		func f15(x, y, z float64) float64 {
  2033  			return x * y - z
  2034  		}
  2035  		`,
  2036  		pos: []string{"\tFMSUB\t"},
  2037  	},
  2038  	{
  2039  		fn: `
  2040  		func f16(x, y, z float32) float32 {
  2041  			return x * y + z
  2042  		}
  2043  		`,
  2044  		pos: []string{"\tFMADDS\t"},
  2045  	},
  2046  	{
  2047  		fn: `
  2048  		func f17(x, y, z float32) float32 {
  2049  			return x * y - z
  2050  		}
  2051  		`,
  2052  		pos: []string{"\tFMSUBS\t"},
  2053  	},
  2054  	// Intrinsic tests for math/bits
  2055  	{
  2056  		fn: `
  2057  		func f18(a uint64) int {
  2058  			return bits.TrailingZeros64(a)
  2059  		}
  2060  		`,
  2061  		pos: []string{"\tFLOGR\t"},
  2062  	},
  2063  	{
  2064  		fn: `
  2065  		func f19(a uint32) int {
  2066  			return bits.TrailingZeros32(a)
  2067  		}
  2068  		`,
  2069  		pos: []string{"\tFLOGR\t", "\tMOVWZ\t"},
  2070  	},
  2071  	{
  2072  		fn: `
  2073  		func f20(a uint16) int {
  2074  			return bits.TrailingZeros16(a)
  2075  		}
  2076  		`,
  2077  		pos: []string{"\tFLOGR\t", "\tOR\t\\$65536,"},
  2078  	},
  2079  	{
  2080  		fn: `
  2081  		func f21(a uint8) int {
  2082  			return bits.TrailingZeros8(a)
  2083  		}
  2084  		`,
  2085  		pos: []string{"\tFLOGR\t", "\tOR\t\\$256,"},
  2086  	},
  2087  	// Intrinsic tests for math/bits
  2088  	{
  2089  		fn: `
  2090  		func f22(a uint64) uint64 {
  2091  			return bits.ReverseBytes64(a)
  2092  		}
  2093  		`,
  2094  		pos: []string{"\tMOVDBR\t"},
  2095  	},
  2096  	{
  2097  		fn: `
  2098  		func f23(a uint32) uint32 {
  2099  			return bits.ReverseBytes32(a)
  2100  		}
  2101  		`,
  2102  		pos: []string{"\tMOVWBR\t"},
  2103  	},
  2104  	{
  2105  		fn: `
  2106  		func f24(a uint64) int {
  2107  			return bits.Len64(a)
  2108  		}
  2109  		`,
  2110  		pos: []string{"\tFLOGR\t"},
  2111  	},
  2112  	{
  2113  		fn: `
  2114  		func f25(a uint32) int {
  2115  			return bits.Len32(a)
  2116  		}
  2117  		`,
  2118  		pos: []string{"\tFLOGR\t"},
  2119  	},
  2120  	{
  2121  		fn: `
  2122  		func f26(a uint16) int {
  2123  			return bits.Len16(a)
  2124  		}
  2125  		`,
  2126  		pos: []string{"\tFLOGR\t"},
  2127  	},
  2128  	{
  2129  		fn: `
  2130  		func f27(a uint8) int {
  2131  			return bits.Len8(a)
  2132  		}
  2133  		`,
  2134  		pos: []string{"\tFLOGR\t"},
  2135  	},
  2136  	{
  2137  		fn: `
  2138  		func f28(a uint) int {
  2139  			return bits.Len(a)
  2140  		}
  2141  		`,
  2142  		pos: []string{"\tFLOGR\t"},
  2143  	},
  2144  	{
  2145  		fn: `
  2146  		func f29(a uint64) int {
  2147  			return bits.LeadingZeros64(a)
  2148  		}
  2149  		`,
  2150  		pos: []string{"\tFLOGR\t"},
  2151  	},
  2152  	{
  2153  		fn: `
  2154  		func f30(a uint32) int {
  2155  			return bits.LeadingZeros32(a)
  2156  		}
  2157  		`,
  2158  		pos: []string{"\tFLOGR\t"},
  2159  	},
  2160  	{
  2161  		fn: `
  2162  		func f31(a uint16) int {
  2163  			return bits.LeadingZeros16(a)
  2164  		}
  2165  		`,
  2166  		pos: []string{"\tFLOGR\t"},
  2167  	},
  2168  	{
  2169  		fn: `
  2170  		func f32(a uint8) int {
  2171  			return bits.LeadingZeros8(a)
  2172  		}
  2173  		`,
  2174  		pos: []string{"\tFLOGR\t"},
  2175  	},
  2176  	{
  2177  		fn: `
  2178  		func f33(a uint) int {
  2179  			return bits.LeadingZeros(a)
  2180  		}
  2181  		`,
  2182  		pos: []string{"\tFLOGR\t"},
  2183  	},
  2184  	// Intrinsic tests for math.
  2185  	{
  2186  		fn: `
  2187  		func ceil(x float64) float64 {
  2188  			return math.Ceil(x)
  2189  		}
  2190  		`,
  2191  		pos: []string{"\tFIDBR\t[$]6"},
  2192  	},
  2193  	{
  2194  		fn: `
  2195  		func floor(x float64) float64 {
  2196  			return math.Floor(x)
  2197  		}
  2198  		`,
  2199  		pos: []string{"\tFIDBR\t[$]7"},
  2200  	},
  2201  	{
  2202  		fn: `
  2203  		func round(x float64) float64 {
  2204  			return math.Round(x)
  2205  		}
  2206  		`,
  2207  		pos: []string{"\tFIDBR\t[$]1"},
  2208  	},
  2209  	{
  2210  		fn: `
  2211  		func trunc(x float64) float64 {
  2212  			return math.Trunc(x)
  2213  		}
  2214  		`,
  2215  		pos: []string{"\tFIDBR\t[$]5"},
  2216  	},
  2217  	{
  2218  		fn: `
  2219  		func roundToEven(x float64) float64 {
  2220  			return math.RoundToEven(x)
  2221  		}
  2222  		`,
  2223  		pos: []string{"\tFIDBR\t[$]4"},
  2224  	},
  2225  	{
  2226  		// check that stack store is optimized away
  2227  		fn: `
  2228  		func $() int {
  2229  			var x int
  2230  			return *(&x)
  2231  		}
  2232  		`,
  2233  		pos: []string{"TEXT\t.*, [$]0-8"},
  2234  	},
  2235  	// Constant propagation through raw bits conversions.
  2236  	{
  2237  		// uint32 constant converted to float32 constant
  2238  		fn: `
  2239  		func $(x float32) float32 {
  2240  			if x > math.Float32frombits(0x3f800000) {
  2241  				return -x
  2242  			}
  2243  			return x
  2244  		}
  2245  		`,
  2246  		pos: []string{"\tFMOVS\t[$]f32.3f800000\\(SB\\)"},
  2247  	},
  2248  	{
  2249  		// float32 constant converted to uint32 constant
  2250  		fn: `
  2251  		func $(x uint32) uint32 {
  2252  			if x > math.Float32bits(1) {
  2253  				return -x
  2254  			}
  2255  			return x
  2256  		}
  2257  		`,
  2258  		neg: []string{"\tFMOVS\t"},
  2259  	},
  2260  	// Constant propagation through float comparisons.
  2261  	{
  2262  		fn: `
  2263  		func $() bool {
  2264  			return 0.5 == float64(uint32(1)) ||
  2265  				1.5 > float64(uint64(1<<63)) ||
  2266  				math.NaN() == math.NaN()
  2267  		}
  2268  		`,
  2269  		pos: []string{"\tMOV(B|BZ|D)\t[$]0,"},
  2270  		neg: []string{"\tFCMPU\t", "\tMOV(B|BZ|D)\t[$]1,"},
  2271  	},
  2272  	{
  2273  		fn: `
  2274  		func $() bool {
  2275  			return float32(0.5) <= float32(int64(1)) &&
  2276  				float32(1.5) >= float32(int32(-1<<31)) &&
  2277  				float32(math.NaN()) != float32(math.NaN())
  2278  		}
  2279  		`,
  2280  		pos: []string{"\tMOV(B|BZ|D)\t[$]1,"},
  2281  		neg: []string{"\tCEBR\t", "\tMOV(B|BZ|D)\t[$]0,"},
  2282  	},
  2283  	// math tests
  2284  	{
  2285  		fn: `
  2286  		func $(x float64) float64 {
  2287  			return math.Abs(x)
  2288  		}
  2289  		`,
  2290  		pos: []string{"\tLPDFR\t"},
  2291  		neg: []string{"\tMOVD\t"}, // no integer loads/stores
  2292  	},
  2293  	{
  2294  		fn: `
  2295  		func $(x float32) float32 {
  2296  			return float32(math.Abs(float64(x)))
  2297  		}
  2298  		`,
  2299  		pos: []string{"\tLPDFR\t"},
  2300  		neg: []string{"\tLDEBR\t", "\tLEDBR\t"}, // no float64 conversion
  2301  	},
  2302  	{
  2303  		fn: `
  2304  		func $(x float64) float64 {
  2305  			return math.Float64frombits(math.Float64bits(x)|1<<63)
  2306  		}
  2307  		`,
  2308  		pos: []string{"\tLNDFR\t"},
  2309  		neg: []string{"\tMOVD\t"}, // no integer loads/stores
  2310  	},
  2311  	{
  2312  		fn: `
  2313  		func $(x float64) float64 {
  2314  			return -math.Abs(x)
  2315  		}
  2316  		`,
  2317  		pos: []string{"\tLNDFR\t"},
  2318  		neg: []string{"\tMOVD\t"}, // no integer loads/stores
  2319  	},
  2320  	{
  2321  		fn: `
  2322  		func $(x, y float64) float64 {
  2323  			return math.Copysign(x, y)
  2324  		}
  2325  		`,
  2326  		pos: []string{"\tCPSDR\t"},
  2327  		neg: []string{"\tMOVD\t"}, // no integer loads/stores
  2328  	},
  2329  	{
  2330  		fn: `
  2331  		func $(x float64) float64 {
  2332  			return math.Copysign(x, -1)
  2333  		}
  2334  		`,
  2335  		pos: []string{"\tLNDFR\t"},
  2336  		neg: []string{"\tMOVD\t"}, // no integer loads/stores
  2337  	},
  2338  	{
  2339  		fn: `
  2340  		func $(x float64) float64 {
  2341  			return math.Copysign(-1, x)
  2342  		}
  2343  		`,
  2344  		pos: []string{"\tCPSDR\t"},
  2345  		neg: []string{"\tMOVD\t"}, // no integer loads/stores
  2346  	},
  2347  }
  2348  
  2349  var linuxARMTests = []*asmTest{
  2350  	// multiplication by powers of two
  2351  	{
  2352  		fn: `
  2353  		func $(n int) int {
  2354  			return 16*n
  2355  		}
  2356  		`,
  2357  		pos: []string{"\tSLL\t[$]4"},
  2358  		neg: []string{"\tMUL\t"},
  2359  	},
  2360  	{
  2361  		fn: `
  2362  		func $(n int) int {
  2363  			return -32*n
  2364  		}
  2365  		`,
  2366  		pos: []string{"\tSLL\t[$]5"},
  2367  		neg: []string{"\tMUL\t"},
  2368  	},
  2369  
  2370  	{
  2371  		fn: `
  2372  		func f0(x uint32) uint32 {
  2373  			return x<<7 + x>>25
  2374  		}
  2375  		`,
  2376  		pos: []string{"\tMOVW\tR[0-9]+@>25,"},
  2377  	},
  2378  	{
  2379  		fn: `
  2380  		func f1(x uint32) uint32 {
  2381  			return x<<7 | x>>25
  2382  		}
  2383  		`,
  2384  		pos: []string{"\tMOVW\tR[0-9]+@>25,"},
  2385  	},
  2386  	{
  2387  		fn: `
  2388  		func f2(x uint32) uint32 {
  2389  			return x<<7 ^ x>>25
  2390  		}
  2391  		`,
  2392  		pos: []string{"\tMOVW\tR[0-9]+@>25,"},
  2393  	},
  2394  	{
  2395  		fn: `
  2396  		func f3(a uint64) int {
  2397  			return bits.Len64(a)
  2398  		}
  2399  		`,
  2400  		pos: []string{"\tCLZ\t"},
  2401  	},
  2402  	{
  2403  		fn: `
  2404  		func f4(a uint32) int {
  2405  			return bits.Len32(a)
  2406  		}
  2407  		`,
  2408  		pos: []string{"\tCLZ\t"},
  2409  	},
  2410  	{
  2411  		fn: `
  2412  		func f5(a uint16) int {
  2413  			return bits.Len16(a)
  2414  		}
  2415  		`,
  2416  		pos: []string{"\tCLZ\t"},
  2417  	},
  2418  	{
  2419  		fn: `
  2420  		func f6(a uint8) int {
  2421  			return bits.Len8(a)
  2422  		}
  2423  		`,
  2424  		pos: []string{"\tCLZ\t"},
  2425  	},
  2426  	{
  2427  		fn: `
  2428  		func f7(a uint) int {
  2429  			return bits.Len(a)
  2430  		}
  2431  		`,
  2432  		pos: []string{"\tCLZ\t"},
  2433  	},
  2434  	{
  2435  		fn: `
  2436  		func f8(a uint64) int {
  2437  			return bits.LeadingZeros64(a)
  2438  		}
  2439  		`,
  2440  		pos: []string{"\tCLZ\t"},
  2441  	},
  2442  	{
  2443  		fn: `
  2444  		func f9(a uint32) int {
  2445  			return bits.LeadingZeros32(a)
  2446  		}
  2447  		`,
  2448  		pos: []string{"\tCLZ\t"},
  2449  	},
  2450  	{
  2451  		fn: `
  2452  		func f10(a uint16) int {
  2453  			return bits.LeadingZeros16(a)
  2454  		}
  2455  		`,
  2456  		pos: []string{"\tCLZ\t"},
  2457  	},
  2458  	{
  2459  		fn: `
  2460  		func f11(a uint8) int {
  2461  			return bits.LeadingZeros8(a)
  2462  		}
  2463  		`,
  2464  		pos: []string{"\tCLZ\t"},
  2465  	},
  2466  	{
  2467  		fn: `
  2468  		func f12(a uint) int {
  2469  			return bits.LeadingZeros(a)
  2470  		}
  2471  		`,
  2472  		pos: []string{"\tCLZ\t"},
  2473  	},
  2474  	{
  2475  		// make sure assembly output has matching offset and base register.
  2476  		fn: `
  2477  		func f13(a, b int) int {
  2478  			runtime.GC() // use some frame
  2479  			return b
  2480  		}
  2481  		`,
  2482  		pos: []string{"b\\+4\\(FP\\)"},
  2483  	},
  2484  	{
  2485  		// check that stack store is optimized away
  2486  		fn: `
  2487  		func $() int {
  2488  			var x int
  2489  			return *(&x)
  2490  		}
  2491  		`,
  2492  		pos: []string{"TEXT\t.*, [$]-4-4"},
  2493  	},
  2494  }
  2495  
  2496  var linuxARM64Tests = []*asmTest{
  2497  	// multiplication by powers of two
  2498  	{
  2499  		fn: `
  2500  		func $(n int) int {
  2501  			return 64*n
  2502  		}
  2503  		`,
  2504  		pos: []string{"\tLSL\t[$]6"},
  2505  		neg: []string{"\tMUL\t"},
  2506  	},
  2507  	{
  2508  		fn: `
  2509  		func $(n int) int {
  2510  			return -128*n
  2511  		}
  2512  		`,
  2513  		pos: []string{"\tLSL\t[$]7"},
  2514  		neg: []string{"\tMUL\t"},
  2515  	},
  2516  
  2517  	{
  2518  		fn: `
  2519  		func f0(x uint64) uint64 {
  2520  			return x<<7 + x>>57
  2521  		}
  2522  		`,
  2523  		pos: []string{"\tROR\t[$]57,"},
  2524  	},
  2525  	{
  2526  		fn: `
  2527  		func f1(x uint64) uint64 {
  2528  			return x<<7 | x>>57
  2529  		}
  2530  		`,
  2531  		pos: []string{"\tROR\t[$]57,"},
  2532  	},
  2533  	{
  2534  		fn: `
  2535  		func f2(x uint64) uint64 {
  2536  			return x<<7 ^ x>>57
  2537  		}
  2538  		`,
  2539  		pos: []string{"\tROR\t[$]57,"},
  2540  	},
  2541  	{
  2542  		fn: `
  2543  		func f3(x uint32) uint32 {
  2544  			return x<<7 + x>>25
  2545  		}
  2546  		`,
  2547  		pos: []string{"\tRORW\t[$]25,"},
  2548  	},
  2549  	{
  2550  		fn: `
  2551  		func f4(x uint32) uint32 {
  2552  			return x<<7 | x>>25
  2553  		}
  2554  		`,
  2555  		pos: []string{"\tRORW\t[$]25,"},
  2556  	},
  2557  	{
  2558  		fn: `
  2559  		func f5(x uint32) uint32 {
  2560  			return x<<7 ^ x>>25
  2561  		}
  2562  		`,
  2563  		pos: []string{"\tRORW\t[$]25,"},
  2564  	},
  2565  	{
  2566  		fn: `
  2567  		func f22(a uint64) uint64 {
  2568  			return bits.ReverseBytes64(a)
  2569  		}
  2570  		`,
  2571  		pos: []string{"\tREV\t"},
  2572  	},
  2573  	{
  2574  		fn: `
  2575  		func f23(a uint32) uint32 {
  2576  			return bits.ReverseBytes32(a)
  2577  		}
  2578  		`,
  2579  		pos: []string{"\tREVW\t"},
  2580  	},
  2581  	{
  2582  		fn: `
  2583  		func f24(a uint64) int {
  2584  			return bits.Len64(a)
  2585  		}
  2586  		`,
  2587  		pos: []string{"\tCLZ\t"},
  2588  	},
  2589  	{
  2590  		fn: `
  2591  		func f25(a uint32) int {
  2592  			return bits.Len32(a)
  2593  		}
  2594  		`,
  2595  		pos: []string{"\tCLZ\t"},
  2596  	},
  2597  	{
  2598  		fn: `
  2599  		func f26(a uint16) int {
  2600  			return bits.Len16(a)
  2601  		}
  2602  		`,
  2603  		pos: []string{"\tCLZ\t"},
  2604  	},
  2605  	{
  2606  		fn: `
  2607  		func f27(a uint8) int {
  2608  			return bits.Len8(a)
  2609  		}
  2610  		`,
  2611  		pos: []string{"\tCLZ\t"},
  2612  	},
  2613  	{
  2614  		fn: `
  2615  		func f28(a uint) int {
  2616  			return bits.Len(a)
  2617  		}
  2618  		`,
  2619  		pos: []string{"\tCLZ\t"},
  2620  	},
  2621  	{
  2622  		fn: `
  2623  		func f29(a uint64) int {
  2624  			return bits.LeadingZeros64(a)
  2625  		}
  2626  		`,
  2627  		pos: []string{"\tCLZ\t"},
  2628  	},
  2629  	{
  2630  		fn: `
  2631  		func f30(a uint32) int {
  2632  			return bits.LeadingZeros32(a)
  2633  		}
  2634  		`,
  2635  		pos: []string{"\tCLZ\t"},
  2636  	},
  2637  	{
  2638  		fn: `
  2639  		func f31(a uint16) int {
  2640  			return bits.LeadingZeros16(a)
  2641  		}
  2642  		`,
  2643  		pos: []string{"\tCLZ\t"},
  2644  	},
  2645  	{
  2646  		fn: `
  2647  		func f32(a uint8) int {
  2648  			return bits.LeadingZeros8(a)
  2649  		}
  2650  		`,
  2651  		pos: []string{"\tCLZ\t"},
  2652  	},
  2653  	{
  2654  		fn: `
  2655  		func f33(a uint) int {
  2656  			return bits.LeadingZeros(a)
  2657  		}
  2658  		`,
  2659  		pos: []string{"\tCLZ\t"},
  2660  	},
  2661  	{
  2662  		fn: `
  2663  		func f34(a uint64) uint64 {
  2664  			return a & ((1<<63)-1)
  2665  		}
  2666  		`,
  2667  		pos: []string{"\tAND\t"},
  2668  	},
  2669  	{
  2670  		fn: `
  2671  		func f35(a uint64) uint64 {
  2672  			return a & (1<<63)
  2673  		}
  2674  		`,
  2675  		pos: []string{"\tAND\t"},
  2676  	},
  2677  	{
  2678  		// make sure offsets are folded into load and store.
  2679  		fn: `
  2680  		func f36(_, a [20]byte) (b [20]byte) {
  2681  			b = a
  2682  			return
  2683  		}
  2684  		`,
  2685  		pos: []string{"\tMOVD\t\"\"\\.a\\+[0-9]+\\(FP\\), R[0-9]+", "\tMOVD\tR[0-9]+, \"\"\\.b\\+[0-9]+\\(FP\\)"},
  2686  	},
  2687  	{
  2688  		// check that stack store is optimized away
  2689  		fn: `
  2690  		func $() int {
  2691  			var x int
  2692  			return *(&x)
  2693  		}
  2694  		`,
  2695  		pos: []string{"TEXT\t.*, [$]-8-8"},
  2696  	},
  2697  	{
  2698  		// check that we don't emit comparisons for constant shift
  2699  		fn: `
  2700  //go:nosplit
  2701  		func $(x int) int {
  2702  			return x << 17
  2703  		}
  2704  		`,
  2705  		pos: []string{"LSL\t\\$17"},
  2706  		neg: []string{"CMP"},
  2707  	},
  2708  }
  2709  
  2710  var linuxMIPSTests = []*asmTest{
  2711  	{
  2712  		fn: `
  2713  		func f0(a uint64) int {
  2714  			return bits.Len64(a)
  2715  		}
  2716  		`,
  2717  		pos: []string{"\tCLZ\t"},
  2718  	},
  2719  	{
  2720  		fn: `
  2721  		func f1(a uint32) int {
  2722  			return bits.Len32(a)
  2723  		}
  2724  		`,
  2725  		pos: []string{"\tCLZ\t"},
  2726  	},
  2727  	{
  2728  		fn: `
  2729  		func f2(a uint16) int {
  2730  			return bits.Len16(a)
  2731  		}
  2732  		`,
  2733  		pos: []string{"\tCLZ\t"},
  2734  	},
  2735  	{
  2736  		fn: `
  2737  		func f3(a uint8) int {
  2738  			return bits.Len8(a)
  2739  		}
  2740  		`,
  2741  		pos: []string{"\tCLZ\t"},
  2742  	},
  2743  	{
  2744  		fn: `
  2745  		func f4(a uint) int {
  2746  			return bits.Len(a)
  2747  		}
  2748  		`,
  2749  		pos: []string{"\tCLZ\t"},
  2750  	},
  2751  	{
  2752  		fn: `
  2753  		func f5(a uint64) int {
  2754  			return bits.LeadingZeros64(a)
  2755  		}
  2756  		`,
  2757  		pos: []string{"\tCLZ\t"},
  2758  	},
  2759  	{
  2760  		fn: `
  2761  		func f6(a uint32) int {
  2762  			return bits.LeadingZeros32(a)
  2763  		}
  2764  		`,
  2765  		pos: []string{"\tCLZ\t"},
  2766  	},
  2767  	{
  2768  		fn: `
  2769  		func f7(a uint16) int {
  2770  			return bits.LeadingZeros16(a)
  2771  		}
  2772  		`,
  2773  		pos: []string{"\tCLZ\t"},
  2774  	},
  2775  	{
  2776  		fn: `
  2777  		func f8(a uint8) int {
  2778  			return bits.LeadingZeros8(a)
  2779  		}
  2780  		`,
  2781  		pos: []string{"\tCLZ\t"},
  2782  	},
  2783  	{
  2784  		fn: `
  2785  		func f9(a uint) int {
  2786  			return bits.LeadingZeros(a)
  2787  		}
  2788  		`,
  2789  		pos: []string{"\tCLZ\t"},
  2790  	},
  2791  	{
  2792  		// check that stack store is optimized away
  2793  		fn: `
  2794  		func $() int {
  2795  			var x int
  2796  			return *(&x)
  2797  		}
  2798  		`,
  2799  		pos: []string{"TEXT\t.*, [$]-4-4"},
  2800  	},
  2801  }
  2802  
  2803  var linuxMIPS64Tests = []*asmTest{
  2804  	{
  2805  		// check that we don't emit comparisons for constant shift
  2806  		fn: `
  2807  		func $(x int) int {
  2808  			return x << 17
  2809  		}
  2810  		`,
  2811  		pos: []string{"SLLV\t\\$17"},
  2812  		neg: []string{"SGT"},
  2813  	},
  2814  }
  2815  
  2816  var linuxPPC64LETests = []*asmTest{
  2817  	// Fused multiply-add/sub instructions.
  2818  	{
  2819  		fn: `
  2820  		func f0(x, y, z float64) float64 {
  2821  			return x * y + z
  2822  		}
  2823  		`,
  2824  		pos: []string{"\tFMADD\t"},
  2825  	},
  2826  	{
  2827  		fn: `
  2828  		func f1(x, y, z float64) float64 {
  2829  			return x * y - z
  2830  		}
  2831  		`,
  2832  		pos: []string{"\tFMSUB\t"},
  2833  	},
  2834  	{
  2835  		fn: `
  2836  		func f2(x, y, z float32) float32 {
  2837  			return x * y + z
  2838  		}
  2839  		`,
  2840  		pos: []string{"\tFMADDS\t"},
  2841  	},
  2842  	{
  2843  		fn: `
  2844  		func f3(x, y, z float32) float32 {
  2845  			return x * y - z
  2846  		}
  2847  		`,
  2848  		pos: []string{"\tFMSUBS\t"},
  2849  	},
  2850  	{
  2851  		fn: `
  2852  		func f4(x uint32) uint32 {
  2853  			return x<<7 | x>>25
  2854  		}
  2855  		`,
  2856  		pos: []string{"\tROTLW\t"},
  2857  	},
  2858  	{
  2859  		fn: `
  2860  		func f5(x uint32) uint32 {
  2861  			return x<<7 + x>>25
  2862  		}
  2863  		`,
  2864  		pos: []string{"\tROTLW\t"},
  2865  	},
  2866  	{
  2867  		fn: `
  2868  		func f6(x uint32) uint32 {
  2869  			return x<<7 ^ x>>25
  2870  		}
  2871  		`,
  2872  		pos: []string{"\tROTLW\t"},
  2873  	},
  2874  	{
  2875  		fn: `
  2876  		func f7(x uint64) uint64 {
  2877  			return x<<7 | x>>57
  2878  		}
  2879  		`,
  2880  		pos: []string{"\tROTL\t"},
  2881  	},
  2882  	{
  2883  		fn: `
  2884  		func f8(x uint64) uint64 {
  2885  			return x<<7 + x>>57
  2886  		}
  2887  		`,
  2888  		pos: []string{"\tROTL\t"},
  2889  	},
  2890  	{
  2891  		fn: `
  2892  		func f9(x uint64) uint64 {
  2893  			return x<<7 ^ x>>57
  2894  		}
  2895  		`,
  2896  		pos: []string{"\tROTL\t"},
  2897  	},
  2898  	{
  2899  		fn: `
  2900  		func f10(a uint32) uint32 {
  2901  			return bits.RotateLeft32(a, 9)
  2902  		}
  2903  		`,
  2904  		pos: []string{"\tROTLW\t"},
  2905  	},
  2906  	{
  2907  		fn: `
  2908  		func f11(a uint64) uint64 {
  2909  			return bits.RotateLeft64(a, 37)
  2910  		}
  2911  		`,
  2912  		pos: []string{"\tROTL\t"},
  2913  	},
  2914  
  2915  	{
  2916  		fn: `
  2917                  func f12(a, b float64) float64 {
  2918                          return math.Copysign(a, b)
  2919                  }
  2920                  `,
  2921  		pos: []string{"\tFCPSGN\t"},
  2922  	},
  2923  
  2924  	{
  2925  		fn: `
  2926                  func f13(a float64) float64 {
  2927                          return math.Abs(a)
  2928                  }
  2929                  `,
  2930  		pos: []string{"\tFABS\t"},
  2931  	},
  2932  
  2933  	{
  2934  		fn: `
  2935  		func f14(b []byte) uint16 {
  2936  			return binary.LittleEndian.Uint16(b)
  2937  	}
  2938  		`,
  2939  		pos: []string{"\tMOVHZ\t"},
  2940  	},
  2941  	{
  2942  		fn: `
  2943  		func f15(b []byte) uint32 {
  2944  			return binary.LittleEndian.Uint32(b)
  2945  		}
  2946  		`,
  2947  		pos: []string{"\tMOVWZ\t"},
  2948  	},
  2949  
  2950  	{
  2951  		fn: `
  2952  		func f16(b []byte) uint64 {
  2953  			return binary.LittleEndian.Uint64(b)
  2954  		}
  2955  		`,
  2956  		pos: []string{"\tMOVD\t"},
  2957  		neg: []string{"MOVBZ", "MOVHZ", "MOVWZ"},
  2958  	},
  2959  
  2960  	{
  2961  		fn: `
  2962  		func f17(b []byte, v uint16) {
  2963  			binary.LittleEndian.PutUint16(b, v)
  2964  		}
  2965  		`,
  2966  		pos: []string{"\tMOVH\t"},
  2967  	},
  2968  
  2969  	{
  2970  		fn: `
  2971  		func f18(b []byte, v uint32) {
  2972  			binary.LittleEndian.PutUint32(b, v)
  2973  		}
  2974  		`,
  2975  		pos: []string{"\tMOVW\t"},
  2976  	},
  2977  
  2978  	{
  2979  		fn: `
  2980  		func f19(b []byte, v uint64) {
  2981  			binary.LittleEndian.PutUint64(b, v)
  2982  		}
  2983  		`,
  2984  		pos: []string{"\tMOVD\t"},
  2985  		neg: []string{"MOVB", "MOVH", "MOVW"},
  2986  	},
  2987  
  2988  	{
  2989  		// check that stack store is optimized away
  2990  		fn: `
  2991  		func $() int {
  2992  			var x int
  2993  			return *(&x)
  2994  		}
  2995  		`,
  2996  		pos: []string{"TEXT\t.*, [$]0-8"},
  2997  	},
  2998  	// Constant propagation through raw bits conversions.
  2999  	{
  3000  		// uint32 constant converted to float32 constant
  3001  		fn: `
  3002  		func $(x float32) float32 {
  3003  			if x > math.Float32frombits(0x3f800000) {
  3004  				return -x
  3005  			}
  3006  			return x
  3007  		}
  3008  		`,
  3009  		pos: []string{"\tFMOVS\t[$]f32.3f800000\\(SB\\)"},
  3010  	},
  3011  	{
  3012  		// float32 constant converted to uint32 constant
  3013  		fn: `
  3014  		func $(x uint32) uint32 {
  3015  			if x > math.Float32bits(1) {
  3016  				return -x
  3017  			}
  3018  			return x
  3019  		}
  3020  		`,
  3021  		neg: []string{"\tFMOVS\t"},
  3022  	},
  3023  }
  3024  
  3025  var plan9AMD64Tests = []*asmTest{
  3026  	// We should make sure that the compiler doesn't generate floating point
  3027  	// instructions for non-float operations on Plan 9, because floating point
  3028  	// operations are not allowed in the note handler.
  3029  	// Array zeroing.
  3030  	{
  3031  		fn: `
  3032  		func $() [16]byte {
  3033  			var a [16]byte
  3034  			return a
  3035  		}
  3036  		`,
  3037  		pos: []string{"\tMOVQ\t\\$0, \"\""},
  3038  	},
  3039  	// Array copy.
  3040  	{
  3041  		fn: `
  3042  		func $(a [16]byte) (b [16]byte) {
  3043  			b = a
  3044  			return
  3045  		}
  3046  		`,
  3047  		pos: []string{"\tMOVQ\t\"\"\\.a\\+[0-9]+\\(SP\\), (AX|CX)", "\tMOVQ\t(AX|CX), \"\"\\.b\\+[0-9]+\\(SP\\)"},
  3048  	},
  3049  }
  3050  
  3051  // TestLineNumber checks to make sure the generated assembly has line numbers
  3052  // see issue #16214
  3053  func TestLineNumber(t *testing.T) {
  3054  	testenv.MustHaveGoBuild(t)
  3055  	dir, err := ioutil.TempDir("", "TestLineNumber")
  3056  	if err != nil {
  3057  		t.Fatalf("could not create directory: %v", err)
  3058  	}
  3059  	defer os.RemoveAll(dir)
  3060  
  3061  	src := filepath.Join(dir, "x.go")
  3062  	err = ioutil.WriteFile(src, []byte(issue16214src), 0644)
  3063  	if err != nil {
  3064  		t.Fatalf("could not write file: %v", err)
  3065  	}
  3066  
  3067  	cmd := exec.Command(testenv.GoToolPath(t), "tool", "compile", "-S", "-o", filepath.Join(dir, "out.o"), src)
  3068  	out, err := cmd.CombinedOutput()
  3069  	if err != nil {
  3070  		t.Fatalf("fail to run go tool compile: %v", err)
  3071  	}
  3072  
  3073  	if strings.Contains(string(out), "unknown line number") {
  3074  		t.Errorf("line number missing in assembly:\n%s", out)
  3075  	}
  3076  }
  3077  
  3078  var issue16214src = `
  3079  package main
  3080  
  3081  func Mod32(x uint32) uint32 {
  3082  	return x % 3 // frontend rewrites it as HMUL with 2863311531, the LITERAL node has unknown Pos
  3083  }
  3084  `