github.com/gagliardetto/golang-go@v0.0.0-20201020153340-53909ea70814/cmd/compile/internal/gc/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 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 }