summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEli Friedman <eli.friedman@gmail.com>2011-09-09 21:04:06 +0000
committerEli Friedman <eli.friedman@gmail.com>2011-09-09 21:04:06 +0000
commit9db817fd0ce0949d0358f5cedfd9ca5a9f1726dd (patch)
treef10649f16d0e014bdae8f391b2b700f420ba1bfc
parent8ddf6531b88937dec35bf2bb3a55245b1af9cbf5 (diff)
downloadllvm-9db817fd0ce0949d0358f5cedfd9ca5a9f1726dd.tar.gz
llvm-9db817fd0ce0949d0358f5cedfd9ca5a9f1726dd.tar.bz2
llvm-9db817fd0ce0949d0358f5cedfd9ca5a9f1726dd.tar.xz
Make the SelectionDAG verify that all the operands of BUILD_VECTOR have the same type. Teach DAGCombiner::visitINSERT_VECTOR_ELT not to make invalid BUILD_VECTORs. Fixes PR10897.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@139407 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/CodeGen/SelectionDAG/DAGCombiner.cpp55
-rw-r--r--lib/CodeGen/SelectionDAG/SelectionDAG.cpp5
-rw-r--r--test/CodeGen/ARM/2011-09-09-OddVectorDivision.ll23
3 files changed, 59 insertions, 24 deletions
diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 6258cb19c3..c47dd0964e 100644
--- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -6770,6 +6770,7 @@ SDValue DAGCombiner::visitINSERT_VECTOR_ELT(SDNode *N) {
SDValue InVec = N->getOperand(0);
SDValue InVal = N->getOperand(1);
SDValue EltNo = N->getOperand(2);
+ DebugLoc dl = N->getDebugLoc();
// If the inserted element is an UNDEF, just use the input vector.
if (InVal.getOpcode() == ISD::UNDEF)
@@ -6781,32 +6782,40 @@ SDValue DAGCombiner::visitINSERT_VECTOR_ELT(SDNode *N) {
if (LegalOperations && !TLI.isOperationLegal(ISD::BUILD_VECTOR, VT))
return SDValue();
- // If the invec is a BUILD_VECTOR and if EltNo is a constant, build a new
- // vector with the inserted element.
- if (InVec.getOpcode() == ISD::BUILD_VECTOR && isa<ConstantSDNode>(EltNo)) {
- unsigned Elt = cast<ConstantSDNode>(EltNo)->getZExtValue();
- SmallVector<SDValue, 8> Ops(InVec.getNode()->op_begin(),
- InVec.getNode()->op_end());
- if (Elt < Ops.size())
- Ops[Elt] = InVal;
- return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(),
- VT, &Ops[0], Ops.size());
- }
- // If the invec is an UNDEF and if EltNo is a constant, create a new
- // BUILD_VECTOR with undef elements and the inserted element.
- if (InVec.getOpcode() == ISD::UNDEF &&
- isa<ConstantSDNode>(EltNo)) {
- EVT EltVT = VT.getVectorElementType();
+ // Check that we know which element is being inserted
+ if (!isa<ConstantSDNode>(EltNo))
+ return SDValue();
+ unsigned Elt = cast<ConstantSDNode>(EltNo)->getZExtValue();
+
+ // Check that the operand is a BUILD_VECTOR (or UNDEF, which can essentially
+ // be converted to a BUILD_VECTOR). Fill in the Ops vector with the
+ // vector elements.
+ SmallVector<SDValue, 8> Ops;
+ if (InVec.getOpcode() == ISD::BUILD_VECTOR) {
+ Ops.append(InVec.getNode()->op_begin(),
+ InVec.getNode()->op_end());
+ } else if (InVec.getOpcode() == ISD::UNDEF) {
unsigned NElts = VT.getVectorNumElements();
- SmallVector<SDValue, 8> Ops(NElts, DAG.getUNDEF(EltVT));
+ Ops.append(NElts, DAG.getUNDEF(InVal.getValueType()));
+ } else {
+ return SDValue();
+ }
- unsigned Elt = cast<ConstantSDNode>(EltNo)->getZExtValue();
- if (Elt < Ops.size())
- Ops[Elt] = InVal;
- return DAG.getNode(ISD::BUILD_VECTOR, N->getDebugLoc(),
- VT, &Ops[0], Ops.size());
+ // Insert the element
+ if (Elt < Ops.size()) {
+ // All the operands of BUILD_VECTOR must have the same type;
+ // we enforce that here.
+ EVT OpVT = Ops[0].getValueType();
+ if (InVal.getValueType() != OpVT)
+ InVal = OpVT.bitsGT(InVal.getValueType()) ?
+ DAG.getNode(ISD::ANY_EXTEND, dl, OpVT, InVal) :
+ DAG.getNode(ISD::TRUNCATE, dl, OpVT, InVal);
+ Ops[Elt] = InVal;
}
- return SDValue();
+
+ // Return the new vector
+ return DAG.getNode(ISD::BUILD_VECTOR, dl,
+ VT, &Ops[0], Ops.size());
}
SDValue DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *N) {
diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
index 19da986fe8..71399cef82 100644
--- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
+++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
@@ -771,11 +771,14 @@ static void VerifyNodeCommon(SDNode *N) {
assert(N->getNumOperands() == N->getValueType(0).getVectorNumElements() &&
"Wrong number of operands!");
EVT EltVT = N->getValueType(0).getVectorElementType();
- for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I)
+ for (SDNode::op_iterator I = N->op_begin(), E = N->op_end(); I != E; ++I) {
assert((I->getValueType() == EltVT ||
(EltVT.isInteger() && I->getValueType().isInteger() &&
EltVT.bitsLE(I->getValueType()))) &&
"Wrong operand type!");
+ assert(I->getValueType() == N->getOperand(0).getValueType() &&
+ "Operands must all have the same type");
+ }
break;
}
}
diff --git a/test/CodeGen/ARM/2011-09-09-OddVectorDivision.ll b/test/CodeGen/ARM/2011-09-09-OddVectorDivision.ll
new file mode 100644
index 0000000000..c4a2e336d3
--- /dev/null
+++ b/test/CodeGen/ARM/2011-09-09-OddVectorDivision.ll
@@ -0,0 +1,23 @@
+; RUN: llc -mtriple=armv7-- %s -mattr=-neon
+
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:64:128-a0:0:64-n32"
+target triple = "armv7-none-linux-gnueabi"
+
+@x1 = common global <3 x i16> zeroinitializer
+@y1 = common global <3 x i16> zeroinitializer
+@z1 = common global <3 x i16> zeroinitializer
+@x2 = common global <4 x i16> zeroinitializer
+@y2 = common global <4 x i16> zeroinitializer
+@z2 = common global <4 x i16> zeroinitializer
+
+define void @f() {
+ %1 = load <3 x i16>* @x1
+ %2 = load <3 x i16>* @y1
+ %3 = sdiv <3 x i16> %1, %2
+ store <3 x i16> %3, <3 x i16>* @z1
+ %4 = load <4 x i16>* @x2
+ %5 = load <4 x i16>* @y2
+ %6 = sdiv <4 x i16> %4, %5
+ store <4 x i16> %6, <4 x i16>* @z2
+ ret void
+}