|
596 | 596 | // into tests for carry flags.
|
597 | 597 | // ULT and SETB check the carry flag; they are identical to CS and SETCS. Same, mutatis
|
598 | 598 | // mutandis, for UGE and SETAE, and CC and SETCC.
|
599 |
| -((NE|EQ) (TESTL (SHLL (MOVLconst [1]) x) y)) && !config.nacl -> ((ULT|UGE) (BTL x y)) |
600 |
| -((NE|EQ) (TESTQ (SHLQ (MOVQconst [1]) x) y)) && !config.nacl -> ((ULT|UGE) (BTQ x y)) |
601 |
| -((NE|EQ) (TESTLconst [c] x)) && isUint32PowerOfTwo(c) && !config.nacl |
| 599 | +((NE|EQ) (TESTL (SHLL (MOVLconst [1]) x) y)) -> ((ULT|UGE) (BTL x y)) |
| 600 | +((NE|EQ) (TESTQ (SHLQ (MOVQconst [1]) x) y)) -> ((ULT|UGE) (BTQ x y)) |
| 601 | +((NE|EQ) (TESTLconst [c] x)) && isUint32PowerOfTwo(c) |
602 | 602 | -> ((ULT|UGE) (BTLconst [log2uint32(c)] x))
|
603 |
| -((NE|EQ) (TESTQconst [c] x)) && isUint64PowerOfTwo(c) && !config.nacl |
| 603 | +((NE|EQ) (TESTQconst [c] x)) && isUint64PowerOfTwo(c) |
604 | 604 | -> ((ULT|UGE) (BTQconst [log2(c)] x))
|
605 |
| -((NE|EQ) (TESTQ (MOVQconst [c]) x)) && isUint64PowerOfTwo(c) && !config.nacl |
| 605 | +((NE|EQ) (TESTQ (MOVQconst [c]) x)) && isUint64PowerOfTwo(c) |
606 | 606 | -> ((ULT|UGE) (BTQconst [log2(c)] x))
|
607 |
| -(SET(NE|EQ) (TESTL (SHLL (MOVLconst [1]) x) y)) && !config.nacl -> (SET(B|AE) (BTL x y)) |
608 |
| -(SET(NE|EQ) (TESTQ (SHLQ (MOVQconst [1]) x) y)) && !config.nacl -> (SET(B|AE) (BTQ x y)) |
609 |
| -(SET(NE|EQ) (TESTLconst [c] x)) && isUint32PowerOfTwo(c) && !config.nacl |
| 607 | +(SET(NE|EQ) (TESTL (SHLL (MOVLconst [1]) x) y)) -> (SET(B|AE) (BTL x y)) |
| 608 | +(SET(NE|EQ) (TESTQ (SHLQ (MOVQconst [1]) x) y)) -> (SET(B|AE) (BTQ x y)) |
| 609 | +(SET(NE|EQ) (TESTLconst [c] x)) && isUint32PowerOfTwo(c) |
610 | 610 | -> (SET(B|AE) (BTLconst [log2uint32(c)] x))
|
611 |
| -(SET(NE|EQ) (TESTQconst [c] x)) && isUint64PowerOfTwo(c) && !config.nacl |
| 611 | +(SET(NE|EQ) (TESTQconst [c] x)) && isUint64PowerOfTwo(c) |
612 | 612 | -> (SET(B|AE) (BTQconst [log2(c)] x))
|
613 |
| -(SET(NE|EQ) (TESTQ (MOVQconst [c]) x)) && isUint64PowerOfTwo(c) && !config.nacl |
| 613 | +(SET(NE|EQ) (TESTQ (MOVQconst [c]) x)) && isUint64PowerOfTwo(c) |
614 | 614 | -> (SET(B|AE) (BTQconst [log2(c)] x))
|
615 | 615 | // SET..store variant
|
616 |
| -(SET(NE|EQ)store [off] {sym} ptr (TESTL (SHLL (MOVLconst [1]) x) y) mem) && !config.nacl |
| 616 | +(SET(NE|EQ)store [off] {sym} ptr (TESTL (SHLL (MOVLconst [1]) x) y) mem) |
617 | 617 | -> (SET(B|AE)store [off] {sym} ptr (BTL x y) mem)
|
618 |
| -(SET(NE|EQ)store [off] {sym} ptr (TESTQ (SHLQ (MOVQconst [1]) x) y) mem) && !config.nacl |
| 618 | +(SET(NE|EQ)store [off] {sym} ptr (TESTQ (SHLQ (MOVQconst [1]) x) y) mem) |
619 | 619 | -> (SET(B|AE)store [off] {sym} ptr (BTQ x y) mem)
|
620 |
| -(SET(NE|EQ)store [off] {sym} ptr (TESTLconst [c] x) mem) && isUint32PowerOfTwo(c) && !config.nacl |
| 620 | +(SET(NE|EQ)store [off] {sym} ptr (TESTLconst [c] x) mem) && isUint32PowerOfTwo(c) |
621 | 621 | -> (SET(B|AE)store [off] {sym} ptr (BTLconst [log2uint32(c)] x) mem)
|
622 |
| -(SET(NE|EQ)store [off] {sym} ptr (TESTQconst [c] x) mem) && isUint64PowerOfTwo(c) && !config.nacl |
| 622 | +(SET(NE|EQ)store [off] {sym} ptr (TESTQconst [c] x) mem) && isUint64PowerOfTwo(c) |
623 | 623 | -> (SET(B|AE)store [off] {sym} ptr (BTQconst [log2(c)] x) mem)
|
624 |
| -(SET(NE|EQ)store [off] {sym} ptr (TESTQ (MOVQconst [c]) x) mem) && isUint64PowerOfTwo(c) && !config.nacl |
| 624 | +(SET(NE|EQ)store [off] {sym} ptr (TESTQ (MOVQconst [c]) x) mem) && isUint64PowerOfTwo(c) |
625 | 625 | -> (SET(B|AE)store [off] {sym} ptr (BTQconst [log2(c)] x) mem)
|
626 | 626 |
|
627 | 627 | // Handle bit-testing in the form (a>>b)&1 != 0 by building the above rules
|
|
641 | 641 | (SET(NE|EQ)store [off] {sym} ptr (CMPQconst [1] s:(ANDQconst [1] _)) mem) -> (SET(EQ|NE)store [off] {sym} ptr (CMPQconst [0] s) mem)
|
642 | 642 |
|
643 | 643 | // Recognize bit setting (a |= 1<<b) and toggling (a ^= 1<<b)
|
644 |
| -(OR(Q|L) (SHL(Q|L) (MOV(Q|L)const [1]) y) x) && !config.nacl -> (BTS(Q|L) x y) |
645 |
| -(XOR(Q|L) (SHL(Q|L) (MOV(Q|L)const [1]) y) x) && !config.nacl -> (BTC(Q|L) x y) |
| 644 | +(OR(Q|L) (SHL(Q|L) (MOV(Q|L)const [1]) y) x) -> (BTS(Q|L) x y) |
| 645 | +(XOR(Q|L) (SHL(Q|L) (MOV(Q|L)const [1]) y) x) -> (BTC(Q|L) x y) |
646 | 646 |
|
647 | 647 | // Convert ORconst into BTS, if the code gets smaller, with boundary being
|
648 | 648 | // (ORL $40,AX is 3 bytes, ORL $80,AX is 6 bytes).
|
649 |
| -((ORQ|XORQ)const [c] x) && isUint64PowerOfTwo(c) && uint64(c) >= 128 && !config.nacl |
| 649 | +((ORQ|XORQ)const [c] x) && isUint64PowerOfTwo(c) && uint64(c) >= 128 |
650 | 650 | -> (BT(S|C)Qconst [log2(c)] x)
|
651 |
| -((ORL|XORL)const [c] x) && isUint32PowerOfTwo(c) && uint64(c) >= 128 && !config.nacl |
| 651 | +((ORL|XORL)const [c] x) && isUint32PowerOfTwo(c) && uint64(c) >= 128 |
652 | 652 | -> (BT(S|C)Lconst [log2uint32(c)] x)
|
653 |
| -((ORQ|XORQ) (MOVQconst [c]) x) && isUint64PowerOfTwo(c) && uint64(c) >= 128 && !config.nacl |
| 653 | +((ORQ|XORQ) (MOVQconst [c]) x) && isUint64PowerOfTwo(c) && uint64(c) >= 128 |
654 | 654 | -> (BT(S|C)Qconst [log2(c)] x)
|
655 |
| -((ORL|XORL) (MOVLconst [c]) x) && isUint32PowerOfTwo(c) && uint64(c) >= 128 && !config.nacl |
| 655 | +((ORL|XORL) (MOVLconst [c]) x) && isUint32PowerOfTwo(c) && uint64(c) >= 128 |
656 | 656 | -> (BT(S|C)Lconst [log2uint32(c)] x)
|
657 | 657 |
|
658 | 658 | // Recognize bit clearing: a &^= 1<<b
|
659 |
| -(AND(Q|L) (NOT(Q|L) (SHL(Q|L) (MOV(Q|L)const [1]) y)) x) && !config.nacl -> (BTR(Q|L) x y) |
660 |
| -(ANDQconst [c] x) && isUint64PowerOfTwo(^c) && uint64(^c) >= 128 && !config.nacl |
| 659 | +(AND(Q|L) (NOT(Q|L) (SHL(Q|L) (MOV(Q|L)const [1]) y)) x) -> (BTR(Q|L) x y) |
| 660 | +(ANDQconst [c] x) && isUint64PowerOfTwo(^c) && uint64(^c) >= 128 |
661 | 661 | -> (BTRQconst [log2(^c)] x)
|
662 |
| -(ANDLconst [c] x) && isUint32PowerOfTwo(^c) && uint64(^c) >= 128 && !config.nacl |
| 662 | +(ANDLconst [c] x) && isUint32PowerOfTwo(^c) && uint64(^c) >= 128 |
663 | 663 | -> (BTRLconst [log2uint32(^c)] x)
|
664 |
| -(ANDQ (MOVQconst [c]) x) && isUint64PowerOfTwo(^c) && uint64(^c) >= 128 && !config.nacl |
| 664 | +(ANDQ (MOVQconst [c]) x) && isUint64PowerOfTwo(^c) && uint64(^c) >= 128 |
665 | 665 | -> (BTRQconst [log2(^c)] x)
|
666 |
| -(ANDL (MOVLconst [c]) x) && isUint32PowerOfTwo(^c) && uint64(^c) >= 128 && !config.nacl |
| 666 | +(ANDL (MOVLconst [c]) x) && isUint32PowerOfTwo(^c) && uint64(^c) >= 128 |
667 | 667 | -> (BTRLconst [log2uint32(^c)] x)
|
668 | 668 |
|
669 | 669 | // Special-case bit patterns on first/last bit.
|
|
677 | 677 | // We thus special-case them, by detecting the shift patterns.
|
678 | 678 |
|
679 | 679 | // Special case resetting first/last bit
|
680 |
| -(SHL(L|Q)const [1] (SHR(L|Q)const [1] x)) && !config.nacl |
| 680 | +(SHL(L|Q)const [1] (SHR(L|Q)const [1] x)) |
681 | 681 | -> (BTR(L|Q)const [0] x)
|
682 |
| -(SHRLconst [1] (SHLLconst [1] x)) && !config.nacl |
| 682 | +(SHRLconst [1] (SHLLconst [1] x)) |
683 | 683 | -> (BTRLconst [31] x)
|
684 |
| -(SHRQconst [1] (SHLQconst [1] x)) && !config.nacl |
| 684 | +(SHRQconst [1] (SHLQconst [1] x)) |
685 | 685 | -> (BTRQconst [63] x)
|
686 | 686 |
|
687 | 687 | // Special case testing first/last bit (with double-shift generated by generic.rules)
|
688 |
| -((SETNE|SETEQ|NE|EQ) (TESTQ z1:(SHLQconst [63] (SHRQconst [63] x)) z2)) && z1==z2 && !config.nacl |
| 688 | +((SETNE|SETEQ|NE|EQ) (TESTQ z1:(SHLQconst [63] (SHRQconst [63] x)) z2)) && z1==z2 |
689 | 689 | -> ((SETB|SETAE|ULT|UGE) (BTQconst [63] x))
|
690 |
| -((SETNE|SETEQ|NE|EQ) (TESTL z1:(SHLLconst [31] (SHRQconst [31] x)) z2)) && z1==z2 && !config.nacl |
| 690 | +((SETNE|SETEQ|NE|EQ) (TESTL z1:(SHLLconst [31] (SHRQconst [31] x)) z2)) && z1==z2 |
691 | 691 | -> ((SETB|SETAE|ULT|UGE) (BTQconst [31] x))
|
692 |
| -(SET(NE|EQ)store [off] {sym} ptr (TESTQ z1:(SHLQconst [63] (SHRQconst [63] x)) z2) mem) && z1==z2 && !config.nacl |
| 692 | +(SET(NE|EQ)store [off] {sym} ptr (TESTQ z1:(SHLQconst [63] (SHRQconst [63] x)) z2) mem) && z1==z2 |
693 | 693 | -> (SET(B|AE)store [off] {sym} ptr (BTQconst [63] x) mem)
|
694 |
| -(SET(NE|EQ)store [off] {sym} ptr (TESTL z1:(SHLLconst [31] (SHRLconst [31] x)) z2) mem) && z1==z2 && !config.nacl |
| 694 | +(SET(NE|EQ)store [off] {sym} ptr (TESTL z1:(SHLLconst [31] (SHRLconst [31] x)) z2) mem) && z1==z2 |
695 | 695 | -> (SET(B|AE)store [off] {sym} ptr (BTLconst [31] x) mem)
|
696 | 696 |
|
697 |
| -((SETNE|SETEQ|NE|EQ) (TESTQ z1:(SHRQconst [63] (SHLQconst [63] x)) z2)) && z1==z2 && !config.nacl |
| 697 | +((SETNE|SETEQ|NE|EQ) (TESTQ z1:(SHRQconst [63] (SHLQconst [63] x)) z2)) && z1==z2 |
698 | 698 | -> ((SETB|SETAE|ULT|UGE) (BTQconst [0] x))
|
699 |
| -((SETNE|SETEQ|NE|EQ) (TESTL z1:(SHRLconst [31] (SHLLconst [31] x)) z2)) && z1==z2 && !config.nacl |
| 699 | +((SETNE|SETEQ|NE|EQ) (TESTL z1:(SHRLconst [31] (SHLLconst [31] x)) z2)) && z1==z2 |
700 | 700 | -> ((SETB|SETAE|ULT|UGE) (BTLconst [0] x))
|
701 |
| -(SET(NE|EQ)store [off] {sym} ptr (TESTQ z1:(SHRQconst [63] (SHLQconst [63] x)) z2) mem) && z1==z2 && !config.nacl |
| 701 | +(SET(NE|EQ)store [off] {sym} ptr (TESTQ z1:(SHRQconst [63] (SHLQconst [63] x)) z2) mem) && z1==z2 |
702 | 702 | -> (SET(B|AE)store [off] {sym} ptr (BTQconst [0] x) mem)
|
703 |
| -(SET(NE|EQ)store [off] {sym} ptr (TESTL z1:(SHRLconst [31] (SHLLconst [31] x)) z2) mem) && z1==z2 && !config.nacl |
| 703 | +(SET(NE|EQ)store [off] {sym} ptr (TESTL z1:(SHRLconst [31] (SHLLconst [31] x)) z2) mem) && z1==z2 |
704 | 704 | -> (SET(B|AE)store [off] {sym} ptr (BTLconst [0] x) mem)
|
705 | 705 |
|
706 | 706 | // Special-case manually testing last bit with "a>>63 != 0" (without "&1")
|
707 |
| -((SETNE|SETEQ|NE|EQ) (TESTQ z1:(SHRQconst [63] x) z2)) && z1==z2 && !config.nacl |
| 707 | +((SETNE|SETEQ|NE|EQ) (TESTQ z1:(SHRQconst [63] x) z2)) && z1==z2 |
708 | 708 | -> ((SETB|SETAE|ULT|UGE) (BTQconst [63] x))
|
709 |
| -((SETNE|SETEQ|NE|EQ) (TESTL z1:(SHRLconst [31] x) z2)) && z1==z2 && !config.nacl |
| 709 | +((SETNE|SETEQ|NE|EQ) (TESTL z1:(SHRLconst [31] x) z2)) && z1==z2 |
710 | 710 | -> ((SETB|SETAE|ULT|UGE) (BTLconst [31] x))
|
711 |
| -(SET(NE|EQ)store [off] {sym} ptr (TESTQ z1:(SHRQconst [63] x) z2) mem) && z1==z2 && !config.nacl |
| 711 | +(SET(NE|EQ)store [off] {sym} ptr (TESTQ z1:(SHRQconst [63] x) z2) mem) && z1==z2 |
712 | 712 | -> (SET(B|AE)store [off] {sym} ptr (BTQconst [63] x) mem)
|
713 |
| -(SET(NE|EQ)store [off] {sym} ptr (TESTL z1:(SHRLconst [31] x) z2) mem) && z1==z2 && !config.nacl |
| 713 | +(SET(NE|EQ)store [off] {sym} ptr (TESTL z1:(SHRLconst [31] x) z2) mem) && z1==z2 |
714 | 714 | -> (SET(B|AE)store [off] {sym} ptr (BTLconst [31] x) mem)
|
715 | 715 |
|
716 | 716 | // Fold combinations of bit ops on same bit. An example is math.Copysign(c,-1)
|
|
0 commit comments