github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/compile/test/testdata/arith_test.go (about) 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 }