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