diff options
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Target/X86/X86InstrCompiler.td | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/llvm/lib/Target/X86/X86InstrCompiler.td b/llvm/lib/Target/X86/X86InstrCompiler.td index 44fb44d55c1..5915e363aa6 100644 --- a/llvm/lib/Target/X86/X86InstrCompiler.td +++ b/llvm/lib/Target/X86/X86InstrCompiler.td @@ -1804,6 +1804,37 @@ let Predicates = [HasBMI2] in { } } +// Use BTR/BTS/BTC for clearing/setting/toggling a bit in a variable location. +multiclass one_bit_patterns<RegisterClass RC, ValueType VT, Instruction BTR, + Instruction BTS, Instruction BTC, + ImmLeaf ImmShift> { + def : Pat<(and RC:$src1, (rotl -2, GR8:$src2)), + (BTR RC:$src1, + (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; + def : Pat<(or RC:$src1, (shl 1, GR8:$src2)), + (BTS RC:$src1, + (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; + def : Pat<(xor RC:$src1, (shl 1, GR8:$src2)), + (BTC RC:$src1, + (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; + + // Similar to above, but removing unneeded masking of the shift amount. + def : Pat<(and RC:$src1, (rotl -2, (and GR8:$src2, ImmShift))), + (BTR RC:$src1, + (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; + def : Pat<(or RC:$src1, (shl 1, (and GR8:$src2, ImmShift))), + (BTS RC:$src1, + (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; + def : Pat<(xor RC:$src1, (shl 1, (and GR8:$src2, ImmShift))), + (BTC RC:$src1, + (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$src2, sub_8bit))>; +} + +defm : one_bit_patterns<GR16, i16, BTR16rr, BTS16rr, BTC16rr, immShift16>; +defm : one_bit_patterns<GR32, i32, BTR32rr, BTS32rr, BTC32rr, immShift32>; +defm : one_bit_patterns<GR64, i64, BTR64rr, BTS64rr, BTC64rr, immShift64>; + + // (anyext (setcc_carry)) -> (setcc_carry) def : Pat<(i16 (anyext (i8 (X86setcc_c X86_COND_B, EFLAGS)))), (SETB_C16r)>; |