From: Nate Begeman Date: Wed, 29 Apr 2009 05:20:52 +0000 (+0000) Subject: Implement review feedback for vector shuffle work. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=5a5ca1519e04310f585197c20e7ae584b7f2d11f;p=oota-llvm.git Implement review feedback for vector shuffle work. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@70372 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/CodeGen/SelectionDAG.h b/include/llvm/CodeGen/SelectionDAG.h index d2d17cfa2eb..90603769d9c 100644 --- a/include/llvm/CodeGen/SelectionDAG.h +++ b/include/llvm/CodeGen/SelectionDAG.h @@ -356,7 +356,7 @@ public: /// getVectorShuffle - Return an ISD::VECTOR_SHUFFLE node. The number of /// elements in VT, which must be a vector type, must match the number of - /// mask elements NumElts. A negative integer mask element is treated as + /// mask elements NumElts. A integer mask element equal to -1 is treated as /// undefined. SDValue getVectorShuffle(MVT VT, DebugLoc dl, SDValue N1, SDValue N2, const int *MaskElts); @@ -822,7 +822,7 @@ public: /// getShuffleScalarElt - Returns the scalar element that will make up the ith /// element of the result of the vector shuffle. - SDValue getShuffleScalarElt(const SDNode *N, unsigned Idx); + SDValue getShuffleScalarElt(const ShuffleVectorSDNode *N, unsigned Idx); private: bool RemoveNodeFromCSEMaps(SDNode *N); diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 34d877a0271..dc7112c63a4 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -1704,12 +1704,24 @@ public: } }; +/// ShuffleVectorSDNode - This SDNode is used to implement the code generator +/// support for the llvm IR shufflevector instruction. It combines elements +/// from two input vectors into a new input vector, with the selection and +/// ordering of elements determined by an array of integers, referred to as +/// the shuffle mask. For input vectors of width N, mask indices of 0..N-1 +/// refer to elements from the LHS input, and indices from N to 2N-1 the RHS. +/// An index of -1 is treated as undef, such that the code generator may put +/// any value in the corresponding element of the result. class ShuffleVectorSDNode : public SDNode { SDUse Ops[2]; - int *Mask; + + // The memory for Mask is owned by the SelectionDAG's OperandAllocator, and + // is freed when the SelectionDAG object is destroyed. + const int *Mask; protected: friend class SelectionDAG; - ShuffleVectorSDNode(MVT VT, DebugLoc dl, SDValue N1, SDValue N2, int *M) + ShuffleVectorSDNode(MVT VT, DebugLoc dl, SDValue N1, SDValue N2, + const int *M) : SDNode(ISD::VECTOR_SHUFFLE, dl, getSDVTList(VT)), Mask(M) { InitOperands(Ops, N1, N2); } diff --git a/include/llvm/Target/TargetLowering.h b/include/llvm/Target/TargetLowering.h index 3dbe89dc538..624f9fc72ce 100644 --- a/include/llvm/Target/TargetLowering.h +++ b/include/llvm/Target/TargetLowering.h @@ -329,7 +329,8 @@ public: /// support *some* VECTOR_SHUFFLE operations, those with specific masks. /// By default, if a target supports the VECTOR_SHUFFLE node, all mask values /// are assumed to be legal. - virtual bool isShuffleMaskLegal(SmallVectorImpl &Mask, MVT VT) const { + virtual bool isShuffleMaskLegal(const SmallVectorImpl &Mask, + MVT VT) const { return true; } @@ -337,7 +338,8 @@ public: /// used by Targets can use this to indicate if there is a suitable /// VECTOR_SHUFFLE that can be used to replace a VAND with a constant /// pool entry. - virtual bool isVectorClearMaskLegal(SmallVectorImpl &M, MVT VT) const { + virtual bool isVectorClearMaskLegal(const SmallVectorImpl &Mask, + MVT VT) const { return false; } diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index 8a41423cbe9..226699b6722 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -5163,13 +5163,14 @@ SDValue DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *N) { } LoadSDNode *LN0 = NULL; + const ShuffleVectorSDNode *SVN = NULL; if (ISD::isNormalLoad(InVec.getNode())) { LN0 = cast(InVec); } else if (InVec.getOpcode() == ISD::SCALAR_TO_VECTOR && InVec.getOperand(0).getValueType() == EVT && ISD::isNormalLoad(InVec.getOperand(0).getNode())) { LN0 = cast(InVec.getOperand(0)); - } else if (InVec.getOpcode() == ISD::VECTOR_SHUFFLE) { + } else if ((SVN = dyn_cast(InVec))) { // (vextract (vector_shuffle (load $addr), v2, <1, u, u, u>), 1) // => // (load $addr+1*size) @@ -5178,14 +5179,17 @@ SDValue DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *N) { // to examine the mask. if (BCNumEltsChanged) return SDValue(); - int Idx = cast(InVec)->getMaskElt(Elt); - int NumElems = InVec.getValueType().getVectorNumElements(); - InVec = (Idx < NumElems) ? InVec.getOperand(0) : InVec.getOperand(1); + + // Select the input vector, guarding against out of range extract vector. + unsigned NumElems = VT.getVectorNumElements(); + int Idx = (Elt > NumElems) ? -1 : SVN->getMaskElt(Elt); + InVec = (Idx < (int)NumElems) ? InVec.getOperand(0) : InVec.getOperand(1); + if (InVec.getOpcode() == ISD::BIT_CONVERT) InVec = InVec.getOperand(0); if (ISD::isNormalLoad(InVec.getNode())) { LN0 = cast(InVec); - Elt = (Idx < NumElems) ? Idx : Idx - NumElems; + Elt = (Idx < (int)NumElems) ? Idx : Idx - NumElems; } } @@ -5280,7 +5284,11 @@ SDValue DAGCombiner::visitBUILD_VECTOR(SDNode *N) { SDValue Extract = N->getOperand(i); SDValue ExtVal = Extract.getOperand(1); if (Extract.getOperand(0) == VecIn1) { - Mask.push_back(cast(ExtVal)->getZExtValue()); + unsigned ExtIndex = cast(ExtVal)->getZExtValue(); + if (ExtIndex > VT.getVectorNumElements()) + return SDValue(); + + Mask.push_back(ExtIndex); continue; } diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 25305ea243e..f772f163267 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -267,10 +267,13 @@ private: bool isVolatile, SDValue ValOp, unsigned StWidth, DebugLoc dl); - /// promoteShuffle - Promote a shuffle mask of a vector VT to perform the - /// same shuffle on a vector of NVT. Must not create an illegal shuffle mask. - SDValue promoteShuffle(MVT NVT, MVT VT, DebugLoc dl, SDValue N1, SDValue N2, - SmallVectorImpl &Mask) const; + /// ShuffleWithNarrowerEltType - Return a vector shuffle operation which + /// performs the same shuffe in terms of order or result bytes, but on a type + /// whose vector element type is narrower than the original shuffle type. + /// e.g. <0, 1, 0, 1> -> v8i16 <0, 1, 2, 3, 0, 1, 2, 3> + SDValue ShuffleWithNarrowerEltType(MVT NVT, MVT VT, DebugLoc dl, + SDValue N1, SDValue N2, + SmallVectorImpl &Mask) const; bool LegalizeAllNodesNotLeadingTo(SDNode *N, SDNode *Dest, SmallPtrSet &NodesLeadingTo); @@ -313,15 +316,17 @@ private: }; } -/// promoteShuffle - Promote a shuffle mask of a vector VT to perform the -/// same shuffle on a vector of NVT. Must not create an illegal shuffle mask. +/// ShuffleWithNarrowerEltType - Return a vector shuffle operation which +/// performs the same shuffe in terms of order or result bytes, but on a type +/// whose vector element type is narrower than the original shuffle type. /// e.g. <0, 1, 0, 1> -> v8i16 <0, 1, 2, 3, 0, 1, 2, 3> -SDValue SelectionDAGLegalize::promoteShuffle(MVT NVT, MVT VT, DebugLoc dl, - SDValue N1, SDValue N2, +SDValue +SelectionDAGLegalize::ShuffleWithNarrowerEltType(MVT NVT, MVT VT, DebugLoc dl, + SDValue N1, SDValue N2, SmallVectorImpl &Mask) const { MVT EltVT = NVT.getVectorElementType(); - int NumMaskElts = VT.getVectorNumElements(); - int NumDestElts = NVT.getVectorNumElements(); + unsigned NumMaskElts = VT.getVectorNumElements(); + unsigned NumDestElts = NVT.getVectorNumElements(); unsigned NumEltsGrowth = NumDestElts / NumMaskElts; assert(NumEltsGrowth && "Cannot promote to vector type with fewer elts!"); @@ -330,7 +335,7 @@ SDValue SelectionDAGLegalize::promoteShuffle(MVT NVT, MVT VT, DebugLoc dl, return DAG.getVectorShuffle(NVT, dl, N1, N2, &Mask[0]); SmallVector NewMask; - for (int i = 0; i != NumMaskElts; ++i) { + for (unsigned i = 0; i != NumMaskElts; ++i) { int Idx = Mask[i]; for (unsigned j = 0; j != NumEltsGrowth; ++j) { if (Idx < 0) @@ -339,7 +344,7 @@ SDValue SelectionDAGLegalize::promoteShuffle(MVT NVT, MVT VT, DebugLoc dl, NewMask.push_back(Idx * NumEltsGrowth + j); } } - assert((int)NewMask.size() == NumDestElts && "Non-integer NumEltsGrowth?"); + assert(NewMask.size() == NumDestElts && "Non-integer NumEltsGrowth?"); assert(TLI.isShuffleMaskLegal(NewMask, NVT) && "Shuffle not legal?"); return DAG.getVectorShuffle(NVT, dl, N1, N2, &NewMask[0]); } @@ -1678,7 +1683,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2); MVT VT = Result.getValueType(); - // Copy the Mask to a local SmallVector for use wi + // Copy the Mask to a local SmallVector for use with isShuffleMaskLegal. SmallVector Mask; cast(Result)->getMask(Mask); @@ -1698,14 +1703,14 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // FALLTHROUGH case TargetLowering::Expand: { MVT EltVT = VT.getVectorElementType(); - int NumElems = VT.getVectorNumElements(); + unsigned NumElems = VT.getVectorNumElements(); SmallVector Ops; - for (int i = 0; i != NumElems; ++i) { + for (unsigned i = 0; i != NumElems; ++i) { if (Mask[i] < 0) { Ops.push_back(DAG.getUNDEF(EltVT)); continue; } - int Idx = Mask[i]; + unsigned Idx = Mask[i]; if (Idx < NumElems) Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, dl, EltVT, Tmp1, DAG.getIntPtrConstant(Idx))); @@ -1726,7 +1731,7 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { Tmp2 = DAG.getNode(ISD::BIT_CONVERT, dl, NVT, Tmp2); // Convert the shuffle mask to the right # elements. - Result = promoteShuffle(NVT, OVT, dl, Tmp1, Tmp2, Mask); + Result = ShuffleWithNarrowerEltType(NVT, OVT, dl, Tmp1, Tmp2, Mask); Result = DAG.getNode(ISD::BIT_CONVERT, dl, OVT, Result); break; } diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/lib/CodeGen/SelectionDAG/LegalizeTypes.h index 330b5e7a652..382e270b214 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -559,7 +559,8 @@ private: void SplitVecRes_LOAD(LoadSDNode *N, SDValue &Lo, SDValue &Hi); void SplitVecRes_SCALAR_TO_VECTOR(SDNode *N, SDValue &Lo, SDValue &Hi); void SplitVecRes_UNDEF(SDNode *N, SDValue &Lo, SDValue &Hi); - void SplitVecRes_VECTOR_SHUFFLE(SDNode *N, SDValue &Lo, SDValue &Hi); + void SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N, SDValue &Lo, + SDValue &Hi); void SplitVecRes_VSETCC(SDNode *N, SDValue &Lo, SDValue &Hi); // Vector Operand Splitting: <128 x ty> -> 2 x <64 x ty>. @@ -602,7 +603,7 @@ private: SDValue WidenVecRes_SELECT(SDNode* N); SDValue WidenVecRes_SELECT_CC(SDNode* N); SDValue WidenVecRes_UNDEF(SDNode *N); - SDValue WidenVecRes_VECTOR_SHUFFLE(SDNode *N); + SDValue WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N); SDValue WidenVecRes_VSETCC(SDNode* N); SDValue WidenVecRes_Binary(SDNode *N); diff --git a/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp index f35db83d8bf..68967cc638f 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -383,7 +383,8 @@ void DAGTypeLegalizer::SplitVectorResult(SDNode *N, unsigned ResNo) { case ISD::INSERT_VECTOR_ELT: SplitVecRes_INSERT_VECTOR_ELT(N, Lo, Hi); break; case ISD::SCALAR_TO_VECTOR: SplitVecRes_SCALAR_TO_VECTOR(N, Lo, Hi); break; case ISD::LOAD: SplitVecRes_LOAD(cast(N), Lo, Hi);break; - case ISD::VECTOR_SHUFFLE: SplitVecRes_VECTOR_SHUFFLE(N, Lo, Hi); break; + case ISD::VECTOR_SHUFFLE: + SplitVecRes_VECTOR_SHUFFLE(cast(N), Lo, Hi); break; case ISD::VSETCC: SplitVecRes_VSETCC(N, Lo, Hi); break; case ISD::CTTZ: @@ -757,11 +758,10 @@ void DAGTypeLegalizer::SplitVecRes_UnaryOp(SDNode *N, SDValue &Lo, Hi = DAG.getNode(N->getOpcode(), dl, HiVT, Hi); } -void DAGTypeLegalizer::SplitVecRes_VECTOR_SHUFFLE(SDNode *N, SDValue &Lo, - SDValue &Hi) { +void DAGTypeLegalizer::SplitVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N, + SDValue &Lo, SDValue &Hi) { // The low and high parts of the original input give four input vectors. SDValue Inputs[4]; - ShuffleVectorSDNode *SVN = cast(N); DebugLoc dl = N->getDebugLoc(); GetSplitVector(N->getOperand(0), Inputs[0], Inputs[1]); GetSplitVector(N->getOperand(1), Inputs[2], Inputs[3]); @@ -786,7 +786,7 @@ void DAGTypeLegalizer::SplitVecRes_VECTOR_SHUFFLE(SDNode *N, SDValue &Lo, bool useBuildVector = false; for (unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) { // The mask element. This indexes into the input. - int Idx = SVN->getMaskElt(FirstMaskIdx + MaskOffset); + int Idx = N->getMaskElt(FirstMaskIdx + MaskOffset); // The input vector this mask element indexes into. unsigned Input = (unsigned)Idx / NewElts; @@ -831,7 +831,7 @@ void DAGTypeLegalizer::SplitVecRes_VECTOR_SHUFFLE(SDNode *N, SDValue &Lo, // Extract the input elements by hand. for (unsigned MaskOffset = 0; MaskOffset < NewElts; ++MaskOffset) { // The mask element. This indexes into the input. - int Idx = SVN->getMaskElt(FirstMaskIdx + MaskOffset); + int Idx = N->getMaskElt(FirstMaskIdx + MaskOffset); // The input vector this mask element indexes into. unsigned Input = (unsigned)Idx / NewElts; @@ -1102,7 +1102,8 @@ void DAGTypeLegalizer::WidenVectorResult(SDNode *N, unsigned ResNo) { case ISD::SELECT: Res = WidenVecRes_SELECT(N); break; case ISD::SELECT_CC: Res = WidenVecRes_SELECT_CC(N); break; case ISD::UNDEF: Res = WidenVecRes_UNDEF(N); break; - case ISD::VECTOR_SHUFFLE: Res = WidenVecRes_VECTOR_SHUFFLE(N); break; + case ISD::VECTOR_SHUFFLE: + Res = WidenVecRes_VECTOR_SHUFFLE(cast(N)); break; case ISD::VSETCC: Res = WidenVecRes_VSETCC(N); break; case ISD::ADD: @@ -1684,13 +1685,12 @@ SDValue DAGTypeLegalizer::WidenVecRes_UNDEF(SDNode *N) { return DAG.getUNDEF(WidenVT); } -SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(SDNode *N) { - ShuffleVectorSDNode *SVN = cast(N); +SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(ShuffleVectorSDNode *N) { MVT VT = N->getValueType(0); - int NumElts = VT.getVectorNumElements(); DebugLoc dl = N->getDebugLoc(); MVT WidenVT = TLI.getTypeToTransformTo(VT); + unsigned NumElts = VT.getVectorNumElements(); unsigned WidenNumElts = WidenVT.getVectorNumElements(); SDValue InOp1 = GetWidenedVector(N->getOperand(0)); @@ -1698,14 +1698,14 @@ SDValue DAGTypeLegalizer::WidenVecRes_VECTOR_SHUFFLE(SDNode *N) { // Adjust mask based on new input vector length. SmallVector NewMask; - for (int i = 0; i < NumElts; ++i) { - int Idx = SVN->getMaskElt(i); - if (Idx < NumElts) + for (unsigned i = 0; i != NumElts; ++i) { + int Idx = N->getMaskElt(i); + if (Idx < (int)NumElts) NewMask.push_back(Idx); else NewMask.push_back(Idx - NumElts + WidenNumElts); } - for (unsigned i = NumElts; i < WidenNumElts; ++i) + for (unsigned i = NumElts; i != WidenNumElts; ++i) NewMask.push_back(-1); return DAG.getVectorShuffle(WidenVT, dl, InOp1, InOp2, &NewMask[0]); } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 1c85e9d743e..d6a421d7a00 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -1133,6 +1133,9 @@ SDValue SelectionDAG::getCondCode(ISD::CondCode Cond) { return SDValue(CondCodeNodes[Cond], 0); } +// commuteShuffle - swaps the values of N1 and N2, and swaps all indices in +// the shuffle mask M that point at N1 to point at N2, and indices that point +// N2 to point at N1. static void commuteShuffle(SDValue &N1, SDValue &N2, SmallVectorImpl &M) { std::swap(N1, N2); int NElts = M.size(); @@ -1158,21 +1161,18 @@ SDValue SelectionDAG::getVectorShuffle(MVT VT, DebugLoc dl, SDValue N1, // Validate that all indices in Mask are within the range of the elements // input to the shuffle. - int NElts = VT.getVectorNumElements(); + unsigned NElts = VT.getVectorNumElements(); SmallVector MaskVec; - for (int i = 0; i != NElts; ++i) { - if (Mask[i] >= (NElts * 2)) { - assert(0 && "Index out of range"); - return SDValue(); - } + for (unsigned i = 0; i != NElts; ++i) { + assert(Mask[i] < (int)(NElts * 2) && "Index out of range"); MaskVec.push_back(Mask[i]); } // Canonicalize shuffle v, v -> v, undef if (N1 == N2) { N2 = getUNDEF(VT); - for (int i = 0; i != NElts; ++i) - if (MaskVec[i] >= NElts) MaskVec[i] -= NElts; + for (unsigned i = 0; i != NElts; ++i) + if (MaskVec[i] >= (int)NElts) MaskVec[i] -= NElts; } // Canonicalize shuffle undef, v -> v, undef. Commute the shuffle mask. @@ -1183,8 +1183,8 @@ SDValue SelectionDAG::getVectorShuffle(MVT VT, DebugLoc dl, SDValue N1, // Canonicalize all index into rhs, -> shuffle rhs, undef bool AllLHS = true, AllRHS = true; bool N2Undef = N2.getOpcode() == ISD::UNDEF; - for (int i = 0; i != NElts; ++i) { - if (MaskVec[i] >= NElts) { + for (unsigned i = 0; i != NElts; ++i) { + if (MaskVec[i] >= (int)NElts) { if (N2Undef) MaskVec[i] = -1; else @@ -1195,7 +1195,7 @@ SDValue SelectionDAG::getVectorShuffle(MVT VT, DebugLoc dl, SDValue N1, } if (AllLHS && AllRHS) return getUNDEF(VT); - if (AllLHS) + if (AllLHS && !N2Undef) N2 = getUNDEF(VT); if (AllRHS) { N1 = getUNDEF(VT); @@ -1205,8 +1205,8 @@ SDValue SelectionDAG::getVectorShuffle(MVT VT, DebugLoc dl, SDValue N1, // If Identity shuffle, or all shuffle in to undef, return that node. bool AllUndef = true; bool Identity = true; - for (int i = 0; i < NElts; ++i) { - if (MaskVec[i] >= 0 && MaskVec[i] != i) Identity = false; + for (unsigned i = 0; i != NElts; ++i) { + if (MaskVec[i] >= 0 && MaskVec[i] != (int)i) Identity = false; if (MaskVec[i] >= 0) AllUndef = false; } if (Identity) @@ -1217,7 +1217,7 @@ SDValue SelectionDAG::getVectorShuffle(MVT VT, DebugLoc dl, SDValue N1, FoldingSetNodeID ID; SDValue Ops[2] = { N1, N2 }; AddNodeIDNode(ID, ISD::VECTOR_SHUFFLE, getVTList(VT), Ops, 2); - for (int i = 0; i != NElts; ++i) + for (unsigned i = 0; i != NElts; ++i) ID.AddInteger(MaskVec[i]); void* IP = 0; @@ -2195,14 +2195,14 @@ bool SelectionDAG::isVerifiedDebugInfoDesc(SDValue Op) const { /// getShuffleScalarElt - Returns the scalar element that will make up the ith /// element of the result of the vector shuffle. -SDValue SelectionDAG::getShuffleScalarElt(const SDNode *N, unsigned i) { +SDValue SelectionDAG::getShuffleScalarElt(const ShuffleVectorSDNode *N, + unsigned i) { MVT VT = N->getValueType(0); DebugLoc dl = N->getDebugLoc(); - const ShuffleVectorSDNode *SVN = cast(N); - int Index = SVN->getMaskElt(i); - if (Index < 0) + if (N->getMaskElt(i) < 0) return getUNDEF(VT.getVectorElementType()); - int NumElems = VT.getVectorNumElements(); + unsigned Index = N->getMaskElt(i); + unsigned NumElems = VT.getVectorNumElements(); SDValue V = (Index < NumElems) ? N->getOperand(0) : N->getOperand(1); Index %= NumElems; @@ -2217,8 +2217,8 @@ SDValue SelectionDAG::getShuffleScalarElt(const SDNode *N, unsigned i) { : getUNDEF(VT.getVectorElementType()); if (V.getOpcode() == ISD::BUILD_VECTOR) return V.getOperand(Index); - if (V.getOpcode() == ISD::VECTOR_SHUFFLE) - return getShuffleScalarElt(V.getNode(), Index); + if (const ShuffleVectorSDNode *SVN = dyn_cast(V)) + return getShuffleScalarElt(SVN, Index); return SDValue(); } @@ -5726,11 +5726,19 @@ bool BuildVectorSDNode::isConstantSplat(APInt &SplatValue, } bool ShuffleVectorSDNode::isSplatMask(const int *Mask, MVT VT) { - int Idx = -1; - for (unsigned i = 0, e = VT.getVectorNumElements(); i != e; ++i) { - if (Idx < 0) Idx = Mask[i]; + // Find the first non-undef value in the shuffle mask. + unsigned i, e; + for (i = 0, e = VT.getVectorNumElements(); i != e && Mask[i] < 0; ++i) + /* search */; + + // If we hit the end of the mask looking for a non-undef value, return false. + if (i == e) + return false; + + // Make sure all remaining elements are either undef or the same as the first + // non-undef value. + for (int Idx = Mask[i]; i != e; ++i) if (Mask[i] >= 0 && Mask[i] != Idx) return false; - } return true; } diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp index 6fe56578b20..afadd62caa3 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuild.cpp @@ -2431,10 +2431,10 @@ void SelectionDAGLowering::visitExtractElement(User &I) { // Utility for visitShuffleVector - Returns true if the mask is mask starting // from SIndx and increasing to the element length (undefs are allowed). -static bool SequentialMask(SmallVectorImpl &Mask, int SIndx) { - int MaskNumElts = Mask.size(); - for (int i = 0; i != MaskNumElts; ++i) - if ((Mask[i] >= 0) && (Mask[i] != i + SIndx)) +static bool SequentialMask(SmallVectorImpl &Mask, unsigned SIndx) { + unsigned MaskNumElts = Mask.size(); + for (unsigned i = 0; i != MaskNumElts; ++i) + if ((Mask[i] >= 0) && (Mask[i] != (int)(i + SIndx))) return false; return true; } @@ -2448,8 +2448,8 @@ void SelectionDAGLowering::visitShuffleVector(User &I) { // representing undef values. SmallVector MaskElts; cast(I.getOperand(2))->getVectorElements(MaskElts); - int MaskNumElts = MaskElts.size(); - for (int i = 0; i != MaskNumElts; ++i) { + unsigned MaskNumElts = MaskElts.size(); + for (unsigned i = 0; i != MaskNumElts; ++i) { if (isa(MaskElts[i])) Mask.push_back(-1); else @@ -2458,7 +2458,7 @@ void SelectionDAGLowering::visitShuffleVector(User &I) { MVT VT = TLI.getValueType(I.getType()); MVT SrcVT = Src1.getValueType(); - int SrcNumElts = SrcVT.getVectorNumElements(); + unsigned SrcNumElts = SrcVT.getVectorNumElements(); if (SrcNumElts == MaskNumElts) { setValue(&I, DAG.getVectorShuffle(VT, getCurDebugLoc(), Src1, Src2, @@ -2498,9 +2498,9 @@ void SelectionDAGLowering::visitShuffleVector(User &I) { // Readjust mask for new input vector length. SmallVector MappedOps; - for (int i = 0; i != MaskNumElts; ++i) { + for (unsigned i = 0; i != MaskNumElts; ++i) { int Idx = Mask[i]; - if (Idx < SrcNumElts) + if (Idx < (int)SrcNumElts) MappedOps.push_back(Idx); else MappedOps.push_back(Idx + MaskNumElts - SrcNumElts); @@ -2511,32 +2511,19 @@ void SelectionDAGLowering::visitShuffleVector(User &I) { } if (SrcNumElts > MaskNumElts) { - // Resulting vector is shorter than the incoming vector. - if (SrcNumElts == MaskNumElts && SequentialMask(Mask,0)) { - // Shuffle extracts 1st vector. - setValue(&I, Src1); - return; - } - - if (SrcNumElts == MaskNumElts && SequentialMask(Mask,MaskNumElts)) { - // Shuffle extracts 2nd vector. - setValue(&I, Src2); - return; - } - // Analyze the access pattern of the vector to see if we can extract // two subvectors and do the shuffle. The analysis is done by calculating // the range of elements the mask access on both vectors. int MinRange[2] = { SrcNumElts+1, SrcNumElts+1}; int MaxRange[2] = {-1, -1}; - for (int i = 0; i != MaskNumElts; ++i) { + for (unsigned i = 0; i != MaskNumElts; ++i) { int Idx = Mask[i]; int Input = 0; if (Idx < 0) continue; - if (Idx >= SrcNumElts) { + if (Idx >= (int)SrcNumElts) { Input = 1; Idx -= SrcNumElts; } @@ -2551,18 +2538,18 @@ void SelectionDAGLowering::visitShuffleVector(User &I) { int RangeUse[2] = { 2, 2 }; // 0 = Unused, 1 = Extract, 2 = Can not Extract. int StartIdx[2]; // StartIdx to extract from for (int Input=0; Input < 2; ++Input) { - if (MinRange[Input] == SrcNumElts+1 && MaxRange[Input] == -1) { + if (MinRange[Input] == (int)(SrcNumElts+1) && MaxRange[Input] == -1) { RangeUse[Input] = 0; // Unused StartIdx[Input] = 0; - } else if (MaxRange[Input] - MinRange[Input] < MaskNumElts) { + } else if (MaxRange[Input] - MinRange[Input] < (int)MaskNumElts) { // Fits within range but we should see if we can find a good // start index that is a multiple of the mask length. - if (MaxRange[Input] < MaskNumElts) { + if (MaxRange[Input] < (int)MaskNumElts) { RangeUse[Input] = 1; // Extract from beginning of the vector StartIdx[Input] = 0; } else { StartIdx[Input] = (MinRange[Input]/MaskNumElts)*MaskNumElts; - if (MaxRange[Input] - StartIdx[Input] < MaskNumElts && + if (MaxRange[Input] - StartIdx[Input] < (int)MaskNumElts && StartIdx[Input] + MaskNumElts < SrcNumElts) RangeUse[Input] = 1; // Extract from a multiple of the mask length. } @@ -2586,11 +2573,11 @@ void SelectionDAGLowering::visitShuffleVector(User &I) { } // Calculate new mask. SmallVector MappedOps; - for (int i = 0; i != MaskNumElts; ++i) { + for (unsigned i = 0; i != MaskNumElts; ++i) { int Idx = Mask[i]; if (Idx < 0) MappedOps.push_back(Idx); - else if (Idx < SrcNumElts) + else if (Idx < (int)SrcNumElts) MappedOps.push_back(Idx - StartIdx[0]); else MappedOps.push_back(Idx - SrcNumElts - StartIdx[1] + MaskNumElts); @@ -2607,12 +2594,12 @@ void SelectionDAGLowering::visitShuffleVector(User &I) { MVT EltVT = VT.getVectorElementType(); MVT PtrVT = TLI.getPointerTy(); SmallVector Ops; - for (int i = 0; i != MaskNumElts; ++i) { + for (unsigned i = 0; i != MaskNumElts; ++i) { if (Mask[i] < 0) { Ops.push_back(DAG.getUNDEF(EltVT)); } else { int Idx = Mask[i]; - if (Idx < SrcNumElts) + if (Idx < (int)SrcNumElts) Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, getCurDebugLoc(), EltVT, Src1, DAG.getConstant(Idx, PtrVT))); else diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 956b69eaf3c..b2ed3b86172 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -2154,7 +2154,7 @@ static bool isUndefOrEqual(int Val, int CmpVal) { /// isPSHUFDMask - Return true if the node specifies a shuffle of elements that /// is suitable for input to PSHUFD or PSHUFW. That is, it doesn't reference /// the second operand. -static bool isPSHUFDMask(SmallVectorImpl &Mask, MVT VT) { +static bool isPSHUFDMask(const SmallVectorImpl &Mask, MVT VT) { if (VT == MVT::v4f32 || VT == MVT::v4i32 || VT == MVT::v4i16) return (Mask[0] < 4 && Mask[1] < 4 && Mask[2] < 4 && Mask[3] < 4); if (VT == MVT::v2f64 || VT == MVT::v2i64) @@ -2170,7 +2170,7 @@ bool X86::isPSHUFDMask(ShuffleVectorSDNode *N) { /// isPSHUFHWMask - Return true if the node specifies a shuffle of elements that /// is suitable for input to PSHUFHW. -static bool isPSHUFHWMask(SmallVectorImpl &Mask, MVT VT) { +static bool isPSHUFHWMask(const SmallVectorImpl &Mask, MVT VT) { if (VT != MVT::v8i16) return false; @@ -2195,7 +2195,7 @@ bool X86::isPSHUFHWMask(ShuffleVectorSDNode *N) { /// isPSHUFLWMask - Return true if the node specifies a shuffle of elements that /// is suitable for input to PSHUFLW. -static bool isPSHUFLWMask(SmallVectorImpl &Mask, MVT VT) { +static bool isPSHUFLWMask(const SmallVectorImpl &Mask, MVT VT) { if (VT != MVT::v8i16) return false; @@ -2220,7 +2220,7 @@ bool X86::isPSHUFLWMask(ShuffleVectorSDNode *N) { /// isSHUFPMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to SHUFP*. -static bool isSHUFPMask(SmallVectorImpl &Mask, MVT VT) { +static bool isSHUFPMask(const SmallVectorImpl &Mask, MVT VT) { int NumElems = VT.getVectorNumElements(); if (NumElems != 2 && NumElems != 4) return false; @@ -2246,7 +2246,7 @@ bool X86::isSHUFPMask(ShuffleVectorSDNode *N) { /// the reverse of what x86 shuffles want. x86 shuffles requires the lower /// half elements to come from vector 1 (which would equal the dest.) and /// the upper half to come from vector 2. -static bool isCommutedSHUFPMask(SmallVectorImpl &Mask, MVT VT) { +static bool isCommutedSHUFPMask(const SmallVectorImpl &Mask, MVT VT) { int NumElems = VT.getVectorNumElements(); if (NumElems != 2 && NumElems != 4) @@ -2337,7 +2337,7 @@ bool X86::isMOVHLPS_v_undef_Mask(ShuffleVectorSDNode *N) { /// isUNPCKLMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to UNPCKL. -static bool isUNPCKLMask(SmallVectorImpl &Mask, MVT VT, +static bool isUNPCKLMask(const SmallVectorImpl &Mask, MVT VT, bool V2IsSplat = false) { int NumElts = VT.getVectorNumElements(); if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16) @@ -2367,7 +2367,7 @@ bool X86::isUNPCKLMask(ShuffleVectorSDNode *N, bool V2IsSplat) { /// isUNPCKHMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to UNPCKH. -static bool isUNPCKHMask(SmallVectorImpl &Mask, MVT VT, +static bool isUNPCKHMask(const SmallVectorImpl &Mask, MVT VT, bool V2IsSplat = false) { int NumElts = VT.getVectorNumElements(); if (NumElts != 2 && NumElts != 4 && NumElts != 8 && NumElts != 16) @@ -2398,7 +2398,7 @@ bool X86::isUNPCKHMask(ShuffleVectorSDNode *N, bool V2IsSplat) { /// isUNPCKL_v_undef_Mask - Special case of isUNPCKLMask for canonical form /// of vector_shuffle v, v, <0, 4, 1, 5>, i.e. vector_shuffle v, undef, /// <0, 0, 1, 1> -static bool isUNPCKL_v_undef_Mask(SmallVectorImpl &Mask, MVT VT) { +static bool isUNPCKL_v_undef_Mask(const SmallVectorImpl &Mask, MVT VT) { int NumElems = VT.getVectorNumElements(); if (NumElems != 2 && NumElems != 4 && NumElems != 8 && NumElems != 16) return false; @@ -2423,7 +2423,7 @@ bool X86::isUNPCKL_v_undef_Mask(ShuffleVectorSDNode *N) { /// isUNPCKH_v_undef_Mask - Special case of isUNPCKHMask for canonical form /// of vector_shuffle v, v, <2, 6, 3, 7>, i.e. vector_shuffle v, undef, /// <2, 2, 3, 3> -static bool isUNPCKH_v_undef_Mask(SmallVectorImpl &Mask, MVT VT) { +static bool isUNPCKH_v_undef_Mask(const SmallVectorImpl &Mask, MVT VT) { int NumElems = VT.getVectorNumElements(); if (NumElems != 2 && NumElems != 4 && NumElems != 8 && NumElems != 16) return false; @@ -2448,7 +2448,7 @@ bool X86::isUNPCKH_v_undef_Mask(ShuffleVectorSDNode *N) { /// isMOVLMask - Return true if the specified VECTOR_SHUFFLE operand /// specifies a shuffle of elements that is suitable for input to MOVSS, /// MOVSD, and MOVD, i.e. setting the lowest element. -static bool isMOVLMask(SmallVectorImpl &Mask, MVT VT) { +static bool isMOVLMask(const SmallVectorImpl &Mask, MVT VT) { int NumElts = VT.getVectorNumElements(); if (NumElts != 2 && NumElts != 4) return false; @@ -2472,7 +2472,7 @@ bool X86::isMOVLMask(ShuffleVectorSDNode *N) { /// isCommutedMOVL - Returns true if the shuffle mask is except the reverse /// of what x86 movss want. X86 movs requires the lowest element to be lowest /// element of vector 2 and the other elements to come from vector 1 in order. -static bool isCommutedMOVLMask(SmallVectorImpl &Mask, MVT VT, +static bool isCommutedMOVLMask(const SmallVectorImpl &Mask, MVT VT, bool V2IsSplat = false, bool V2IsUndef = false) { int NumOps = VT.getVectorNumElements(); if (NumOps != 2 && NumOps != 4 && NumOps != 8 && NumOps != 16) @@ -2619,14 +2619,14 @@ unsigned X86::getShufflePSHUFLWImmediate(SDNode *N) { static SDValue CommuteVectorShuffle(ShuffleVectorSDNode *SVOp, SelectionDAG &DAG) { MVT VT = SVOp->getValueType(0); - int NumElems = VT.getVectorNumElements(); + unsigned NumElems = VT.getVectorNumElements(); SmallVector MaskVec; - for (int i = 0; i != NumElems; ++i) { + for (unsigned i = 0; i != NumElems; ++i) { int idx = SVOp->getMaskElt(i); if (idx < 0) MaskVec.push_back(idx); - else if (idx < NumElems) + else if (idx < (int)NumElems) MaskVec.push_back(idx + NumElems); else MaskVec.push_back(idx - NumElems); @@ -2638,12 +2638,12 @@ static SDValue CommuteVectorShuffle(ShuffleVectorSDNode *SVOp, /// CommuteVectorShuffleMask - Change values in a shuffle permute mask assuming /// the two vector operands have swapped position. static void CommuteVectorShuffleMask(SmallVectorImpl &Mask, MVT VT) { - int NumElems = VT.getVectorNumElements(); - for (int i = 0; i != NumElems; ++i) { + unsigned NumElems = VT.getVectorNumElements(); + for (unsigned i = 0; i != NumElems; ++i) { int idx = Mask[i]; if (idx < 0) continue; - else if (idx < NumElems) + else if (idx < (int)NumElems) Mask[i] = idx + NumElems; else Mask[i] = idx - NumElems; @@ -2694,14 +2694,14 @@ static bool ShouldXformToMOVLP(SDNode *V1, SDNode *V2, if (ISD::isNON_EXTLoad(V2)) return false; - int NumElems = Op->getValueType(0).getVectorNumElements(); + unsigned NumElems = Op->getValueType(0).getVectorNumElements(); if (NumElems != 2 && NumElems != 4) return false; - for (int i = 0, e = NumElems/2; i != e; ++i) + for (unsigned i = 0, e = NumElems/2; i != e; ++i) if (!isUndefOrEqual(Op->getMaskElt(i), i)) return false; - for (int i = NumElems/2; i != NumElems; ++i) + for (unsigned i = NumElems/2; i != NumElems; ++i) if (!isUndefOrEqual(Op->getMaskElt(i), i+NumElems)) return false; return true; @@ -2731,14 +2731,14 @@ static inline bool isZeroNode(SDValue Elt) { /// isZeroShuffle - Returns true if N is a VECTOR_SHUFFLE that can be resolved /// to an zero vector. -/// FIXME: move to dag combiner? +/// FIXME: move to dag combiner / method on ShuffleVectorSDNode static bool isZeroShuffle(ShuffleVectorSDNode *N) { SDValue V1 = N->getOperand(0); SDValue V2 = N->getOperand(1); - int NumElems = N->getValueType(0).getVectorNumElements(); - for (int i = 0; i != NumElems; ++i) { + unsigned NumElems = N->getValueType(0).getVectorNumElements(); + for (unsigned i = 0; i != NumElems; ++i) { int Idx = N->getMaskElt(i); - if (Idx >= NumElems) { + if (Idx >= (int)NumElems) { unsigned Opc = V2.getOpcode(); if (Opc == ISD::UNDEF || ISD::isBuildVectorAllZeros(V2.getNode())) continue; @@ -2798,14 +2798,14 @@ static SDValue getOnesVector(MVT VT, SelectionDAG &DAG, DebugLoc dl) { /// that point to V2 points to its first element. static SDValue NormalizeMask(ShuffleVectorSDNode *SVOp, SelectionDAG &DAG) { MVT VT = SVOp->getValueType(0); - int NumElems = VT.getVectorNumElements(); + unsigned NumElems = VT.getVectorNumElements(); bool Changed = false; SmallVector MaskVec; SVOp->getMask(MaskVec); - for (int i = 0; i != NumElems; ++i) { - if (MaskVec[i] > NumElems) { + for (unsigned i = 0; i != NumElems; ++i) { + if (MaskVec[i] > (int)NumElems) { MaskVec[i] = NumElems; Changed = true; } @@ -6917,7 +6917,8 @@ bool X86TargetLowering::isZExtFree(MVT VT1, MVT VT2) const { /// By default, if a target supports the VECTOR_SHUFFLE node, all mask values /// are assumed to be legal. bool -X86TargetLowering::isShuffleMaskLegal(SmallVectorImpl &M, MVT VT) const { +X86TargetLowering::isShuffleMaskLegal(const SmallVectorImpl &M, + MVT VT) const { // Only do shuffles on 128-bit vector types for now. if (VT.getSizeInBits() == 64) return false; @@ -6937,7 +6938,7 @@ X86TargetLowering::isShuffleMaskLegal(SmallVectorImpl &M, MVT VT) const { } bool -X86TargetLowering::isVectorClearMaskLegal(SmallVectorImpl &Mask, +X86TargetLowering::isVectorClearMaskLegal(const SmallVectorImpl &Mask, MVT VT) const { unsigned NumElts = VT.getVectorNumElements(); // FIXME: This collection of masks seems suspect. diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index 5832702ea48..a68a6fa1963 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -470,13 +470,15 @@ namespace llvm { /// support *some* VECTOR_SHUFFLE operations, those with specific masks. /// By default, if a target supports the VECTOR_SHUFFLE node, all mask /// values are assumed to be legal. - virtual bool isShuffleMaskLegal(SmallVectorImpl &Mask, MVT VT) const; + virtual bool isShuffleMaskLegal(const SmallVectorImpl &Mask, + MVT VT) const; /// isVectorClearMaskLegal - Similar to isShuffleMaskLegal. This is /// used by Targets can use this to indicate if there is a suitable /// VECTOR_SHUFFLE that can be used to replace a VAND with a constant /// pool entry. - virtual bool isVectorClearMaskLegal(SmallVectorImpl &M, MVT VT) const; + virtual bool isVectorClearMaskLegal(const SmallVectorImpl &Mask, + MVT VT) const; /// ShouldShrinkFPConstant - If true, then instruction selection should /// seek to shrink the FP constant of the specified type to a smaller type