From 92abc62399881ba9c525be80362c134ad836e2d9 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Sat, 31 Jan 2009 15:50:11 +0000 Subject: [PATCH] Fix PR3401: when using large integers, the type returned by getShiftAmountTy may be too small to hold shift values (it is an i8 on x86-32). Before and during type legalization, use a large but legal type for shift amounts: getPointerTy; afterwards use getShiftAmountTy, fixing up any shift amounts with a big type during operation legalization. Thanks to Dan for writing the original patch (which I shamelessly pillaged). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@63482 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/SelectionDAG.h | 4 ++ lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 42 +++++++++------- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 45 ++++++++--------- .../SelectionDAG/LegalizeIntegerTypes.cpp | 48 +++++++++---------- lib/CodeGen/SelectionDAG/LegalizeTypes.cpp | 7 ++- .../SelectionDAG/LegalizeVectorTypes.cpp | 5 -- lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 14 ++++-- .../SelectionDAG/SelectionDAGBuild.cpp | 32 ++++++------- lib/CodeGen/SelectionDAG/TargetLowering.cpp | 8 ++-- test/CodeGen/X86/2009-01-31-BigShift.ll | 9 ++++ test/CodeGen/X86/2009-01-31-BigShift2.ll | 11 +++++ test/CodeGen/X86/2009-01-31-BigShift3.ll | 31 ++++++++++++ 12 files changed, 155 insertions(+), 101 deletions(-) create mode 100644 test/CodeGen/X86/2009-01-31-BigShift.ll create mode 100644 test/CodeGen/X86/2009-01-31-BigShift2.ll create mode 100644 test/CodeGen/X86/2009-01-31-BigShift3.ll diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index f8be1679e7e..4937df79b99 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -636,6 +636,10 @@ public: /// through the backend. SDValue getMemOperand(const MachineMemOperand &MO); + /// getShiftAmountOperand - Return the specified value casted to + /// the target's desired shift amount type. + SDValue getShiftAmountOperand(SDValue Op); + /// UpdateNodeOperands - *Mutate* the specified node in-place to have the /// specified operands. If the resultant node already exists in the DAG, /// this does not modify the specified node, instead it returns the node that diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 7240fb9a717..1dbbf4f5a96 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -240,7 +240,13 @@ namespace { /// FindBetterChain - Walk up chain skipping non-aliasing memory nodes, /// looking for a better chain (aliasing node.) SDValue FindBetterChain(SDNode *N, SDValue Chain); - + + /// getShiftAmountTy - Returns a type large enough to hold any valid + /// shift amount - before type legalization these can be huge. + MVT getShiftAmountTy() { + return LegalTypes ? TLI.getShiftAmountTy() : TLI.getPointerTy(); + } + public: DAGCombiner(SelectionDAG &D, AliasAnalysis &A, bool fast) : DAG(D), @@ -1301,7 +1307,7 @@ SDValue DAGCombiner::visitMUL(SDNode *N) { if (N1C && N1C->getAPIntValue().isPowerOf2()) return DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0, DAG.getConstant(N1C->getAPIntValue().logBase2(), - TLI.getShiftAmountTy())); + getShiftAmountTy())); // fold (mul x, -(1 << c)) -> -(x << c) or (-x) << c if (N1C && isPowerOf2_64(-N1C->getSExtValue())) // FIXME: If the input is something that is easily negated (e.g. a @@ -1310,7 +1316,7 @@ SDValue DAGCombiner::visitMUL(SDNode *N) { DAG.getConstant(0, VT), DAG.getNode(ISD::SHL, N->getDebugLoc(), VT, N0, DAG.getConstant(Log2_64(-N1C->getSExtValue()), - TLI.getShiftAmountTy()))); + getShiftAmountTy()))); // (mul (shl X, c1), c2) -> (mul X, c2 << c1) if (N1C && N0.getOpcode() == ISD::SHL && isa(N0.getOperand(1))) { @@ -1406,18 +1412,18 @@ SDValue DAGCombiner::visitSDIV(SDNode *N) { // Splat the sign bit into the register SDValue SGN = DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, N0, DAG.getConstant(VT.getSizeInBits()-1, - TLI.getShiftAmountTy())); + getShiftAmountTy())); AddToWorkList(SGN.getNode()); // Add (N0 < 0) ? abs2 - 1 : 0; SDValue SRL = DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, SGN, DAG.getConstant(VT.getSizeInBits() - lg2, - TLI.getShiftAmountTy())); + getShiftAmountTy())); SDValue ADD = DAG.getNode(ISD::ADD, N->getDebugLoc(), VT, N0, SRL); AddToWorkList(SRL.getNode()); AddToWorkList(ADD.getNode()); // Divide by pow2 SDValue SRA = DAG.getNode(ISD::SRA, N->getDebugLoc(), VT, ADD, - DAG.getConstant(lg2, TLI.getShiftAmountTy())); + DAG.getConstant(lg2, getShiftAmountTy())); // If we're dividing by a positive value, we're done. Otherwise, we must // negate the result. @@ -1467,7 +1473,7 @@ SDValue DAGCombiner::visitUDIV(SDNode *N) { if (N1C && N1C->getAPIntValue().isPowerOf2()) return DAG.getNode(ISD::SRL, N->getDebugLoc(), VT, N0, DAG.getConstant(N1C->getAPIntValue().logBase2(), - TLI.getShiftAmountTy())); + getShiftAmountTy())); // fold (udiv x, (shl c, y)) -> x >>u (log2(c)+y) iff c is power of 2 if (N1.getOpcode() == ISD::SHL) { if (ConstantSDNode *SHC = dyn_cast(N1.getOperand(0))) { @@ -1607,7 +1613,7 @@ SDValue DAGCombiner::visitMULHS(SDNode *N) { if (N1C && N1C->getAPIntValue() == 1) return DAG.getNode(ISD::SRA, N->getDebugLoc(), N0.getValueType(), N0, DAG.getConstant(N0.getValueType().getSizeInBits() - 1, - TLI.getShiftAmountTy())); + getShiftAmountTy())); // fold (mulhs x, undef) -> 0 if (N0.getOpcode() == ISD::UNDEF || N1.getOpcode() == ISD::UNDEF) return DAG.getConstant(0, VT); @@ -2613,7 +2619,7 @@ SDValue DAGCombiner::visitSRA(SDNode *N) { TLI.isOperationLegalOrCustom(ISD::TRUNCATE, VT) && TLI.isTruncateFree(VT, TruncVT)) { - SDValue Amt = DAG.getConstant(ShiftAmt, TLI.getShiftAmountTy()); + SDValue Amt = DAG.getConstant(ShiftAmt, getShiftAmountTy()); SDValue Shift = DAG.getNode(ISD::SRL, N0.getDebugLoc(), VT, N0.getOperand(0), Amt); SDValue Trunc = DAG.getNode(ISD::TRUNCATE, N0.getDebugLoc(), TruncVT, @@ -2740,7 +2746,7 @@ SDValue DAGCombiner::visitSRL(SDNode *N) { if (ShAmt) { Op = DAG.getNode(ISD::SRL, N0.getDebugLoc(), VT, Op, - DAG.getConstant(ShAmt, TLI.getShiftAmountTy())); + DAG.getConstant(ShAmt, getShiftAmountTy())); AddToWorkList(Op.getNode()); } @@ -5722,7 +5728,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, if (N2C && ((N2C->getAPIntValue() & (N2C->getAPIntValue()-1)) == 0)) { unsigned ShCtV = N2C->getAPIntValue().logBase2(); ShCtV = XType.getSizeInBits()-ShCtV-1; - SDValue ShCt = DAG.getConstant(ShCtV, TLI.getShiftAmountTy()); + SDValue ShCt = DAG.getConstant(ShCtV, getShiftAmountTy()); SDValue Shift = DAG.getNode(ISD::SRL, N0.getDebugLoc(), XType, N0, ShCt); AddToWorkList(Shift.getNode()); @@ -5738,7 +5744,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, SDValue Shift = DAG.getNode(ISD::SRA, N0.getDebugLoc(), XType, N0, DAG.getConstant(XType.getSizeInBits()-1, - TLI.getShiftAmountTy())); + getShiftAmountTy())); AddToWorkList(Shift.getNode()); if (XType.bitsGT(AType)) { @@ -5787,7 +5793,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, // shl setcc result by log2 n2c return DAG.getNode(ISD::SHL, DL, N2.getValueType(), Temp, DAG.getConstant(N2C->getAPIntValue().logBase2(), - TLI.getShiftAmountTy())); + getShiftAmountTy())); } // Check to see if this is the equivalent of setcc @@ -5810,7 +5816,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, SDValue Ctlz = DAG.getNode(ISD::CTLZ, N0.getDebugLoc(), XType, N0); return DAG.getNode(ISD::SRL, DL, XType, Ctlz, DAG.getConstant(Log2_32(XType.getSizeInBits()), - TLI.getShiftAmountTy())); + getShiftAmountTy())); } // fold (setgt X, 0) -> (srl (and (-X, ~X), size(X)-1)) if (N1C && N1C->isNullValue() && CC == ISD::SETGT) { @@ -5820,13 +5826,13 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, return DAG.getNode(ISD::SRL, DL, XType, DAG.getNode(ISD::AND, XType, NegN0, NotN0), DAG.getConstant(XType.getSizeInBits()-1, - TLI.getShiftAmountTy())); + getShiftAmountTy())); } // fold (setgt X, -1) -> (xor (srl (X, size(X)-1), 1)) if (N1C && N1C->isAllOnesValue() && CC == ISD::SETGT) { SDValue Sign = DAG.getNode(ISD::SRL, N0.getDebugLoc(), XType, N0, DAG.getConstant(XType.getSizeInBits()-1, - TLI.getShiftAmountTy())); + getShiftAmountTy())); return DAG.getNode(ISD::XOR, DL, XType, Sign, DAG.getConstant(1, XType)); } } @@ -5839,7 +5845,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, MVT XType = N0.getValueType(); SDValue Shift = DAG.getNode(ISD::SRA, N0.getDebugLoc(), XType, N0, DAG.getConstant(XType.getSizeInBits()-1, - TLI.getShiftAmountTy())); + getShiftAmountTy())); SDValue Add = DAG.getNode(ISD::ADD, N0.getDebugLoc(), XType, N0, Shift); AddToWorkList(Shift.getNode()); @@ -5856,7 +5862,7 @@ SDValue DAGCombiner::SimplifySelectCC(DebugLoc DL, SDValue N0, SDValue N1, SDValue Shift = DAG.getNode(ISD::SRA, N0.getDebugLoc(), XType, N0, DAG.getConstant(XType.getSizeInBits()-1, - TLI.getShiftAmountTy())); + getShiftAmountTy())); SDValue Add = DAG.getNode(ISD::ADD, N0.getDebugLoc(), XType, N0, Shift); AddToWorkList(Shift.getNode()); diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 71fce0decfa..4dd5dd25424 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -301,9 +301,6 @@ private: SDValue ExpandEXTRACT_SUBVECTOR(SDValue Op); SDValue ExpandEXTRACT_VECTOR_ELT(SDValue Op); - - // Returns the legalized (truncated or extended) shift amount. - SDValue LegalizeShiftAmount(SDValue ShiftAmt); }; } @@ -903,8 +900,10 @@ SDValue SelectionDAGLegalize::UnrollVectorOp(SDValue Op) { case ISD::SHL: case ISD::SRA: case ISD::SRL: + case ISD::ROTL: + case ISD::ROTR: Scalars.push_back(DAG.getNode(Op.getOpcode(), EltVT, Operands[0], - LegalizeShiftAmount(Operands[1]))); + DAG.getShiftAmountOperand(Operands[1]))); break; } } @@ -969,16 +968,6 @@ PerformInsertVectorEltInMemory(SDValue Vec, SDValue Val, SDValue Idx) { PseudoSourceValue::getFixedStack(SPFI), 0); } -SDValue SelectionDAGLegalize::LegalizeShiftAmount(SDValue ShiftAmt) { - if (TLI.getShiftAmountTy().bitsLT(ShiftAmt.getValueType())) - return DAG.getNode(ISD::TRUNCATE, TLI.getShiftAmountTy(), ShiftAmt); - - if (TLI.getShiftAmountTy().bitsGT(ShiftAmt.getValueType())) - return DAG.getNode(ISD::ZERO_EXTEND, TLI.getShiftAmountTy(), ShiftAmt); - - return ShiftAmt; -} - /// LegalizeOp - We know that the specified value has a legal type, and /// that its operands are legal. Now ensure that the operation itself @@ -3137,10 +3126,13 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case ISD::SRL_PARTS: { SmallVector Ops; bool Changed = false; - for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) { + unsigned N = Node->getNumOperands(); + for (unsigned i = 0; i + 1 < N; ++i) { Ops.push_back(LegalizeOp(Node->getOperand(i))); Changed |= Ops.back() != Node->getOperand(i); } + Ops.push_back(LegalizeOp(DAG.getShiftAmountOperand(Node->getOperand(N-1)))); + Changed |= Ops.back() != Node->getOperand(N-1); if (Changed) Result = DAG.UpdateNodeOperands(Result, &Ops[0], Ops.size()); @@ -3191,23 +3183,24 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case ISD::FDIV: case ISD::FPOW: Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS - switch (getTypeAction(Node->getOperand(1).getValueType())) { + Tmp2 = LegalizeOp(Node->getOperand(1)); // RHS + + if ((Node->getOpcode() == ISD::SHL || + Node->getOpcode() == ISD::SRL || + Node->getOpcode() == ISD::SRA) && + !Node->getValueType(0).isVector()) + Tmp2 = DAG.getShiftAmountOperand(Tmp2); + + switch (getTypeAction(Tmp2.getValueType())) { case Expand: assert(0 && "Not possible"); case Legal: - Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the RHS. + Tmp2 = LegalizeOp(Tmp2); // Legalize the RHS. break; case Promote: - Tmp2 = PromoteOp(Node->getOperand(1)); // Promote the RHS. + Tmp2 = PromoteOp(Tmp2); // Promote the RHS. break; } - if ((Node->getOpcode() == ISD::SHL || - Node->getOpcode() == ISD::SRL || - Node->getOpcode() == ISD::SRA) && - !Node->getValueType(0).isVector()) { - Tmp2 = LegalizeShiftAmount(Tmp2); - } - Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2); switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) { @@ -3673,7 +3666,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { case ISD::ROTL: case ISD::ROTR: Tmp1 = LegalizeOp(Node->getOperand(0)); // LHS - Tmp2 = LegalizeOp(Node->getOperand(1)); // RHS + Tmp2 = LegalizeOp(DAG.getShiftAmountOperand(Node->getOperand(1))); // RHS Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2); switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) { default: diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index fac80a61496..f28da358693 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -230,7 +230,7 @@ SDValue DAGTypeLegalizer::PromoteIntRes_BSWAP(SDNode *N) { unsigned DiffBits = NVT.getSizeInBits() - OVT.getSizeInBits(); return DAG.getNode(ISD::SRL, dl, NVT, DAG.getNode(ISD::BSWAP, dl, NVT, Op), - DAG.getConstant(DiffBits, TLI.getShiftAmountTy())); + DAG.getConstant(DiffBits, TLI.getPointerTy())); } SDValue DAGTypeLegalizer::PromoteIntRes_BUILD_PAIR(SDNode *N) { @@ -327,7 +327,7 @@ SDValue DAGTypeLegalizer::PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N) { // Extract the element at OldIdx / 2 from the new vector. SDValue OldIdx = N->getOperand(1); SDValue NewIdx = DAG.getNode(ISD::SRL, dl, OldIdx.getValueType(), OldIdx, - DAG.getConstant(1, TLI.getShiftAmountTy())); + DAG.getConstant(1, TLI.getPointerTy())); SDValue Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, NewVT, NewVec, NewIdx); // Select the appropriate half of the element: Lo if OldIdx was even, @@ -335,7 +335,7 @@ SDValue DAGTypeLegalizer::PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N) { SDValue Lo = Elt; SDValue Hi = DAG.getNode(ISD::SRL, dl, NewVT, Elt, DAG.getConstant(OldVT.getSizeInBits(), - TLI.getShiftAmountTy())); + TLI.getPointerTy())); if (TLI.isBigEndian()) std::swap(Lo, Hi); @@ -621,7 +621,7 @@ SDValue DAGTypeLegalizer::PromoteIntRes_VAARG(SDNode *N) { // Shift it to the right position and "or" it in. Part = DAG.getNode(ISD::SHL, dl, NVT, Part, DAG.getConstant(i * RegVT.getSizeInBits(), - TLI.getShiftAmountTy())); + TLI.getPointerTy())); Res = DAG.getNode(ISD::OR, dl, NVT, Res, Part); } @@ -768,8 +768,7 @@ SDValue DAGTypeLegalizer::PromoteIntOp_BUILD_PAIR(SDNode *N) { DebugLoc dl = N->getDebugLoc(); Hi = DAG.getNode(ISD::SHL, dl, N->getValueType(0), Hi, - DAG.getConstant(OVT.getSizeInBits(), - TLI.getShiftAmountTy())); + DAG.getConstant(OVT.getSizeInBits(), TLI.getPointerTy())); return DAG.getNode(ISD::OR, dl, N->getValueType(0), Lo, Hi); } @@ -1329,7 +1328,7 @@ void DAGTypeLegalizer::ExpandIntRes_AssertSext(SDNode *N, Lo = DAG.getNode(ISD::AssertSext, dl, NVT, Lo, DAG.getValueType(EVT)); // The high part replicates the sign bit of Lo, make it explicit. Hi = DAG.getNode(ISD::SRA, dl, NVT, Lo, - DAG.getConstant(NVTBits-1, TLI.getShiftAmountTy())); + DAG.getConstant(NVTBits-1, TLI.getPointerTy())); } } @@ -1473,7 +1472,7 @@ void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, // lo part. unsigned LoSize = Lo.getValueType().getSizeInBits(); Hi = DAG.getNode(ISD::SRA, dl, NVT, Lo, - DAG.getConstant(LoSize-1, TLI.getShiftAmountTy())); + DAG.getConstant(LoSize-1, TLI.getPointerTy())); } else if (ExtType == ISD::ZEXTLOAD) { // The high part is just a zero. Hi = DAG.getConstant(0, NVT); @@ -1535,12 +1534,12 @@ void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, Lo = DAG.getNode(ISD::OR, dl, NVT, Lo, DAG.getNode(ISD::SHL, dl, NVT, Hi, DAG.getConstant(ExcessBits, - TLI.getShiftAmountTy()))); + TLI.getPointerTy()))); // Move high bits to the right position in Hi. Hi = DAG.getNode(ExtType == ISD::SEXTLOAD ? ISD::SRA : ISD::SRL, dl, NVT, Hi, DAG.getConstant(NVT.getSizeInBits() - ExcessBits, - TLI.getShiftAmountTy())); + TLI.getPointerTy())); } } @@ -1762,7 +1761,7 @@ void DAGTypeLegalizer::ExpandIntRes_SIGN_EXTEND(SDNode *N, // The high part is obtained by SRA'ing all but one of the bits of low part. unsigned LoSize = NVT.getSizeInBits(); Hi = DAG.getNode(ISD::SRA, dl, NVT, Lo, - DAG.getConstant(LoSize-1, TLI.getShiftAmountTy())); + DAG.getConstant(LoSize-1, TLI.getPointerTy())); } else { // For example, extension of an i48 to an i64. The operand type necessarily // promotes to the result type, so will end up being expanded too. @@ -1795,7 +1794,7 @@ ExpandIntRes_SIGN_EXTEND_INREG(SDNode *N, SDValue &Lo, SDValue &Hi) { // things like sextinreg V:i64 from i8. Hi = DAG.getNode(ISD::SRA, dl, Hi.getValueType(), Lo, DAG.getConstant(Hi.getValueType().getSizeInBits()-1, - TLI.getShiftAmountTy())); + TLI.getPointerTy())); } else { // For example, extension of an i48 to an i64. Leave the low part alone, // sext_inreg the high part. @@ -1831,8 +1830,7 @@ void DAGTypeLegalizer::ExpandIntRes_TRUNCATE(SDNode *N, Lo = DAG.getNode(ISD::TRUNCATE, dl, NVT, N->getOperand(0)); Hi = DAG.getNode(ISD::SRL, dl, N->getOperand(0).getValueType(), N->getOperand(0), - DAG.getConstant(NVT.getSizeInBits(), - TLI.getShiftAmountTy())); + DAG.getConstant(NVT.getSizeInBits(), TLI.getPointerTy())); Hi = DAG.getNode(ISD::TRUNCATE, dl, NVT, Hi); } @@ -1922,20 +1920,18 @@ bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) { assert(0 && "Do not know how to expand this operator's operand!"); abort(); - case ISD::BUILD_VECTOR: Res = ExpandOp_BUILD_VECTOR(N); break; case ISD::BIT_CONVERT: Res = ExpandOp_BIT_CONVERT(N); break; + case ISD::BR_CC: Res = ExpandIntOp_BR_CC(N); break; + case ISD::BUILD_VECTOR: Res = ExpandOp_BUILD_VECTOR(N); break; case ISD::EXTRACT_ELEMENT: Res = ExpandOp_EXTRACT_ELEMENT(N); break; case ISD::INSERT_VECTOR_ELT: Res = ExpandOp_INSERT_VECTOR_ELT(N); break; case ISD::SCALAR_TO_VECTOR: Res = ExpandOp_SCALAR_TO_VECTOR(N); break; - - case ISD::BR_CC: Res = ExpandIntOp_BR_CC(N); break; - case ISD::SELECT_CC: Res = ExpandIntOp_SELECT_CC(N); break; - case ISD::SETCC: Res = ExpandIntOp_SETCC(N); break; - case ISD::SINT_TO_FP: Res = ExpandIntOp_SINT_TO_FP(N); break; - case ISD::STORE: Res = ExpandIntOp_STORE(cast(N), OpNo); - break; - case ISD::TRUNCATE: Res = ExpandIntOp_TRUNCATE(N); break; - case ISD::UINT_TO_FP: Res = ExpandIntOp_UINT_TO_FP(N); break; + case ISD::SELECT_CC: Res = ExpandIntOp_SELECT_CC(N); break; + case ISD::SETCC: Res = ExpandIntOp_SETCC(N); break; + case ISD::SINT_TO_FP: Res = ExpandIntOp_SINT_TO_FP(N); break; + case ISD::STORE: Res = ExpandIntOp_STORE(cast(N), OpNo); break; + case ISD::TRUNCATE: Res = ExpandIntOp_TRUNCATE(N); break; + case ISD::UINT_TO_FP: Res = ExpandIntOp_UINT_TO_FP(N); break; } // If the result is null, the sub-method took care of registering results etc. @@ -2175,11 +2171,11 @@ SDValue DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) { // Transfer high bits from the top of Lo to the bottom of Hi. Hi = DAG.getNode(ISD::SHL, dl, NVT, Hi, DAG.getConstant(NVT.getSizeInBits() - ExcessBits, - TLI.getShiftAmountTy())); + TLI.getPointerTy())); Hi = DAG.getNode(ISD::OR, dl, NVT, Hi, DAG.getNode(ISD::SRL, NVT, Lo, DAG.getConstant(ExcessBits, - TLI.getShiftAmountTy()))); + TLI.getPointerTy()))); } // Store both the high bits and maybe some of the low bits. diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp index c88fd5d1dd8..3e79ecb50c5 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp @@ -942,8 +942,8 @@ SDValue DAGTypeLegalizer::JoinIntegers(SDValue Lo, SDValue Hi) { Lo = DAG.getNode(ISD::ZERO_EXTEND, NVT, Lo); Hi = DAG.getNode(ISD::ANY_EXTEND, NVT, Hi); - Hi = DAG.getNode(ISD::SHL, NVT, Hi, DAG.getConstant(LVT.getSizeInBits(), - TLI.getShiftAmountTy())); + Hi = DAG.getNode(ISD::SHL, NVT, Hi, + DAG.getConstant(LVT.getSizeInBits(), TLI.getPointerTy())); return DAG.getNode(ISD::OR, NVT, Lo, Hi); } @@ -1028,8 +1028,7 @@ void DAGTypeLegalizer::SplitInteger(SDValue Op, Op.getValueType().getSizeInBits() && "Invalid integer splitting!"); Lo = DAG.getNode(ISD::TRUNCATE, LoVT, Op); Hi = DAG.getNode(ISD::SRL, Op.getValueType(), Op, - DAG.getConstant(LoVT.getSizeInBits(), - TLI.getShiftAmountTy())); + DAG.getConstant(LoVT.getSizeInBits(), TLI.getPointerTy())); Hi = DAG.getNode(ISD::TRUNCATE, HiVT, Hi); } diff --git a/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp index 128dc3351e4..ac814f28576 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -111,11 +111,6 @@ SDValue DAGTypeLegalizer::ScalarizeVecRes_BinOp(SDNode *N) { SDValue DAGTypeLegalizer::ScalarizeVecRes_ShiftOp(SDNode *N) { SDValue LHS = GetScalarizedVector(N->getOperand(0)); SDValue ShiftAmt = GetScalarizedVector(N->getOperand(1)); - if (TLI.getShiftAmountTy().bitsLT(ShiftAmt.getValueType())) - ShiftAmt = DAG.getNode(ISD::TRUNCATE, TLI.getShiftAmountTy(), ShiftAmt); - else if (TLI.getShiftAmountTy().bitsGT(ShiftAmt.getValueType())) - ShiftAmt = DAG.getNode(ISD::ZERO_EXTEND, TLI.getShiftAmountTy(), ShiftAmt); - return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, ShiftAmt); } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index f5287b0cf2c..1b0d61ca0a7 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -1287,6 +1287,17 @@ SDValue SelectionDAG::getMemOperand(const MachineMemOperand &MO) { return SDValue(N, 0); } +/// getShiftAmountOperand - Return the specified value casted to +/// the target's desired shift amount type. +SDValue SelectionDAG::getShiftAmountOperand(SDValue Op) { + MVT OpTy = Op.getValueType(); + MVT ShTy = TLI.getShiftAmountTy(); + if (OpTy == ShTy || OpTy.isVector()) return Op; + + ISD::NodeType Opcode = OpTy.bitsGT(ShTy) ? ISD::TRUNCATE : ISD::ZERO_EXTEND; + return getNode(Opcode, ShTy, Op); +} + /// CreateStackTemporary - Create a stack temporary, suitable for holding the /// specified value type. SDValue SelectionDAG::CreateStackTemporary(MVT VT, unsigned minAlign) { @@ -2529,9 +2540,6 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, MVT VT, "Shift operators return type must be the same as their first arg"); assert(VT.isInteger() && N2.getValueType().isInteger() && "Shifts only work on integers"); - assert((N2.getValueType() == TLI.getShiftAmountTy() || - (N2.getValueType().isVector() && N2.getValueType().isInteger())) && - "Wrong type for shift amount"); // Always fold shifts of i1 values so the code generator doesn't need to // handle them. Since we know the size of the shift has to be less than the diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index 024cb4b92f4..9057775a5cd 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -427,7 +427,7 @@ static SDValue getCopyFromParts(SelectionDAG &DAG, DebugLoc dl, Hi = DAG.getNode(ISD::ANY_EXTEND, dl, TotalVT, Hi); Hi = DAG.getNode(ISD::SHL, dl, TotalVT, Hi, DAG.getConstant(Lo.getValueType().getSizeInBits(), - TLI.getShiftAmountTy())); + TLI.getPointerTy())); Lo = DAG.getNode(ISD::ZERO_EXTEND, dl, TotalVT, Lo); Val = DAG.getNode(ISD::OR, dl, TotalVT, Lo, Hi); } @@ -587,7 +587,7 @@ static void getCopyToParts(SelectionDAG &DAG, DebugLoc dl, SDValue Val, unsigned OddParts = NumParts - RoundParts; SDValue OddVal = DAG.getNode(ISD::SRL, dl, ValueVT, Val, DAG.getConstant(RoundBits, - TLI.getShiftAmountTy())); + TLI.getPointerTy())); getCopyToParts(DAG, dl, OddVal, Parts + RoundParts, OddParts, PartVT); if (TLI.isBigEndian()) // The odd parts were reversed by getCopyToParts - unreverse them. @@ -1424,14 +1424,14 @@ void SelectionDAGLowering::visitBitTestHeader(BitTestBlock &B) { ISD::SETUGT); SDValue ShiftOp; - if (VT.bitsGT(TLI.getShiftAmountTy())) + if (VT.bitsGT(TLI.getPointerTy())) ShiftOp = DAG.getNode(ISD::TRUNCATE, getCurDebugLoc(), - TLI.getShiftAmountTy(), SUB); + TLI.getPointerTy(), SUB); else ShiftOp = DAG.getNode(ISD::ZERO_EXTEND, getCurDebugLoc(), - TLI.getShiftAmountTy(), SUB); + TLI.getPointerTy(), SUB); - B.Reg = FuncInfo.MakeReg(TLI.getShiftAmountTy()); + B.Reg = FuncInfo.MakeReg(TLI.getPointerTy()); SDValue CopyTo = DAG.getCopyToReg(getControlRoot(), B.Reg, ShiftOp); // Set NextBlock to be the MBB immediately after the current one, if any. @@ -1463,7 +1463,7 @@ void SelectionDAGLowering::visitBitTestCase(MachineBasicBlock* NextMBB, BitTestCase &B) { // Make desired shift SDValue ShiftOp = DAG.getCopyFromReg(getControlRoot(), Reg, - TLI.getShiftAmountTy()); + TLI.getPointerTy()); SDValue SwitchVal = DAG.getNode(ISD::SHL, getCurDebugLoc(), TLI.getPointerTy(), DAG.getConstant(1, TLI.getPointerTy()), @@ -2121,12 +2121,12 @@ void SelectionDAGLowering::visitShift(User &I, unsigned Opcode) { SDValue Op1 = getValue(I.getOperand(0)); SDValue Op2 = getValue(I.getOperand(1)); if (!isa(I.getType())) { - if (TLI.getShiftAmountTy().bitsLT(Op2.getValueType())) + if (TLI.getPointerTy().bitsLT(Op2.getValueType())) Op2 = DAG.getNode(ISD::TRUNCATE, getCurDebugLoc(), - TLI.getShiftAmountTy(), Op2); - else if (TLI.getShiftAmountTy().bitsGT(Op2.getValueType())) + TLI.getPointerTy(), Op2); + else if (TLI.getPointerTy().bitsGT(Op2.getValueType())) Op2 = DAG.getNode(ISD::ANY_EXTEND, getCurDebugLoc(), - TLI.getShiftAmountTy(), Op2); + TLI.getPointerTy(), Op2); } setValue(&I, DAG.getNode(Opcode, getCurDebugLoc(), @@ -2673,7 +2673,7 @@ void SelectionDAGLowering::visitGetElementPtr(User &I) { unsigned Amt = Log2_64(ElementSize); IdxN = DAG.getNode(ISD::SHL, getCurDebugLoc(), N.getValueType(), IdxN, - DAG.getConstant(Amt, TLI.getShiftAmountTy())); + DAG.getConstant(Amt, TLI.getPointerTy())); } else { SDValue Scale = DAG.getIntPtrConstant(ElementSize); IdxN = DAG.getNode(ISD::MUL, getCurDebugLoc(), @@ -3023,7 +3023,7 @@ GetExponent(SelectionDAG &DAG, SDValue Op, const TargetLowering &TLI, SDValue t0 = DAG.getNode(ISD::AND, dl, MVT::i32, Op, DAG.getConstant(0x7f800000, MVT::i32)); SDValue t1 = DAG.getNode(ISD::SRL, dl, MVT::i32, t0, - DAG.getConstant(23, TLI.getShiftAmountTy())); + DAG.getConstant(23, TLI.getPointerTy())); SDValue t2 = DAG.getNode(ISD::SUB, dl, MVT::i32, t1, DAG.getConstant(127, MVT::i32)); return DAG.getNode(ISD::SINT_TO_FP, dl, MVT::f32, t2); @@ -3095,7 +3095,7 @@ SelectionDAGLowering::visitExp(CallInst &I) { // IntegerPartOfX <<= 23; IntegerPartOfX = DAG.getNode(ISD::SHL, dl, MVT::i32, IntegerPartOfX, - DAG.getConstant(23, TLI.getShiftAmountTy())); + DAG.getConstant(23, TLI.getPointerTy())); if (LimitFloatPrecision <= 6) { // For floating-point precision of 6: @@ -3535,7 +3535,7 @@ SelectionDAGLowering::visitExp2(CallInst &I) { // IntegerPartOfX <<= 23; IntegerPartOfX = DAG.getNode(ISD::SHL, dl, MVT::i32, IntegerPartOfX, - DAG.getConstant(23, TLI.getShiftAmountTy())); + DAG.getConstant(23, TLI.getPointerTy())); if (LimitFloatPrecision <= 6) { // For floating-point precision of 6: @@ -3668,7 +3668,7 @@ SelectionDAGLowering::visitPow(CallInst &I) { // IntegerPartOfX <<= 23; IntegerPartOfX = DAG.getNode(ISD::SHL, dl, MVT::i32, IntegerPartOfX, - DAG.getConstant(23, TLI.getShiftAmountTy())); + DAG.getConstant(23, TLI.getPointerTy())); if (LimitFloatPrecision <= 6) { // For floating-point precision of 6: diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index ebc5067c704..7d524753cd4 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -1651,19 +1651,21 @@ TargetLowering::SimplifySetCC(MVT VT, SDValue N0, SDValue N1, VT == N0.getValueType() && N0.getOpcode() == ISD::AND) if (ConstantSDNode *AndRHS = dyn_cast(N0.getOperand(1))) { + MVT ShiftTy = DCI.isBeforeLegalize() ? + getPointerTy() : getShiftAmountTy(); if (Cond == ISD::SETNE && C1 == 0) {// (X & 8) != 0 --> (X & 8) >> 3 // Perform the xform if the AND RHS is a single bit. if (isPowerOf2_64(AndRHS->getZExtValue())) { return DAG.getNode(ISD::SRL, VT, N0, - DAG.getConstant(Log2_64(AndRHS->getZExtValue()), - getShiftAmountTy())); + DAG.getConstant(Log2_64(AndRHS->getZExtValue()), + ShiftTy)); } } else if (Cond == ISD::SETEQ && C1 == AndRHS->getZExtValue()) { // (X & 8) == 8 --> (X & 8) >> 3 // Perform the xform if C1 is a single bit. if (C1.isPowerOf2()) { return DAG.getNode(ISD::SRL, VT, N0, - DAG.getConstant(C1.logBase2(), getShiftAmountTy())); + DAG.getConstant(C1.logBase2(), ShiftTy)); } } } diff --git a/test/CodeGen/X86/2009-01-31-BigShift.ll b/test/CodeGen/X86/2009-01-31-BigShift.ll new file mode 100644 index 00000000000..360b4f0e46b --- /dev/null +++ b/test/CodeGen/X86/2009-01-31-BigShift.ll @@ -0,0 +1,9 @@ +; RUN: llvm-as < %s | llc -march=x86 | not grep and +; PR3401 + +define void @x(i288 %i) nounwind { + call void @add(i288 %i) + ret void +} + +declare void @add(i288) diff --git a/test/CodeGen/X86/2009-01-31-BigShift2.ll b/test/CodeGen/X86/2009-01-31-BigShift2.ll new file mode 100644 index 00000000000..2b5b1895783 --- /dev/null +++ b/test/CodeGen/X86/2009-01-31-BigShift2.ll @@ -0,0 +1,11 @@ +; RUN: llvm-as < %s | llc -march=x86 | grep {mov.*56} +; PR3449 + +define void @test(<8 x double>* %P, i64* %Q) nounwind { + %A = load <8 x double>* %P ; <<8 x double>> [#uses=1] + %B = bitcast <8 x double> %A to i512 ; [#uses=1] + %C = lshr i512 %B, 448 ; [#uses=1] + %D = trunc i512 %C to i64 ; [#uses=1] + volatile store i64 %D, i64* %Q + ret void +} diff --git a/test/CodeGen/X86/2009-01-31-BigShift3.ll b/test/CodeGen/X86/2009-01-31-BigShift3.ll new file mode 100644 index 00000000000..c92c86a092a --- /dev/null +++ b/test/CodeGen/X86/2009-01-31-BigShift3.ll @@ -0,0 +1,31 @@ +; RUN: llvm-as < %s | llc -march=x86 +; PR3450 + +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128" +target triple = "i386-apple-darwin7" + %struct.BitMap = type { i8* } + %struct.BitMapListStruct = type { %struct.BitMap, %struct.BitMapListStruct*, %struct.BitMapListStruct* } + %struct.Material = type { float, float, float, %struct.Material*, %struct.Material* } + %struct.ObjPoint = type { double, double, double, double, double, double } + %struct.ObjectStruct = type { [57 x i8], %struct.PointListStruct*, %struct.Poly3Struct*, %struct.Poly4Struct*, %struct.Texture*, %struct.Material*, %struct.Point, i32, i32, %struct.Point, %struct.Point, %struct.Point, %struct.ObjectStruct*, %struct.ObjectStruct*, i32, i32, i32, i32, i32, i32, i32, %struct.ObjectStruct*, %struct.ObjectStruct* } + %struct.Point = type { double, double, double } + %struct.PointListStruct = type { %struct.ObjPoint*, %struct.PointListStruct*, %struct.PointListStruct* } + %struct.Poly3Struct = type { [3 x %struct.ObjPoint*], %struct.Material*, %struct.Texture*, %struct.Poly3Struct*, %struct.Poly3Struct* } + %struct.Poly4Struct = type { [4 x %struct.ObjPoint*], %struct.Material*, %struct.Texture*, %struct.Poly4Struct*, %struct.Poly4Struct* } + %struct.Texture = type { %struct.Point, %struct.BitMapListStruct*, %struct.Point, %struct.Point, %struct.Point, %struct.Texture*, %struct.Texture* } + +define fastcc void @ScaleObjectAdd(%struct.ObjectStruct* %o, double %sx, double %sy, double %sz) nounwind { +entry: + %sz101112.ins = or i960 0, 0 ; [#uses=1] + br i1 false, label %return, label %bb1.preheader + +bb1.preheader: ; preds = %entry + %0 = lshr i960 %sz101112.ins, 640 ; [#uses=0] + br label %bb1 + +bb1: ; preds = %bb1, %bb1.preheader + br label %bb1 + +return: ; preds = %entry + ret void +} -- 2.34.1