From: Evan Cheng Date: Mon, 17 Apr 2006 20:43:08 +0000 (+0000) Subject: Implement v8i16, v16i8 splat using unpckl + pshufd. X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=c575ca22eaf8a656f3fa2c3f0f75264c4c4fcd21;p=oota-llvm.git Implement v8i16, v16i8 splat using unpckl + pshufd. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@27768 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 5d6db65be29..22fd0a92a89 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -1759,13 +1759,9 @@ bool X86::isMOVSLDUPMask(SDNode *N) { /// isSplatMask - Return true if the specified VECTOR_SHUFFLE operand specifies /// a splat of a single element. -bool X86::isSplatMask(SDNode *N) { +static bool isSplatMask(SDNode *N) { assert(N->getOpcode() == ISD::BUILD_VECTOR); - // We can only splat 64-bit, and 32-bit quantities. - if (N->getNumOperands() != 4 && N->getNumOperands() != 2) - return false; - // This is a splat operation if each element of the permute is the same, and // if the value doesn't reference the second vector. SDOperand Elt = N->getOperand(0); @@ -1781,6 +1777,17 @@ bool X86::isSplatMask(SDNode *N) { return cast(Elt)->getValue() < N->getNumOperands(); } +/// isSplatMask - Return true if the specified VECTOR_SHUFFLE operand specifies +/// a splat of a single element and it's a 2 or 4 element mask. +bool X86::isSplatMask(SDNode *N) { + assert(N->getOpcode() == ISD::BUILD_VECTOR); + + // We can only splat 64-bit, and 32-bit quantities. + if (N->getNumOperands() != 4 && N->getNumOperands() != 2) + return false; + return ::isSplatMask(N); +} + /// getShuffleSHUFImmediate - Return the appropriate immediate to shuffle /// the specified isShuffleMask VECTOR_SHUFFLE mask with PSHUF* and SHUFP* /// instructions. @@ -1947,6 +1954,43 @@ static bool isLowerFromV2UpperFromV1(SDOperand Op) { return true; } +/// getUnpacklMask - Returns a vector_shuffle mask for an unpackl operation +/// of specified width. +static SDOperand getUnpacklMask(unsigned NumElems, SelectionDAG &DAG) { + MVT::ValueType MaskVT = MVT::getIntVectorWithNumElements(NumElems); + MVT::ValueType BaseVT = MVT::getVectorBaseType(MaskVT); + std::vector MaskVec; + for (unsigned i = 0, e = NumElems/2; i != e; ++i) { + MaskVec.push_back(DAG.getConstant(i, BaseVT)); + MaskVec.push_back(DAG.getConstant(i + NumElems, BaseVT)); + } + return DAG.getNode(ISD::BUILD_VECTOR, MaskVT, MaskVec); +} + +/// PromoteSplat - Promote a splat of v8i16 or v16i8 to v4i32. +/// +static SDOperand PromoteSplat(SDOperand Op, SelectionDAG &DAG) { + SDOperand V1 = Op.getOperand(0); + SDOperand PermMask = Op.getOperand(2); + MVT::ValueType VT = Op.getValueType(); + unsigned NumElems = PermMask.getNumOperands(); + PermMask = getUnpacklMask(NumElems, DAG); + while (NumElems != 4) { + V1 = DAG.getNode(ISD::VECTOR_SHUFFLE, VT, V1, V1, PermMask); + NumElems >>= 1; + } + V1 = DAG.getNode(ISD::BIT_CONVERT, MVT::v4i32, V1); + + MVT::ValueType MaskVT = MVT::getIntVectorWithNumElements(4); + SDOperand Zero = DAG.getConstant(0, MVT::getVectorBaseType(MaskVT)); + std::vector ZeroVec(4, Zero); + SDOperand SplatMask = DAG.getNode(ISD::BUILD_VECTOR, MaskVT, ZeroVec); + SDOperand Shuffle = DAG.getNode(ISD::VECTOR_SHUFFLE, MVT::v4i32, V1, + DAG.getNode(ISD::UNDEF, MVT::v4i32), + SplatMask); + return DAG.getNode(ISD::BIT_CONVERT, VT, Shuffle); +} + /// LowerOperation - Provide custom lowering hooks for some operations. /// SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { @@ -2753,8 +2797,11 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { MVT::ValueType VT = Op.getValueType(); unsigned NumElems = PermMask.getNumOperands(); - if (X86::isSplatMask(PermMask.Val)) - return Op; + if (isSplatMask(PermMask.Val)) { + if (NumElems <= 4) return Op; + // Promote it to a v4i32 splat. + return PromoteSplat(Op, DAG); + } // Normalize the node to match x86 shuffle ops if needed if (V2.getOpcode() != ISD::UNDEF) { @@ -2877,14 +2924,7 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { // : unpcklps 1, 3 ==> Y: // Step 2: unpcklps X, Y ==> <3, 2, 1, 0> MVT::ValueType VT = Op.getValueType(); - MVT::ValueType MaskVT = MVT::getIntVectorWithNumElements(NumElems); - MVT::ValueType BaseVT = MVT::getVectorBaseType(MaskVT); - std::vector MaskVec; - for (unsigned i = 0, e = NumElems/2; i != e; ++i) { - MaskVec.push_back(DAG.getConstant(i, BaseVT)); - MaskVec.push_back(DAG.getConstant(i + NumElems, BaseVT)); - } - SDOperand PermMask = DAG.getNode(ISD::BUILD_VECTOR, MaskVT, MaskVec); + SDOperand PermMask = getUnpacklMask(NumElems, DAG); std::vector V(NumElems); for (unsigned i = 0; i < NumElems; ++i) V[i] = DAG.getNode(ISD::SCALAR_TO_VECTOR, VT, Op.getOperand(i)); @@ -3208,7 +3248,7 @@ X86TargetLowering::isShuffleMaskLegal(SDOperand Mask, MVT::ValueType VT) const { // Only do shuffles on 128-bit vector types for now. if (MVT::getSizeInBits(VT) == 64) return false; return (Mask.Val->getNumOperands() == 2 || - X86::isSplatMask(Mask.Val) || + isSplatMask(Mask.Val) || X86::isMOVSMask(Mask.Val) || X86::isMOVSHDUPMask(Mask.Val) || X86::isMOVSLDUPMask(Mask.Val) ||