aboutsummaryrefslogtreecommitdiff
path: root/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp
diff options
context:
space:
mode:
authorDuncan Sands <baldrick@free.fr>2008-02-27 13:34:40 +0000
committerDuncan Sands <baldrick@free.fr>2008-02-27 13:34:40 +0000
commit077f9b20d0e8659d00a09046a63e28edf0665ffe (patch)
tree19536af56a9bc4a2f026f4b006c016d51fbff242 /lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp
parent0a4c3782c8d558a9859a90ae8e2d5d0efa057e41 (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.cpp69
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));
}