From 9db817fd0ce0949d0358f5cedfd9ca5a9f1726dd Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Fri, 9 Sep 2011 21:04:06 +0000 Subject: 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 --- lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 55 ++++++++++++++---------- lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 5 ++- test/CodeGen/ARM/2011-09-09-OddVectorDivision.ll | 23 ++++++++++ 3 files changed, 59 insertions(+), 24 deletions(-) create mode 100644 test/CodeGen/ARM/2011-09-09-OddVectorDivision.ll 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(EltNo)) { - unsigned Elt = cast(EltNo)->getZExtValue(); - SmallVector 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(EltNo)) { - EVT EltVT = VT.getVectorElementType(); + // Check that we know which element is being inserted + if (!isa(EltNo)) + return SDValue(); + unsigned Elt = cast(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 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 Ops(NElts, DAG.getUNDEF(EltVT)); + Ops.append(NElts, DAG.getUNDEF(InVal.getValueType())); + } else { + return SDValue(); + } - unsigned Elt = cast(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 +} -- cgit v1.2.3