summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorChad Rosier <mcrosier@codeaurora.org>2016-05-19 14:19:47 +0000
committerChad Rosier <mcrosier@codeaurora.org>2016-05-19 14:19:47 +0000
commit02f25a95655e9e320c524978e54df8e4a22ef921 (patch)
treebabcfe9f5df8aef9b092fb08af720479639ec783 /llvm/lib
parent01319e93abe3a4d3e722de4e849762ea54d12d70 (diff)
downloadbcm5719-llvm-02f25a95655e9e320c524978e54df8e4a22ef921.tar.gz
bcm5719-llvm-02f25a95655e9e320c524978e54df8e4a22ef921.zip
[AArch64 ] Generate a BFXIL from 'or (and X, Mask0Imm),(and Y, Mask1Imm)'.
Mask0Imm and ~Mask1Imm must be equivalent and one of the MaskImms is a shifted mask (e.g., 0x000ffff0). Both 'and's must have a single use. This changes code like: and w8, w0, #0xffff000f and w9, w1, #0x0000fff0 orr w0, w9, w8 into lsr w8, w1, #4 bfi w0, w8, #4, #12 llvm-svn: 270063
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp59
1 files changed, 59 insertions, 0 deletions
diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
index b8ee03a3558..fe5d6045bde 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp
@@ -1974,6 +1974,13 @@ static bool isBitfieldPositioningOp(SelectionDAG *CurDAG, SDValue Op,
return true;
}
+static bool isShiftedMask(uint64_t Mask, EVT VT) {
+ assert(VT == MVT::i32 || VT == MVT::i64);
+ if (VT == MVT::i32)
+ return isShiftedMask_32(Mask);
+ return isShiftedMask_64(Mask);
+}
+
static bool tryBitfieldInsertOpFromOr(SDNode *N, const APInt &UsefulBits,
SelectionDAG *CurDAG) {
assert(N->getOpcode() == ISD::OR && "Expect a OR operation");
@@ -2084,6 +2091,58 @@ static bool tryBitfieldInsertOpFromOr(SDNode *N, const APInt &UsefulBits,
CurDAG->SelectNodeTo(N, Opc, VT, Ops);
return true;
}
+
+ // Generate a BFXIL from 'or (and X, Mask0Imm), (and Y, Mask1Imm)' iff
+ // Mask0Imm and ~Mask1Imm are equivalent and one of the MaskImms is a shifted
+ // mask (e.g., 0x000ffff0).
+ uint64_t Mask0Imm, Mask1Imm;
+ SDValue And0 = N->getOperand(0);
+ SDValue And1 = N->getOperand(1);
+ if (And0.hasOneUse() && And1.hasOneUse() &&
+ isOpcWithIntImmediate(And0.getNode(), ISD::AND, Mask0Imm) &&
+ isOpcWithIntImmediate(And1.getNode(), ISD::AND, Mask1Imm) &&
+ APInt(BitWidth, Mask0Imm) == ~APInt(BitWidth, Mask1Imm) &&
+ (isShiftedMask(Mask0Imm, VT) || isShiftedMask(Mask1Imm, VT))) {
+
+ // We should have already caught the case where we extract hi and low parts.
+ // E.g. BFXIL from 'or (and X, 0xffff0000), (and Y, 0x0000ffff)'.
+ assert(!(isShiftedMask(Mask0Imm, VT) && isShiftedMask(Mask1Imm, VT)) &&
+ "BFXIL should have already been optimized.");
+
+ // ORR is commutative, so canonicalize to the form 'or (and X, Mask0Imm),
+ // (and Y, Mask1Imm)' where Mask1Imm is the shifted mask masking off the
+ // bits to be inserted.
+ if (isShiftedMask(Mask0Imm, VT)) {
+ std::swap(And0, And1);
+ std::swap(Mask0Imm, Mask1Imm);
+ }
+
+ SDValue Src = And1->getOperand(0);
+ SDValue Dst = And0->getOperand(0);
+ unsigned LSB = countTrailingZeros(Mask1Imm);
+ int Width = BitWidth - APInt(BitWidth, Mask0Imm).countPopulation();
+
+ // The BFXIL inserts the low-order bits from a source register, so right
+ // shift the needed bits into place.
+ SDLoc DL(N);
+ unsigned ShiftOpc = (VT == MVT::i32) ? AArch64::UBFMWri : AArch64::UBFMXri;
+ SDNode *LSR = CurDAG->getMachineNode(
+ ShiftOpc, DL, VT, Src, CurDAG->getTargetConstant(LSB, DL, VT),
+ CurDAG->getTargetConstant(BitWidth - 1, DL, VT));
+
+ // BFXIL is an alias of BFM, so translate to BFM operands.
+ unsigned ImmR = (BitWidth - LSB) % BitWidth;
+ unsigned ImmS = Width - 1;
+
+ // Create the BFXIL instruction.
+ SDValue Ops[] = {Dst, SDValue(LSR, 0),
+ CurDAG->getTargetConstant(ImmR, DL, VT),
+ CurDAG->getTargetConstant(ImmS, DL, VT)};
+ unsigned Opc = (VT == MVT::i32) ? AArch64::BFMWri : AArch64::BFMXri;
+ CurDAG->SelectNodeTo(N, Opc, VT, Ops);
+ return true;
+ }
+
return false;
}
OpenPOWER on IntegriCloud