aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp12
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeTypes.h11
-rw-r--r--lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp43
-rw-r--r--test/CodeGen/X86/insertelement-legalize.ll10
4 files changed, 67 insertions, 9 deletions
diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
index db45e44da9..8e864050ed 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
@@ -359,8 +359,10 @@ SDValue DAGTypeLegalizer::PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N) {
if (TLI.isBigEndian())
std::swap(Lo, Hi);
+ // Signed extend to the promoted type.
SDValue Odd = DAG.getNode(ISD::TRUNCATE, MVT::i1, OldIdx);
- return DAG.getNode(ISD::SELECT, NewVT, Odd, Hi, Lo);
+ SDValue Res = DAG.getNode(ISD::SELECT, NewVT, Odd, Hi, Lo);
+ return DAG.getNode(ISD::ANY_EXTEND, TLI.getTypeToTransformTo(OldVT), Res);
}
SDValue DAGTypeLegalizer::PromoteIntRes_FP_TO_XINT(SDNode *N) {
@@ -1938,9 +1940,11 @@ bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) {
assert(0 && "Do not know how to expand this operator's operand!");
abort();
- case ISD::BUILD_VECTOR: Res = ExpandOp_BUILD_VECTOR(N); break;
- case ISD::BIT_CONVERT: Res = ExpandOp_BIT_CONVERT(N); break;
- case ISD::EXTRACT_ELEMENT: Res = ExpandOp_EXTRACT_ELEMENT(N); break;
+ case ISD::BUILD_VECTOR: Res = ExpandOp_BUILD_VECTOR(N); break;
+ case ISD::BIT_CONVERT: Res = ExpandOp_BIT_CONVERT(N); break;
+ case ISD::EXTRACT_ELEMENT: Res = ExpandOp_EXTRACT_ELEMENT(N); break;
+ case ISD::INSERT_VECTOR_ELT: Res = ExpandOp_INSERT_VECTOR_ELT(N); break;
+ case ISD::SCALAR_TO_VECTOR: Res = ExpandOp_SCALAR_TO_VECTOR(N); break;
case ISD::BR_CC: Res = ExpandIntOp_BR_CC(N); break;
case ISD::SELECT_CC: Res = ExpandIntOp_SELECT_CC(N); break;
diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/lib/CodeGen/SelectionDAG/LegalizeTypes.h
index 31bf1d1cb6..36c89adebc 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeTypes.h
+++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.h
@@ -613,11 +613,12 @@ private:
void ExpandRes_VAARG (SDNode *N, SDValue &Lo, SDValue &Hi);
// Generic Operand Expansion.
- SDValue ExpandOp_BIT_CONVERT (SDNode *N);
- SDValue ExpandOp_BUILD_VECTOR (SDNode *N);
- SDValue ExpandOp_EXTRACT_ELEMENT(SDNode *N);
- SDValue ExpandOp_NormalStore (SDNode *N, unsigned OpNo);
-
+ SDValue ExpandOp_BIT_CONVERT (SDNode *N);
+ SDValue ExpandOp_BUILD_VECTOR (SDNode *N);
+ SDValue ExpandOp_EXTRACT_ELEMENT (SDNode *N);
+ SDValue ExpandOp_INSERT_VECTOR_ELT(SDNode *N);
+ SDValue ExpandOp_SCALAR_TO_VECTOR (SDNode *N);
+ SDValue ExpandOp_NormalStore (SDNode *N, unsigned OpNo);
};
} // end namespace llvm.
diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp
index 21a69f578f..91fd589db9 100644
--- a/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp
+++ b/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp
@@ -280,6 +280,49 @@ SDValue DAGTypeLegalizer::ExpandOp_EXTRACT_ELEMENT(SDNode *N) {
return cast<ConstantSDNode>(N->getOperand(1))->getZExtValue() ? Hi : Lo;
}
+SDValue DAGTypeLegalizer::ExpandOp_INSERT_VECTOR_ELT(SDNode *N) {
+ // The vector type is legal but the element type needs expansion.
+ MVT VecVT = N->getValueType(0);
+ unsigned NumElts = VecVT.getVectorNumElements();
+
+ SDValue Val = N->getOperand(1);
+ MVT OldEVT = Val.getValueType();
+ MVT NewEVT = TLI.getTypeToTransformTo(OldEVT);
+
+ assert(OldEVT == VecVT.getVectorElementType() &&
+ "Inserted element type doesn't match vector element type!");
+
+ // Bitconvert to a vector of twice the length with elements of the expanded
+ // type, insert the expanded vector elements, and then convert back.
+ MVT NewVecVT = MVT::getVectorVT(NewEVT, NumElts*2);
+ SDValue NewVec = DAG.getNode(ISD::BIT_CONVERT, NewVecVT, N->getOperand(0));
+
+ SDValue Lo, Hi;
+ GetExpandedOp(Val, Lo, Hi);
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+
+ SDValue Idx = N->getOperand(2);
+ Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, Idx);
+ NewVec = DAG.getNode(ISD::INSERT_VECTOR_ELT, NewVecVT, NewVec, Lo, Idx);
+ Idx = DAG.getNode(ISD::ADD,Idx.getValueType(), Idx, DAG.getIntPtrConstant(1));
+ NewVec = DAG.getNode(ISD::INSERT_VECTOR_ELT, NewVecVT, NewVec, Hi, Idx);
+
+ // Convert the new vector to the old vector type.
+ return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec);
+}
+
+SDValue DAGTypeLegalizer::ExpandOp_SCALAR_TO_VECTOR(SDNode *N) {
+ MVT VT = N->getValueType(0);
+ unsigned NumElts = VT.getVectorNumElements();
+ SmallVector<SDValue, 16> Ops(NumElts);
+ Ops[0] = N->getOperand(0);
+ SDValue UndefVal = DAG.getNode(ISD::UNDEF, Ops[0].getValueType());
+ for (unsigned i = 1; i < NumElts; ++i)
+ Ops[i] = UndefVal;
+ return DAG.getNode(ISD::BUILD_VECTOR, VT, &Ops[0], NumElts);
+}
+
SDValue DAGTypeLegalizer::ExpandOp_NormalStore(SDNode *N, unsigned OpNo) {
assert(ISD::isNormalStore(N) && "This routine only for normal stores!");
assert(OpNo == 1 && "Can only expand the stored value so far");
diff --git a/test/CodeGen/X86/insertelement-legalize.ll b/test/CodeGen/X86/insertelement-legalize.ll
new file mode 100644
index 0000000000..95e17b40bc
--- /dev/null
+++ b/test/CodeGen/X86/insertelement-legalize.ll
@@ -0,0 +1,10 @@
+; RUN: llvm-as < %s | llc -march=x86 -disable-mmx
+
+; Test to check that we properly legalize an insert vector element
+define void @test(<2 x i64> %val, <2 x i64>* %dst, i64 %x) nounwind {
+entry:
+ %tmp4 = insertelement <2 x i64> %val, i64 %x, i32 0 ; <<2 x i64>> [#uses=1]
+ %add = add <2 x i64> %tmp4, %val ; <<2 x i64>> [#uses=1]
+ store <2 x i64> %add, <2 x i64>* %dst
+ ret void
+}