[llvm-commits] [llvm] r47672 - in /llvm/trunk/lib/CodeGen/SelectionDAG: LegalizeTypes.cpp LegalizeTypes.h LegalizeTypesExpand.cpp LegalizeTypesPromote.cpp LegalizeTypesScalarize.cpp LegalizeTypesSplit.cpp
Evan Cheng
evan.cheng at apple.com
Wed Feb 27 12:42:00 PST 2008
Very nice! Thanks.
Evan
On Feb 27, 2008, at 5:34 AM, Duncan Sands wrote:
> Author: baldrick
> Date: Wed Feb 27 07:34:40 2008
> New Revision: 47672
>
> URL: http://llvm.org/viewvc/llvm-project?rev=47672&view=rev
> Log:
> LegalizeTypes support for EXTRACT_VECTOR_ELT. The
> approach taken is different to that in LegalizeDAG
> when it is a question of expanding or promoting the
> result type: for example, if extracting an i64 from
> a <2 x i64>, when i64 needs expanding, it bitcasts
> the vector to <4 x i32>, extracts the appropriate
> two i32's, and uses those for the Lo and Hi parts.
> Likewise, when extracting an i16 from a <4 x i16>,
> and i16 needs promoting, it bitcasts the vector to
> <2 x i32>, extracts the appropriate i32, twiddles
> the bits if necessary, and uses that as the promoted
> value. This puts more pressure on bitcast legalization,
> and I've added the appropriate cases. They needed to
> be added anyway since users can generate such bitcasts
> too if they want to. Also, when considering various
> cases (Legal, Promote, Expand, Scalarize, Split) it is
> a pain that expand can correspond to Expand, Scalarize
> or Split, so I've changed the LegalizeTypes enum so it
> lists those different cases - now Expand only means
> splitting a scalar in two.
> The code produced is the same as by LegalizeDAG for
> all relevant testcases, except for
> 2007-10-31-extractelement-i64.ll, where the code seems
> to have improved (see below; can an expert please tell
> me if it is better or not).
> Before < vs after >.
>
> < subl $92, %esp
> < movaps %xmm0, 64(%esp)
> < movaps %xmm0, (%esp)
> < movl 4(%esp), %eax
> < movl %eax, 28(%esp)
> < movl (%esp), %eax
> < movl %eax, 24(%esp)
> < movq 24(%esp), %mm0
> < movq %mm0, 56(%esp)
> ---
>> subl $44, %esp
>> movaps %xmm0, 16(%esp)
>> pshufd $1, %xmm0, %xmm1
>> movd %xmm1, 4(%esp)
>> movd %xmm0, (%esp)
>> movq (%esp), %mm0
>> movq %mm0, 8(%esp)
>
> < subl $92, %esp
> < movaps %xmm0, 64(%esp)
> < movaps %xmm0, (%esp)
> < movl 12(%esp), %eax
> < movl %eax, 28(%esp)
> < movl 8(%esp), %eax
> < movl %eax, 24(%esp)
> < movq 24(%esp), %mm0
> < movq %mm0, 56(%esp)
> ---
>> subl $44, %esp
>> movaps %xmm0, 16(%esp)
>> pshufd $3, %xmm0, %xmm1
>> movd %xmm1, 4(%esp)
>> movhlps %xmm0, %xmm0
>> movd %xmm0, (%esp)
>> movq (%esp), %mm0
>> movq %mm0, 8(%esp)
>
> < subl $92, %esp
> < movaps %xmm0, 64(%esp)
> ---
>> subl $44, %esp
>
> < movl 16(%esp), %eax
> < movl %eax, 48(%esp)
> < movl 20(%esp), %eax
> < movl %eax, 52(%esp)
> < movaps %xmm0, (%esp)
> < movl 4(%esp), %eax
> < movl %eax, 60(%esp)
> < movl (%esp), %eax
> < movl %eax, 56(%esp)
> ---
>> pshufd $1, %xmm0, %xmm1
>> movd %xmm1, 4(%esp)
>> movd %xmm0, (%esp)
>> movd %xmm1, 12(%esp)
>> movd %xmm0, 8(%esp)
>
> < subl $92, %esp
> < movaps %xmm0, 64(%esp)
> ---
>> subl $44, %esp
>
> < movl 24(%esp), %eax
> < movl %eax, 48(%esp)
> < movl 28(%esp), %eax
> < movl %eax, 52(%esp)
> < movaps %xmm0, (%esp)
> < movl 12(%esp), %eax
> < movl %eax, 60(%esp)
> < movl 8(%esp), %eax
> < movl %eax, 56(%esp)
> ---
>> pshufd $3, %xmm0, %xmm1
>> movd %xmm1, 4(%esp)
>> movhlps %xmm0, %xmm0
>> movd %xmm0, (%esp)
>> movd %xmm1, 12(%esp)
>> movd %xmm0, 8(%esp)
>
> Modified:
> llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
> llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h
> llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp
> llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp
> llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp
> llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp
>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp?rev=47672&r1=47671&r2=47672&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp Wed Feb 27
> 07:34:40 2008
> @@ -68,25 +68,26 @@
> unsigned NumResults = N->getNumValues();
> do {
> MVT::ValueType ResultVT = N->getValueType(i);
> - LegalizeAction Action = getTypeAction(ResultVT);
> - if (Action == Promote) {
> + switch (getTypeAction(ResultVT)) {
> + default:
> + assert(false && "Unknown action!");
> + case Legal:
> + break;
> + case Promote:
> PromoteResult(N, i);
> goto NodeDone;
> - } else if (Action == Expand) {
> - // Expand can mean 1) split integer in half 2) scalarize
> single-element
> - // vector 3) split vector in half.
> - if (!MVT::isVector(ResultVT))
> - ExpandResult(N, i);
> - else if (MVT::getVectorNumElements(ResultVT) == 1)
> - ScalarizeResult(N, i); // Scalarize the single-
> element vector.
> - else
> - SplitResult(N, i); // Split the vector in half.
> + case Expand:
> + ExpandResult(N, i);
> + goto NodeDone;
> + case Scalarize:
> + ScalarizeResult(N, i);
> + goto NodeDone;
> + case Split:
> + SplitResult(N, i);
> goto NodeDone;
> - } else {
> - assert(Action == Legal && "Unknown action!");
> }
> } while (++i < NumResults);
> -
> +
> // Scan the operand list for the node, handling any nodes with
> operands that
> // are illegal.
> {
> @@ -94,25 +95,25 @@
> bool NeedsRevisit = false;
> for (i = 0; i != NumOperands; ++i) {
> MVT::ValueType OpVT = N->getOperand(i).getValueType();
> - LegalizeAction Action = getTypeAction(OpVT);
> - if (Action == Promote) {
> + switch (getTypeAction(OpVT)) {
> + default:
> + assert(false && "Unknown action!");
> + case Legal:
> + continue;
> + case Promote:
> NeedsRevisit = PromoteOperand(N, i);
> break;
> - } else if (Action == Expand) {
> - // Expand can mean 1) split integer in half 2) scalarize
> single-element
> - // vector 3) split vector in half.
> - if (!MVT::isVector(OpVT)) {
> - NeedsRevisit = ExpandOperand(N, i);
> - } else if (MVT::getVectorNumElements(OpVT) == 1) {
> - // Scalarize the single-element vector.
> - NeedsRevisit = ScalarizeOperand(N, i);
> - } else {
> - NeedsRevisit = SplitOperand(N, i); // Split the vector in
> half.
> - }
> + case Expand:
> + NeedsRevisit = ExpandOperand(N, i);
> + break;
> + case Scalarize:
> + NeedsRevisit = ScalarizeOperand(N, i);
> + break;
> + case Split:
> + NeedsRevisit = SplitOperand(N, i);
> break;
> - } else {
> - assert(Action == Legal && "Unknown action!");
> }
> + break;
> }
>
> // If the node needs revisiting, don't add all users to the
> worklist etc.
> @@ -432,7 +433,7 @@
> case Legal: break;
> case Promote: Op2 = GetPromotedOp(Op2); break;
> }
> -
> +
> // The length could have any action required.
> SDOperand Length = N->getOperand(3);
> switch (getTypeAction(Length.getValueType())) {
> @@ -444,21 +445,21 @@
> GetExpandedOp(Length, Length, Dummy);
> break;
> }
> -
> +
> SDOperand Align = N->getOperand(4);
> switch (getTypeAction(Align.getValueType())) {
> default: assert(0 && "Unknown action for memop operand");
> case Legal: break;
> case Promote: Align = GetPromotedZExtOp(Align); break;
> }
> -
> +
> SDOperand AlwaysInline = N->getOperand(5);
> switch (getTypeAction(AlwaysInline.getValueType())) {
> default: assert(0 && "Unknown action for memop operand");
> case Legal: break;
> case Promote: AlwaysInline = GetPromotedZExtOp(AlwaysInline); break;
> }
> -
> +
> SDOperand Ops[] = { Chain, Ptr, Op2, Length, Align, AlwaysInline };
> return DAG.UpdateNodeOperands(SDOperand(N, 0), Ops, 6);
> }
>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h?rev=47672&r1=47671&r2=47672&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h Wed Feb 27
> 07:34:40 2008
> @@ -61,27 +61,46 @@
> enum LegalizeAction {
> Legal, // The target natively supports this type.
> Promote, // This type should be executed in a larger type.
> - Expand // This type should be split into two types of half
> the size.
> + Expand, // This type should be split into two types of half
> the size.
> + Scalarize, // Replace this one-element vector type with its
> element type.
> + Split // This vector type should be split into smaller
> vectors.
> };
> -
> +
> /// ValueTypeActions - This is a bitvector that contains two bits
> for each
> /// simple value type, where the two bits correspond to the
> LegalizeAction
> - /// enum. This can be queried with "getTypeAction(VT)".
> + /// enum from TargetLowering. This can be queried with
> "getTypeAction(VT)".
> TargetLowering::ValueTypeActionImpl ValueTypeActions;
>
> /// getTypeAction - Return how we should legalize values of this
> type, either
> - /// it is already legal or we need to expand it into multiple
> registers of
> - /// smaller integer type, or we need to promote it to a larger
> type.
> + /// it is already legal, or we need to promote it to a larger
> integer type, or
> + /// we need to expand it into multiple registers of a smaller
> integer type, or
> + /// we need to scalarize a one-element vector type into the
> element type, or
> + /// we need to split a vector type into smaller vector types.
> LegalizeAction getTypeAction(MVT::ValueType VT) const {
> - return (LegalizeAction)ValueTypeActions.getTypeAction(VT);
> + switch (ValueTypeActions.getTypeAction(VT)) {
> + default:
> + assert(false && "Unknown legalize action!");
> + case TargetLowering::Legal:
> + return Legal;
> + case TargetLowering::Promote:
> + return Promote;
> + case TargetLowering::Expand:
> + // Expand can mean 1) split integer in half 2) scalarize
> single-element
> + // vector 3) split vector in two.
> + if (!MVT::isVector(VT))
> + return Expand;
> + else if (MVT::getVectorNumElements(VT) == 1)
> + return Scalarize;
> + else
> + return Split;
> + }
> }
> -
> +
> /// isTypeLegal - Return true if this type is legal on this target.
> - ///
> bool isTypeLegal(MVT::ValueType VT) const {
> - return getTypeAction(VT) == Legal;
> + return ValueTypeActions.getTypeAction(VT) ==
> TargetLowering::Legal;
> }
> -
> +
> /// PromotedNodes - For nodes that are below legal width, this map
> indicates
> /// what promoted value to use.
> DenseMap<SDOperand, SDOperand> PromotedNodes;
> @@ -159,11 +178,13 @@
>
> // Result Promotion.
> void PromoteResult(SDNode *N, unsigned ResNo);
> + SDOperand PromoteResult_BIT_CONVERT(SDNode *N);
> SDOperand PromoteResult_BUILD_PAIR(SDNode *N);
> SDOperand PromoteResult_Constant(SDNode *N);
> SDOperand PromoteResult_CTLZ(SDNode *N);
> SDOperand PromoteResult_CTPOP(SDNode *N);
> SDOperand PromoteResult_CTTZ(SDNode *N);
> + SDOperand PromoteResult_EXTRACT_VECTOR_ELT(SDNode *N);
> SDOperand PromoteResult_FP_ROUND(SDNode *N);
> SDOperand PromoteResult_FP_TO_XINT(SDNode *N);
> SDOperand PromoteResult_INT_EXTEND(SDNode *N);
> @@ -219,6 +240,7 @@
> void ExpandResult_CTLZ (SDNode *N, SDOperand &Lo, SDOperand
> &Hi);
> void ExpandResult_CTPOP (SDNode *N, SDOperand &Lo, SDOperand
> &Hi);
> void ExpandResult_CTTZ (SDNode *N, SDOperand &Lo, SDOperand
> &Hi);
> + void ExpandResult_EXTRACT_VECTOR_ELT(SDNode *N, SDOperand &Lo,
> SDOperand &Hi);
> void ExpandResult_LOAD (LoadSDNode *N, SDOperand &Lo,
> SDOperand &Hi);
> void ExpandResult_MERGE_VALUES(SDNode *N, SDOperand &Lo, SDOperand
> &Hi);
> void ExpandResult_SIGN_EXTEND(SDNode *N, SDOperand &Lo, SDOperand
> &Hi);
> @@ -283,6 +305,7 @@
>
> // Operand Vector Scalarization: <1 x ty> -> ty.
> bool ScalarizeOperand(SDNode *N, unsigned OpNo);
> + SDOperand ScalarizeOp_BIT_CONVERT(SDNode *N);
> SDOperand ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N);
> SDOperand ScalarizeOp_STORE(StoreSDNode *N, unsigned OpNo);
>
> @@ -313,7 +336,9 @@
> // Operand Vector Scalarization: <128 x ty> -> 2 x <64 x ty>.
> bool SplitOperand(SDNode *N, unsigned OpNo);
>
> + SDOperand SplitOp_BIT_CONVERT(SDNode *N);
> SDOperand SplitOp_EXTRACT_SUBVECTOR(SDNode *N);
> + SDOperand SplitOp_EXTRACT_VECTOR_ELT(SDNode *N);
> SDOperand SplitOp_RET(SDNode *N, unsigned OpNo);
> SDOperand SplitOp_STORE(StoreSDNode *N, unsigned OpNo);
> SDOperand SplitOp_VECTOR_SHUFFLE(SDNode *N, unsigned OpNo);
>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp?rev=47672&r1=47671&r2=47672&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp
> (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp Wed
> Feb 27 07:34:40 2008
> @@ -86,6 +86,10 @@
> case ISD::CTLZ: ExpandResult_CTLZ(N, Lo, Hi); break;
> case ISD::CTPOP: ExpandResult_CTPOP(N, Lo, Hi); break;
> case ISD::CTTZ: ExpandResult_CTTZ(N, Lo, Hi); break;
> +
> + case ISD::EXTRACT_VECTOR_ELT:
> + ExpandResult_EXTRACT_VECTOR_ELT(N, Lo, Hi);
> + break;
> }
>
> // If Lo/Hi is null, the sub-method took care of registering
> results etc.
> @@ -147,7 +151,7 @@
> // 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.
> assert(getTypeAction(Op.getValueType()) == Promote &&
> - "Don't know how to expand this result!");
> + "Only know how to promote this result!");
> SDOperand Res = GetPromotedOp(Op);
> assert(Res.getValueType() == N->getValueType(0) &&
> "Operand over promoted?");
> @@ -168,7 +172,7 @@
> // 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.
> assert(getTypeAction(Op.getValueType()) == Promote &&
> - "Don't know how to expand this result!");
> + "Only know how to promote this result!");
> SDOperand Res = GetPromotedOp(Op);
> assert(Res.getValueType() == N->getValueType(0) &&
> "Operand over promoted?");
> @@ -195,7 +199,7 @@
> // 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.
> assert(getTypeAction(Op.getValueType()) == Promote &&
> - "Don't know how to expand this result!");
> + "Only know how to promote this result!");
> SDOperand Res = GetPromotedOp(Op);
> assert(Res.getValueType() == N->getValueType(0) &&
> "Operand over promoted?");
> @@ -239,6 +243,8 @@
> void DAGTypeLegalizer::ExpandResult_BIT_CONVERT(SDNode *N,
> SDOperand &Lo,
> SDOperand &Hi) {
> // Lower the bit-convert to a store/load from the stack, then
> expand the load.
> + // TODO: If the operand also needs expansion then this could be
> turned into
> + // conversion of the expanded pieces. But there needs to be a
> testcase first!
> SDOperand Op = CreateStackStoreLoad(N->getOperand(0), N-
> >getValueType(0));
> ExpandResult_LOAD(cast<LoadSDNode>(Op.Val), Lo, Hi);
> }
> @@ -666,6 +672,41 @@
> Hi = DAG.getConstant(0, NVT);
> }
>
> +void DAGTypeLegalizer::ExpandResult_EXTRACT_VECTOR_ELT(SDNode *N,
> + SDOperand &Lo,
> + SDOperand
> &Hi) {
> + SDOperand OldVec = N->getOperand(0);
> + unsigned OldElts =
> MVT::getVectorNumElements(OldVec.getValueType());
> +
> + // Convert to a vector of the expanded element type, for example
> + // <2 x i64> -> <4 x i32>.
> + MVT::ValueType OldVT = N->getValueType(0);
> + MVT::ValueType NewVT = TLI.getTypeToTransformTo(OldVT);
> + assert(MVT::getSizeInBits(OldVT) == 2 * MVT::getSizeInBits(NewVT)
> &&
> + "Do not know how to handle this expansion!");
> +
> + SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT,
> + MVT::getVectorType(NewVT, 2 *
> OldElts),
> + OldVec);
> +
> + // Extract the elements at 2 * Idx and 2 * Idx + 1 from the new
> vector.
> + SDOperand Idx = N->getOperand(1);
> +
> + // Make sure the type of Idx is big enough to hold the new values.
> + if (MVT::getSizeInBits(Idx.getValueType()) < 32)
> + Idx = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Idx);
> +
> + Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, Idx);
> + Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx);
> +
> + Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx,
> + DAG.getConstant(1, Idx.getValueType()));
> + Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx);
> +
> + if (TLI.isBigEndian())
> + std::swap(Lo, Hi);
> +}
> +
> /// ExpandShiftByConstant - N is a shift by a value that needs to be
> expanded,
> /// and the shift amount is a constant 'Amt'. Expand the operation.
> void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt,
> @@ -898,6 +939,28 @@
> }
>
> SDOperand DAGTypeLegalizer::ExpandOperand_BIT_CONVERT(SDNode *N) {
> + if (MVT::isVector(N->getValueType(0))) {
> + // An illegal integer type is being converted to a legal vector
> type.
> + // Make a two element vector out of the expanded parts and
> convert that
> + // instead, but only if the new vector type is legal (otherwise
> there
> + // is no point, and it might create expansion loops). For
> example, on
> + // x86 this turns v1i64 = BIT_CONVERT i64 into v1i64 =
> BIT_CONVERT v2i32.
> + MVT::ValueType OVT = N->getOperand(0).getValueType();
> + MVT::ValueType NVT =
> MVT::getVectorType(TLI.getTypeToTransformTo(OVT), 2);
> +
> + if (isTypeLegal(NVT)) {
> + SDOperand Parts[2];
> + GetExpandedOp(N->getOperand(0), Parts[0], Parts[1]);
> +
> + if (TLI.isBigEndian())
> + std::swap(Parts[0], Parts[1]);
> +
> + SDOperand Vec = DAG.getNode(ISD::BUILD_VECTOR, NVT, Parts, 2);
> + return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Vec);
> + }
> + }
> +
> + // Otherwise, store to a temporary and load out again as the new
> type.
> return CreateStackStoreLoad(N->getOperand(0), N->getValueType(0));
> }
>
>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp?rev=47672&r1=47671&r2=47672&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp
> (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp Wed
> Feb 27 07:34:40 2008
> @@ -50,6 +50,7 @@
> case ISD::SETCC: Result = PromoteResult_SETCC(N); break;
> case ISD::LOAD: Result =
> PromoteResult_LOAD(cast<LoadSDNode>(N)); break;
> case ISD::BUILD_PAIR: Result = PromoteResult_BUILD_PAIR(N); break;
> + case ISD::BIT_CONVERT: Result = PromoteResult_BIT_CONVERT(N);
> break;
>
> case ISD::AND:
> case ISD::OR:
> @@ -74,8 +75,12 @@
> case ISD::CTLZ: Result = PromoteResult_CTLZ(N); break;
> case ISD::CTPOP: Result = PromoteResult_CTPOP(N); break;
> case ISD::CTTZ: Result = PromoteResult_CTTZ(N); break;
> +
> + case ISD::EXTRACT_VECTOR_ELT:
> + Result = PromoteResult_EXTRACT_VECTOR_ELT(N);
> + break;
> }
> -
> +
> // If Result is null, the sub-method took care of registering the
> result.
> if (Result.Val)
> SetPromotedOp(SDOperand(N, ResNo), Result);
> @@ -214,6 +219,65 @@
> return DAG.getNode(ISD::OR, NVT, Lo, Hi);
> }
>
> +SDOperand DAGTypeLegalizer::PromoteResult_BIT_CONVERT(SDNode *N) {
> + SDOperand InOp = N->getOperand(0);
> + MVT::ValueType InVT = InOp.getValueType();
> + MVT::ValueType NInVT = TLI.getTypeToTransformTo(InVT);
> + MVT::ValueType OutVT = TLI.getTypeToTransformTo(N-
> >getValueType(0));
> +
> + switch (getTypeAction(InVT)) {
> + default:
> + assert(false && "Unknown type action!");
> + break;
> + case Legal:
> + break;
> + case Promote:
> + if (MVT::getSizeInBits(OutVT) == MVT::getSizeInBits(NInVT))
> + // The input promotes to the same size. Convert the promoted
> value.
> + return DAG.getNode(ISD::BIT_CONVERT, OutVT,
> GetPromotedOp(InOp));
> + break;
> + case Expand:
> + break;
> + case Scalarize:
> + // Convert the element to an integer and promote it by hand.
> + InOp = DAG.getNode(ISD::BIT_CONVERT,
> + MVT::getIntegerType(MVT::getSizeInBits(InVT)),
> + GetScalarizedOp(InOp));
> + InOp = DAG.getNode(ISD::ANY_EXTEND,
> +
> MVT::getIntegerType(MVT::getSizeInBits(OutVT)), InOp);
> + return DAG.getNode(ISD::BIT_CONVERT, OutVT, InOp);
> + case Split:
> + // For example, i32 = BIT_CONVERT v2i16 on alpha. Convert the
> split
> + // pieces of the input into integers and reassemble in the
> final type.
> + SDOperand Lo, Hi;
> + GetSplitOp(N->getOperand(0), Lo, Hi);
> +
> + unsigned LoBits = MVT::getSizeInBits(Lo.getValueType());
> + Lo = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(LoBits),
> Lo);
> +
> + unsigned HiBits = MVT::getSizeInBits(Hi.getValueType());
> + Hi = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(HiBits),
> Hi);
> +
> + if (TLI.isBigEndian())
> + std::swap(Lo, Hi);
> +
> + MVT::ValueType TargetTy =
> MVT::getIntegerType(MVT::getSizeInBits(OutVT));
> + Hi = DAG.getNode(ISD::ANY_EXTEND, TargetTy, Hi);
> + Hi = DAG.getNode(ISD::SHL, TargetTy, Hi,
> +
> DAG.getConstant(MVT::getSizeInBits(Lo.getValueType()),
> + TLI.getShiftAmountTy()));
> + Lo = DAG.getNode(ISD::ZERO_EXTEND, TargetTy, Lo);
> +
> + return DAG.getNode(ISD::BIT_CONVERT, OutVT,
> + DAG.getNode(ISD::OR, TargetTy, Lo, Hi));
> + }
> +
> + // Otherwise, lower the bit-convert to a store/load from the
> stack, then
> + // promote the load.
> + SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0));
> + return PromoteResult_LOAD(cast<LoadSDNode>(Op.Val));
> +}
> +
> SDOperand DAGTypeLegalizer::PromoteResult_SimpleIntBinOp(SDNode *N) {
> // The input may have strange things in the top bits of the
> registers, but
> // these operations don't care. They may have weird bits going
> out, but
> @@ -315,6 +379,51 @@
> return DAG.getNode(ISD::CTTZ, NVT, Op);
> }
>
> +SDOperand DAGTypeLegalizer::PromoteResult_EXTRACT_VECTOR_ELT(SDNode
> *N) {
> + MVT::ValueType OldVT = N->getValueType(0);
> + SDOperand OldVec = N->getOperand(0);
> + unsigned OldElts =
> MVT::getVectorNumElements(OldVec.getValueType());
> +
> + if (OldElts == 1) {
> + assert(!isTypeLegal(OldVec.getValueType()) &&
> + "Legal one-element vector of a type needing promotion!");
> + // It is tempting to follow GetScalarizedOp by a call to
> GetPromotedOp,
> + // but this would be wrong because the scalarized value may not
> yet have
> + // been processed.
> + return DAG.getNode(ISD::ANY_EXTEND,
> TLI.getTypeToTransformTo(OldVT),
> + GetScalarizedOp(OldVec));
> + }
> +
> + // Convert to a vector half as long with an element type of twice
> the width,
> + // for example <4 x i16> -> <2 x i32>.
> + assert(!(OldElts & 1) && "Odd length vectors not supported!");
> + MVT::ValueType NewVT = MVT::getIntegerType(2 *
> MVT::getSizeInBits(OldVT));
> + assert(!MVT::isExtendedVT(OldVT) && !MVT::isExtendedVT(NewVT));
> +
> + SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT,
> + MVT::getVectorType(NewVT,
> OldElts / 2),
> + OldVec);
> +
> + // Extract the element at OldIdx / 2 from the new vector.
> + SDOperand OldIdx = N->getOperand(1);
> + SDOperand NewIdx = DAG.getNode(ISD::SRL, OldIdx.getValueType(),
> OldIdx,
> + DAG.getConstant(1,
> TLI.getShiftAmountTy()));
> + SDOperand Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT,
> NewVec, NewIdx);
> +
> + // Select the appropriate half of the element: Lo if OldIdx was
> even,
> + // Hi if it was odd.
> + SDOperand Lo = Elt;
> + SDOperand Hi = DAG.getNode(ISD::SRL, NewVT, Elt,
> +
> DAG.getConstant(MVT::getSizeInBits(OldVT),
> +
> TLI.getShiftAmountTy()));
> + if (TLI.isBigEndian())
> + std::swap(Lo, Hi);
> +
> + SDOperand Odd = DAG.getNode(ISD::AND, OldIdx.getValueType(),
> OldIdx,
> + DAG.getConstant(1,
> TLI.getShiftAmountTy()));
> + return DAG.getNode(ISD::SELECT, NewVT, Odd, Hi, Lo);
> +}
> +
> //
> =
> =
> =
> ----------------------------------------------------------------------=
> ==//
> // Operand Promotion
> //
> =
> =
> =
> ----------------------------------------------------------------------=
> ==//
>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/
> LegalizeTypesScalarize.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp?rev=47672&r1=47671&r2=47672&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp
> (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp
> Wed Feb 27 07:34:40 2008
> @@ -176,6 +176,9 @@
> assert(0 && "Do not know how to scalarize this operator's
> operand!");
> abort();
>
> + case ISD::BIT_CONVERT:
> + Res = ScalarizeOp_BIT_CONVERT(N); break;
> +
> case ISD::EXTRACT_VECTOR_ELT:
> Res = ScalarizeOp_EXTRACT_VECTOR_ELT(N); break;
>
> @@ -204,6 +207,13 @@
> return false;
> }
>
> +/// ScalarizeOp_BIT_CONVERT - If the value to convert is a vector
> that needs
> +/// to be scalarized, it must be <1 x ty>. Convert the element
> instead.
> +SDOperand DAGTypeLegalizer::ScalarizeOp_BIT_CONVERT(SDNode *N) {
> + SDOperand Elt = GetScalarizedOp(N->getOperand(0));
> + return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Elt);
> +}
> +
> /// ScalarizeOp_EXTRACT_VECTOR_ELT - If the input is a vector that
> needs to be
> /// scalarized, it must be <1 x ty>, so just return the element,
> ignoring the
> /// index.
>
> Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp?rev=47672&r1=47671&r2=47672&view=diff
>
> =
> =
> =
> =
> =
> =
> =
> =
> ======================================================================
> --- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp
> (original)
> +++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp Wed
> Feb 27 07:34:40 2008
> @@ -172,7 +172,6 @@
> else
> Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, Hi.getValueType(), Hi,
> ScalarOp,
> DAG.getConstant(Index - LoNumElts,
> TLI.getPointerTy()));
> -
> }
>
> void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N,
> @@ -253,22 +252,50 @@
> SDOperand &Lo, SDOperand
> &Hi) {
> // We know the result is a vector. The input may be either a
> vector or a
> // scalar value.
> + MVT::ValueType LoVT, HiVT;
> + GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
> +
> SDOperand InOp = N->getOperand(0);
> - if (MVT::isVector(InOp.getValueType()) &&
> - MVT::getVectorNumElements(InOp.getValueType()) != 1) {
> - // If this is a vector, split the vector and convert each of
> the pieces now.
> - GetSplitOp(InOp, Lo, Hi);
> -
> - MVT::ValueType LoVT, HiVT;
> - GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
> + MVT::ValueType InVT = InOp.getValueType();
> + MVT::ValueType NewInVT = TLI.getTypeToTransformTo(InVT);
>
> + switch (getTypeAction(InVT)) {
> + default:
> + assert(false && "Unknown type action!");
> + case Legal:
> + break;
> + case Promote:
> + break;
> + case Scalarize:
> + // While it is tempting to extract the scalarized operand,
> check whether it
> + // needs expansion, and if so process it in the Expand case
> below, there is
> + // no guarantee that the scalarized operand has been processed
> yet. If it
> + // hasn't then the call to GetExpandedOp will abort. So just
> give up.
> + break;
> + case Expand:
> + // A scalar to vector conversion, where the scalar needs
> expansion.
> + // Check that the vector is being split in two.
> + if (MVT::getSizeInBits(NewInVT) == MVT::getSizeInBits(LoVT)) {
> + // Convert each expanded piece of the scalar now.
> + GetExpandedOp(InOp, Lo, Hi);
> + if (TLI.isBigEndian())
> + std::swap(Lo, Hi);
> + Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo);
> + Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi);
> + return;
> + }
> + break;
> + case Split:
> + // If the input is a vector that needs to be split, convert
> each split
> + // piece of the input now.
> + GetSplitOp(InOp, Lo, Hi);
> Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo);
> Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi);
> return;
> }
> -
> +
> // Lower the bit-convert to a store/load from the stack, then
> split the load.
> - SDOperand Op = CreateStackStoreLoad(N->getOperand(0), N-
> >getValueType(0));
> + SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0));
> SplitRes_LOAD(cast<LoadSDNode>(Op.Val), Lo, Hi);
> }
>
> @@ -340,8 +367,11 @@
> case ISD::STORE: Res = SplitOp_STORE(cast<StoreSDNode>(N),
> OpNo); break;
> case ISD::RET: Res = SplitOp_RET(N, OpNo); break;
>
> - case ISD::EXTRACT_SUBVECTOR: Res =
> SplitOp_EXTRACT_SUBVECTOR(N); break;
> - case ISD::VECTOR_SHUFFLE: Res = SplitOp_VECTOR_SHUFFLE(N,
> OpNo); break;
> + case ISD::BIT_CONVERT: Res = SplitOp_BIT_CONVERT(N); break;
> +
> + case ISD::EXTRACT_VECTOR_ELT: Res =
> SplitOp_EXTRACT_VECTOR_ELT(N); break;
> + case ISD::EXTRACT_SUBVECTOR: Res =
> SplitOp_EXTRACT_SUBVECTOR(N); break;
> + case ISD::VECTOR_SHUFFLE: Res = SplitOp_VECTOR_SHUFFLE(N,
> OpNo); break;
> }
> }
>
> @@ -402,6 +432,72 @@
> return DAG.getNode(ISD::RET, MVT::Other, Chain, Lo, Sign, Hi, Sign);
> }
>
> +SDOperand DAGTypeLegalizer::SplitOp_BIT_CONVERT(SDNode *N) {
> + // For example, i64 = BIT_CONVERT v4i16 on alpha. Typically the
> vector will
> + // end up being split all the way down to individual components.
> Convert the
> + // split pieces into integers and reassemble.
> + SDOperand Lo, Hi;
> + GetSplitOp(N->getOperand(0), Lo, Hi);
> +
> + unsigned LoBits = MVT::getSizeInBits(Lo.getValueType());
> + Lo = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(LoBits),
> Lo);
> +
> + unsigned HiBits = MVT::getSizeInBits(Hi.getValueType());
> + Hi = DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerType(HiBits),
> Hi);
> +
> + if (TLI.isBigEndian())
> + std::swap(Lo, Hi);
> +
> + assert(LoBits == HiBits && "Do not know how to assemble odd sized
> vectors!");
> +
> + return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0),
> + DAG.getNode(ISD::BUILD_PAIR,
> + MVT::getIntegerType(LoBits
> +HiBits), Lo, Hi));
> +}
> +
> +SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_VECTOR_ELT(SDNode *N) {
> + SDOperand Vec = N->getOperand(0);
> + SDOperand Idx = N->getOperand(1);
> + MVT::ValueType VecVT = Vec.getValueType();
> +
> + if (isa<ConstantSDNode>(Idx)) {
> + uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getValue();
> + assert(IdxVal < MVT::getVectorNumElements(VecVT) &&
> + "Invalid vector index!");
> +
> + SDOperand Lo, Hi;
> + GetSplitOp(Vec, Lo, Hi);
> +
> + uint64_t LoElts = MVT::getVectorNumElements(Lo.getValueType());
> +
> + if (IdxVal < LoElts)
> + return DAG.UpdateNodeOperands(SDOperand(N, 0), Lo, Idx);
> + else
> + return DAG.UpdateNodeOperands(SDOperand(N, 0), Hi,
> + DAG.getConstant(IdxVal - LoElts,
> +
> Idx.getValueType()));
> + }
> +
> + // Store the vector to the stack and load back the required
> element.
> + SDOperand StackPtr = DAG.CreateStackTemporary(VecVT);
> + SDOperand Store = DAG.getStore(DAG.getEntryNode(), Vec, StackPtr,
> NULL, 0);
> +
> + // Add the offset to the index.
> + MVT::ValueType EltVT = MVT::getVectorElementType(VecVT);
> + unsigned EltSize = MVT::getSizeInBits(EltVT)/8; // FIXME: should
> be ABI size.
> + Idx = DAG.getNode(ISD::MUL, Idx.getValueType(), Idx,
> + DAG.getConstant(EltSize, Idx.getValueType()));
> +
> + if (MVT::getSizeInBits(Idx.getValueType()) >
> + MVT::getSizeInBits(TLI.getPointerTy()))
> + Idx = DAG.getNode(ISD::TRUNCATE, TLI.getPointerTy(), Idx);
> + else
> + Idx = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(), Idx);
> +
> + StackPtr = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx,
> StackPtr);
> + return DAG.getLoad(EltVT, Store, StackPtr, NULL, 0);
> +}
> +
> SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_SUBVECTOR(SDNode *N) {
> // We know that the extracted result type is legal. For now,
> assume the index
> // is a constant.
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list