diff options
Diffstat (limited to 'llvm/lib')
| -rw-r--r-- | llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 6 | ||||
| -rw-r--r-- | llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 22 |
2 files changed, 23 insertions, 5 deletions
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index a2eca91c67e..a69fe1d8e20 100644 --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2244,6 +2244,12 @@ bool SelectionDAG::MaskedValueIsZero(SDValue V, const APInt &Mask, return Mask.isSubsetOf(computeKnownBits(V, DemandedElts, Depth).Zero); } +/// MaskedValueIsAllOnes - Return true if '(Op & Mask) == Mask'. +bool SelectionDAG::MaskedValueIsAllOnes(SDValue V, const APInt &Mask, + unsigned Depth) const { + return Mask.isSubsetOf(computeKnownBits(V, Depth).One); +} + /// isSplatValue - Return true if the vector V has the same value /// across all DemandedElts. bool SelectionDAG::isSplatValue(SDValue V, const APInt &DemandedElts, diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index 537a68910ab..36f71d0b234 100644 --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -3179,16 +3179,28 @@ bool X86DAGToDAGISel::matchBitExtract(SDNode *Node) { return true; }; + auto isAllOnes = [this, peekThroughOneUseTruncation, NVT](SDValue V) { + V = peekThroughOneUseTruncation(V); + return CurDAG->MaskedValueIsAllOnes( + V, APInt::getLowBitsSet(V.getSimpleValueType().getSizeInBits(), + NVT.getSizeInBits())); + }; + // b) x & ~(-1 << nbits) - auto matchPatternB = [&checkOneUse, &NBits](SDValue Mask) -> bool { + auto matchPatternB = [&checkOneUse, isAllOnes, &peekThroughOneUseTruncation, + &NBits](SDValue Mask) -> bool { // Match `~()`. Must only have one use! - if (!isBitwiseNot(Mask) || !checkOneUse(Mask)) + if (Mask.getOpcode() != ISD::XOR || !checkOneUse(Mask)) return false; - // Match `-1 << nbits`. Must only have one use! - SDValue M0 = Mask->getOperand(0); + // The -1 only has to be all-ones for the final Node's NVT. + if (!isAllOnes(Mask->getOperand(1))) + return false; + // Match `-1 << nbits`. Might be truncated. Must only have one use! + SDValue M0 = peekThroughOneUseTruncation(Mask->getOperand(0)); if (M0->getOpcode() != ISD::SHL || !checkOneUse(M0)) return false; - if (!isAllOnesConstant(M0->getOperand(0))) + // The -1 only has to be all-ones for the final Node's NVT. + if (!isAllOnes(M0->getOperand(0))) return false; NBits = M0->getOperand(1); return true; |

