diff options
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 58 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86InstrInfo.td | 40 |
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> { |

