github.com/go-asm/go@v1.21.1-0.20240213172139-40c5ead50c48/cmd/compile/test/shift_test.go (about) 1 // Copyright 2016 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package test 6 7 import ( 8 "reflect" 9 "testing" 10 ) 11 12 // Tests shifts of zero. 13 14 //go:noinline 15 func ofz64l64(n uint64) int64 { 16 var x int64 17 return x << n 18 } 19 20 //go:noinline 21 func ofz64l32(n uint32) int64 { 22 var x int64 23 return x << n 24 } 25 26 //go:noinline 27 func ofz64l16(n uint16) int64 { 28 var x int64 29 return x << n 30 } 31 32 //go:noinline 33 func ofz64l8(n uint8) int64 { 34 var x int64 35 return x << n 36 } 37 38 //go:noinline 39 func ofz64r64(n uint64) int64 { 40 var x int64 41 return x >> n 42 } 43 44 //go:noinline 45 func ofz64r32(n uint32) int64 { 46 var x int64 47 return x >> n 48 } 49 50 //go:noinline 51 func ofz64r16(n uint16) int64 { 52 var x int64 53 return x >> n 54 } 55 56 //go:noinline 57 func ofz64r8(n uint8) int64 { 58 var x int64 59 return x >> n 60 } 61 62 //go:noinline 63 func ofz64ur64(n uint64) uint64 { 64 var x uint64 65 return x >> n 66 } 67 68 //go:noinline 69 func ofz64ur32(n uint32) uint64 { 70 var x uint64 71 return x >> n 72 } 73 74 //go:noinline 75 func ofz64ur16(n uint16) uint64 { 76 var x uint64 77 return x >> n 78 } 79 80 //go:noinline 81 func ofz64ur8(n uint8) uint64 { 82 var x uint64 83 return x >> n 84 } 85 86 //go:noinline 87 func ofz32l64(n uint64) int32 { 88 var x int32 89 return x << n 90 } 91 92 //go:noinline 93 func ofz32l32(n uint32) int32 { 94 var x int32 95 return x << n 96 } 97 98 //go:noinline 99 func ofz32l16(n uint16) int32 { 100 var x int32 101 return x << n 102 } 103 104 //go:noinline 105 func ofz32l8(n uint8) int32 { 106 var x int32 107 return x << n 108 } 109 110 //go:noinline 111 func ofz32r64(n uint64) int32 { 112 var x int32 113 return x >> n 114 } 115 116 //go:noinline 117 func ofz32r32(n uint32) int32 { 118 var x int32 119 return x >> n 120 } 121 122 //go:noinline 123 func ofz32r16(n uint16) int32 { 124 var x int32 125 return x >> n 126 } 127 128 //go:noinline 129 func ofz32r8(n uint8) int32 { 130 var x int32 131 return x >> n 132 } 133 134 //go:noinline 135 func ofz32ur64(n uint64) uint32 { 136 var x uint32 137 return x >> n 138 } 139 140 //go:noinline 141 func ofz32ur32(n uint32) uint32 { 142 var x uint32 143 return x >> n 144 } 145 146 //go:noinline 147 func ofz32ur16(n uint16) uint32 { 148 var x uint32 149 return x >> n 150 } 151 152 //go:noinline 153 func ofz32ur8(n uint8) uint32 { 154 var x uint32 155 return x >> n 156 } 157 158 //go:noinline 159 func ofz16l64(n uint64) int16 { 160 var x int16 161 return x << n 162 } 163 164 //go:noinline 165 func ofz16l32(n uint32) int16 { 166 var x int16 167 return x << n 168 } 169 170 //go:noinline 171 func ofz16l16(n uint16) int16 { 172 var x int16 173 return x << n 174 } 175 176 //go:noinline 177 func ofz16l8(n uint8) int16 { 178 var x int16 179 return x << n 180 } 181 182 //go:noinline 183 func ofz16r64(n uint64) int16 { 184 var x int16 185 return x >> n 186 } 187 188 //go:noinline 189 func ofz16r32(n uint32) int16 { 190 var x int16 191 return x >> n 192 } 193 194 //go:noinline 195 func ofz16r16(n uint16) int16 { 196 var x int16 197 return x >> n 198 } 199 200 //go:noinline 201 func ofz16r8(n uint8) int16 { 202 var x int16 203 return x >> n 204 } 205 206 //go:noinline 207 func ofz16ur64(n uint64) uint16 { 208 var x uint16 209 return x >> n 210 } 211 212 //go:noinline 213 func ofz16ur32(n uint32) uint16 { 214 var x uint16 215 return x >> n 216 } 217 218 //go:noinline 219 func ofz16ur16(n uint16) uint16 { 220 var x uint16 221 return x >> n 222 } 223 224 //go:noinline 225 func ofz16ur8(n uint8) uint16 { 226 var x uint16 227 return x >> n 228 } 229 230 //go:noinline 231 func ofz8l64(n uint64) int8 { 232 var x int8 233 return x << n 234 } 235 236 //go:noinline 237 func ofz8l32(n uint32) int8 { 238 var x int8 239 return x << n 240 } 241 242 //go:noinline 243 func ofz8l16(n uint16) int8 { 244 var x int8 245 return x << n 246 } 247 248 //go:noinline 249 func ofz8l8(n uint8) int8 { 250 var x int8 251 return x << n 252 } 253 254 //go:noinline 255 func ofz8r64(n uint64) int8 { 256 var x int8 257 return x >> n 258 } 259 260 //go:noinline 261 func ofz8r32(n uint32) int8 { 262 var x int8 263 return x >> n 264 } 265 266 //go:noinline 267 func ofz8r16(n uint16) int8 { 268 var x int8 269 return x >> n 270 } 271 272 //go:noinline 273 func ofz8r8(n uint8) int8 { 274 var x int8 275 return x >> n 276 } 277 278 //go:noinline 279 func ofz8ur64(n uint64) uint8 { 280 var x uint8 281 return x >> n 282 } 283 284 //go:noinline 285 func ofz8ur32(n uint32) uint8 { 286 var x uint8 287 return x >> n 288 } 289 290 //go:noinline 291 func ofz8ur16(n uint16) uint8 { 292 var x uint8 293 return x >> n 294 } 295 296 //go:noinline 297 func ofz8ur8(n uint8) uint8 { 298 var x uint8 299 return x >> n 300 } 301 302 func TestShiftOfZero(t *testing.T) { 303 if got := ofz64l64(5); got != 0 { 304 t.Errorf("0<<5 == %d, want 0", got) 305 } 306 if got := ofz64l32(5); got != 0 { 307 t.Errorf("0<<5 == %d, want 0", got) 308 } 309 if got := ofz64l16(5); got != 0 { 310 t.Errorf("0<<5 == %d, want 0", got) 311 } 312 if got := ofz64l8(5); got != 0 { 313 t.Errorf("0<<5 == %d, want 0", got) 314 } 315 if got := ofz64r64(5); got != 0 { 316 t.Errorf("0>>5 == %d, want 0", got) 317 } 318 if got := ofz64r32(5); got != 0 { 319 t.Errorf("0>>5 == %d, want 0", got) 320 } 321 if got := ofz64r16(5); got != 0 { 322 t.Errorf("0>>5 == %d, want 0", got) 323 } 324 if got := ofz64r8(5); got != 0 { 325 t.Errorf("0>>5 == %d, want 0", got) 326 } 327 if got := ofz64ur64(5); got != 0 { 328 t.Errorf("0>>>5 == %d, want 0", got) 329 } 330 if got := ofz64ur32(5); got != 0 { 331 t.Errorf("0>>>5 == %d, want 0", got) 332 } 333 if got := ofz64ur16(5); got != 0 { 334 t.Errorf("0>>>5 == %d, want 0", got) 335 } 336 if got := ofz64ur8(5); got != 0 { 337 t.Errorf("0>>>5 == %d, want 0", got) 338 } 339 340 if got := ofz32l64(5); got != 0 { 341 t.Errorf("0<<5 == %d, want 0", got) 342 } 343 if got := ofz32l32(5); got != 0 { 344 t.Errorf("0<<5 == %d, want 0", got) 345 } 346 if got := ofz32l16(5); got != 0 { 347 t.Errorf("0<<5 == %d, want 0", got) 348 } 349 if got := ofz32l8(5); got != 0 { 350 t.Errorf("0<<5 == %d, want 0", got) 351 } 352 if got := ofz32r64(5); got != 0 { 353 t.Errorf("0>>5 == %d, want 0", got) 354 } 355 if got := ofz32r32(5); got != 0 { 356 t.Errorf("0>>5 == %d, want 0", got) 357 } 358 if got := ofz32r16(5); got != 0 { 359 t.Errorf("0>>5 == %d, want 0", got) 360 } 361 if got := ofz32r8(5); got != 0 { 362 t.Errorf("0>>5 == %d, want 0", got) 363 } 364 if got := ofz32ur64(5); got != 0 { 365 t.Errorf("0>>>5 == %d, want 0", got) 366 } 367 if got := ofz32ur32(5); got != 0 { 368 t.Errorf("0>>>5 == %d, want 0", got) 369 } 370 if got := ofz32ur16(5); got != 0 { 371 t.Errorf("0>>>5 == %d, want 0", got) 372 } 373 if got := ofz32ur8(5); got != 0 { 374 t.Errorf("0>>>5 == %d, want 0", got) 375 } 376 377 if got := ofz16l64(5); got != 0 { 378 t.Errorf("0<<5 == %d, want 0", got) 379 } 380 if got := ofz16l32(5); got != 0 { 381 t.Errorf("0<<5 == %d, want 0", got) 382 } 383 if got := ofz16l16(5); got != 0 { 384 t.Errorf("0<<5 == %d, want 0", got) 385 } 386 if got := ofz16l8(5); got != 0 { 387 t.Errorf("0<<5 == %d, want 0", got) 388 } 389 if got := ofz16r64(5); got != 0 { 390 t.Errorf("0>>5 == %d, want 0", got) 391 } 392 if got := ofz16r32(5); got != 0 { 393 t.Errorf("0>>5 == %d, want 0", got) 394 } 395 if got := ofz16r16(5); got != 0 { 396 t.Errorf("0>>5 == %d, want 0", got) 397 } 398 if got := ofz16r8(5); got != 0 { 399 t.Errorf("0>>5 == %d, want 0", got) 400 } 401 if got := ofz16ur64(5); got != 0 { 402 t.Errorf("0>>>5 == %d, want 0", got) 403 } 404 if got := ofz16ur32(5); got != 0 { 405 t.Errorf("0>>>5 == %d, want 0", got) 406 } 407 if got := ofz16ur16(5); got != 0 { 408 t.Errorf("0>>>5 == %d, want 0", got) 409 } 410 if got := ofz16ur8(5); got != 0 { 411 t.Errorf("0>>>5 == %d, want 0", got) 412 } 413 414 if got := ofz8l64(5); got != 0 { 415 t.Errorf("0<<5 == %d, want 0", got) 416 } 417 if got := ofz8l32(5); got != 0 { 418 t.Errorf("0<<5 == %d, want 0", got) 419 } 420 if got := ofz8l16(5); got != 0 { 421 t.Errorf("0<<5 == %d, want 0", got) 422 } 423 if got := ofz8l8(5); got != 0 { 424 t.Errorf("0<<5 == %d, want 0", got) 425 } 426 if got := ofz8r64(5); got != 0 { 427 t.Errorf("0>>5 == %d, want 0", got) 428 } 429 if got := ofz8r32(5); got != 0 { 430 t.Errorf("0>>5 == %d, want 0", got) 431 } 432 if got := ofz8r16(5); got != 0 { 433 t.Errorf("0>>5 == %d, want 0", got) 434 } 435 if got := ofz8r8(5); got != 0 { 436 t.Errorf("0>>5 == %d, want 0", got) 437 } 438 if got := ofz8ur64(5); got != 0 { 439 t.Errorf("0>>>5 == %d, want 0", got) 440 } 441 if got := ofz8ur32(5); got != 0 { 442 t.Errorf("0>>>5 == %d, want 0", got) 443 } 444 if got := ofz8ur16(5); got != 0 { 445 t.Errorf("0>>>5 == %d, want 0", got) 446 } 447 if got := ofz8ur8(5); got != 0 { 448 t.Errorf("0>>>5 == %d, want 0", got) 449 } 450 } 451 452 //go:noinline 453 func byz64l(n int64) int64 { 454 return n << 0 455 } 456 457 //go:noinline 458 func byz64r(n int64) int64 { 459 return n >> 0 460 } 461 462 //go:noinline 463 func byz64ur(n uint64) uint64 { 464 return n >> 0 465 } 466 467 //go:noinline 468 func byz32l(n int32) int32 { 469 return n << 0 470 } 471 472 //go:noinline 473 func byz32r(n int32) int32 { 474 return n >> 0 475 } 476 477 //go:noinline 478 func byz32ur(n uint32) uint32 { 479 return n >> 0 480 } 481 482 //go:noinline 483 func byz16l(n int16) int16 { 484 return n << 0 485 } 486 487 //go:noinline 488 func byz16r(n int16) int16 { 489 return n >> 0 490 } 491 492 //go:noinline 493 func byz16ur(n uint16) uint16 { 494 return n >> 0 495 } 496 497 //go:noinline 498 func byz8l(n int8) int8 { 499 return n << 0 500 } 501 502 //go:noinline 503 func byz8r(n int8) int8 { 504 return n >> 0 505 } 506 507 //go:noinline 508 func byz8ur(n uint8) uint8 { 509 return n >> 0 510 } 511 512 func TestShiftByZero(t *testing.T) { 513 { 514 var n int64 = 0x5555555555555555 515 if got := byz64l(n); got != n { 516 t.Errorf("%x<<0 == %x, want %x", n, got, n) 517 } 518 if got := byz64r(n); got != n { 519 t.Errorf("%x>>0 == %x, want %x", n, got, n) 520 } 521 } 522 { 523 var n uint64 = 0xaaaaaaaaaaaaaaaa 524 if got := byz64ur(n); got != n { 525 t.Errorf("%x>>>0 == %x, want %x", n, got, n) 526 } 527 } 528 529 { 530 var n int32 = 0x55555555 531 if got := byz32l(n); got != n { 532 t.Errorf("%x<<0 == %x, want %x", n, got, n) 533 } 534 if got := byz32r(n); got != n { 535 t.Errorf("%x>>0 == %x, want %x", n, got, n) 536 } 537 } 538 { 539 var n uint32 = 0xaaaaaaaa 540 if got := byz32ur(n); got != n { 541 t.Errorf("%x>>>0 == %x, want %x", n, got, n) 542 } 543 } 544 545 { 546 var n int16 = 0x5555 547 if got := byz16l(n); got != n { 548 t.Errorf("%x<<0 == %x, want %x", n, got, n) 549 } 550 if got := byz16r(n); got != n { 551 t.Errorf("%x>>0 == %x, want %x", n, got, n) 552 } 553 } 554 { 555 var n uint16 = 0xaaaa 556 if got := byz16ur(n); got != n { 557 t.Errorf("%x>>>0 == %x, want %x", n, got, n) 558 } 559 } 560 561 { 562 var n int8 = 0x55 563 if got := byz8l(n); got != n { 564 t.Errorf("%x<<0 == %x, want %x", n, got, n) 565 } 566 if got := byz8r(n); got != n { 567 t.Errorf("%x>>0 == %x, want %x", n, got, n) 568 } 569 } 570 { 571 var n uint8 = 0x55 572 if got := byz8ur(n); got != n { 573 t.Errorf("%x>>>0 == %x, want %x", n, got, n) 574 } 575 } 576 } 577 578 //go:noinline 579 func two64l(x int64) int64 { 580 return x << 1 << 1 581 } 582 583 //go:noinline 584 func two64r(x int64) int64 { 585 return x >> 1 >> 1 586 } 587 588 //go:noinline 589 func two64ur(x uint64) uint64 { 590 return x >> 1 >> 1 591 } 592 593 //go:noinline 594 func two32l(x int32) int32 { 595 return x << 1 << 1 596 } 597 598 //go:noinline 599 func two32r(x int32) int32 { 600 return x >> 1 >> 1 601 } 602 603 //go:noinline 604 func two32ur(x uint32) uint32 { 605 return x >> 1 >> 1 606 } 607 608 //go:noinline 609 func two16l(x int16) int16 { 610 return x << 1 << 1 611 } 612 613 //go:noinline 614 func two16r(x int16) int16 { 615 return x >> 1 >> 1 616 } 617 618 //go:noinline 619 func two16ur(x uint16) uint16 { 620 return x >> 1 >> 1 621 } 622 623 //go:noinline 624 func two8l(x int8) int8 { 625 return x << 1 << 1 626 } 627 628 //go:noinline 629 func two8r(x int8) int8 { 630 return x >> 1 >> 1 631 } 632 633 //go:noinline 634 func two8ur(x uint8) uint8 { 635 return x >> 1 >> 1 636 } 637 638 func TestShiftCombine(t *testing.T) { 639 if got, want := two64l(4), int64(16); want != got { 640 t.Errorf("4<<1<<1 == %d, want %d", got, want) 641 } 642 if got, want := two64r(64), int64(16); want != got { 643 t.Errorf("64>>1>>1 == %d, want %d", got, want) 644 } 645 if got, want := two64ur(64), uint64(16); want != got { 646 t.Errorf("64>>1>>1 == %d, want %d", got, want) 647 } 648 if got, want := two32l(4), int32(16); want != got { 649 t.Errorf("4<<1<<1 == %d, want %d", got, want) 650 } 651 if got, want := two32r(64), int32(16); want != got { 652 t.Errorf("64>>1>>1 == %d, want %d", got, want) 653 } 654 if got, want := two32ur(64), uint32(16); want != got { 655 t.Errorf("64>>1>>1 == %d, want %d", got, want) 656 } 657 if got, want := two16l(4), int16(16); want != got { 658 t.Errorf("4<<1<<1 == %d, want %d", got, want) 659 } 660 if got, want := two16r(64), int16(16); want != got { 661 t.Errorf("64>>1>>1 == %d, want %d", got, want) 662 } 663 if got, want := two16ur(64), uint16(16); want != got { 664 t.Errorf("64>>1>>1 == %d, want %d", got, want) 665 } 666 if got, want := two8l(4), int8(16); want != got { 667 t.Errorf("4<<1<<1 == %d, want %d", got, want) 668 } 669 if got, want := two8r(64), int8(16); want != got { 670 t.Errorf("64>>1>>1 == %d, want %d", got, want) 671 } 672 if got, want := two8ur(64), uint8(16); want != got { 673 t.Errorf("64>>1>>1 == %d, want %d", got, want) 674 } 675 676 } 677 678 //go:noinline 679 func three64l(x int64) int64 { 680 return x << 3 >> 1 << 2 681 } 682 683 //go:noinline 684 func three64ul(x uint64) uint64 { 685 return x << 3 >> 1 << 2 686 } 687 688 //go:noinline 689 func three64r(x int64) int64 { 690 return x >> 3 << 1 >> 2 691 } 692 693 //go:noinline 694 func three64ur(x uint64) uint64 { 695 return x >> 3 << 1 >> 2 696 } 697 698 //go:noinline 699 func three32l(x int32) int32 { 700 return x << 3 >> 1 << 2 701 } 702 703 //go:noinline 704 func three32ul(x uint32) uint32 { 705 return x << 3 >> 1 << 2 706 } 707 708 //go:noinline 709 func three32r(x int32) int32 { 710 return x >> 3 << 1 >> 2 711 } 712 713 //go:noinline 714 func three32ur(x uint32) uint32 { 715 return x >> 3 << 1 >> 2 716 } 717 718 //go:noinline 719 func three16l(x int16) int16 { 720 return x << 3 >> 1 << 2 721 } 722 723 //go:noinline 724 func three16ul(x uint16) uint16 { 725 return x << 3 >> 1 << 2 726 } 727 728 //go:noinline 729 func three16r(x int16) int16 { 730 return x >> 3 << 1 >> 2 731 } 732 733 //go:noinline 734 func three16ur(x uint16) uint16 { 735 return x >> 3 << 1 >> 2 736 } 737 738 //go:noinline 739 func three8l(x int8) int8 { 740 return x << 3 >> 1 << 2 741 } 742 743 //go:noinline 744 func three8ul(x uint8) uint8 { 745 return x << 3 >> 1 << 2 746 } 747 748 //go:noinline 749 func three8r(x int8) int8 { 750 return x >> 3 << 1 >> 2 751 } 752 753 //go:noinline 754 func three8ur(x uint8) uint8 { 755 return x >> 3 << 1 >> 2 756 } 757 758 func TestShiftCombine3(t *testing.T) { 759 if got, want := three64l(4), int64(64); want != got { 760 t.Errorf("4<<1<<1 == %d, want %d", got, want) 761 } 762 if got, want := three64ul(4), uint64(64); want != got { 763 t.Errorf("4<<1<<1 == %d, want %d", got, want) 764 } 765 if got, want := three64r(64), int64(4); want != got { 766 t.Errorf("64>>1>>1 == %d, want %d", got, want) 767 } 768 if got, want := three64ur(64), uint64(4); want != got { 769 t.Errorf("64>>1>>1 == %d, want %d", got, want) 770 } 771 if got, want := three32l(4), int32(64); want != got { 772 t.Errorf("4<<1<<1 == %d, want %d", got, want) 773 } 774 if got, want := three32ul(4), uint32(64); want != got { 775 t.Errorf("4<<1<<1 == %d, want %d", got, want) 776 } 777 if got, want := three32r(64), int32(4); want != got { 778 t.Errorf("64>>1>>1 == %d, want %d", got, want) 779 } 780 if got, want := three32ur(64), uint32(4); want != got { 781 t.Errorf("64>>1>>1 == %d, want %d", got, want) 782 } 783 if got, want := three16l(4), int16(64); want != got { 784 t.Errorf("4<<1<<1 == %d, want %d", got, want) 785 } 786 if got, want := three16ul(4), uint16(64); want != got { 787 t.Errorf("4<<1<<1 == %d, want %d", got, want) 788 } 789 if got, want := three16r(64), int16(4); want != got { 790 t.Errorf("64>>1>>1 == %d, want %d", got, want) 791 } 792 if got, want := three16ur(64), uint16(4); want != got { 793 t.Errorf("64>>1>>1 == %d, want %d", got, want) 794 } 795 if got, want := three8l(4), int8(64); want != got { 796 t.Errorf("4<<1<<1 == %d, want %d", got, want) 797 } 798 if got, want := three8ul(4), uint8(64); want != got { 799 t.Errorf("4<<1<<1 == %d, want %d", got, want) 800 } 801 if got, want := three8r(64), int8(4); want != got { 802 t.Errorf("64>>1>>1 == %d, want %d", got, want) 803 } 804 if got, want := three8ur(64), uint8(4); want != got { 805 t.Errorf("64>>1>>1 == %d, want %d", got, want) 806 } 807 } 808 809 var ( 810 one64 int64 = 1 811 one64u uint64 = 1 812 one32 int32 = 1 813 one32u uint32 = 1 814 one16 int16 = 1 815 one16u uint16 = 1 816 one8 int8 = 1 817 one8u uint8 = 1 818 ) 819 820 func TestShiftLargeCombine(t *testing.T) { 821 var N uint64 = 0x8000000000000000 822 if one64<<N<<N == 1 { 823 t.Errorf("shift overflow mishandled") 824 } 825 if one64>>N>>N == 1 { 826 t.Errorf("shift overflow mishandled") 827 } 828 if one64u>>N>>N == 1 { 829 t.Errorf("shift overflow mishandled") 830 } 831 if one32<<N<<N == 1 { 832 t.Errorf("shift overflow mishandled") 833 } 834 if one32>>N>>N == 1 { 835 t.Errorf("shift overflow mishandled") 836 } 837 if one32u>>N>>N == 1 { 838 t.Errorf("shift overflow mishandled") 839 } 840 if one16<<N<<N == 1 { 841 t.Errorf("shift overflow mishandled") 842 } 843 if one16>>N>>N == 1 { 844 t.Errorf("shift overflow mishandled") 845 } 846 if one16u>>N>>N == 1 { 847 t.Errorf("shift overflow mishandled") 848 } 849 if one8<<N<<N == 1 { 850 t.Errorf("shift overflow mishandled") 851 } 852 if one8>>N>>N == 1 { 853 t.Errorf("shift overflow mishandled") 854 } 855 if one8u>>N>>N == 1 { 856 t.Errorf("shift overflow mishandled") 857 } 858 } 859 860 func TestShiftLargeCombine3(t *testing.T) { 861 var N uint64 = 0x8000000000000001 862 if one64<<N>>2<<N == 1 { 863 t.Errorf("shift overflow mishandled") 864 } 865 if one64u<<N>>2<<N == 1 { 866 t.Errorf("shift overflow mishandled") 867 } 868 if one64>>N<<2>>N == 1 { 869 t.Errorf("shift overflow mishandled") 870 } 871 if one64u>>N<<2>>N == 1 { 872 t.Errorf("shift overflow mishandled") 873 } 874 if one32<<N>>2<<N == 1 { 875 t.Errorf("shift overflow mishandled") 876 } 877 if one32u<<N>>2<<N == 1 { 878 t.Errorf("shift overflow mishandled") 879 } 880 if one32>>N<<2>>N == 1 { 881 t.Errorf("shift overflow mishandled") 882 } 883 if one32u>>N<<2>>N == 1 { 884 t.Errorf("shift overflow mishandled") 885 } 886 if one16<<N>>2<<N == 1 { 887 t.Errorf("shift overflow mishandled") 888 } 889 if one16u<<N>>2<<N == 1 { 890 t.Errorf("shift overflow mishandled") 891 } 892 if one16>>N<<2>>N == 1 { 893 t.Errorf("shift overflow mishandled") 894 } 895 if one16u>>N<<2>>N == 1 { 896 t.Errorf("shift overflow mishandled") 897 } 898 if one8<<N>>2<<N == 1 { 899 t.Errorf("shift overflow mishandled") 900 } 901 if one8u<<N>>2<<N == 1 { 902 t.Errorf("shift overflow mishandled") 903 } 904 if one8>>N<<2>>N == 1 { 905 t.Errorf("shift overflow mishandled") 906 } 907 if one8u>>N<<2>>N == 1 { 908 t.Errorf("shift overflow mishandled") 909 } 910 } 911 912 func TestShiftGeneric(t *testing.T) { 913 for _, test := range [...]struct { 914 valueWidth int 915 signed bool 916 shiftWidth int 917 left bool 918 f interface{} 919 }{ 920 {64, true, 64, true, func(n int64, s uint64) int64 { return n << s }}, 921 {64, true, 64, false, func(n int64, s uint64) int64 { return n >> s }}, 922 {64, false, 64, false, func(n uint64, s uint64) uint64 { return n >> s }}, 923 {64, true, 32, true, func(n int64, s uint32) int64 { return n << s }}, 924 {64, true, 32, false, func(n int64, s uint32) int64 { return n >> s }}, 925 {64, false, 32, false, func(n uint64, s uint32) uint64 { return n >> s }}, 926 {64, true, 16, true, func(n int64, s uint16) int64 { return n << s }}, 927 {64, true, 16, false, func(n int64, s uint16) int64 { return n >> s }}, 928 {64, false, 16, false, func(n uint64, s uint16) uint64 { return n >> s }}, 929 {64, true, 8, true, func(n int64, s uint8) int64 { return n << s }}, 930 {64, true, 8, false, func(n int64, s uint8) int64 { return n >> s }}, 931 {64, false, 8, false, func(n uint64, s uint8) uint64 { return n >> s }}, 932 933 {32, true, 64, true, func(n int32, s uint64) int32 { return n << s }}, 934 {32, true, 64, false, func(n int32, s uint64) int32 { return n >> s }}, 935 {32, false, 64, false, func(n uint32, s uint64) uint32 { return n >> s }}, 936 {32, true, 32, true, func(n int32, s uint32) int32 { return n << s }}, 937 {32, true, 32, false, func(n int32, s uint32) int32 { return n >> s }}, 938 {32, false, 32, false, func(n uint32, s uint32) uint32 { return n >> s }}, 939 {32, true, 16, true, func(n int32, s uint16) int32 { return n << s }}, 940 {32, true, 16, false, func(n int32, s uint16) int32 { return n >> s }}, 941 {32, false, 16, false, func(n uint32, s uint16) uint32 { return n >> s }}, 942 {32, true, 8, true, func(n int32, s uint8) int32 { return n << s }}, 943 {32, true, 8, false, func(n int32, s uint8) int32 { return n >> s }}, 944 {32, false, 8, false, func(n uint32, s uint8) uint32 { return n >> s }}, 945 946 {16, true, 64, true, func(n int16, s uint64) int16 { return n << s }}, 947 {16, true, 64, false, func(n int16, s uint64) int16 { return n >> s }}, 948 {16, false, 64, false, func(n uint16, s uint64) uint16 { return n >> s }}, 949 {16, true, 32, true, func(n int16, s uint32) int16 { return n << s }}, 950 {16, true, 32, false, func(n int16, s uint32) int16 { return n >> s }}, 951 {16, false, 32, false, func(n uint16, s uint32) uint16 { return n >> s }}, 952 {16, true, 16, true, func(n int16, s uint16) int16 { return n << s }}, 953 {16, true, 16, false, func(n int16, s uint16) int16 { return n >> s }}, 954 {16, false, 16, false, func(n uint16, s uint16) uint16 { return n >> s }}, 955 {16, true, 8, true, func(n int16, s uint8) int16 { return n << s }}, 956 {16, true, 8, false, func(n int16, s uint8) int16 { return n >> s }}, 957 {16, false, 8, false, func(n uint16, s uint8) uint16 { return n >> s }}, 958 959 {8, true, 64, true, func(n int8, s uint64) int8 { return n << s }}, 960 {8, true, 64, false, func(n int8, s uint64) int8 { return n >> s }}, 961 {8, false, 64, false, func(n uint8, s uint64) uint8 { return n >> s }}, 962 {8, true, 32, true, func(n int8, s uint32) int8 { return n << s }}, 963 {8, true, 32, false, func(n int8, s uint32) int8 { return n >> s }}, 964 {8, false, 32, false, func(n uint8, s uint32) uint8 { return n >> s }}, 965 {8, true, 16, true, func(n int8, s uint16) int8 { return n << s }}, 966 {8, true, 16, false, func(n int8, s uint16) int8 { return n >> s }}, 967 {8, false, 16, false, func(n uint8, s uint16) uint8 { return n >> s }}, 968 {8, true, 8, true, func(n int8, s uint8) int8 { return n << s }}, 969 {8, true, 8, false, func(n int8, s uint8) int8 { return n >> s }}, 970 {8, false, 8, false, func(n uint8, s uint8) uint8 { return n >> s }}, 971 } { 972 fv := reflect.ValueOf(test.f) 973 var args [2]reflect.Value 974 for i := 0; i < test.valueWidth; i++ { 975 // Build value to be shifted. 976 var n int64 = 1 977 for j := 0; j < i; j++ { 978 n <<= 1 979 } 980 args[0] = reflect.ValueOf(n).Convert(fv.Type().In(0)) 981 for s := 0; s <= test.shiftWidth; s++ { 982 args[1] = reflect.ValueOf(s).Convert(fv.Type().In(1)) 983 984 // Compute desired result. We're testing variable shifts 985 // assuming constant shifts are correct. 986 r := n 987 var op string 988 switch { 989 case test.left: 990 op = "<<" 991 for j := 0; j < s; j++ { 992 r <<= 1 993 } 994 switch test.valueWidth { 995 case 32: 996 r = int64(int32(r)) 997 case 16: 998 r = int64(int16(r)) 999 case 8: 1000 r = int64(int8(r)) 1001 } 1002 case test.signed: 1003 op = ">>" 1004 switch test.valueWidth { 1005 case 32: 1006 r = int64(int32(r)) 1007 case 16: 1008 r = int64(int16(r)) 1009 case 8: 1010 r = int64(int8(r)) 1011 } 1012 for j := 0; j < s; j++ { 1013 r >>= 1 1014 } 1015 default: 1016 op = ">>>" 1017 for j := 0; j < s; j++ { 1018 r = int64(uint64(r) >> 1) 1019 } 1020 } 1021 1022 // Call function. 1023 res := fv.Call(args[:])[0].Convert(reflect.ValueOf(r).Type()) 1024 1025 if res.Int() != r { 1026 t.Errorf("%s%dx%d(%x,%x)=%x, want %x", op, test.valueWidth, test.shiftWidth, n, s, res.Int(), r) 1027 } 1028 } 1029 } 1030 } 1031 } 1032 1033 var shiftSink64 int64 1034 1035 func BenchmarkShiftArithmeticRight(b *testing.B) { 1036 x := shiftSink64 1037 for i := 0; i < b.N; i++ { 1038 x = x >> (i & 63) 1039 } 1040 shiftSink64 = x 1041 } 1042 1043 //go:noinline 1044 func incorrectRotate1(x, c uint64) uint64 { 1045 // This should not compile to a rotate instruction. 1046 return x<<c | x>>(64-c) 1047 } 1048 1049 //go:noinline 1050 func incorrectRotate2(x uint64) uint64 { 1051 var c uint64 = 66 1052 // This should not compile to a rotate instruction. 1053 return x<<c | x>>(64-c) 1054 } 1055 1056 func TestIncorrectRotate(t *testing.T) { 1057 if got := incorrectRotate1(1, 66); got != 0 { 1058 t.Errorf("got %x want 0", got) 1059 } 1060 if got := incorrectRotate2(1); got != 0 { 1061 t.Errorf("got %x want 0", got) 1062 } 1063 } 1064 1065 //go:noinline 1066 func variableShiftOverflow64x8(x int64, y, z uint8) (a, b, c int64) { 1067 // Verify junk bits are ignored when doing a variable shift. 1068 return x >> (y + z), x << (y + z), int64(uint64(x) >> (y + z)) 1069 } 1070 1071 //go:noinline 1072 func variableShiftOverflow32x8(x int32, y, z uint8) (a, b, c int32) { 1073 // Verify junk bits are ignored when doing a variable shift. 1074 return x >> (y + z), x << (y + z), int32(uint32(x) >> (y + z)) 1075 } 1076 1077 //go:noinline 1078 func variableShiftOverflow16x8(x int16, y, z uint8) (a, b, c int16) { 1079 // Verify junk bits are ignored when doing a variable shift. 1080 return x >> (y + z), x << (y + z), int16(uint16(x) >> (y + z)) 1081 } 1082 1083 //go:noinline 1084 func variableShiftOverflow8x8(x int8, y, z uint8) (a, b, c int8) { 1085 // Verify junk bits are ignored when doing a variable shift. 1086 return x >> (y + z), x << (y + z), int8(uint8(x) >> (y + z)) 1087 } 1088 1089 //go:noinline 1090 func variableShiftOverflow64x16(x int64, y, z uint16) (a, b, c int64) { 1091 // Verify junk bits are ignored when doing a variable shift. 1092 return x >> (y + z), x << (y + z), int64(uint64(x) >> (y + z)) 1093 } 1094 1095 //go:noinline 1096 func variableShiftOverflow32x16(x int32, y, z uint16) (a, b, c int32) { 1097 // Verify junk bits are ignored when doing a variable shift. 1098 return x >> (y + z), x << (y + z), int32(uint32(x) >> (y + z)) 1099 } 1100 1101 //go:noinline 1102 func variableShiftOverflow16x16(x int16, y, z uint16) (a, b, c int16) { 1103 // Verify junk bits are ignored when doing a variable shift. 1104 return x >> (y + z), x << (y + z), int16(uint16(x) >> (y + z)) 1105 } 1106 1107 //go:noinline 1108 func variableShiftOverflow8x16(x int8, y, z uint16) (a, b, c int8) { 1109 // Verify junk bits are ignored when doing a variable shift. 1110 return x >> (y + z), x << (y + z), int8(uint8(x) >> (y + z)) 1111 } 1112 1113 //go:noinline 1114 func makeU8(x uint64) uint8 { 1115 // Ensure the upper portions of the register are clear before testing large shift values 1116 // using non-native types (e.g uint8 on PPC64). 1117 return uint8(x) 1118 } 1119 1120 //go:noinline 1121 func makeU16(x uint64) uint16 { 1122 // Ensure the upper portions of the register are clear before testing large shift values 1123 // using non-native types (e.g uint8 on PPC64). 1124 return uint16(x) 1125 } 1126 1127 func TestShiftOverflow(t *testing.T) { 1128 if v, w, z := variableShiftOverflow64x8(-64, makeU8(255), 2); v != -32 || w != -128 || z != 0x7fffffffffffffe0 { 1129 t.Errorf("got %d %d 0x%x, expected -32 -128 0x7fffffffffffffe0", v, w, z) 1130 } 1131 if v, w, z := variableShiftOverflow32x8(-64, makeU8(255), 2); v != -32 || w != -128 || z != 0x7fffffe0 { 1132 t.Errorf("got %d %d 0x%x, expected -32 -128 0x7fffffe0", v, w, z) 1133 } 1134 if v, w, z := variableShiftOverflow16x8(-64, makeU8(255), 2); v != -32 || w != -128 || z != 0x7fe0 { 1135 t.Errorf("got %d %d 0x%x, expected -32 -128 0x7fe0", v, w, z) 1136 } 1137 if v, w, z := variableShiftOverflow8x8(-64, makeU8(255), 2); v != -32 || w != -128 || z != 0x60 { 1138 t.Errorf("got %d %d 0x%x, expected -32 -128 0x60", v, w, z) 1139 } 1140 if v, w, z := variableShiftOverflow64x16(-64, makeU16(0xffff), 2); v != -32 || w != -128 || z != 0x7fffffffffffffe0 { 1141 t.Errorf("got %d %d 0x%x, expected -32 -128 0x7fffffffffffffe0", v, w, z) 1142 } 1143 if v, w, z := variableShiftOverflow32x16(-64, makeU16(0xffff), 2); v != -32 || w != -128 || z != 0x7fffffe0 { 1144 t.Errorf("got %d %d 0x%x, expected -32 -128 0x7fffffe0,", v, w, z) 1145 } 1146 if v, w, z := variableShiftOverflow16x16(-64, makeU16(0xffff), 2); v != -32 || w != -128 || z != 0x7fe0 { 1147 t.Errorf("got %d %d 0x%x, expected -32 -128 0x7fe0", v, w, z) 1148 } 1149 if v, w, z := variableShiftOverflow8x16(-64, makeU16(0xffff), 2); v != -32 || w != -128 || z != 0x60 { 1150 t.Errorf("got %d %d 0x%x, expected -32 -128 0x60", v, w, z) 1151 } 1152 }