summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target
diff options
context:
space:
mode:
authorRoman Lebedev <lebedev.ri@gmail.com>2018-10-11 07:51:13 +0000
committerRoman Lebedev <lebedev.ri@gmail.com>2018-10-11 07:51:13 +0000
commit4225f4adfff842284e22d9e61e66a9eccd1ea426 (patch)
tree88ad978f5b19d7fd9bd1693c179153c51e5f2d5d /llvm/lib/Target
parentb2e51090a427be5a804af53ac3615672ae356074 (diff)
downloadbcm5719-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.cpp83
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;
OpenPOWER on IntegriCloud