Generalize BFI isel lowering a bit.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121714 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Evan Cheng 2010-12-13 20:32:54 +00:00
parent 94c58a0906
commit 30fb13f97a

View File

@ -4713,57 +4713,43 @@ static SDValue PerformORCombine(SDNode *N,
if (VT != MVT::i32) if (VT != MVT::i32)
return SDValue(); return SDValue();
SDValue N00 = N0.getOperand(0);
// The value and the mask need to be constants so we can verify this is // The value and the mask need to be constants so we can verify this is
// actually a bitfield set. If the mask is 0xffff, we can do better // actually a bitfield set. If the mask is 0xffff, we can do better
// via a movt instruction, so don't use BFI in that case. // via a movt instruction, so don't use BFI in that case.
ConstantSDNode *C = dyn_cast<ConstantSDNode>(N0.getOperand(1)); SDValue MaskOp = N0.getOperand(1);
if (!C) ConstantSDNode *MaskC = dyn_cast<ConstantSDNode>(MaskOp);
if (!MaskC)
return SDValue(); return SDValue();
unsigned Mask = C->getZExtValue(); unsigned Mask = MaskC->getZExtValue();
if (Mask == 0xffff) if (Mask == 0xffff)
return SDValue(); return SDValue();
SDValue Res; SDValue Res;
// Case (1): or (and A, mask), val => ARMbfi A, val, mask // Case (1): or (and A, mask), val => ARMbfi A, val, mask
if ((C = dyn_cast<ConstantSDNode>(N1))) { ConstantSDNode *N1C = dyn_cast<ConstantSDNode>(N1);
unsigned Val = C->getZExtValue(); if (N1C) {
unsigned Val = N1C->getZExtValue();
if ((Val & ~Mask) != Val) if ((Val & ~Mask) != Val)
return SDValue(); return SDValue();
if (ARM::isBitFieldInvertedMask(Mask)) { if (ARM::isBitFieldInvertedMask(Mask)) {
Val >>= CountTrailingZeros_32(~Mask); Val >>= CountTrailingZeros_32(~Mask);
Res = DAG.getNode(ARMISD::BFI, DL, VT, N0.getOperand(0), Res = DAG.getNode(ARMISD::BFI, DL, VT, N00,
DAG.getConstant(Val, MVT::i32), DAG.getConstant(Val, MVT::i32),
DAG.getConstant(Mask, MVT::i32)); DAG.getConstant(Mask, MVT::i32));
// Do not add new nodes to DAG combiner worklist. // Do not add new nodes to DAG combiner worklist.
DCI.CombineTo(N, Res, false); DCI.CombineTo(N, Res, false);
} else if (N0.getOperand(0).getOpcode() == ISD::SHL &&
isa<ConstantSDNode>(N0.getOperand(0).getOperand(1)) &&
ARM::isBitFieldInvertedMask(~Mask)) {
// Case (3): or (and (shl A, #shamt), mask), B => ARMbfi B, A, ~mask
// where lsb(mask) == #shamt
SDValue ShAmt = N0.getOperand(0).getOperand(1);
unsigned ShAmtC = cast<ConstantSDNode>(ShAmt)->getZExtValue();
unsigned LSB = CountTrailingZeros_32(Mask);
if (ShAmtC != LSB)
return SDValue(); return SDValue();
//unsigned Width = (32 - CountLeadingZeros_32(Mask)) - LSB;
Res = DAG.getNode(ARMISD::BFI, DL, VT, N1,
N0.getOperand(0).getOperand(0),
DAG.getConstant(~Mask, MVT::i32));
// Do not add new nodes to DAG combiner worklist.
DCI.CombineTo(N, Res, false);
} }
} else if (N1.getOpcode() == ISD::AND) { } else if (N1.getOpcode() == ISD::AND) {
// case (2) or (and A, mask), (and B, mask2) => ARMbfi A, (lsr B, amt), mask // case (2) or (and A, mask), (and B, mask2) => ARMbfi A, (lsr B, amt), mask
C = dyn_cast<ConstantSDNode>(N1.getOperand(1)); ConstantSDNode *N11C = dyn_cast<ConstantSDNode>(N1.getOperand(1));
if (!C) if (!N11C)
return SDValue(); return SDValue();
unsigned Mask2 = C->getZExtValue(); unsigned Mask2 = N11C->getZExtValue();
if (ARM::isBitFieldInvertedMask(Mask) && if (ARM::isBitFieldInvertedMask(Mask) &&
ARM::isBitFieldInvertedMask(~Mask2) && ARM::isBitFieldInvertedMask(~Mask2) &&
@ -4777,10 +4763,11 @@ static SDValue PerformORCombine(SDNode *N,
unsigned lsb = CountTrailingZeros_32(Mask2); unsigned lsb = CountTrailingZeros_32(Mask2);
Res = DAG.getNode(ISD::SRL, DL, VT, N1.getOperand(0), Res = DAG.getNode(ISD::SRL, DL, VT, N1.getOperand(0),
DAG.getConstant(lsb, MVT::i32)); DAG.getConstant(lsb, MVT::i32));
Res = DAG.getNode(ARMISD::BFI, DL, VT, N0.getOperand(0), Res, Res = DAG.getNode(ARMISD::BFI, DL, VT, N00, Res,
DAG.getConstant(Mask, MVT::i32)); DAG.getConstant(Mask, MVT::i32));
// Do not add new nodes to DAG combiner worklist. // Do not add new nodes to DAG combiner worklist.
DCI.CombineTo(N, Res, false); DCI.CombineTo(N, Res, false);
return SDValue();
} else if (ARM::isBitFieldInvertedMask(~Mask) && } else if (ARM::isBitFieldInvertedMask(~Mask) &&
ARM::isBitFieldInvertedMask(Mask2) && ARM::isBitFieldInvertedMask(Mask2) &&
(CountPopulation_32(~Mask) == CountPopulation_32(Mask2))) { (CountPopulation_32(~Mask) == CountPopulation_32(Mask2))) {
@ -4791,15 +4778,34 @@ static SDValue PerformORCombine(SDNode *N,
return SDValue(); return SDValue();
// 2b // 2b
unsigned lsb = CountTrailingZeros_32(Mask); unsigned lsb = CountTrailingZeros_32(Mask);
Res = DAG.getNode(ISD::SRL, DL, VT, N0.getOperand(0), Res = DAG.getNode(ISD::SRL, DL, VT, N00,
DAG.getConstant(lsb, MVT::i32)); DAG.getConstant(lsb, MVT::i32));
Res = DAG.getNode(ARMISD::BFI, DL, VT, N1.getOperand(0), Res, Res = DAG.getNode(ARMISD::BFI, DL, VT, N1.getOperand(0), Res,
DAG.getConstant(Mask2, MVT::i32)); DAG.getConstant(Mask2, MVT::i32));
// Do not add new nodes to DAG combiner worklist. // Do not add new nodes to DAG combiner worklist.
DCI.CombineTo(N, Res, false); DCI.CombineTo(N, Res, false);
return SDValue();
} }
} }
if (DAG.MaskedValueIsZero(N1, MaskC->getAPIntValue()) &&
N00.getOpcode() == ISD::SHL && isa<ConstantSDNode>(N00.getOperand(1)) &&
ARM::isBitFieldInvertedMask(~Mask)) {
// Case (3): or (and (shl A, #shamt), mask), B => ARMbfi B, A, ~mask
// where lsb(mask) == #shamt and masked bits of B are known zero.
SDValue ShAmt = N00.getOperand(1);
unsigned ShAmtC = cast<ConstantSDNode>(ShAmt)->getZExtValue();
unsigned LSB = CountTrailingZeros_32(Mask);
if (ShAmtC != LSB)
return SDValue();
Res = DAG.getNode(ARMISD::BFI, DL, VT, N1, N00.getOperand(0),
DAG.getConstant(~Mask, MVT::i32));
// Do not add new nodes to DAG combiner worklist.
DCI.CombineTo(N, Res, false);
}
return SDValue(); return SDValue();
} }