|
624 | 624 | // Recognize bit setting (a |= 1<<b) and toggling (a ^= 1<<b) |
625 | 625 | (OR(Q|L) (SHL(Q|L) (MOV(Q|L)const [1]) y) x) => (BTS(Q|L) x y) |
626 | 626 | (XOR(Q|L) (SHL(Q|L) (MOV(Q|L)const [1]) y) x) => (BTC(Q|L) x y) |
| 627 | +(ORLmodify [off] {sym} ptr s:(SHLL (MOVLconst [1]) <t> x) mem) => |
| 628 | + (BTSLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem) |
| 629 | +(ORQmodify [off] {sym} ptr s:(SHLQ (MOVQconst [1]) <t> x) mem) => |
| 630 | + (BTSQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem) |
| 631 | +(XORLmodify [off] {sym} ptr s:(SHLL (MOVLconst [1]) <t> x) mem) => |
| 632 | + (BTCLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem) |
| 633 | +(XORQmodify [off] {sym} ptr s:(SHLQ (MOVQconst [1]) <t> x) mem) => |
| 634 | + (BTCQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem) |
627 | 635 |
|
628 | 636 | // Convert ORconst into BTS, if the code gets smaller, with boundary being |
629 | 637 | // (ORL $40,AX is 3 bytes, ORL $80,AX is 6 bytes). |
|
646 | 654 | => (BTRQconst [int8(log64(^c))] x) |
647 | 655 | (ANDL (MOVLconst [c]) x) && isUint32PowerOfTwo(int64(^c)) && uint64(^c) >= 128 |
648 | 656 | => (BTRLconst [int8(log32(^c))] x) |
| 657 | +(ANDLmodify [off] {sym} ptr (NOTL s:(SHLL (MOVLconst [1]) <t> x)) mem) => |
| 658 | + (BTRLmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem) |
| 659 | +(ANDQmodify [off] {sym} ptr (NOTQ s:(SHLQ (MOVQconst [1]) <t> x)) mem) => |
| 660 | + (BTRQmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem) |
649 | 661 |
|
650 | 662 | // Special-case bit patterns on first/last bit. |
651 | 663 | // generic.rules changes ANDs of high-part/low-part masks into a couple of shifts, |
|
2064 | 2076 | ((ADD|SUB|MUL|DIV)SD x l:(MOVSDload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && clobber(l) => ((ADD|SUB|MUL|DIV)SDload x [off] {sym} ptr mem) |
2065 | 2077 | ((ADD|SUB|MUL|DIV)SS x l:(MOVSSload [off] {sym} ptr mem)) && canMergeLoadClobber(v, l, x) && clobber(l) => ((ADD|SUB|MUL|DIV)SSload x [off] {sym} ptr mem) |
2066 | 2078 | (MOVLstore {sym} [off] ptr y:((ADD|AND|OR|XOR)Lload x [off] {sym} ptr mem) mem) && y.Uses==1 && clobber(y) => ((ADD|AND|OR|XOR)Lmodify [off] {sym} ptr x mem) |
2067 | | -(MOVLstore {sym} [off] ptr y:((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)L l:(MOVLload [off] {sym} ptr mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) => |
2068 | | - ((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Lmodify [off] {sym} ptr x mem) |
| 2079 | +(MOVLstore {sym} [off] ptr y:((ADD|SUB|AND|OR|XOR)L l:(MOVLload [off] {sym} ptr mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) => |
| 2080 | + ((ADD|SUB|AND|OR|XOR)Lmodify [off] {sym} ptr x mem) |
| 2081 | +(MOVLstore {sym} [off] ptr y:((BTC|BTR|BTS)L l:(MOVLload [off] {sym} ptr mem) <t> x) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) => |
| 2082 | + ((BTC|BTR|BTS)Lmodify [off] {sym} ptr (ANDLconst <t> [31] x) mem) |
2069 | 2083 | (MOVQstore {sym} [off] ptr y:((ADD|AND|OR|XOR)Qload x [off] {sym} ptr mem) mem) && y.Uses==1 && clobber(y) => ((ADD|AND|OR|XOR)Qmodify [off] {sym} ptr x mem) |
2070 | | -(MOVQstore {sym} [off] ptr y:((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Q l:(MOVQload [off] {sym} ptr mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) => |
2071 | | - ((ADD|SUB|AND|OR|XOR|BTC|BTR|BTS)Qmodify [off] {sym} ptr x mem) |
| 2084 | +(MOVQstore {sym} [off] ptr y:((ADD|SUB|AND|OR|XOR)Q l:(MOVQload [off] {sym} ptr mem) x) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) => |
| 2085 | + ((ADD|SUB|AND|OR|XOR)Qmodify [off] {sym} ptr x mem) |
| 2086 | +(MOVQstore {sym} [off] ptr y:((BTC|BTR|BTS)Q l:(MOVQload [off] {sym} ptr mem) <t> x) mem) && y.Uses==1 && l.Uses==1 && clobber(y, l) => |
| 2087 | + ((BTC|BTR|BTS)Qmodify [off] {sym} ptr (ANDQconst <t> [63] x) mem) |
2072 | 2088 |
|
2073 | 2089 | // Merge ADDQconst and LEAQ into atomic loads. |
2074 | 2090 | (MOV(Q|L|B)atomicload [off1] {sym} (ADDQconst [off2] ptr) mem) && is32Bit(int64(off1)+int64(off2)) => |
|
0 commit comments