Source file src/cmd/compile/internal/test/testdata/arith_test.go

     1  // Copyright 2015 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  // Tests arithmetic expressions
     6  
     7  package main
     8  
     9  import (
    10  	"math"
    11  	"runtime"
    12  	"testing"
    13  )
    14  
    15  const (
    16  	y = 0x0fffFFFF
    17  )
    18  
    19  var (
    20  	g8  int8
    21  	g16 int16
    22  	g32 int32
    23  	g64 int64
    24  )
    25  
    26  //go:noinline
    27  func lshNop1(x uint64) uint64 {
    28  	// two outer shifts should be removed
    29  	return (((x << 5) >> 2) << 2)
    30  }
    31  
    32  //go:noinline
    33  func lshNop2(x uint64) uint64 {
    34  	return (((x << 5) >> 2) << 3)
    35  }
    36  
    37  //go:noinline
    38  func lshNop3(x uint64) uint64 {
    39  	return (((x << 5) >> 2) << 6)
    40  }
    41  
    42  //go:noinline
    43  func lshNotNop(x uint64) uint64 {
    44  	// outer shift can't be removed
    45  	return (((x << 5) >> 2) << 1)
    46  }
    47  
    48  //go:noinline
    49  func rshNop1(x uint64) uint64 {
    50  	return (((x >> 5) << 2) >> 2)
    51  }
    52  
    53  //go:noinline
    54  func rshNop2(x uint64) uint64 {
    55  	return (((x >> 5) << 2) >> 3)
    56  }
    57  
    58  //go:noinline
    59  func rshNop3(x uint64) uint64 {
    60  	return (((x >> 5) << 2) >> 6)
    61  }
    62  
    63  //go:noinline
    64  func rshNotNop(x uint64) uint64 {
    65  	return (((x >> 5) << 2) >> 1)
    66  }
    67  
    68  func testShiftRemoval(t *testing.T) {
    69  	allSet := ^uint64(0)
    70  	if want, got := uint64(0x7ffffffffffffff), rshNop1(allSet); want != got {
    71  		t.Errorf("testShiftRemoval rshNop1 failed, wanted %d got %d", want, got)
    72  	}
    73  	if want, got := uint64(0x3ffffffffffffff), rshNop2(allSet); want != got {
    74  		t.Errorf("testShiftRemoval rshNop2 failed, wanted %d got %d", want, got)
    75  	}
    76  	if want, got := uint64(0x7fffffffffffff), rshNop3(allSet); want != got {
    77  		t.Errorf("testShiftRemoval rshNop3 failed, wanted %d got %d", want, got)
    78  	}
    79  	if want, got := uint64(0xffffffffffffffe), rshNotNop(allSet); want != got {
    80  		t.Errorf("testShiftRemoval rshNotNop failed, wanted %d got %d", want, got)
    81  	}
    82  	if want, got := uint64(0xffffffffffffffe0), lshNop1(allSet); want != got {
    83  		t.Errorf("testShiftRemoval lshNop1 failed, wanted %d got %d", want, got)
    84  	}
    85  	if want, got := uint64(0xffffffffffffffc0), lshNop2(allSet); want != got {
    86  		t.Errorf("testShiftRemoval lshNop2 failed, wanted %d got %d", want, got)
    87  	}
    88  	if want, got := uint64(0xfffffffffffffe00), lshNop3(allSet); want != got {
    89  		t.Errorf("testShiftRemoval lshNop3 failed, wanted %d got %d", want, got)
    90  	}
    91  	if want, got := uint64(0x7ffffffffffffff0), lshNotNop(allSet); want != got {
    92  		t.Errorf("testShiftRemoval lshNotNop failed, wanted %d got %d", want, got)
    93  	}
    94  }
    95  
    96  //go:noinline
    97  func parseLE64(b []byte) uint64 {
    98  	// skip the first two bytes, and parse the remaining 8 as a uint64
    99  	return uint64(b[2]) | uint64(b[3])<<8 | uint64(b[4])<<16 | uint64(b[5])<<24 |
   100  		uint64(b[6])<<32 | uint64(b[7])<<40 | uint64(b[8])<<48 | uint64(b[9])<<56
   101  }
   102  
   103  //go:noinline
   104  func parseLE32(b []byte) uint32 {
   105  	return uint32(b[2]) | uint32(b[3])<<8 | uint32(b[4])<<16 | uint32(b[5])<<24
   106  }
   107  
   108  //go:noinline
   109  func parseLE16(b []byte) uint16 {
   110  	return uint16(b[2]) | uint16(b[3])<<8
   111  }
   112  
   113  // testLoadCombine tests for issue #14694 where load combining didn't respect the pointer offset.
   114  func testLoadCombine(t *testing.T) {
   115  	testData := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09}
   116  	if want, got := uint64(0x0908070605040302), parseLE64(testData); want != got {
   117  		t.Errorf("testLoadCombine failed, wanted %d got %d", want, got)
   118  	}
   119  	if want, got := uint32(0x05040302), parseLE32(testData); want != got {
   120  		t.Errorf("testLoadCombine failed, wanted %d got %d", want, got)
   121  	}
   122  	if want, got := uint16(0x0302), parseLE16(testData); want != got {
   123  		t.Errorf("testLoadCombine failed, wanted %d got %d", want, got)
   124  	}
   125  }
   126  
   127  var loadSymData = [...]byte{0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08}
   128  
   129  func testLoadSymCombine(t *testing.T) {
   130  	w2 := uint16(0x0201)
   131  	g2 := uint16(loadSymData[0]) | uint16(loadSymData[1])<<8
   132  	if g2 != w2 {
   133  		t.Errorf("testLoadSymCombine failed, wanted %d got %d", w2, g2)
   134  	}
   135  	w4 := uint32(0x04030201)
   136  	g4 := uint32(loadSymData[0]) | uint32(loadSymData[1])<<8 |
   137  		uint32(loadSymData[2])<<16 | uint32(loadSymData[3])<<24
   138  	if g4 != w4 {
   139  		t.Errorf("testLoadSymCombine failed, wanted %d got %d", w4, g4)
   140  	}
   141  	w8 := uint64(0x0807060504030201)
   142  	g8 := uint64(loadSymData[0]) | uint64(loadSymData[1])<<8 |
   143  		uint64(loadSymData[2])<<16 | uint64(loadSymData[3])<<24 |
   144  		uint64(loadSymData[4])<<32 | uint64(loadSymData[5])<<40 |
   145  		uint64(loadSymData[6])<<48 | uint64(loadSymData[7])<<56
   146  	if g8 != w8 {
   147  		t.Errorf("testLoadSymCombine failed, wanted %d got %d", w8, g8)
   148  	}
   149  }
   150  
   151  //go:noinline
   152  func invalidAdd_ssa(x uint32) uint32 {
   153  	return x + y + y + y + y + y + y + y + y + y + y + y + y + y + y + y + y + y
   154  }
   155  
   156  //go:noinline
   157  func invalidSub_ssa(x uint32) uint32 {
   158  	return x - y - y - y - y - y - y - y - y - y - y - y - y - y - y - y - y - y
   159  }
   160  
   161  //go:noinline
   162  func invalidMul_ssa(x uint32) uint32 {
   163  	return x * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y * y
   164  }
   165  
   166  // testLargeConst tests a situation where larger than 32 bit consts were passed to ADDL
   167  // causing an invalid instruction error.
   168  func testLargeConst(t *testing.T) {
   169  	if want, got := uint32(268435440), invalidAdd_ssa(1); want != got {
   170  		t.Errorf("testLargeConst add failed, wanted %d got %d", want, got)
   171  	}
   172  	if want, got := uint32(4026531858), invalidSub_ssa(1); want != got {
   173  		t.Errorf("testLargeConst sub failed, wanted %d got %d", want, got)
   174  	}
   175  	if want, got := uint32(268435455), invalidMul_ssa(1); want != got {
   176  		t.Errorf("testLargeConst mul failed, wanted %d got %d", want, got)
   177  	}
   178  }
   179  
   180  // testArithRshConst ensures that "const >> const" right shifts correctly perform
   181  // sign extension on the lhs constant
   182  func testArithRshConst(t *testing.T) {
   183  	wantu := uint64(0x4000000000000000)
   184  	if got := arithRshuConst_ssa(); got != wantu {
   185  		t.Errorf("arithRshuConst failed, wanted %d got %d", wantu, got)
   186  	}
   187  
   188  	wants := int64(-0x4000000000000000)
   189  	if got := arithRshConst_ssa(); got != wants {
   190  		t.Errorf("arithRshConst failed, wanted %d got %d", wants, got)
   191  	}
   192  }
   193  
   194  //go:noinline
   195  func arithRshuConst_ssa() uint64 {
   196  	y := uint64(0x8000000000000001)
   197  	z := uint64(1)
   198  	return uint64(y >> z)
   199  }
   200  
   201  //go:noinline
   202  func arithRshConst_ssa() int64 {
   203  	y := int64(-0x8000000000000000)
   204  	z := uint64(1)
   205  	return int64(y >> z)
   206  }
   207  
   208  //go:noinline
   209  func arithConstShift_ssa(x int64) int64 {
   210  	return x >> 100
   211  }
   212  
   213  // testArithConstShift tests that right shift by large constants preserve
   214  // the sign of the input.
   215  func testArithConstShift(t *testing.T) {
   216  	want := int64(-1)
   217  	if got := arithConstShift_ssa(-1); want != got {
   218  		t.Errorf("arithConstShift_ssa(-1) failed, wanted %d got %d", want, got)
   219  	}
   220  	want = 0
   221  	if got := arithConstShift_ssa(1); want != got {
   222  		t.Errorf("arithConstShift_ssa(1) failed, wanted %d got %d", want, got)
   223  	}
   224  }
   225  
   226  // overflowConstShift_ssa verifies that constant folding for shift
   227  // doesn't wrap (i.e. x << MAX_INT << 1 doesn't get folded to x << 0).
   228  //
   229  //go:noinline
   230  func overflowConstShift64_ssa(x int64) int64 {
   231  	return x << uint64(0xffffffffffffffff) << uint64(1)
   232  }
   233  
   234  //go:noinline
   235  func overflowConstShift32_ssa(x int64) int32 {
   236  	return int32(x) << uint32(0xffffffff) << uint32(1)
   237  }
   238  
   239  //go:noinline
   240  func overflowConstShift16_ssa(x int64) int16 {
   241  	return int16(x) << uint16(0xffff) << uint16(1)
   242  }
   243  
   244  //go:noinline
   245  func overflowConstShift8_ssa(x int64) int8 {
   246  	return int8(x) << uint8(0xff) << uint8(1)
   247  }
   248  
   249  func testOverflowConstShift(t *testing.T) {
   250  	want := int64(0)
   251  	for x := int64(-127); x < int64(127); x++ {
   252  		got := overflowConstShift64_ssa(x)
   253  		if want != got {
   254  			t.Errorf("overflowShift64 failed, wanted %d got %d", want, got)
   255  		}
   256  		got = int64(overflowConstShift32_ssa(x))
   257  		if want != got {
   258  			t.Errorf("overflowShift32 failed, wanted %d got %d", want, got)
   259  		}
   260  		got = int64(overflowConstShift16_ssa(x))
   261  		if want != got {
   262  			t.Errorf("overflowShift16 failed, wanted %d got %d", want, got)
   263  		}
   264  		got = int64(overflowConstShift8_ssa(x))
   265  		if want != got {
   266  			t.Errorf("overflowShift8 failed, wanted %d got %d", want, got)
   267  		}
   268  	}
   269  }
   270  
   271  //go:noinline
   272  func rsh64x64ConstOverflow8(x int8) int64 {
   273  	return int64(x) >> 9
   274  }
   275  
   276  //go:noinline
   277  func rsh64x64ConstOverflow16(x int16) int64 {
   278  	return int64(x) >> 17
   279  }
   280  
   281  //go:noinline
   282  func rsh64x64ConstOverflow32(x int32) int64 {
   283  	return int64(x) >> 33
   284  }
   285  
   286  func testArithRightShiftConstOverflow(t *testing.T) {
   287  	allSet := int64(-1)
   288  	if got, want := rsh64x64ConstOverflow8(0x7f), int64(0); got != want {
   289  		t.Errorf("rsh64x64ConstOverflow8 failed: got %v, want %v", got, want)
   290  	}
   291  	if got, want := rsh64x64ConstOverflow16(0x7fff), int64(0); got != want {
   292  		t.Errorf("rsh64x64ConstOverflow16 failed: got %v, want %v", got, want)
   293  	}
   294  	if got, want := rsh64x64ConstOverflow32(0x7ffffff), int64(0); got != want {
   295  		t.Errorf("rsh64x64ConstOverflow32 failed: got %v, want %v", got, want)
   296  	}
   297  	if got, want := rsh64x64ConstOverflow8(int8(-1)), allSet; got != want {
   298  		t.Errorf("rsh64x64ConstOverflow8 failed: got %v, want %v", got, want)
   299  	}
   300  	if got, want := rsh64x64ConstOverflow16(int16(-1)), allSet; got != want {
   301  		t.Errorf("rsh64x64ConstOverflow16 failed: got %v, want %v", got, want)
   302  	}
   303  	if got, want := rsh64x64ConstOverflow32(int32(-1)), allSet; got != want {
   304  		t.Errorf("rsh64x64ConstOverflow32 failed: got %v, want %v", got, want)
   305  	}
   306  }
   307  
   308  //go:noinline
   309  func rsh64Ux64ConstOverflow8(x uint8) uint64 {
   310  	return uint64(x) >> 9
   311  }
   312  
   313  //go:noinline
   314  func rsh64Ux64ConstOverflow16(x uint16) uint64 {
   315  	return uint64(x) >> 17
   316  }
   317  
   318  //go:noinline
   319  func rsh64Ux64ConstOverflow32(x uint32) uint64 {
   320  	return uint64(x) >> 33
   321  }
   322  
   323  func testRightShiftConstOverflow(t *testing.T) {
   324  	if got, want := rsh64Ux64ConstOverflow8(0xff), uint64(0); got != want {
   325  		t.Errorf("rsh64Ux64ConstOverflow8 failed: got %v, want %v", got, want)
   326  	}
   327  	if got, want := rsh64Ux64ConstOverflow16(0xffff), uint64(0); got != want {
   328  		t.Errorf("rsh64Ux64ConstOverflow16 failed: got %v, want %v", got, want)
   329  	}
   330  	if got, want := rsh64Ux64ConstOverflow32(0xffffffff), uint64(0); got != want {
   331  		t.Errorf("rsh64Ux64ConstOverflow32 failed: got %v, want %v", got, want)
   332  	}
   333  }
   334  
   335  // test64BitConstMult tests that rewrite rules don't fold 64 bit constants
   336  // into multiply instructions.
   337  func test64BitConstMult(t *testing.T) {
   338  	want := int64(103079215109)
   339  	if got := test64BitConstMult_ssa(1, 2); want != got {
   340  		t.Errorf("test64BitConstMult failed, wanted %d got %d", want, got)
   341  	}
   342  }
   343  
   344  //go:noinline
   345  func test64BitConstMult_ssa(a, b int64) int64 {
   346  	return 34359738369*a + b*34359738370
   347  }
   348  
   349  // test64BitConstAdd tests that rewrite rules don't fold 64 bit constants
   350  // into add instructions.
   351  func test64BitConstAdd(t *testing.T) {
   352  	want := int64(3567671782835376650)
   353  	if got := test64BitConstAdd_ssa(1, 2); want != got {
   354  		t.Errorf("test64BitConstAdd failed, wanted %d got %d", want, got)
   355  	}
   356  }
   357  
   358  //go:noinline
   359  func test64BitConstAdd_ssa(a, b int64) int64 {
   360  	return a + 575815584948629622 + b + 2991856197886747025
   361  }
   362  
   363  // testRegallocCVSpill tests that regalloc spills a value whose last use is the
   364  // current value.
   365  func testRegallocCVSpill(t *testing.T) {
   366  	want := int8(-9)
   367  	if got := testRegallocCVSpill_ssa(1, 2, 3, 4); want != got {
   368  		t.Errorf("testRegallocCVSpill failed, wanted %d got %d", want, got)
   369  	}
   370  }
   371  
   372  //go:noinline
   373  func testRegallocCVSpill_ssa(a, b, c, d int8) int8 {
   374  	return a + -32 + b + 63*c*-87*d
   375  }
   376  
   377  func testBitwiseLogic(t *testing.T) {
   378  	a, b := uint32(57623283), uint32(1314713839)
   379  	if want, got := uint32(38551779), testBitwiseAnd_ssa(a, b); want != got {
   380  		t.Errorf("testBitwiseAnd failed, wanted %d got %d", want, got)
   381  	}
   382  	if want, got := uint32(1333785343), testBitwiseOr_ssa(a, b); want != got {
   383  		t.Errorf("testBitwiseOr failed, wanted %d got %d", want, got)
   384  	}
   385  	if want, got := uint32(1295233564), testBitwiseXor_ssa(a, b); want != got {
   386  		t.Errorf("testBitwiseXor failed, wanted %d got %d", want, got)
   387  	}
   388  	if want, got := int32(832), testBitwiseLsh_ssa(13, 4, 2); want != got {
   389  		t.Errorf("testBitwiseLsh failed, wanted %d got %d", want, got)
   390  	}
   391  	if want, got := int32(0), testBitwiseLsh_ssa(13, 25, 15); want != got {
   392  		t.Errorf("testBitwiseLsh failed, wanted %d got %d", want, got)
   393  	}
   394  	if want, got := int32(0), testBitwiseLsh_ssa(-13, 25, 15); want != got {
   395  		t.Errorf("testBitwiseLsh failed, wanted %d got %d", want, got)
   396  	}
   397  	if want, got := int32(-13), testBitwiseRsh_ssa(-832, 4, 2); want != got {
   398  		t.Errorf("testBitwiseRsh failed, wanted %d got %d", want, got)
   399  	}
   400  	if want, got := int32(0), testBitwiseRsh_ssa(13, 25, 15); want != got {
   401  		t.Errorf("testBitwiseRsh failed, wanted %d got %d", want, got)
   402  	}
   403  	if want, got := int32(-1), testBitwiseRsh_ssa(-13, 25, 15); want != got {
   404  		t.Errorf("testBitwiseRsh failed, wanted %d got %d", want, got)
   405  	}
   406  	if want, got := uint32(0x3ffffff), testBitwiseRshU_ssa(0xffffffff, 4, 2); want != got {
   407  		t.Errorf("testBitwiseRshU failed, wanted %d got %d", want, got)
   408  	}
   409  	if want, got := uint32(0), testBitwiseRshU_ssa(13, 25, 15); want != got {
   410  		t.Errorf("testBitwiseRshU failed, wanted %d got %d", want, got)
   411  	}
   412  	if want, got := uint32(0), testBitwiseRshU_ssa(0x8aaaaaaa, 25, 15); want != got {
   413  		t.Errorf("testBitwiseRshU failed, wanted %d got %d", want, got)
   414  	}
   415  }
   416  
   417  //go:noinline
   418  func testBitwiseAnd_ssa(a, b uint32) uint32 {
   419  	return a & b
   420  }
   421  
   422  //go:noinline
   423  func testBitwiseOr_ssa(a, b uint32) uint32 {
   424  	return a | b
   425  }
   426  
   427  //go:noinline
   428  func testBitwiseXor_ssa(a, b uint32) uint32 {
   429  	return a ^ b
   430  }
   431  
   432  //go:noinline
   433  func testBitwiseLsh_ssa(a int32, b, c uint32) int32 {
   434  	return a << b << c
   435  }
   436  
   437  //go:noinline
   438  func testBitwiseRsh_ssa(a int32, b, c uint32) int32 {
   439  	return a >> b >> c
   440  }
   441  
   442  //go:noinline
   443  func testBitwiseRshU_ssa(a uint32, b, c uint32) uint32 {
   444  	return a >> b >> c
   445  }
   446  
   447  //go:noinline
   448  func testShiftCX_ssa() int {
   449  	v1 := uint8(3)
   450  	v4 := (v1 * v1) ^ v1 | v1 - v1 - v1&v1 ^ uint8(3+2) + v1*1>>0 - v1 | 1 | v1<<(2*3|0-0*0^1)
   451  	v5 := v4>>(3-0-uint(3)) | v1 | v1 + v1 ^ v4<<(0+1|3&1)<<(uint64(1)<<0*2*0<<0) ^ v1
   452  	v6 := v5 ^ (v1+v1)*v1 | v1 | v1*v1>>(v1&v1)>>(uint(1)<<0*uint(3)>>1)*v1<<2*v1<<v1 - v1>>2 | (v4 - v1) ^ v1 + v1 ^ v1>>1 | v1 + v1 - v1 ^ v1
   453  	v7 := v6 & v5 << 0
   454  	v1++
   455  	v11 := 2&1 ^ 0 + 3 | int(0^0)<<1>>(1*0*3) ^ 0*0 ^ 3&0*3&3 ^ 3*3 ^ 1 ^ int(2)<<(2*3) + 2 | 2 | 2 ^ 2 + 1 | 3 | 0 ^ int(1)>>1 ^ 2 // int
   456  	v7--
   457  	return int(uint64(2*1)<<(3-2)<<uint(3>>v7)-2)&v11 | v11 - int(2)<<0>>(2-1)*(v11*0&v11<<1<<(uint8(2)+v4))
   458  }
   459  
   460  func testShiftCX(t *testing.T) {
   461  	want := 141
   462  	if got := testShiftCX_ssa(); want != got {
   463  		t.Errorf("testShiftCX failed, wanted %d got %d", want, got)
   464  	}
   465  }
   466  
   467  // testSubqToNegq ensures that the SUBQ -> NEGQ translation works correctly.
   468  func testSubqToNegq(t *testing.T) {
   469  	want := int64(-318294940372190156)
   470  	if got := testSubqToNegq_ssa(1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 2); want != got {
   471  		t.Errorf("testSubqToNegq failed, wanted %d got %d", want, got)
   472  	}
   473  }
   474  
   475  //go:noinline
   476  func testSubqToNegq_ssa(a, b, c, d, e, f, g, h, i, j, k int64) int64 {
   477  	return a + 8207351403619448057 - b - 1779494519303207690 + c*8810076340510052032*d - 4465874067674546219 - e*4361839741470334295 - f + 8688847565426072650*g*8065564729145417479
   478  }
   479  
   480  func testOcom(t *testing.T) {
   481  	want1, want2 := int32(0x55555555), int32(-0x55555556)
   482  	if got1, got2 := testOcom_ssa(0x55555555, 0x55555555); want1 != got1 || want2 != got2 {
   483  		t.Errorf("testOcom failed, wanted %d and %d got %d and %d", want1, want2, got1, got2)
   484  	}
   485  }
   486  
   487  //go:noinline
   488  func testOcom_ssa(a, b int32) (int32, int32) {
   489  	return ^^^^a, ^^^^^b
   490  }
   491  
   492  func lrot1_ssa(w uint8, x uint16, y uint32, z uint64) (a uint8, b uint16, c uint32, d uint64) {
   493  	a = (w << 5) | (w >> 3)
   494  	b = (x << 13) | (x >> 3)
   495  	c = (y << 29) | (y >> 3)
   496  	d = (z << 61) | (z >> 3)
   497  	return
   498  }
   499  
   500  //go:noinline
   501  func lrot2_ssa(w, n uint32) uint32 {
   502  	// Want to be sure that a "rotate by 32" which
   503  	// is really 0 | (w >> 0) == w
   504  	// is correctly compiled.
   505  	return (w << n) | (w >> (32 - n))
   506  }
   507  
   508  //go:noinline
   509  func lrot3_ssa(w uint32) uint32 {
   510  	// Want to be sure that a "rotate by 32" which
   511  	// is really 0 | (w >> 0) == w
   512  	// is correctly compiled.
   513  	return (w << 32) | (w >> (32 - 32))
   514  }
   515  
   516  func testLrot(t *testing.T) {
   517  	wantA, wantB, wantC, wantD := uint8(0xe1), uint16(0xe001),
   518  		uint32(0xe0000001), uint64(0xe000000000000001)
   519  	a, b, c, d := lrot1_ssa(0xf, 0xf, 0xf, 0xf)
   520  	if a != wantA || b != wantB || c != wantC || d != wantD {
   521  		t.Errorf("lrot1_ssa(0xf, 0xf, 0xf, 0xf)=%d %d %d %d, got %d %d %d %d", wantA, wantB, wantC, wantD, a, b, c, d)
   522  	}
   523  	x := lrot2_ssa(0xb0000001, 32)
   524  	wantX := uint32(0xb0000001)
   525  	if x != wantX {
   526  		t.Errorf("lrot2_ssa(0xb0000001, 32)=%d, got %d", wantX, x)
   527  	}
   528  	x = lrot3_ssa(0xb0000001)
   529  	if x != wantX {
   530  		t.Errorf("lrot3_ssa(0xb0000001)=%d, got %d", wantX, x)
   531  	}
   532  
   533  }
   534  
   535  //go:noinline
   536  func sub1_ssa() uint64 {
   537  	v1 := uint64(3) // uint64
   538  	return v1*v1 - (v1&v1)&v1
   539  }
   540  
   541  //go:noinline
   542  func sub2_ssa() uint8 {
   543  	v1 := uint8(0)
   544  	v3 := v1 + v1 + v1 ^ v1 | 3 + v1 ^ v1 | v1 ^ v1
   545  	v1-- // dev.ssa doesn't see this one
   546  	return v1 ^ v1*v1 - v3
   547  }
   548  
   549  func testSubConst(t *testing.T) {
   550  	x1 := sub1_ssa()
   551  	want1 := uint64(6)
   552  	if x1 != want1 {
   553  		t.Errorf("sub1_ssa()=%d, got %d", want1, x1)
   554  	}
   555  	x2 := sub2_ssa()
   556  	want2 := uint8(251)
   557  	if x2 != want2 {
   558  		t.Errorf("sub2_ssa()=%d, got %d", want2, x2)
   559  	}
   560  }
   561  
   562  //go:noinline
   563  func orPhi_ssa(a bool, x int) int {
   564  	v := 0
   565  	if a {
   566  		v = -1
   567  	} else {
   568  		v = -1
   569  	}
   570  	return x | v
   571  }
   572  
   573  func testOrPhi(t *testing.T) {
   574  	if want, got := -1, orPhi_ssa(true, 4); got != want {
   575  		t.Errorf("orPhi_ssa(true, 4)=%d, want %d", got, want)
   576  	}
   577  	if want, got := -1, orPhi_ssa(false, 0); got != want {
   578  		t.Errorf("orPhi_ssa(false, 0)=%d, want %d", got, want)
   579  	}
   580  }
   581  
   582  //go:noinline
   583  func addshiftLL_ssa(a, b uint32) uint32 {
   584  	return a + b<<3
   585  }
   586  
   587  //go:noinline
   588  func subshiftLL_ssa(a, b uint32) uint32 {
   589  	return a - b<<3
   590  }
   591  
   592  //go:noinline
   593  func rsbshiftLL_ssa(a, b uint32) uint32 {
   594  	return a<<3 - b
   595  }
   596  
   597  //go:noinline
   598  func andshiftLL_ssa(a, b uint32) uint32 {
   599  	return a & (b << 3)
   600  }
   601  
   602  //go:noinline
   603  func orshiftLL_ssa(a, b uint32) uint32 {
   604  	return a | b<<3
   605  }
   606  
   607  //go:noinline
   608  func xorshiftLL_ssa(a, b uint32) uint32 {
   609  	return a ^ b<<3
   610  }
   611  
   612  //go:noinline
   613  func bicshiftLL_ssa(a, b uint32) uint32 {
   614  	return a &^ (b << 3)
   615  }
   616  
   617  //go:noinline
   618  func notshiftLL_ssa(a uint32) uint32 {
   619  	return ^(a << 3)
   620  }
   621  
   622  //go:noinline
   623  func addshiftRL_ssa(a, b uint32) uint32 {
   624  	return a + b>>3
   625  }
   626  
   627  //go:noinline
   628  func subshiftRL_ssa(a, b uint32) uint32 {
   629  	return a - b>>3
   630  }
   631  
   632  //go:noinline
   633  func rsbshiftRL_ssa(a, b uint32) uint32 {
   634  	return a>>3 - b
   635  }
   636  
   637  //go:noinline
   638  func andshiftRL_ssa(a, b uint32) uint32 {
   639  	return a & (b >> 3)
   640  }
   641  
   642  //go:noinline
   643  func orshiftRL_ssa(a, b uint32) uint32 {
   644  	return a | b>>3
   645  }
   646  
   647  //go:noinline
   648  func xorshiftRL_ssa(a, b uint32) uint32 {
   649  	return a ^ b>>3
   650  }
   651  
   652  //go:noinline
   653  func bicshiftRL_ssa(a, b uint32) uint32 {
   654  	return a &^ (b >> 3)
   655  }
   656  
   657  //go:noinline
   658  func notshiftRL_ssa(a uint32) uint32 {
   659  	return ^(a >> 3)
   660  }
   661  
   662  //go:noinline
   663  func addshiftRA_ssa(a, b int32) int32 {
   664  	return a + b>>3
   665  }
   666  
   667  //go:noinline
   668  func subshiftRA_ssa(a, b int32) int32 {
   669  	return a - b>>3
   670  }
   671  
   672  //go:noinline
   673  func rsbshiftRA_ssa(a, b int32) int32 {
   674  	return a>>3 - b
   675  }
   676  
   677  //go:noinline
   678  func andshiftRA_ssa(a, b int32) int32 {
   679  	return a & (b >> 3)
   680  }
   681  
   682  //go:noinline
   683  func orshiftRA_ssa(a, b int32) int32 {
   684  	return a | b>>3
   685  }
   686  
   687  //go:noinline
   688  func xorshiftRA_ssa(a, b int32) int32 {
   689  	return a ^ b>>3
   690  }
   691  
   692  //go:noinline
   693  func bicshiftRA_ssa(a, b int32) int32 {
   694  	return a &^ (b >> 3)
   695  }
   696  
   697  //go:noinline
   698  func notshiftRA_ssa(a int32) int32 {
   699  	return ^(a >> 3)
   700  }
   701  
   702  //go:noinline
   703  func addshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
   704  	return a + b<<s
   705  }
   706  
   707  //go:noinline
   708  func subshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
   709  	return a - b<<s
   710  }
   711  
   712  //go:noinline
   713  func rsbshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
   714  	return a<<s - b
   715  }
   716  
   717  //go:noinline
   718  func andshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
   719  	return a & (b << s)
   720  }
   721  
   722  //go:noinline
   723  func orshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
   724  	return a | b<<s
   725  }
   726  
   727  //go:noinline
   728  func xorshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
   729  	return a ^ b<<s
   730  }
   731  
   732  //go:noinline
   733  func bicshiftLLreg_ssa(a, b uint32, s uint8) uint32 {
   734  	return a &^ (b << s)
   735  }
   736  
   737  //go:noinline
   738  func notshiftLLreg_ssa(a uint32, s uint8) uint32 {
   739  	return ^(a << s)
   740  }
   741  
   742  //go:noinline
   743  func addshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
   744  	return a + b>>s
   745  }
   746  
   747  //go:noinline
   748  func subshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
   749  	return a - b>>s
   750  }
   751  
   752  //go:noinline
   753  func rsbshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
   754  	return a>>s - b
   755  }
   756  
   757  //go:noinline
   758  func andshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
   759  	return a & (b >> s)
   760  }
   761  
   762  //go:noinline
   763  func orshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
   764  	return a | b>>s
   765  }
   766  
   767  //go:noinline
   768  func xorshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
   769  	return a ^ b>>s
   770  }
   771  
   772  //go:noinline
   773  func bicshiftRLreg_ssa(a, b uint32, s uint8) uint32 {
   774  	return a &^ (b >> s)
   775  }
   776  
   777  //go:noinline
   778  func notshiftRLreg_ssa(a uint32, s uint8) uint32 {
   779  	return ^(a >> s)
   780  }
   781  
   782  //go:noinline
   783  func addshiftRAreg_ssa(a, b int32, s uint8) int32 {
   784  	return a + b>>s
   785  }
   786  
   787  //go:noinline
   788  func subshiftRAreg_ssa(a, b int32, s uint8) int32 {
   789  	return a - b>>s
   790  }
   791  
   792  //go:noinline
   793  func rsbshiftRAreg_ssa(a, b int32, s uint8) int32 {
   794  	return a>>s - b
   795  }
   796  
   797  //go:noinline
   798  func andshiftRAreg_ssa(a, b int32, s uint8) int32 {
   799  	return a & (b >> s)
   800  }
   801  
   802  //go:noinline
   803  func orshiftRAreg_ssa(a, b int32, s uint8) int32 {
   804  	return a | b>>s
   805  }
   806  
   807  //go:noinline
   808  func xorshiftRAreg_ssa(a, b int32, s uint8) int32 {
   809  	return a ^ b>>s
   810  }
   811  
   812  //go:noinline
   813  func bicshiftRAreg_ssa(a, b int32, s uint8) int32 {
   814  	return a &^ (b >> s)
   815  }
   816  
   817  //go:noinline
   818  func notshiftRAreg_ssa(a int32, s uint8) int32 {
   819  	return ^(a >> s)
   820  }
   821  
   822  // test ARM shifted ops
   823  func testShiftedOps(t *testing.T) {
   824  	a, b := uint32(10), uint32(42)
   825  	if want, got := a+b<<3, addshiftLL_ssa(a, b); got != want {
   826  		t.Errorf("addshiftLL_ssa(10, 42) = %d want %d", got, want)
   827  	}
   828  	if want, got := a-b<<3, subshiftLL_ssa(a, b); got != want {
   829  		t.Errorf("subshiftLL_ssa(10, 42) = %d want %d", got, want)
   830  	}
   831  	if want, got := a<<3-b, rsbshiftLL_ssa(a, b); got != want {
   832  		t.Errorf("rsbshiftLL_ssa(10, 42) = %d want %d", got, want)
   833  	}
   834  	if want, got := a&(b<<3), andshiftLL_ssa(a, b); got != want {
   835  		t.Errorf("andshiftLL_ssa(10, 42) = %d want %d", got, want)
   836  	}
   837  	if want, got := a|b<<3, orshiftLL_ssa(a, b); got != want {
   838  		t.Errorf("orshiftLL_ssa(10, 42) = %d want %d", got, want)
   839  	}
   840  	if want, got := a^b<<3, xorshiftLL_ssa(a, b); got != want {
   841  		t.Errorf("xorshiftLL_ssa(10, 42) = %d want %d", got, want)
   842  	}
   843  	if want, got := a&^(b<<3), bicshiftLL_ssa(a, b); got != want {
   844  		t.Errorf("bicshiftLL_ssa(10, 42) = %d want %d", got, want)
   845  	}
   846  	if want, got := ^(a << 3), notshiftLL_ssa(a); got != want {
   847  		t.Errorf("notshiftLL_ssa(10) = %d want %d", got, want)
   848  	}
   849  	if want, got := a+b>>3, addshiftRL_ssa(a, b); got != want {
   850  		t.Errorf("addshiftRL_ssa(10, 42) = %d want %d", got, want)
   851  	}
   852  	if want, got := a-b>>3, subshiftRL_ssa(a, b); got != want {
   853  		t.Errorf("subshiftRL_ssa(10, 42) = %d want %d", got, want)
   854  	}
   855  	if want, got := a>>3-b, rsbshiftRL_ssa(a, b); got != want {
   856  		t.Errorf("rsbshiftRL_ssa(10, 42) = %d want %d", got, want)
   857  	}
   858  	if want, got := a&(b>>3), andshiftRL_ssa(a, b); got != want {
   859  		t.Errorf("andshiftRL_ssa(10, 42) = %d want %d", got, want)
   860  	}
   861  	if want, got := a|b>>3, orshiftRL_ssa(a, b); got != want {
   862  		t.Errorf("orshiftRL_ssa(10, 42) = %d want %d", got, want)
   863  	}
   864  	if want, got := a^b>>3, xorshiftRL_ssa(a, b); got != want {
   865  		t.Errorf("xorshiftRL_ssa(10, 42) = %d want %d", got, want)
   866  	}
   867  	if want, got := a&^(b>>3), bicshiftRL_ssa(a, b); got != want {
   868  		t.Errorf("bicshiftRL_ssa(10, 42) = %d want %d", got, want)
   869  	}
   870  	if want, got := ^(a >> 3), notshiftRL_ssa(a); got != want {
   871  		t.Errorf("notshiftRL_ssa(10) = %d want %d", got, want)
   872  	}
   873  	c, d := int32(10), int32(-42)
   874  	if want, got := c+d>>3, addshiftRA_ssa(c, d); got != want {
   875  		t.Errorf("addshiftRA_ssa(10, -42) = %d want %d", got, want)
   876  	}
   877  	if want, got := c-d>>3, subshiftRA_ssa(c, d); got != want {
   878  		t.Errorf("subshiftRA_ssa(10, -42) = %d want %d", got, want)
   879  	}
   880  	if want, got := c>>3-d, rsbshiftRA_ssa(c, d); got != want {
   881  		t.Errorf("rsbshiftRA_ssa(10, -42) = %d want %d", got, want)
   882  	}
   883  	if want, got := c&(d>>3), andshiftRA_ssa(c, d); got != want {
   884  		t.Errorf("andshiftRA_ssa(10, -42) = %d want %d", got, want)
   885  	}
   886  	if want, got := c|d>>3, orshiftRA_ssa(c, d); got != want {
   887  		t.Errorf("orshiftRA_ssa(10, -42) = %d want %d", got, want)
   888  	}
   889  	if want, got := c^d>>3, xorshiftRA_ssa(c, d); got != want {
   890  		t.Errorf("xorshiftRA_ssa(10, -42) = %d want %d", got, want)
   891  	}
   892  	if want, got := c&^(d>>3), bicshiftRA_ssa(c, d); got != want {
   893  		t.Errorf("bicshiftRA_ssa(10, -42) = %d want %d", got, want)
   894  	}
   895  	if want, got := ^(d >> 3), notshiftRA_ssa(d); got != want {
   896  		t.Errorf("notshiftRA_ssa(-42) = %d want %d", got, want)
   897  	}
   898  	s := uint8(3)
   899  	if want, got := a+b<<s, addshiftLLreg_ssa(a, b, s); got != want {
   900  		t.Errorf("addshiftLLreg_ssa(10, 42, 3) = %d want %d", got, want)
   901  	}
   902  	if want, got := a-b<<s, subshiftLLreg_ssa(a, b, s); got != want {
   903  		t.Errorf("subshiftLLreg_ssa(10, 42, 3) = %d want %d", got, want)
   904  	}
   905  	if want, got := a<<s-b, rsbshiftLLreg_ssa(a, b, s); got != want {
   906  		t.Errorf("rsbshiftLLreg_ssa(10, 42, 3) = %d want %d", got, want)
   907  	}
   908  	if want, got := a&(b<<s), andshiftLLreg_ssa(a, b, s); got != want {
   909  		t.Errorf("andshiftLLreg_ssa(10, 42, 3) = %d want %d", got, want)
   910  	}
   911  	if want, got := a|b<<s, orshiftLLreg_ssa(a, b, s); got != want {
   912  		t.Errorf("orshiftLLreg_ssa(10, 42, 3) = %d want %d", got, want)
   913  	}
   914  	if want, got := a^b<<s, xorshiftLLreg_ssa(a, b, s); got != want {
   915  		t.Errorf("xorshiftLLreg_ssa(10, 42, 3) = %d want %d", got, want)
   916  	}
   917  	if want, got := a&^(b<<s), bicshiftLLreg_ssa(a, b, s); got != want {
   918  		t.Errorf("bicshiftLLreg_ssa(10, 42, 3) = %d want %d", got, want)
   919  	}
   920  	if want, got := ^(a << s), notshiftLLreg_ssa(a, s); got != want {
   921  		t.Errorf("notshiftLLreg_ssa(10) = %d want %d", got, want)
   922  	}
   923  	if want, got := a+b>>s, addshiftRLreg_ssa(a, b, s); got != want {
   924  		t.Errorf("addshiftRLreg_ssa(10, 42, 3) = %d want %d", got, want)
   925  	}
   926  	if want, got := a-b>>s, subshiftRLreg_ssa(a, b, s); got != want {
   927  		t.Errorf("subshiftRLreg_ssa(10, 42, 3) = %d want %d", got, want)
   928  	}
   929  	if want, got := a>>s-b, rsbshiftRLreg_ssa(a, b, s); got != want {
   930  		t.Errorf("rsbshiftRLreg_ssa(10, 42, 3) = %d want %d", got, want)
   931  	}
   932  	if want, got := a&(b>>s), andshiftRLreg_ssa(a, b, s); got != want {
   933  		t.Errorf("andshiftRLreg_ssa(10, 42, 3) = %d want %d", got, want)
   934  	}
   935  	if want, got := a|b>>s, orshiftRLreg_ssa(a, b, s); got != want {
   936  		t.Errorf("orshiftRLreg_ssa(10, 42, 3) = %d want %d", got, want)
   937  	}
   938  	if want, got := a^b>>s, xorshiftRLreg_ssa(a, b, s); got != want {
   939  		t.Errorf("xorshiftRLreg_ssa(10, 42, 3) = %d want %d", got, want)
   940  	}
   941  	if want, got := a&^(b>>s), bicshiftRLreg_ssa(a, b, s); got != want {
   942  		t.Errorf("bicshiftRLreg_ssa(10, 42, 3) = %d want %d", got, want)
   943  	}
   944  	if want, got := ^(a >> s), notshiftRLreg_ssa(a, s); got != want {
   945  		t.Errorf("notshiftRLreg_ssa(10) = %d want %d", got, want)
   946  	}
   947  	if want, got := c+d>>s, addshiftRAreg_ssa(c, d, s); got != want {
   948  		t.Errorf("addshiftRAreg_ssa(10, -42, 3) = %d want %d", got, want)
   949  	}
   950  	if want, got := c-d>>s, subshiftRAreg_ssa(c, d, s); got != want {
   951  		t.Errorf("subshiftRAreg_ssa(10, -42, 3) = %d want %d", got, want)
   952  	}
   953  	if want, got := c>>s-d, rsbshiftRAreg_ssa(c, d, s); got != want {
   954  		t.Errorf("rsbshiftRAreg_ssa(10, -42, 3) = %d want %d", got, want)
   955  	}
   956  	if want, got := c&(d>>s), andshiftRAreg_ssa(c, d, s); got != want {
   957  		t.Errorf("andshiftRAreg_ssa(10, -42, 3) = %d want %d", got, want)
   958  	}
   959  	if want, got := c|d>>s, orshiftRAreg_ssa(c, d, s); got != want {
   960  		t.Errorf("orshiftRAreg_ssa(10, -42, 3) = %d want %d", got, want)
   961  	}
   962  	if want, got := c^d>>s, xorshiftRAreg_ssa(c, d, s); got != want {
   963  		t.Errorf("xorshiftRAreg_ssa(10, -42, 3) = %d want %d", got, want)
   964  	}
   965  	if want, got := c&^(d>>s), bicshiftRAreg_ssa(c, d, s); got != want {
   966  		t.Errorf("bicshiftRAreg_ssa(10, -42, 3) = %d want %d", got, want)
   967  	}
   968  	if want, got := ^(d >> s), notshiftRAreg_ssa(d, s); got != want {
   969  		t.Errorf("notshiftRAreg_ssa(-42, 3) = %d want %d", got, want)
   970  	}
   971  }
   972  
   973  // TestArithmetic tests that both backends have the same result for arithmetic expressions.
   974  func TestArithmetic(t *testing.T) {
   975  	test64BitConstMult(t)
   976  	test64BitConstAdd(t)
   977  	testRegallocCVSpill(t)
   978  	testSubqToNegq(t)
   979  	testBitwiseLogic(t)
   980  	testOcom(t)
   981  	testLrot(t)
   982  	testShiftCX(t)
   983  	testSubConst(t)
   984  	testOverflowConstShift(t)
   985  	testArithRightShiftConstOverflow(t)
   986  	testRightShiftConstOverflow(t)
   987  	testArithConstShift(t)
   988  	testArithRshConst(t)
   989  	testLargeConst(t)
   990  	testLoadCombine(t)
   991  	testLoadSymCombine(t)
   992  	testShiftRemoval(t)
   993  	testShiftedOps(t)
   994  	testDivFixUp(t)
   995  	testDivisibleSignedPow2(t)
   996  	testDivisibility(t)
   997  }
   998  
   999  // testDivFixUp ensures that signed division fix-ups are being generated.
  1000  func testDivFixUp(t *testing.T) {
  1001  	defer func() {
  1002  		if r := recover(); r != nil {
  1003  			t.Error("testDivFixUp failed")
  1004  			if e, ok := r.(runtime.Error); ok {
  1005  				t.Logf("%v\n", e.Error())
  1006  			}
  1007  		}
  1008  	}()
  1009  	var w int8 = -128
  1010  	var x int16 = -32768
  1011  	var y int32 = -2147483648
  1012  	var z int64 = -9223372036854775808
  1013  
  1014  	for i := -5; i < 0; i++ {
  1015  		g8 = w / int8(i)
  1016  		g16 = x / int16(i)
  1017  		g32 = y / int32(i)
  1018  		g64 = z / int64(i)
  1019  		g8 = w % int8(i)
  1020  		g16 = x % int16(i)
  1021  		g32 = y % int32(i)
  1022  		g64 = z % int64(i)
  1023  	}
  1024  }
  1025  
  1026  //go:noinline
  1027  func divisible_int8_2to1(x int8) bool {
  1028  	return x%(1<<1) == 0
  1029  }
  1030  
  1031  //go:noinline
  1032  func divisible_int8_2to2(x int8) bool {
  1033  	return x%(1<<2) == 0
  1034  }
  1035  
  1036  //go:noinline
  1037  func divisible_int8_2to3(x int8) bool {
  1038  	return x%(1<<3) == 0
  1039  }
  1040  
  1041  //go:noinline
  1042  func divisible_int8_2to4(x int8) bool {
  1043  	return x%(1<<4) == 0
  1044  }
  1045  
  1046  //go:noinline
  1047  func divisible_int8_2to5(x int8) bool {
  1048  	return x%(1<<5) == 0
  1049  }
  1050  
  1051  //go:noinline
  1052  func divisible_int8_2to6(x int8) bool {
  1053  	return x%(1<<6) == 0
  1054  }
  1055  
  1056  //go:noinline
  1057  func divisible_int16_2to1(x int16) bool {
  1058  	return x%(1<<1) == 0
  1059  }
  1060  
  1061  //go:noinline
  1062  func divisible_int16_2to2(x int16) bool {
  1063  	return x%(1<<2) == 0
  1064  }
  1065  
  1066  //go:noinline
  1067  func divisible_int16_2to3(x int16) bool {
  1068  	return x%(1<<3) == 0
  1069  }
  1070  
  1071  //go:noinline
  1072  func divisible_int16_2to4(x int16) bool {
  1073  	return x%(1<<4) == 0
  1074  }
  1075  
  1076  //go:noinline
  1077  func divisible_int16_2to5(x int16) bool {
  1078  	return x%(1<<5) == 0
  1079  }
  1080  
  1081  //go:noinline
  1082  func divisible_int16_2to6(x int16) bool {
  1083  	return x%(1<<6) == 0
  1084  }
  1085  
  1086  //go:noinline
  1087  func divisible_int16_2to7(x int16) bool {
  1088  	return x%(1<<7) == 0
  1089  }
  1090  
  1091  //go:noinline
  1092  func divisible_int16_2to8(x int16) bool {
  1093  	return x%(1<<8) == 0
  1094  }
  1095  
  1096  //go:noinline
  1097  func divisible_int16_2to9(x int16) bool {
  1098  	return x%(1<<9) == 0
  1099  }
  1100  
  1101  //go:noinline
  1102  func divisible_int16_2to10(x int16) bool {
  1103  	return x%(1<<10) == 0
  1104  }
  1105  
  1106  //go:noinline
  1107  func divisible_int16_2to11(x int16) bool {
  1108  	return x%(1<<11) == 0
  1109  }
  1110  
  1111  //go:noinline
  1112  func divisible_int16_2to12(x int16) bool {
  1113  	return x%(1<<12) == 0
  1114  }
  1115  
  1116  //go:noinline
  1117  func divisible_int16_2to13(x int16) bool {
  1118  	return x%(1<<13) == 0
  1119  }
  1120  
  1121  //go:noinline
  1122  func divisible_int16_2to14(x int16) bool {
  1123  	return x%(1<<14) == 0
  1124  }
  1125  
  1126  //go:noinline
  1127  func divisible_int32_2to4(x int32) bool {
  1128  	return x%(1<<4) == 0
  1129  }
  1130  
  1131  //go:noinline
  1132  func divisible_int32_2to15(x int32) bool {
  1133  	return x%(1<<15) == 0
  1134  }
  1135  
  1136  //go:noinline
  1137  func divisible_int32_2to26(x int32) bool {
  1138  	return x%(1<<26) == 0
  1139  }
  1140  
  1141  //go:noinline
  1142  func divisible_int64_2to4(x int64) bool {
  1143  	return x%(1<<4) == 0
  1144  }
  1145  
  1146  //go:noinline
  1147  func divisible_int64_2to15(x int64) bool {
  1148  	return x%(1<<15) == 0
  1149  }
  1150  
  1151  //go:noinline
  1152  func divisible_int64_2to26(x int64) bool {
  1153  	return x%(1<<26) == 0
  1154  }
  1155  
  1156  //go:noinline
  1157  func divisible_int64_2to34(x int64) bool {
  1158  	return x%(1<<34) == 0
  1159  }
  1160  
  1161  //go:noinline
  1162  func divisible_int64_2to48(x int64) bool {
  1163  	return x%(1<<48) == 0
  1164  }
  1165  
  1166  //go:noinline
  1167  func divisible_int64_2to57(x int64) bool {
  1168  	return x%(1<<57) == 0
  1169  }
  1170  
  1171  // testDivisibleSignedPow2 confirms that x%(1<<k)==0 is rewritten correctly
  1172  func testDivisibleSignedPow2(t *testing.T) {
  1173  	var i int64
  1174  	var pow2 = []int64{
  1175  		1,
  1176  		1 << 1,
  1177  		1 << 2,
  1178  		1 << 3,
  1179  		1 << 4,
  1180  		1 << 5,
  1181  		1 << 6,
  1182  		1 << 7,
  1183  		1 << 8,
  1184  		1 << 9,
  1185  		1 << 10,
  1186  		1 << 11,
  1187  		1 << 12,
  1188  		1 << 13,
  1189  		1 << 14,
  1190  	}
  1191  	// exhaustive test for int8
  1192  	for i = math.MinInt8; i <= math.MaxInt8; i++ {
  1193  		if want, got := int8(i)%int8(pow2[1]) == 0, divisible_int8_2to1(int8(i)); got != want {
  1194  			t.Errorf("divisible_int8_2to1(%d) = %v want %v", i, got, want)
  1195  		}
  1196  		if want, got := int8(i)%int8(pow2[2]) == 0, divisible_int8_2to2(int8(i)); got != want {
  1197  			t.Errorf("divisible_int8_2to2(%d) = %v want %v", i, got, want)
  1198  		}
  1199  		if want, got := int8(i)%int8(pow2[3]) == 0, divisible_int8_2to3(int8(i)); got != want {
  1200  			t.Errorf("divisible_int8_2to3(%d) = %v want %v", i, got, want)
  1201  		}
  1202  		if want, got := int8(i)%int8(pow2[4]) == 0, divisible_int8_2to4(int8(i)); got != want {
  1203  			t.Errorf("divisible_int8_2to4(%d) = %v want %v", i, got, want)
  1204  		}
  1205  		if want, got := int8(i)%int8(pow2[5]) == 0, divisible_int8_2to5(int8(i)); got != want {
  1206  			t.Errorf("divisible_int8_2to5(%d) = %v want %v", i, got, want)
  1207  		}
  1208  		if want, got := int8(i)%int8(pow2[6]) == 0, divisible_int8_2to6(int8(i)); got != want {
  1209  			t.Errorf("divisible_int8_2to6(%d) = %v want %v", i, got, want)
  1210  		}
  1211  	}
  1212  	// exhaustive test for int16
  1213  	for i = math.MinInt16; i <= math.MaxInt16; i++ {
  1214  		if want, got := int16(i)%int16(pow2[1]) == 0, divisible_int16_2to1(int16(i)); got != want {
  1215  			t.Errorf("divisible_int16_2to1(%d) = %v want %v", i, got, want)
  1216  		}
  1217  		if want, got := int16(i)%int16(pow2[2]) == 0, divisible_int16_2to2(int16(i)); got != want {
  1218  			t.Errorf("divisible_int16_2to2(%d) = %v want %v", i, got, want)
  1219  		}
  1220  		if want, got := int16(i)%int16(pow2[3]) == 0, divisible_int16_2to3(int16(i)); got != want {
  1221  			t.Errorf("divisible_int16_2to3(%d) = %v want %v", i, got, want)
  1222  		}
  1223  		if want, got := int16(i)%int16(pow2[4]) == 0, divisible_int16_2to4(int16(i)); got != want {
  1224  			t.Errorf("divisible_int16_2to4(%d) = %v want %v", i, got, want)
  1225  		}
  1226  		if want, got := int16(i)%int16(pow2[5]) == 0, divisible_int16_2to5(int16(i)); got != want {
  1227  			t.Errorf("divisible_int16_2to5(%d) = %v want %v", i, got, want)
  1228  		}
  1229  		if want, got := int16(i)%int16(pow2[6]) == 0, divisible_int16_2to6(int16(i)); got != want {
  1230  			t.Errorf("divisible_int16_2to6(%d) = %v want %v", i, got, want)
  1231  		}
  1232  		if want, got := int16(i)%int16(pow2[7]) == 0, divisible_int16_2to7(int16(i)); got != want {
  1233  			t.Errorf("divisible_int16_2to7(%d) = %v want %v", i, got, want)
  1234  		}
  1235  		if want, got := int16(i)%int16(pow2[8]) == 0, divisible_int16_2to8(int16(i)); got != want {
  1236  			t.Errorf("divisible_int16_2to8(%d) = %v want %v", i, got, want)
  1237  		}
  1238  		if want, got := int16(i)%int16(pow2[9]) == 0, divisible_int16_2to9(int16(i)); got != want {
  1239  			t.Errorf("divisible_int16_2to9(%d) = %v want %v", i, got, want)
  1240  		}
  1241  		if want, got := int16(i)%int16(pow2[10]) == 0, divisible_int16_2to10(int16(i)); got != want {
  1242  			t.Errorf("divisible_int16_2to10(%d) = %v want %v", i, got, want)
  1243  		}
  1244  		if want, got := int16(i)%int16(pow2[11]) == 0, divisible_int16_2to11(int16(i)); got != want {
  1245  			t.Errorf("divisible_int16_2to11(%d) = %v want %v", i, got, want)
  1246  		}
  1247  		if want, got := int16(i)%int16(pow2[12]) == 0, divisible_int16_2to12(int16(i)); got != want {
  1248  			t.Errorf("divisible_int16_2to12(%d) = %v want %v", i, got, want)
  1249  		}
  1250  		if want, got := int16(i)%int16(pow2[13]) == 0, divisible_int16_2to13(int16(i)); got != want {
  1251  			t.Errorf("divisible_int16_2to13(%d) = %v want %v", i, got, want)
  1252  		}
  1253  		if want, got := int16(i)%int16(pow2[14]) == 0, divisible_int16_2to14(int16(i)); got != want {
  1254  			t.Errorf("divisible_int16_2to14(%d) = %v want %v", i, got, want)
  1255  		}
  1256  	}
  1257  	// spot check for int32 and int64
  1258  	var (
  1259  		two4  int64 = 1 << 4
  1260  		two15 int64 = 1 << 15
  1261  		two26 int64 = 1 << 26
  1262  		two34 int64 = 1 << 34
  1263  		two48 int64 = 1 << 48
  1264  		two57 int64 = 1 << 57
  1265  	)
  1266  	var xs = []int64{two4, two4 + 3, -3 * two4, -3*two4 + 1,
  1267  		two15, two15 + 3, -3 * two15, -3*two15 + 1,
  1268  		two26, two26 + 37, -5 * two26, -5*two26 + 2,
  1269  		two34, two34 + 356, -7 * two34, -7*two34 + 13,
  1270  		two48, two48 + 3000, -12 * two48, -12*two48 + 1111,
  1271  		two57, two57 + 397654, -15 * two57, -15*two57 + 11234,
  1272  	}
  1273  	for _, x := range xs {
  1274  		if int64(int32(x)) == x {
  1275  			if want, got := int32(x)%int32(two4) == 0, divisible_int32_2to4(int32(x)); got != want {
  1276  				t.Errorf("divisible_int32_2to4(%d) = %v want %v", x, got, want)
  1277  			}
  1278  
  1279  			if want, got := int32(x)%int32(two15) == 0, divisible_int32_2to15(int32(x)); got != want {
  1280  				t.Errorf("divisible_int32_2to15(%d) = %v want %v", x, got, want)
  1281  			}
  1282  
  1283  			if want, got := int32(x)%int32(two26) == 0, divisible_int32_2to26(int32(x)); got != want {
  1284  				t.Errorf("divisible_int32_2to26(%d) = %v want %v", x, got, want)
  1285  			}
  1286  		}
  1287  		// spot check for int64
  1288  		if want, got := x%two4 == 0, divisible_int64_2to4(x); got != want {
  1289  			t.Errorf("divisible_int64_2to4(%d) = %v want %v", x, got, want)
  1290  		}
  1291  
  1292  		if want, got := x%two15 == 0, divisible_int64_2to15(x); got != want {
  1293  			t.Errorf("divisible_int64_2to15(%d) = %v want %v", x, got, want)
  1294  		}
  1295  
  1296  		if want, got := x%two26 == 0, divisible_int64_2to26(x); got != want {
  1297  			t.Errorf("divisible_int64_2to26(%d) = %v want %v", x, got, want)
  1298  		}
  1299  
  1300  		if want, got := x%two34 == 0, divisible_int64_2to34(x); got != want {
  1301  			t.Errorf("divisible_int64_2to34(%d) = %v want %v", x, got, want)
  1302  		}
  1303  
  1304  		if want, got := x%two48 == 0, divisible_int64_2to48(x); got != want {
  1305  			t.Errorf("divisible_int64_2to48(%d) = %v want %v", x, got, want)
  1306  		}
  1307  
  1308  		if want, got := x%two57 == 0, divisible_int64_2to57(x); got != want {
  1309  			t.Errorf("divisible_int64_2to57(%d) = %v want %v", x, got, want)
  1310  		}
  1311  	}
  1312  }
  1313  
  1314  func div6_uint8(n uint8) bool {
  1315  	return n%6 == 0
  1316  }
  1317  
  1318  //go:noinline
  1319  func div6_uint16(n uint16) bool {
  1320  	return n%6 == 0
  1321  }
  1322  
  1323  //go:noinline
  1324  func div6_uint32(n uint32) bool {
  1325  	return n%6 == 0
  1326  }
  1327  
  1328  //go:noinline
  1329  func div6_uint64(n uint64) bool {
  1330  	return n%6 == 0
  1331  }
  1332  
  1333  //go:noinline
  1334  func div19_uint8(n uint8) bool {
  1335  	return n%19 == 0
  1336  }
  1337  
  1338  //go:noinline
  1339  func div19_uint16(n uint16) bool {
  1340  	return n%19 == 0
  1341  }
  1342  
  1343  //go:noinline
  1344  func div19_uint32(n uint32) bool {
  1345  	return n%19 == 0
  1346  }
  1347  
  1348  //go:noinline
  1349  func div19_uint64(n uint64) bool {
  1350  	return n%19 == 0
  1351  }
  1352  
  1353  //go:noinline
  1354  func div6_int8(n int8) bool {
  1355  	return n%6 == 0
  1356  }
  1357  
  1358  //go:noinline
  1359  func div6_int16(n int16) bool {
  1360  	return n%6 == 0
  1361  }
  1362  
  1363  //go:noinline
  1364  func div6_int32(n int32) bool {
  1365  	return n%6 == 0
  1366  }
  1367  
  1368  //go:noinline
  1369  func div6_int64(n int64) bool {
  1370  	return n%6 == 0
  1371  }
  1372  
  1373  //go:noinline
  1374  func div19_int8(n int8) bool {
  1375  	return n%19 == 0
  1376  }
  1377  
  1378  //go:noinline
  1379  func div19_int16(n int16) bool {
  1380  	return n%19 == 0
  1381  }
  1382  
  1383  //go:noinline
  1384  func div19_int32(n int32) bool {
  1385  	return n%19 == 0
  1386  }
  1387  
  1388  //go:noinline
  1389  func div19_int64(n int64) bool {
  1390  	return n%19 == 0
  1391  }
  1392  
  1393  // testDivisibility confirms that rewrite rules x%c ==0 for c constant are correct.
  1394  func testDivisibility(t *testing.T) {
  1395  	// unsigned tests
  1396  	// test an even and an odd divisor
  1397  	var sixU, nineteenU uint64 = 6, 19
  1398  	// test all inputs for uint8, uint16
  1399  	for i := uint64(0); i <= math.MaxUint16; i++ {
  1400  		if i <= math.MaxUint8 {
  1401  			if want, got := uint8(i)%uint8(sixU) == 0, div6_uint8(uint8(i)); got != want {
  1402  				t.Errorf("div6_uint8(%d) = %v want %v", i, got, want)
  1403  			}
  1404  			if want, got := uint8(i)%uint8(nineteenU) == 0, div19_uint8(uint8(i)); got != want {
  1405  				t.Errorf("div6_uint19(%d) = %v want %v", i, got, want)
  1406  			}
  1407  		}
  1408  		if want, got := uint16(i)%uint16(sixU) == 0, div6_uint16(uint16(i)); got != want {
  1409  			t.Errorf("div6_uint16(%d) = %v want %v", i, got, want)
  1410  		}
  1411  		if want, got := uint16(i)%uint16(nineteenU) == 0, div19_uint16(uint16(i)); got != want {
  1412  			t.Errorf("div19_uint16(%d) = %v want %v", i, got, want)
  1413  		}
  1414  	}
  1415  	var maxU32, maxU64 uint64 = math.MaxUint32, math.MaxUint64
  1416  	// spot check inputs for uint32 and uint64
  1417  	xu := []uint64{
  1418  		0, 1, 2, 3, 4, 5,
  1419  		sixU, 2 * sixU, 3 * sixU, 5 * sixU, 12345 * sixU,
  1420  		sixU + 1, 2*sixU - 5, 3*sixU + 3, 5*sixU + 4, 12345*sixU - 2,
  1421  		nineteenU, 2 * nineteenU, 3 * nineteenU, 5 * nineteenU, 12345 * nineteenU,
  1422  		nineteenU + 1, 2*nineteenU - 5, 3*nineteenU + 3, 5*nineteenU + 4, 12345*nineteenU - 2,
  1423  		maxU32, maxU32 - 1, maxU32 - 2, maxU32 - 3, maxU32 - 4,
  1424  		maxU32 - 5, maxU32 - 6, maxU32 - 7, maxU32 - 8,
  1425  		maxU32 - 9, maxU32 - 10, maxU32 - 11, maxU32 - 12,
  1426  		maxU32 - 13, maxU32 - 14, maxU32 - 15, maxU32 - 16,
  1427  		maxU32 - 17, maxU32 - 18, maxU32 - 19, maxU32 - 20,
  1428  		maxU64, maxU64 - 1, maxU64 - 2, maxU64 - 3, maxU64 - 4,
  1429  		maxU64 - 5, maxU64 - 6, maxU64 - 7, maxU64 - 8,
  1430  		maxU64 - 9, maxU64 - 10, maxU64 - 11, maxU64 - 12,
  1431  		maxU64 - 13, maxU64 - 14, maxU64 - 15, maxU64 - 16,
  1432  		maxU64 - 17, maxU64 - 18, maxU64 - 19, maxU64 - 20,
  1433  	}
  1434  	for _, x := range xu {
  1435  		if x <= maxU32 {
  1436  			if want, got := uint32(x)%uint32(sixU) == 0, div6_uint32(uint32(x)); got != want {
  1437  				t.Errorf("div6_uint32(%d) = %v want %v", x, got, want)
  1438  			}
  1439  			if want, got := uint32(x)%uint32(nineteenU) == 0, div19_uint32(uint32(x)); got != want {
  1440  				t.Errorf("div19_uint32(%d) = %v want %v", x, got, want)
  1441  			}
  1442  		}
  1443  		if want, got := x%sixU == 0, div6_uint64(x); got != want {
  1444  			t.Errorf("div6_uint64(%d) = %v want %v", x, got, want)
  1445  		}
  1446  		if want, got := x%nineteenU == 0, div19_uint64(x); got != want {
  1447  			t.Errorf("div19_uint64(%d) = %v want %v", x, got, want)
  1448  		}
  1449  	}
  1450  
  1451  	// signed tests
  1452  	// test an even and an odd divisor
  1453  	var sixS, nineteenS int64 = 6, 19
  1454  	// test all inputs for int8, int16
  1455  	for i := int64(math.MinInt16); i <= math.MaxInt16; i++ {
  1456  		if math.MinInt8 <= i && i <= math.MaxInt8 {
  1457  			if want, got := int8(i)%int8(sixS) == 0, div6_int8(int8(i)); got != want {
  1458  				t.Errorf("div6_int8(%d) = %v want %v", i, got, want)
  1459  			}
  1460  			if want, got := int8(i)%int8(nineteenS) == 0, div19_int8(int8(i)); got != want {
  1461  				t.Errorf("div6_int19(%d) = %v want %v", i, got, want)
  1462  			}
  1463  		}
  1464  		if want, got := int16(i)%int16(sixS) == 0, div6_int16(int16(i)); got != want {
  1465  			t.Errorf("div6_int16(%d) = %v want %v", i, got, want)
  1466  		}
  1467  		if want, got := int16(i)%int16(nineteenS) == 0, div19_int16(int16(i)); got != want {
  1468  			t.Errorf("div19_int16(%d) = %v want %v", i, got, want)
  1469  		}
  1470  	}
  1471  	var minI32, maxI32, minI64, maxI64 int64 = math.MinInt32, math.MaxInt32, math.MinInt64, math.MaxInt64
  1472  	// spot check inputs for int32 and int64
  1473  	xs := []int64{
  1474  		0, 1, 2, 3, 4, 5,
  1475  		-1, -2, -3, -4, -5,
  1476  		sixS, 2 * sixS, 3 * sixS, 5 * sixS, 12345 * sixS,
  1477  		sixS + 1, 2*sixS - 5, 3*sixS + 3, 5*sixS + 4, 12345*sixS - 2,
  1478  		-sixS, -2 * sixS, -3 * sixS, -5 * sixS, -12345 * sixS,
  1479  		-sixS + 1, -2*sixS - 5, -3*sixS + 3, -5*sixS + 4, -12345*sixS - 2,
  1480  		nineteenS, 2 * nineteenS, 3 * nineteenS, 5 * nineteenS, 12345 * nineteenS,
  1481  		nineteenS + 1, 2*nineteenS - 5, 3*nineteenS + 3, 5*nineteenS + 4, 12345*nineteenS - 2,
  1482  		-nineteenS, -2 * nineteenS, -3 * nineteenS, -5 * nineteenS, -12345 * nineteenS,
  1483  		-nineteenS + 1, -2*nineteenS - 5, -3*nineteenS + 3, -5*nineteenS + 4, -12345*nineteenS - 2,
  1484  		minI32, minI32 + 1, minI32 + 2, minI32 + 3, minI32 + 4,
  1485  		minI32 + 5, minI32 + 6, minI32 + 7, minI32 + 8,
  1486  		minI32 + 9, minI32 + 10, minI32 + 11, minI32 + 12,
  1487  		minI32 + 13, minI32 + 14, minI32 + 15, minI32 + 16,
  1488  		minI32 + 17, minI32 + 18, minI32 + 19, minI32 + 20,
  1489  		maxI32, maxI32 - 1, maxI32 - 2, maxI32 - 3, maxI32 - 4,
  1490  		maxI32 - 5, maxI32 - 6, maxI32 - 7, maxI32 - 8,
  1491  		maxI32 - 9, maxI32 - 10, maxI32 - 11, maxI32 - 12,
  1492  		maxI32 - 13, maxI32 - 14, maxI32 - 15, maxI32 - 16,
  1493  		maxI32 - 17, maxI32 - 18, maxI32 - 19, maxI32 - 20,
  1494  		minI64, minI64 + 1, minI64 + 2, minI64 + 3, minI64 + 4,
  1495  		minI64 + 5, minI64 + 6, minI64 + 7, minI64 + 8,
  1496  		minI64 + 9, minI64 + 10, minI64 + 11, minI64 + 12,
  1497  		minI64 + 13, minI64 + 14, minI64 + 15, minI64 + 16,
  1498  		minI64 + 17, minI64 + 18, minI64 + 19, minI64 + 20,
  1499  		maxI64, maxI64 - 1, maxI64 - 2, maxI64 - 3, maxI64 - 4,
  1500  		maxI64 - 5, maxI64 - 6, maxI64 - 7, maxI64 - 8,
  1501  		maxI64 - 9, maxI64 - 10, maxI64 - 11, maxI64 - 12,
  1502  		maxI64 - 13, maxI64 - 14, maxI64 - 15, maxI64 - 16,
  1503  		maxI64 - 17, maxI64 - 18, maxI64 - 19, maxI64 - 20,
  1504  	}
  1505  	for _, x := range xs {
  1506  		if minI32 <= x && x <= maxI32 {
  1507  			if want, got := int32(x)%int32(sixS) == 0, div6_int32(int32(x)); got != want {
  1508  				t.Errorf("div6_int32(%d) = %v want %v", x, got, want)
  1509  			}
  1510  			if want, got := int32(x)%int32(nineteenS) == 0, div19_int32(int32(x)); got != want {
  1511  				t.Errorf("div19_int32(%d) = %v want %v", x, got, want)
  1512  			}
  1513  		}
  1514  		if want, got := x%sixS == 0, div6_int64(x); got != want {
  1515  			t.Errorf("div6_int64(%d) = %v want %v", x, got, want)
  1516  		}
  1517  		if want, got := x%nineteenS == 0, div19_int64(x); got != want {
  1518  			t.Errorf("div19_int64(%d) = %v want %v", x, got, want)
  1519  		}
  1520  	}
  1521  }
  1522  
  1523  //go:noinline
  1524  func genREV16_1(c uint64) uint64 {
  1525  	b := ((c & 0xff00ff00ff00ff00) >> 8) | ((c & 0x00ff00ff00ff00ff) << 8)
  1526  	return b
  1527  }
  1528  
  1529  //go:noinline
  1530  func genREV16_2(c uint64) uint64 {
  1531  	b := ((c & 0xff00ff00) >> 8) | ((c & 0x00ff00ff) << 8)
  1532  	return b
  1533  }
  1534  
  1535  //go:noinline
  1536  func genREV16W(c uint32) uint32 {
  1537  	b := ((c & 0xff00ff00) >> 8) | ((c & 0x00ff00ff) << 8)
  1538  	return b
  1539  }
  1540  
  1541  func TestREV16(t *testing.T) {
  1542  	x := uint64(0x8f7f6f5f4f3f2f1f)
  1543  	want1 := uint64(0x7f8f5f6f3f4f1f2f)
  1544  	want2 := uint64(0x3f4f1f2f)
  1545  
  1546  	got1 := genREV16_1(x)
  1547  	if got1 != want1 {
  1548  		t.Errorf("genREV16_1(%#x) = %#x want %#x", x, got1, want1)
  1549  	}
  1550  	got2 := genREV16_2(x)
  1551  	if got2 != want2 {
  1552  		t.Errorf("genREV16_2(%#x) = %#x want %#x", x, got2, want2)
  1553  	}
  1554  }
  1555  
  1556  func TestREV16W(t *testing.T) {
  1557  	x := uint32(0x4f3f2f1f)
  1558  	want := uint32(0x3f4f1f2f)
  1559  
  1560  	got := genREV16W(x)
  1561  	if got != want {
  1562  		t.Errorf("genREV16W(%#x) = %#x want %#x", x, got, want)
  1563  	}
  1564  }
  1565  

View as plain text