|
621 | 621 | (SARB x (MOVQconst [c])) -> (SARBconst [min(c&31,7)] x)
|
622 | 622 | (SARB x (MOVLconst [c])) -> (SARBconst [min(c&31,7)] x)
|
623 | 623 |
|
624 |
| -(SARL x (ANDLconst [31] y)) -> (SARL x y) |
625 |
| -(SARQ x (ANDQconst [63] y)) -> (SARQ x y) |
626 |
| - |
627 |
| -(SHLL x (ANDLconst [31] y)) -> (SHLL x y) |
628 |
| -(SHLQ x (ANDQconst [63] y)) -> (SHLQ x y) |
629 |
| -(SHLQ x (ANDLconst [63] y)) -> (SHLQ x y) |
630 |
| - |
631 |
| -(SHRL x (ANDLconst [31] y)) -> (SHRL x y) |
632 |
| -(SHRQ x (ANDQconst [63] y)) -> (SHRQ x y) |
633 |
| -(SHRQ x (ANDLconst [63] y)) -> (SHRQ x y) |
634 |
| - |
635 |
| -// Rotate instructions |
636 |
| - |
| 624 | +// Operations which don't affect the low 6/5 bits of the shift amount are NOPs. |
| 625 | +(SHLQ x (ADDQconst [c] y)) && c & 63 == 0 -> (SHLQ x y) |
| 626 | +(SHRQ x (ADDQconst [c] y)) && c & 63 == 0 -> (SHRQ x y) |
| 627 | +(SARQ x (ADDQconst [c] y)) && c & 63 == 0 -> (SARQ x y) |
| 628 | +(SHLQ x (NEGQ <t> (ADDQconst [c] y))) && c & 63 == 0 -> (SHLQ x (NEGQ <t> y)) |
| 629 | +(SHRQ x (NEGQ <t> (ADDQconst [c] y))) && c & 63 == 0 -> (SHRQ x (NEGQ <t> y)) |
| 630 | +(SARQ x (NEGQ <t> (ADDQconst [c] y))) && c & 63 == 0 -> (SARQ x (NEGQ <t> y)) |
| 631 | +(SHLQ x (ANDQconst [c] y)) && c & 63 == 63 -> (SHLQ x y) |
| 632 | +(SHRQ x (ANDQconst [c] y)) && c & 63 == 63 -> (SHRQ x y) |
| 633 | +(SARQ x (ANDQconst [c] y)) && c & 63 == 63 -> (SARQ x y) |
| 634 | +(SHLQ x (NEGQ <t> (ANDQconst [c] y))) && c & 63 == 63 -> (SHLQ x (NEGQ <t> y)) |
| 635 | +(SHRQ x (NEGQ <t> (ANDQconst [c] y))) && c & 63 == 63 -> (SHRQ x (NEGQ <t> y)) |
| 636 | +(SARQ x (NEGQ <t> (ANDQconst [c] y))) && c & 63 == 63 -> (SARQ x (NEGQ <t> y)) |
| 637 | + |
| 638 | +(SHLL x (ADDQconst [c] y)) && c & 31 == 0 -> (SHLL x y) |
| 639 | +(SHRL x (ADDQconst [c] y)) && c & 31 == 0 -> (SHRL x y) |
| 640 | +(SARL x (ADDQconst [c] y)) && c & 31 == 0 -> (SARL x y) |
| 641 | +(SHLL x (NEGQ <t> (ADDQconst [c] y))) && c & 31 == 0 -> (SHLL x (NEGQ <t> y)) |
| 642 | +(SHRL x (NEGQ <t> (ADDQconst [c] y))) && c & 31 == 0 -> (SHRL x (NEGQ <t> y)) |
| 643 | +(SARL x (NEGQ <t> (ADDQconst [c] y))) && c & 31 == 0 -> (SARL x (NEGQ <t> y)) |
| 644 | +(SHLL x (ANDQconst [c] y)) && c & 31 == 31 -> (SHLL x y) |
| 645 | +(SHRL x (ANDQconst [c] y)) && c & 31 == 31 -> (SHRL x y) |
| 646 | +(SARL x (ANDQconst [c] y)) && c & 31 == 31 -> (SARL x y) |
| 647 | +(SHLL x (NEGQ <t> (ANDQconst [c] y))) && c & 31 == 31 -> (SHLL x (NEGQ <t> y)) |
| 648 | +(SHRL x (NEGQ <t> (ANDQconst [c] y))) && c & 31 == 31 -> (SHRL x (NEGQ <t> y)) |
| 649 | +(SARL x (NEGQ <t> (ANDQconst [c] y))) && c & 31 == 31 -> (SARL x (NEGQ <t> y)) |
| 650 | + |
| 651 | +(SHLQ x (ADDLconst [c] y)) && c & 63 == 0 -> (SHLQ x y) |
| 652 | +(SHRQ x (ADDLconst [c] y)) && c & 63 == 0 -> (SHRQ x y) |
| 653 | +(SARQ x (ADDLconst [c] y)) && c & 63 == 0 -> (SARQ x y) |
| 654 | +(SHLQ x (NEGL <t> (ADDLconst [c] y))) && c & 63 == 0 -> (SHLQ x (NEGL <t> y)) |
| 655 | +(SHRQ x (NEGL <t> (ADDLconst [c] y))) && c & 63 == 0 -> (SHRQ x (NEGL <t> y)) |
| 656 | +(SARQ x (NEGL <t> (ADDLconst [c] y))) && c & 63 == 0 -> (SARQ x (NEGL <t> y)) |
| 657 | +(SHLQ x (ANDLconst [c] y)) && c & 63 == 63 -> (SHLQ x y) |
| 658 | +(SHRQ x (ANDLconst [c] y)) && c & 63 == 63 -> (SHRQ x y) |
| 659 | +(SARQ x (ANDLconst [c] y)) && c & 63 == 63 -> (SARQ x y) |
| 660 | +(SHLQ x (NEGL <t> (ANDLconst [c] y))) && c & 63 == 63 -> (SHLQ x (NEGL <t> y)) |
| 661 | +(SHRQ x (NEGL <t> (ANDLconst [c] y))) && c & 63 == 63 -> (SHRQ x (NEGL <t> y)) |
| 662 | +(SARQ x (NEGL <t> (ANDLconst [c] y))) && c & 63 == 63 -> (SARQ x (NEGL <t> y)) |
| 663 | + |
| 664 | +(SHLL x (ADDLconst [c] y)) && c & 31 == 0 -> (SHLL x y) |
| 665 | +(SHRL x (ADDLconst [c] y)) && c & 31 == 0 -> (SHRL x y) |
| 666 | +(SARL x (ADDLconst [c] y)) && c & 31 == 0 -> (SARL x y) |
| 667 | +(SHLL x (NEGL <t> (ADDLconst [c] y))) && c & 31 == 0 -> (SHLL x (NEGL <t> y)) |
| 668 | +(SHRL x (NEGL <t> (ADDLconst [c] y))) && c & 31 == 0 -> (SHRL x (NEGL <t> y)) |
| 669 | +(SARL x (NEGL <t> (ADDLconst [c] y))) && c & 31 == 0 -> (SARL x (NEGL <t> y)) |
| 670 | +(SHLL x (ANDLconst [c] y)) && c & 31 == 31 -> (SHLL x y) |
| 671 | +(SHRL x (ANDLconst [c] y)) && c & 31 == 31 -> (SHRL x y) |
| 672 | +(SARL x (ANDLconst [c] y)) && c & 31 == 31 -> (SARL x y) |
| 673 | +(SHLL x (NEGL <t> (ANDLconst [c] y))) && c & 31 == 31 -> (SHLL x (NEGL <t> y)) |
| 674 | +(SHRL x (NEGL <t> (ANDLconst [c] y))) && c & 31 == 31 -> (SHRL x (NEGL <t> y)) |
| 675 | +(SARL x (NEGL <t> (ANDLconst [c] y))) && c & 31 == 31 -> (SARL x (NEGL <t> y)) |
| 676 | + |
| 677 | +// Constant rotate instructions |
637 | 678 | (ADDQ (SHLQconst x [c]) (SHRQconst x [d])) && d==64-c -> (ROLQconst x [c])
|
638 | 679 | ( ORQ (SHLQconst x [c]) (SHRQconst x [d])) && d==64-c -> (ROLQconst x [c])
|
639 | 680 | (XORQ (SHLQconst x [c]) (SHRQconst x [d])) && d==64-c -> (ROLQconst x [c])
|
|
655 | 696 | (ROLWconst [c] (ROLWconst [d] x)) -> (ROLWconst [(c+d)&15] x)
|
656 | 697 | (ROLBconst [c] (ROLBconst [d] x)) -> (ROLBconst [(c+d)& 7] x)
|
657 | 698 |
|
658 |
| -// TODO: non-constant rotates if shift amount is known to be bounded (shift & 63 or something). |
| 699 | +// Non-constant rotates. |
| 700 | +// We want to issue a rotate when the Go source contains code like |
| 701 | +// y &= 63 |
| 702 | +// x << y | x >> (64-y) |
| 703 | +// The shift rules above convert << to SHLx and >> to SHRx. |
| 704 | +// SHRx converts its shift argument from 64-y to -y. |
| 705 | +// A tricky situation occurs when y==0. Then the original code would be: |
| 706 | +// x << 0 | x >> 64 |
| 707 | +// But x >> 64 is 0, not x. So there's an additional mask that is ANDed in |
| 708 | +// to force the second term to 0. We don't need that mask, but we must match |
| 709 | +// it in order to strip it out. |
| 710 | +(ORQ (SHLQ x y) (ANDQ (SHRQ x (NEGQ y)) (SBBQcarrymask (CMPQconst (NEGQ (ADDQconst (ANDQconst y [63]) [-64])) [64])))) -> (ROLQ x y) |
| 711 | +(ORQ (SHLQ x y) (ANDQ (SHRQ x (NEGL y)) (SBBQcarrymask (CMPLconst (NEGL (ADDLconst (ANDLconst y [63]) [-64])) [64])))) -> (ROLQ x y) |
| 712 | +(ORQ (SHRQ x y) (ANDQ (SHLQ x (NEGQ y)) (SBBQcarrymask (CMPQconst (NEGQ (ADDQconst (ANDQconst y [63]) [-64])) [64])))) -> (RORQ x y) |
| 713 | +(ORQ (SHRQ x y) (ANDQ (SHLQ x (NEGL y)) (SBBQcarrymask (CMPLconst (NEGL (ADDLconst (ANDLconst y [63]) [-64])) [64])))) -> (RORQ x y) |
| 714 | + |
| 715 | +(ORL (SHLL x y) (ANDL (SHRL x (NEGQ y)) (SBBLcarrymask (CMPQconst (NEGQ (ADDQconst (ANDQconst y [31]) [-32])) [32])))) -> (ROLL x y) |
| 716 | +(ORL (SHLL x y) (ANDL (SHRL x (NEGL y)) (SBBLcarrymask (CMPLconst (NEGL (ADDLconst (ANDLconst y [31]) [-32])) [32])))) -> (ROLL x y) |
| 717 | +(ORL (SHRL x y) (ANDL (SHLL x (NEGQ y)) (SBBLcarrymask (CMPQconst (NEGQ (ADDQconst (ANDQconst y [31]) [-32])) [32])))) -> (RORL x y) |
| 718 | +(ORL (SHRL x y) (ANDL (SHLL x (NEGL y)) (SBBLcarrymask (CMPLconst (NEGL (ADDLconst (ANDLconst y [31]) [-32])) [32])))) -> (RORL x y) |
| 719 | + |
| 720 | +// Help with rotate detection |
| 721 | +(CMPQconst (NEGQ (ADDQconst [-16] (ANDQconst [15] _))) [32]) -> (FlagLT_ULT) |
| 722 | +(CMPQconst (NEGQ (ADDQconst [ -8] (ANDQconst [7] _))) [32]) -> (FlagLT_ULT) |
| 723 | + |
| 724 | +(ORL (SHLL x (ANDQconst y [15])) |
| 725 | + (ANDL (SHRW x (NEGQ (ADDQconst (ANDQconst y [15]) [-16]))) |
| 726 | + (SBBLcarrymask (CMPQconst (NEGQ (ADDQconst (ANDQconst y [15]) [-16])) [16])))) |
| 727 | + && v.Type.Size() == 2 |
| 728 | + -> (ROLW x y) |
| 729 | +(ORL (SHLL x (ANDLconst y [15])) |
| 730 | + (ANDL (SHRW x (NEGL (ADDLconst (ANDLconst y [15]) [-16]))) |
| 731 | + (SBBLcarrymask (CMPLconst (NEGL (ADDLconst (ANDLconst y [15]) [-16])) [16])))) |
| 732 | + && v.Type.Size() == 2 |
| 733 | + -> (ROLW x y) |
| 734 | +(ORL (SHRW x (ANDQconst y [15])) |
| 735 | + (SHLL x (NEGQ (ADDQconst (ANDQconst y [15]) [-16])))) |
| 736 | + && v.Type.Size() == 2 |
| 737 | + -> (RORW x y) |
| 738 | +(ORL (SHRW x (ANDLconst y [15])) |
| 739 | + (SHLL x (NEGL (ADDLconst (ANDLconst y [15]) [-16])))) |
| 740 | + && v.Type.Size() == 2 |
| 741 | + -> (RORW x y) |
| 742 | + |
| 743 | +(ORL (SHLL x (ANDQconst y [ 7])) |
| 744 | + (ANDL (SHRB x (NEGQ (ADDQconst (ANDQconst y [ 7]) [ -8]))) |
| 745 | + (SBBLcarrymask (CMPQconst (NEGQ (ADDQconst (ANDQconst y [ 7]) [ -8])) [ 8])))) |
| 746 | + && v.Type.Size() == 1 |
| 747 | + -> (ROLB x y) |
| 748 | +(ORL (SHLL x (ANDLconst y [ 7])) |
| 749 | + (ANDL (SHRB x (NEGL (ADDLconst (ANDLconst y [ 7]) [ -8]))) |
| 750 | + (SBBLcarrymask (CMPLconst (NEGL (ADDLconst (ANDLconst y [ 7]) [ -8])) [ 8])))) |
| 751 | + && v.Type.Size() == 1 |
| 752 | + -> (ROLB x y) |
| 753 | +(ORL (SHRB x (ANDQconst y [ 7])) |
| 754 | + (SHLL x (NEGQ (ADDQconst (ANDQconst y [ 7]) [ -8])))) |
| 755 | + && v.Type.Size() == 1 |
| 756 | + -> (RORB x y) |
| 757 | +(ORL (SHRB x (ANDLconst y [ 7])) |
| 758 | + (SHLL x (NEGL (ADDLconst (ANDLconst y [ 7]) [ -8])))) |
| 759 | + && v.Type.Size() == 1 |
| 760 | + -> (RORB x y) |
| 761 | + |
| 762 | +// rotate left negative = rotate right |
| 763 | +(ROLQ x (NEGQ y)) -> (RORQ x y) |
| 764 | +(ROLQ x (NEGL y)) -> (RORQ x y) |
| 765 | +(ROLL x (NEGQ y)) -> (RORL x y) |
| 766 | +(ROLL x (NEGL y)) -> (RORL x y) |
| 767 | +(ROLW x (NEGQ y)) -> (RORW x y) |
| 768 | +(ROLW x (NEGL y)) -> (RORW x y) |
| 769 | +(ROLB x (NEGQ y)) -> (RORB x y) |
| 770 | +(ROLB x (NEGL y)) -> (RORB x y) |
| 771 | + |
| 772 | +// rotate right negative = rotate left |
| 773 | +(RORQ x (NEGQ y)) -> (ROLQ x y) |
| 774 | +(RORQ x (NEGL y)) -> (ROLQ x y) |
| 775 | +(RORL x (NEGQ y)) -> (ROLL x y) |
| 776 | +(RORL x (NEGL y)) -> (ROLL x y) |
| 777 | +(RORW x (NEGQ y)) -> (ROLW x y) |
| 778 | +(RORW x (NEGL y)) -> (ROLW x y) |
| 779 | +(RORB x (NEGQ y)) -> (ROLB x y) |
| 780 | +(RORB x (NEGL y)) -> (ROLB x y) |
| 781 | + |
| 782 | +// rotate by constants |
| 783 | +(ROLQ x (MOVQconst [c])) -> (ROLQconst [c&63] x) |
| 784 | +(ROLQ x (MOVLconst [c])) -> (ROLQconst [c&63] x) |
| 785 | +(ROLL x (MOVQconst [c])) -> (ROLLconst [c&31] x) |
| 786 | +(ROLL x (MOVLconst [c])) -> (ROLLconst [c&31] x) |
| 787 | +(ROLW x (MOVQconst [c])) -> (ROLWconst [c&15] x) |
| 788 | +(ROLW x (MOVLconst [c])) -> (ROLWconst [c&15] x) |
| 789 | +(ROLB x (MOVQconst [c])) -> (ROLBconst [c&7 ] x) |
| 790 | +(ROLB x (MOVLconst [c])) -> (ROLBconst [c&7 ] x) |
| 791 | + |
| 792 | +(RORQ x (MOVQconst [c])) -> (ROLQconst [(-c)&63] x) |
| 793 | +(RORQ x (MOVLconst [c])) -> (ROLQconst [(-c)&63] x) |
| 794 | +(RORL x (MOVQconst [c])) -> (ROLLconst [(-c)&31] x) |
| 795 | +(RORL x (MOVLconst [c])) -> (ROLLconst [(-c)&31] x) |
| 796 | +(RORW x (MOVQconst [c])) -> (ROLWconst [(-c)&15] x) |
| 797 | +(RORW x (MOVLconst [c])) -> (ROLWconst [(-c)&15] x) |
| 798 | +(RORB x (MOVQconst [c])) -> (ROLBconst [(-c)&7 ] x) |
| 799 | +(RORB x (MOVLconst [c])) -> (ROLBconst [(-c)&7 ] x) |
659 | 800 |
|
660 | 801 | // Constant shift simplifications
|
661 |
| - |
662 | 802 | (SHLQconst x [0]) -> x
|
663 | 803 | (SHRQconst x [0]) -> x
|
664 | 804 | (SARQconst x [0]) -> x
|
|
1171 | 1311 | (CMPLconst (ANDLconst _ [m]) [n]) && 0 <= int32(m) && int32(m) < int32(n) -> (FlagLT_ULT)
|
1172 | 1312 | (CMPWconst (ANDLconst _ [m]) [n]) && 0 <= int16(m) && int16(m) < int16(n) -> (FlagLT_ULT)
|
1173 | 1313 | (CMPBconst (ANDLconst _ [m]) [n]) && 0 <= int8(m) && int8(m) < int8(n) -> (FlagLT_ULT)
|
| 1314 | + |
1174 | 1315 | // TODO: DIVxU also.
|
1175 | 1316 |
|
1176 | 1317 | // Absorb flag constants into SBB ops.
|
|
0 commit comments