summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorRoman Lebedev <lebedev.ri@gmail.com>2018-11-16 13:04:54 +0000
committerRoman Lebedev <lebedev.ri@gmail.com>2018-11-16 13:04:54 +0000
commit90c5b3f78ecfc08a428ea6022a5e80ddc437b99b (patch)
tree7befdbc238b05da6bc4739faf06ac89b05f67c86 /llvm/lib
parent831be096c72fc29d62f641f95d97a35f463eb202 (diff)
downloadbcm5719-llvm-90c5b3f78ecfc08a428ea6022a5e80ddc437b99b.tar.gz
bcm5719-llvm-90c5b3f78ecfc08a428ea6022a5e80ddc437b99b.zip
[X86] X86DAGToDAGISel::matchBitExtract(): extract 'lshr' from `X`
Summary: As discussed in previous review, and noted in the FIXME, if `X` is actually an `lshr Y, Z` (logical!), we can fold the `Z` into 'control`, and let the `BEXTR` do this too. We could just insert those 8 bits of shift amount into control, but it is better to instead zero-extend them, and 'or' them in place. We can only do this for `lshr`, not `ashr`, because we do not know that the mask cover only the bits of `Y`, and not any of the sign-extended bits. The obvious question is, is this actually legal to do? I believe it is. Relevant quotes, from `Intel® 64 and IA-32 Architectures Software Developer’s Manual`, `BEXTR — Bit Field Extract`: * `Bit 7:0 of the second source operand specifies the starting bit position of bit extraction.` * `A START value exceeding the operand size will not extract any bits from the second source operand.` * `Only bit positions up to (OperandSize -1) of the first source operand are extracted.` * `All higher order bits in the destination operand (starting at bit position LENGTH) are zeroed.` * `The destination register is cleared if no bits are extracted.` FIXME: if we can do this, i wonder if we should prefer `BEXTR` over `BZHI` in such cases. Reviewers: RKSimon, craig.topper, spatel, andreadb Reviewed By: RKSimon, craig.topper, andreadb Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D54095 llvm-svn: 347048
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/X86/X86ISelDAGToDAG.cpp20
1 files changed, 19 insertions, 1 deletions
diff --git a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
index 16819f4451c..b015afc1353 100644
--- a/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -2858,10 +2858,28 @@ bool X86DAGToDAGISel::matchBitExtract(SDNode *Node) {
// I.e. 0b000000011'00000001 means (x >> 0b1) & 0b11
// Shift NBits left by 8 bits, thus producing 'control'.
+ // This makes the low 8 bits to be zero.
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)
+
+ // If the 'X' is *logically* shifted, we can fold that shift into 'control'.
+ if (X.getOpcode() == ISD::SRL) {
+ SDValue ShiftAmt = X.getOperand(1);
+ X = X.getOperand(0);
+
+ assert(ShiftAmt.getValueType() == MVT::i8 &&
+ "Expected shift amount to be i8");
+
+ // Now, *zero*-extend the shift amount. The bits 8...15 *must* be zero!
+ SDValue OrigShiftAmt = ShiftAmt;
+ ShiftAmt = CurDAG->getNode(ISD::ZERO_EXTEND, DL, NVT, ShiftAmt);
+ insertDAGNode(*CurDAG, OrigShiftAmt, ShiftAmt);
+
+ // And now 'or' these low 8 bits of shift amount into the 'control'.
+ Control = CurDAG->getNode(ISD::OR, DL, NVT, Control, ShiftAmt);
+ insertDAGNode(*CurDAG, OrigNBits, Control);
+ }
// And finally, form the BEXTR itself.
SDValue Extract = CurDAG->getNode(X86ISD::BEXTR, DL, NVT, X, Control);
OpenPOWER on IntegriCloud