[llvm] r363645 - [X86] Move code that shrinks immediates for ((x << C1) op C2) into a helper function. NFCI
Craig Topper via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 17 21:23:58 PDT 2019
Author: ctopper
Date: Mon Jun 17 21:23:58 2019
New Revision: 363645
URL: http://llvm.org/viewvc/llvm-project?rev=363645&view=rev
Log:
[X86] Move code that shrinks immediates for ((x << C1) op C2) into a helper function. NFCI
Preliminary step for D59909
Modified:
llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
Modified: llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp?rev=363645&r1=363644&r2=363645&view=diff
==============================================================================
--- llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86ISelDAGToDAG.cpp Mon Jun 17 21:23:58 2019
@@ -502,6 +502,7 @@ namespace {
bool shrinkAndImmediate(SDNode *N);
bool isMaskZeroExtended(SDNode *N) const;
bool tryShiftAmountMod(SDNode *N);
+ bool tryShrinkShlLogicImm(SDNode *N);
bool tryVPTESTM(SDNode *Root, SDValue Setcc, SDValue Mask);
MachineSDNode *emitPCMPISTR(unsigned ROpc, unsigned MOpc, bool MayFoldLoad,
@@ -3567,6 +3568,119 @@ bool X86DAGToDAGISel::tryShiftAmountMod(
return true;
}
+bool X86DAGToDAGISel::tryShrinkShlLogicImm(SDNode *N) {
+ MVT NVT = N->getSimpleValueType(0);
+ unsigned Opcode = N->getOpcode();
+ SDLoc dl(N);
+
+ // For operations of the form (x << C1) op C2, check if we can use a smaller
+ // encoding for C2 by transforming it into (x op (C2>>C1)) << C1.
+ SDValue Shift = N->getOperand(0);
+ SDValue N1 = N->getOperand(1);
+
+ ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(N1);
+ if (!Cst)
+ return false;
+
+ int64_t Val = Cst->getSExtValue();
+
+ // If we have an any_extend feeding the AND, look through it to see if there
+ // is a shift behind it. But only if the AND doesn't use the extended bits.
+ // FIXME: Generalize this to other ANY_EXTEND than i32 to i64?
+ bool FoundAnyExtend = false;
+ if (Shift.getOpcode() == ISD::ANY_EXTEND && Shift.hasOneUse() &&
+ Shift.getOperand(0).getSimpleValueType() == MVT::i32 &&
+ isUInt<32>(Val)) {
+ FoundAnyExtend = true;
+ Shift = Shift.getOperand(0);
+ }
+
+ if (Shift.getOpcode() != ISD::SHL || !Shift.hasOneUse())
+ return false;
+
+ // i8 is unshrinkable, i16 should be promoted to i32.
+ if (NVT != MVT::i32 && NVT != MVT::i64)
+ return false;
+
+ ConstantSDNode *ShlCst = dyn_cast<ConstantSDNode>(Shift.getOperand(1));
+ if (!ShlCst)
+ return false;
+
+ uint64_t ShAmt = ShlCst->getZExtValue();
+
+ // Make sure that we don't change the operation by removing bits.
+ // This only matters for OR and XOR, AND is unaffected.
+ uint64_t RemovedBitsMask = (1ULL << ShAmt) - 1;
+ if (Opcode != ISD::AND && (Val & RemovedBitsMask) != 0)
+ return false;
+
+ // Check the minimum bitwidth for the new constant.
+ // TODO: Using 16 and 8 bit operations is also possible for or32 & xor32.
+ auto CanShrinkImmediate = [&](int64_t &ShiftedVal) {
+ if (Opcode == ISD::AND) {
+ // AND32ri is the same as AND64ri32 with zext imm.
+ // Try this before sign extended immediates below.
+ ShiftedVal = (uint64_t)Val >> ShAmt;
+ if (NVT == MVT::i64 && !isUInt<32>(Val) && isUInt<32>(ShiftedVal))
+ return true;
+ // Also swap order when the AND can become MOVZX.
+ if (ShiftedVal == UINT8_MAX || ShiftedVal == UINT16_MAX)
+ return true;
+ }
+ ShiftedVal = Val >> ShAmt;
+ if ((!isInt<8>(Val) && isInt<8>(ShiftedVal)) ||
+ (!isInt<32>(Val) && isInt<32>(ShiftedVal)))
+ return true;
+ if (Opcode != ISD::AND) {
+ // MOV32ri+OR64r/XOR64r is cheaper than MOV64ri64+OR64rr/XOR64rr
+ ShiftedVal = (uint64_t)Val >> ShAmt;
+ if (NVT == MVT::i64 && !isUInt<32>(Val) && isUInt<32>(ShiftedVal))
+ return true;
+ }
+ return false;
+ };
+
+ int64_t ShiftedVal;
+ if (!CanShrinkImmediate(ShiftedVal))
+ return false;
+
+ // Ok, we can reorder to get a smaller immediate.
+
+ // But, its possible the original immediate allowed an AND to become MOVZX.
+ // Doing this late due to avoid the MakedValueIsZero call as late as
+ // possible.
+ if (Opcode == ISD::AND) {
+ // Find the smallest zext this could possibly be.
+ unsigned ZExtWidth = Cst->getAPIntValue().getActiveBits();
+ ZExtWidth = PowerOf2Ceil(std::max(ZExtWidth, 8U));
+
+ // Figure out which bits need to be zero to achieve that mask.
+ APInt NeededMask = APInt::getLowBitsSet(NVT.getSizeInBits(),
+ ZExtWidth);
+ NeededMask &= ~Cst->getAPIntValue();
+
+ if (CurDAG->MaskedValueIsZero(N->getOperand(0), NeededMask))
+ return false;
+ }
+
+ SDValue X = Shift.getOperand(0);
+ if (FoundAnyExtend) {
+ SDValue NewX = CurDAG->getNode(ISD::ANY_EXTEND, dl, NVT, X);
+ insertDAGNode(*CurDAG, SDValue(N, 0), NewX);
+ X = NewX;
+ }
+
+ SDValue NewCst = CurDAG->getConstant(ShiftedVal, dl, NVT);
+ insertDAGNode(*CurDAG, SDValue(N, 0), NewCst);
+ SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT, X, NewCst);
+ insertDAGNode(*CurDAG, SDValue(N, 0), NewBinOp);
+ SDValue NewSHL = CurDAG->getNode(ISD::SHL, dl, NVT, NewBinOp,
+ Shift.getOperand(1));
+ ReplaceNode(N, NewSHL.getNode());
+ SelectCode(NewSHL.getNode());
+ return true;
+}
+
/// If the high bits of an 'and' operand are known zero, try setting the
/// high bits of an 'and' constant operand to produce a smaller encoding by
/// creating a small, sign-extended negative immediate rather than a large
@@ -4131,115 +4245,11 @@ void X86DAGToDAGISel::Select(SDNode *Nod
LLVM_FALLTHROUGH;
case ISD::OR:
- case ISD::XOR: {
-
- // For operations of the form (x << C1) op C2, check if we can use a smaller
- // encoding for C2 by transforming it into (x op (C2>>C1)) << C1.
- SDValue Shift = Node->getOperand(0);
- SDValue N1 = Node->getOperand(1);
-
- ConstantSDNode *Cst = dyn_cast<ConstantSDNode>(N1);
- if (!Cst)
- break;
-
- int64_t Val = Cst->getSExtValue();
-
- // If we have an any_extend feeding the AND, look through it to see if there
- // is a shift behind it. But only if the AND doesn't use the extended bits.
- // FIXME: Generalize this to other ANY_EXTEND than i32 to i64?
- bool FoundAnyExtend = false;
- if (Shift.getOpcode() == ISD::ANY_EXTEND && Shift.hasOneUse() &&
- Shift.getOperand(0).getSimpleValueType() == MVT::i32 &&
- isUInt<32>(Val)) {
- FoundAnyExtend = true;
- Shift = Shift.getOperand(0);
- }
-
- if (Shift.getOpcode() != ISD::SHL || !Shift.hasOneUse())
- break;
-
- // i8 is unshrinkable, i16 should be promoted to i32.
- if (NVT != MVT::i32 && NVT != MVT::i64)
- break;
-
- ConstantSDNode *ShlCst = dyn_cast<ConstantSDNode>(Shift.getOperand(1));
- if (!ShlCst)
- break;
-
- uint64_t ShAmt = ShlCst->getZExtValue();
-
- // Make sure that we don't change the operation by removing bits.
- // This only matters for OR and XOR, AND is unaffected.
- uint64_t RemovedBitsMask = (1ULL << ShAmt) - 1;
- if (Opcode != ISD::AND && (Val & RemovedBitsMask) != 0)
- break;
-
- // Check the minimum bitwidth for the new constant.
- // TODO: Using 16 and 8 bit operations is also possible for or32 & xor32.
- auto CanShrinkImmediate = [&](int64_t &ShiftedVal) {
- if (Opcode == ISD::AND) {
- // AND32ri is the same as AND64ri32 with zext imm.
- // Try this before sign extended immediates below.
- ShiftedVal = (uint64_t)Val >> ShAmt;
- if (NVT == MVT::i64 && !isUInt<32>(Val) && isUInt<32>(ShiftedVal))
- return true;
- // Also swap order when the AND can become MOVZX.
- if (ShiftedVal == UINT8_MAX || ShiftedVal == UINT16_MAX)
- return true;
- }
- ShiftedVal = Val >> ShAmt;
- if ((!isInt<8>(Val) && isInt<8>(ShiftedVal)) ||
- (!isInt<32>(Val) && isInt<32>(ShiftedVal)))
- return true;
- if (Opcode != ISD::AND) {
- // MOV32ri+OR64r/XOR64r is cheaper than MOV64ri64+OR64rr/XOR64rr
- ShiftedVal = (uint64_t)Val >> ShAmt;
- if (NVT == MVT::i64 && !isUInt<32>(Val) && isUInt<32>(ShiftedVal))
- return true;
- }
- return false;
- };
-
- int64_t ShiftedVal;
- if (!CanShrinkImmediate(ShiftedVal))
- break;
-
- // Ok, we can reorder to get a smaller immediate.
-
- // But, its possible the original immediate allowed an AND to become MOVZX.
- // Doing this late due to avoid the MakedValueIsZero call as late as
- // possible.
- if (Opcode == ISD::AND) {
- // Find the smallest zext this could possibly be.
- unsigned ZExtWidth = Cst->getAPIntValue().getActiveBits();
- ZExtWidth = PowerOf2Ceil(std::max(ZExtWidth, 8U));
-
- // Figure out which bits need to be zero to achieve that mask.
- APInt NeededMask = APInt::getLowBitsSet(NVT.getSizeInBits(),
- ZExtWidth);
- NeededMask &= ~Cst->getAPIntValue();
-
- if (CurDAG->MaskedValueIsZero(Node->getOperand(0), NeededMask))
- break;
- }
-
- SDValue X = Shift.getOperand(0);
- if (FoundAnyExtend) {
- SDValue NewX = CurDAG->getNode(ISD::ANY_EXTEND, dl, NVT, X);
- insertDAGNode(*CurDAG, SDValue(Node, 0), NewX);
- X = NewX;
- }
+ case ISD::XOR:
+ if (tryShrinkShlLogicImm(Node))
+ return;
+ break;
- SDValue NewCst = CurDAG->getConstant(ShiftedVal, dl, NVT);
- insertDAGNode(*CurDAG, SDValue(Node, 0), NewCst);
- SDValue NewBinOp = CurDAG->getNode(Opcode, dl, NVT, X, NewCst);
- insertDAGNode(*CurDAG, SDValue(Node, 0), NewBinOp);
- SDValue NewSHL = CurDAG->getNode(ISD::SHL, dl, NVT, NewBinOp,
- Shift.getOperand(1));
- ReplaceNode(Node, NewSHL.getNode());
- SelectCode(NewSHL.getNode());
- return;
- }
case X86ISD::SMUL:
// i16/i32/i64 are handled with isel patterns.
if (NVT != MVT::i8)
More information about the llvm-commits
mailing list