diff options
author | Roman Lebedev <lebedev.ri@gmail.com> | 2018-10-11 07:51:13 +0000 |
---|---|---|
committer | Roman Lebedev <lebedev.ri@gmail.com> | 2018-10-11 07:51:13 +0000 |
commit | 4225f4adfff842284e22d9e61e66a9eccd1ea426 (patch) | |
tree | 88ad978f5b19d7fd9bd1693c179153c51e5f2d5d /llvm/lib/Target | |
parent | b2e51090a427be5a804af53ac3615672ae356074 (diff) | |
download | bcm5719-llvm-4225f4adfff842284e22d9e61e66a9eccd1ea426.tar.gz bcm5719-llvm-4225f4adfff842284e22d9e61e66a9eccd1ea426.zip |
[X86][BMI1]: X86DAGToDAGISel: select BEXTR from x & ~(-1 << nbits) pattern
Summary:
As discussed in D48491, we can't really do this in the TableGen,
since we need to produce *two* instructions. This only implements
one single pattern. The other 3 patterns will be in follow-ups.
I'm not sure yet if we want to also fuse shift into here
(i.e `(x >> start) & ...`)
Reviewers: RKSimon, craig.topper, spatel
Reviewed By: craig.topper
Differential Revision: https://reviews.llvm.org/D52304
llvm-svn: 344224
Diffstat (limited to 'llvm/lib/Target')
-rw-r--r-- | llvm/lib/Target/X86/X86ISelDAGToDAG.cpp | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp index 5eb4dbb1d98..c043c7c54cc 100644 --- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp +++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp @@ -451,6 +451,7 @@ namespace { } bool foldLoadStoreIntoMemOperand(SDNode *Node); + bool matchBEXTR(SDNode *Node); bool shrinkAndImmediate(SDNode *N); bool isMaskZeroExtended(SDNode *N) const; bool tryShiftAmountMod(SDNode *N); @@ -2565,6 +2566,86 @@ bool X86DAGToDAGISel::foldLoadStoreIntoMemOperand(SDNode *Node) { return true; } +// See if this is an X & Mask that we can match to BEXTR. +// Where Mask is one of the following patterns: +// a) x & (1 << nbits) - 1 +// b) x & ~(-1 << nbits) +// c) x & (-1 >> (32 - y)) +// d) x << (32 - y) >> (32 - y) +bool X86DAGToDAGISel::matchBEXTR(SDNode *Node) { + // BEXTR is BMI instruction. However, if we have BMI2, we prefer BZHI. + if (!Subtarget->hasBMI() || Subtarget->hasBMI2()) + return false; + + MVT NVT = Node->getSimpleValueType(0); + + // Only supported for 32 and 64 bits. + if (NVT != MVT::i32 && NVT != MVT::i64) + return false; + + SDValue NBits; + + // b) x & ~(-1 << nbits) + auto matchPatternB = [&NBits](SDValue Mask) -> bool { + // Match `~()`. Must only have one use! + if (!isBitwiseNot(Mask) || !Mask->hasOneUse()) + return false; + // Match `-1 << nbits`. Must only have one use! + SDValue M0 = Mask->getOperand(0); + if (M0->getOpcode() != ISD::SHL || !M0->hasOneUse()) + return false; + if (!isAllOnesConstant(M0->getOperand(0))) + return false; + NBits = M0->getOperand(1); + return true; + }; + + auto matchLowBitMask = [&matchPatternB](SDValue Mask) -> bool { + // FIXME: patterns a, c, d. + return matchPatternB(Mask); + }; + + SDValue X = Node->getOperand(0); + SDValue Mask = Node->getOperand(1); + + if (matchLowBitMask(Mask)) { + // Great. + } else { + std::swap(X, Mask); + if (!matchLowBitMask(Mask)) + return false; + } + + SDLoc DL(Node); + + // Insert 8-bit NBits into lowest 8 bits of NVT-sized (32 or 64-bit) register. + // All the other bits are undefined, we do not care about them. + SDValue ImplDef = + SDValue(CurDAG->getMachineNode(TargetOpcode::IMPLICIT_DEF, DL, NVT), 0); + insertDAGNode(*CurDAG, NBits, ImplDef); + SDValue OrigNBits = NBits; + NBits = CurDAG->getTargetInsertSubreg(X86::sub_8bit, DL, NVT, ImplDef, NBits); + insertDAGNode(*CurDAG, OrigNBits, NBits); + + // The 'control' of BEXTR has the pattern of: + // [15...8 bit][ 7...0 bit] location + // [ bit count][ shift] name + // I.e. 0b000000011'00000001 means (x >> 0b1) & 0b11 + + // Shift NBits left by 8 bits, thus producing 'control'. + SDValue C8 = CurDAG->getConstant(8, DL, MVT::i8); + SDValue Control = CurDAG->getNode(ISD::SHL, DL, NVT, NBits, C8); + insertDAGNode(*CurDAG, OrigNBits, Control); + // NOTE: could also try to extract start from (x >> start) + + // And finally, form the BEXTR itself. + SDValue Extract = CurDAG->getNode(X86ISD::BEXTR, DL, NVT, X, Control); + ReplaceNode(Node, Extract.getNode()); + SelectCode(Extract.getNode()); + + return true; +} + // Emit a PCMISTR(I/M) instruction. MachineSDNode *X86DAGToDAGISel::emitPCMPISTR(unsigned ROpc, unsigned MOpc, bool MayFoldLoad, const SDLoc &dl, @@ -2872,6 +2953,8 @@ void X86DAGToDAGISel::Select(SDNode *Node) { break; case ISD::AND: + if (matchBEXTR(Node)) + return; if (AndImmShrink && shrinkAndImmediate(Node)) return; |