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

View as plain text