summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorCraig Topper <craig.topper@intel.com>2018-06-27 16:47:39 +0000
committerCraig Topper <craig.topper@intel.com>2018-06-27 16:47:39 +0000
commit812fcb35e79ac3aab4c3ec8ae239ab54f820d94c (patch)
tree672953bf6893a5d42d106dd9b935a4ac7f4a6e6d /llvm/lib
parent069628b4dff2f358da7b94f76410060c2dacaad1 (diff)
downloadbcm5719-llvm-812fcb35e79ac3aab4c3ec8ae239ab54f820d94c.tar.gz
bcm5719-llvm-812fcb35e79ac3aab4c3ec8ae239ab54f820d94c.zip
[X86] Use bts/btr/btc for single bit set/clear/complement of a variable bit position
If we are just modifying a single bit at a variable bit position we can use the BT* instructions to make the change instead of shifting a 1(or rotating a -1) and doing a binop. These instruction also ignore the upper bits of their index input so we can also remove an and if one is present on the index. Fixes PR37938. llvm-svn: 335754
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/X86/X86InstrCompiler.td31
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)>;
OpenPOWER on IntegriCloud