summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/X86/X86ISelDAGToDAG.cpp58
-rw-r--r--llvm/lib/Target/X86/X86InstrInfo.td40
2 files changed, 40 insertions, 58 deletions
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index 83d5be34dc7..717ecc031c0 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -2749,11 +2749,45 @@ bool X86DAGToDAGISel::matchBitExtract(SDNode *Node) {
return true;
};
+ // Match potentially-truncated (bitwidth - y)
+ auto matchShiftAmt = [checkOneUse, Size, &NBits](SDValue ShiftAmt) {
+ // Skip over a truncate of the shift amount.
+ if (ShiftAmt.getOpcode() == ISD::TRUNCATE) {
+ ShiftAmt = ShiftAmt.getOperand(0);
+ // The trunc should have been the only user of the real shift amount.
+ if (!checkOneUse(ShiftAmt))
+ return false;
+ }
+ // Match the shift amount as: (bitwidth - y). It should go away, too.
+ if (ShiftAmt.getOpcode() != ISD::SUB)
+ return false;
+ auto V0 = dyn_cast<ConstantSDNode>(ShiftAmt.getOperand(0));
+ if (!V0 || V0->getZExtValue() != Size)
+ return false;
+ NBits = ShiftAmt.getOperand(1);
+ return true;
+ };
+
+ // c) x & (-1 >> (32 - y))
+ auto matchPatternC = [&checkOneUse, matchShiftAmt](SDValue Mask) -> bool {
+ // Match `l>>`. Must only have one use!
+ if (Mask.getOpcode() != ISD::SRL || !checkOneUse(Mask))
+ return false;
+ // We should be shifting all-ones constant.
+ if (!isAllOnesConstant(Mask.getOperand(0)))
+ return false;
+ SDValue M1 = Mask.getOperand(1);
+ // The shift amount should not be used externally.
+ if (!checkOneUse(M1))
+ return false;
+ return matchShiftAmt(M1);
+ };
+
SDValue X;
// d) x << (32 - y) >> (32 - y)
- auto matchPatternD = [&checkOneUse, &checkTwoUse, Size, &X,
- &NBits](SDNode *Node) -> bool {
+ auto matchPatternD = [&checkOneUse, &checkTwoUse, matchShiftAmt,
+ &X](SDNode *Node) -> bool {
if (Node->getOpcode() != ISD::SRL)
return false;
SDValue N0 = Node->getOperand(0);
@@ -2765,28 +2799,16 @@ bool X86DAGToDAGISel::matchBitExtract(SDNode *Node) {
// There should not be any uses of the shift amount outside of the pattern.
if (N1 != N01 || !checkTwoUse(N1))
return false;
- // Skip over a truncate of the shift amount.
- if (N1->getOpcode() == ISD::TRUNCATE) {
- N1 = N1->getOperand(0);
- // The trunc should have been the only user of the real shift amount.
- if (!checkOneUse(N1))
- return false;
- }
- // Match the shift amount as: (bitwidth - y). It should go away, too.
- if (N1.getOpcode() != ISD::SUB)
- return false;
- auto N10 = dyn_cast<ConstantSDNode>(N1.getOperand(0));
- if (!N10 || N10->getZExtValue() != Size)
+ if (!matchShiftAmt(N1))
return false;
X = N0->getOperand(0);
- NBits = N1.getOperand(1);
return true;
};
- auto matchLowBitMask = [&matchPatternA,
- &matchPatternB](SDValue Mask) -> bool {
+ auto matchLowBitMask = [&matchPatternA, &matchPatternB,
+ &matchPatternC](SDValue Mask) -> bool {
// FIXME: pattern c.
- return matchPatternA(Mask) || matchPatternB(Mask);
+ return matchPatternA(Mask) || matchPatternB(Mask) || matchPatternC(Mask);
};
if (Node->getOpcode() == ISD::AND) {
diff --git a/llvm/lib/Target/X86/X86InstrInfo.td b/llvm/lib/Target/X86/X86InstrInfo.td
index 8d3f7c856d0..992e9543b33 100644
--- a/llvm/lib/Target/X86/X86InstrInfo.td
+++ b/llvm/lib/Target/X86/X86InstrInfo.td
@@ -2499,46 +2499,6 @@ let Predicates = [HasBMI2, NoTBM] in {
(MOV8ri (CountTrailingOnes imm:$mask)), sub_8bit))>;
}
-let Predicates = [HasBMI2] in {
- multiclass _bmi_bzhi_pattern<dag regpattern, dag mempattern, RegisterClass RC,
- ValueType VT, Instruction DstInst,
- Instruction DstMemInst> {
- def : Pat<regpattern,
- (DstInst RC:$src,
- (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$lz, sub_8bit))>;
- def : Pat<mempattern,
- (DstMemInst addr:$src,
- (INSERT_SUBREG (VT (IMPLICIT_DEF)), GR8:$lz, sub_8bit))>;
- }
-
- multiclass bmi_bzhi_patterns<RegisterClass RC, int bitwidth, ValueType VT,
- Instruction DstInst, X86MemOperand x86memop,
- Instruction DstMemInst> {
- // x & (-1 >> (bitwidth - y))
- defm : _bmi_bzhi_pattern<(and RC:$src, (srl -1, (sub bitwidth, GR8:$lz))),
- (and (x86memop addr:$src),
- (srl -1, (sub bitwidth, GR8:$lz))),
- RC, VT, DstInst, DstMemInst>;
- }
-
- defm : bmi_bzhi_patterns<GR32, 32, i32, BZHI32rr, loadi32, BZHI32rm>;
- defm : bmi_bzhi_patterns<GR64, 64, i64, BZHI64rr, loadi64, BZHI64rm>;
-
- // x & (-1 >> (32 - y))
- def : Pat<(and GR32:$src, (srl -1, (i8 (trunc (sub 32, GR32:$lz))))),
- (BZHI32rr GR32:$src, GR32:$lz)>;
- def : Pat<(and (loadi32 addr:$src), (srl -1, (i8 (trunc (sub 32, GR32:$lz))))),
- (BZHI32rm addr:$src, GR32:$lz)>;
-
- // x & (-1 >> (64 - y))
- def : Pat<(and GR64:$src, (srl -1, (i8 (trunc (sub 64, GR32:$lz))))),
- (BZHI64rr GR64:$src,
- (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$lz, sub_32bit))>;
- def : Pat<(and (loadi64 addr:$src), (srl -1, (i8 (trunc (sub 64, GR32:$lz))))),
- (BZHI64rm addr:$src,
- (INSERT_SUBREG (i64 (IMPLICIT_DEF)), GR32:$lz, sub_32bit))>;
-} // HasBMI2
-
multiclass bmi_pdep_pext<string mnemonic, RegisterClass RC,
X86MemOperand x86memop, Intrinsic Int,
PatFrag ld_frag> {
OpenPOWER on IntegriCloud