diff options
author | Duncan Sands <baldrick@free.fr> | 2008-02-27 13:34:40 +0000 |
---|---|---|
committer | Duncan Sands <baldrick@free.fr> | 2008-02-27 13:34:40 +0000 |
commit | 077f9b20d0e8659d00a09046a63e28edf0665ffe (patch) | |
tree | 19536af56a9bc4a2f026f4b006c016d51fbff242 /lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp | |
parent | 0a4c3782c8d558a9859a90ae8e2d5d0efa057e41 (diff) |
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)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47672 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp')
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp | 69 |
1 files changed, 66 insertions, 3 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp index 0852d7623f..3d9bbc2c36 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp @@ -86,6 +86,10 @@ void DAGTypeLegalizer::ExpandResult(SDNode *N, unsigned ResNo) { 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 @@ void DAGTypeLegalizer::ExpandResult_ANY_EXTEND(SDNode *N, // 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 @@ void DAGTypeLegalizer::ExpandResult_ZERO_EXTEND(SDNode *N, // 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 @@ void DAGTypeLegalizer::ExpandResult_SIGN_EXTEND(SDNode *N, // 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_TRUNCATE(SDNode *N, 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 @@ void DAGTypeLegalizer::ExpandResult_CTTZ(SDNode *N, 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_TRUNCATE(SDNode *N) { } 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)); } |