From b10b5ac8d9da43ca2db61401a20af6b676c98438 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Sat, 18 Apr 2009 20:16:54 +0000 Subject: [PATCH] Don't try to make BUILD_VECTOR operands have the same type as the vector element type: allow them to be of a wider integer type than the element type all the way through the system, and not just as far as LegalizeDAG. This should be safe because it used to be this way (the old type legalizer would produce such nodes), so backends should be able to handle it. In fact only targets which have legal vector types with an illegal promoted element type will ever see this (eg: <4 x i16> on ppc). This fixes a regression with the new type legalizer (vec_splat.ll). Also, treat SCALAR_TO_VECTOR the same as BUILD_VECTOR. After all, it is just a special case of BUILD_VECTOR. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@69467 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/SelectionDAGNodes.h | 5 +- lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 11 +++- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 50 ++++--------------- .../SelectionDAG/LegalizeIntegerTypes.cpp | 22 ++------ .../SelectionDAG/LegalizeTypesGeneric.cpp | 2 + .../SelectionDAG/LegalizeVectorTypes.cpp | 8 ++- lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 5 +- test/CodeGen/PowerPC/vec_splat.ll | 2 +- 8 files changed, 40 insertions(+), 65 deletions(-) diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 3ae26fdd247..56706689fd6 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -328,7 +328,10 @@ namespace ISD { /// SCALAR_TO_VECTOR(VAL) - This represents the operation of loading a /// scalar value into element 0 of the resultant vector type. The top - /// elements 1 to N-1 of the N-element vector are undefined. + /// elements 1 to N-1 of the N-element vector are undefined. The type + /// of the operand must match the vector element type, except when they + /// are integer types. In this case the operand is allowed to be wider + /// than the vector element type, and is implicitly truncated to it. SCALAR_TO_VECTOR, // MULHU/MULHS - Multiply high - Multiply two integers of type iN, producing diff --git a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp index dd4fda1e842..d1ef0815c81 100644 --- a/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -5110,8 +5110,15 @@ SDValue DAGCombiner::visitEXTRACT_VECTOR_ELT(SDNode *N) { // (vextract (scalar_to_vector val, 0) -> val SDValue InVec = N->getOperand(0); - if (InVec.getOpcode() == ISD::SCALAR_TO_VECTOR) - return InVec.getOperand(0); + if (InVec.getOpcode() == ISD::SCALAR_TO_VECTOR) { + // If the operand is wider than the vector element type then it is implicitly + // truncated. Make that explicit here. + MVT EltVT = InVec.getValueType().getVectorElementType(); + SDValue InOp = InVec.getOperand(0); + if (InOp.getValueType() != EltVT) + return DAG.getNode(ISD::TRUNCATE, InVec.getDebugLoc(), EltVT, InOp); + return InOp; + } // Perform only after legalization to ensure build_vector / vector_shuffle // optimizations have already been done. diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index 5932aebf5ca..5ea1ce34307 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -1643,9 +1643,11 @@ SDValue SelectionDAGLegalize::LegalizeOp(SDValue Op) { // then a shuffle that inserts it into the right position in the vector. if (ConstantSDNode *InsertPos = dyn_cast(Tmp3)) { // SCALAR_TO_VECTOR requires that the type of the value being inserted - // match the element type of the vector being created. - if (Tmp2.getValueType() == - Op.getValueType().getVectorElementType()) { + // match the element type of the vector being created, except for + // integers in which case the inserted value can be over width. + MVT EltVT = Op.getValueType().getVectorElementType(); + if (Tmp2.getValueType() == EltVT || + (EltVT.isInteger() && Tmp2.getValueType().bitsGE(EltVT))) { SDValue ScVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, Tmp1.getValueType(), Tmp2); @@ -5463,9 +5465,10 @@ SDValue SelectionDAGLegalize::ExpandSCALAR_TO_VECTOR(SDNode *Node) { FrameIndexSDNode *StackPtrFI = cast(StackPtr); int SPFI = StackPtrFI->getIndex(); - SDValue Ch = DAG.getStore(DAG.getEntryNode(), dl, Node->getOperand(0), - StackPtr, - PseudoSourceValue::getFixedStack(SPFI), 0); + SDValue Ch = DAG.getTruncStore(DAG.getEntryNode(), dl, Node->getOperand(0), + StackPtr, + PseudoSourceValue::getFixedStack(SPFI), 0, + Node->getValueType(0).getVectorElementType()); return DAG.getLoad(Node->getValueType(0), dl, Ch, StackPtr, PseudoSourceValue::getFixedStack(SPFI), 0); } @@ -5481,41 +5484,6 @@ SDValue SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) { MVT OpVT = SplatValue.getValueType(); MVT EltVT = VT.getVectorElementType(); - // Check if the BUILD_VECTOR operands were promoted to legalize their types. - if (OpVT != EltVT) { - // Now that the DAG combiner and target-specific lowering have had a - // chance to optimize/recognize the BUILD_VECTOR with promoted operands, - // transform it so the operand types match the vector. Build a vector of - // half the length out of elements of twice the bitwidth. - // For example <4 x i16> -> <2 x i32>. - MVT NewVT = MVT::getIntegerVT(2 * EltVT.getSizeInBits()); - assert(OpVT.isSimple() && NewVT.isSimple()); - SmallVector NewElts; - - for (unsigned i = 0; i < NumElems; i += 2) { - // Combine two successive elements into one promoted element. - SDValue Lo = Node->getOperand(i); - SDValue Hi = Node->getOperand(i+1); - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - Lo = DAG.getZeroExtendInReg(Lo, dl, EltVT); - Hi = DAG.getNode(ISD::SHL, dl, OpVT, Hi, - DAG.getConstant(EltVT.getSizeInBits(), - TLI.getPointerTy())); - NewElts.push_back(DAG.getNode(ISD::OR, dl, OpVT, Lo, Hi)); - } - - SDValue NewVec = DAG.getNode(ISD::BUILD_VECTOR, dl, - MVT::getVectorVT(NewVT, NewElts.size()), - &NewElts[0], NewElts.size()); - - // Recurse - NewVec = ExpandBUILD_VECTOR(NewVec.getNode()); - - // Convert the new vector to the old vector type. - return DAG.getNode(ISD::BIT_CONVERT, dl, VT, NewVec); - } - // If the only non-undef value is the low element, turn this into a // SCALAR_TO_VECTOR node. If this is { X, X, X, X }, determine X. bool isOnlyLowElement = true; diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index 115c9f8924f..2dfe0e3b7de 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -863,24 +863,10 @@ SDValue DAGTypeLegalizer::PromoteIntOp_MEMBARRIER(SDNode *N) { } SDValue DAGTypeLegalizer::PromoteIntOp_SCALAR_TO_VECTOR(SDNode *N) { - // The vector type is legal but the element type is not. This implies - // that the vector is a power-of-two in length and that the element - // type does not have a strange size (eg: it is not i1). - MVT VecVT = N->getValueType(0); - unsigned NumElts = VecVT.getVectorNumElements(); - assert(!(NumElts & 1) && "Legal vector of one illegal element?"); - DebugLoc dl = N->getDebugLoc(); - - MVT OldVT = N->getOperand(0).getValueType(); - MVT NewVT = MVT::getIntegerVT(2 * OldVT.getSizeInBits()); - assert(OldVT.isSimple() && NewVT.isSimple()); - - SDValue ExtVal = DAG.getNode(ISD::ANY_EXTEND, dl, NewVT, N->getOperand(0)); - SDValue NewVec = DAG.getNode(ISD::SCALAR_TO_VECTOR, dl, - MVT::getVectorVT(NewVT, NumElts/2), ExtVal); - - // Convert the new vector to the old vector type. - return DAG.getNode(ISD::BIT_CONVERT, dl, VecVT, NewVec); + // Integer SCALAR_TO_VECTOR operands are implicitly truncated, so just promote + // the operand in place. + return DAG.UpdateNodeOperands(SDValue(N, 0), + GetPromotedInteger(N->getOperand(0))); } SDValue DAGTypeLegalizer::PromoteIntOp_SELECT(SDNode *N, unsigned OpNo) { diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp index f1d1f5b077e..7826270a8f8 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp @@ -347,6 +347,8 @@ SDValue DAGTypeLegalizer::ExpandOp_INSERT_VECTOR_ELT(SDNode *N) { SDValue DAGTypeLegalizer::ExpandOp_SCALAR_TO_VECTOR(SDNode *N) { DebugLoc dl = N->getDebugLoc(); MVT VT = N->getValueType(0); + assert(VT.getVectorElementType() == N->getOperand(0).getValueType() && + "SCALAR_TO_VECTOR operand type doesn't match vector element type!"); unsigned NumElts = VT.getVectorNumElements(); SmallVector Ops(NumElts); Ops[0] = N->getOperand(0); diff --git a/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp index 935f4209129..eec328f52ff 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp @@ -183,7 +183,13 @@ SDValue DAGTypeLegalizer::ScalarizeVecRes_UnaryOp(SDNode *N) { } SDValue DAGTypeLegalizer::ScalarizeVecRes_SCALAR_TO_VECTOR(SDNode *N) { - return N->getOperand(0); + // If the operand is wider than the vector element type then it is implicitly + // truncated. Make that explicit here. + MVT EltVT = N->getValueType(0).getVectorElementType(); + SDValue InOp = N->getOperand(0); + if (InOp.getValueType() != EltVT) + return DAG.getNode(ISD::TRUNCATE, N->getDebugLoc(), EltVT, InOp); + return InOp; } SDValue DAGTypeLegalizer::ScalarizeVecRes_SELECT(SDNode *N) { diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index 4b8591eb856..0b2ef855fd6 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -2302,7 +2302,10 @@ SDValue SelectionDAG::getNode(unsigned Opcode, DebugLoc DL, break; case ISD::SCALAR_TO_VECTOR: assert(VT.isVector() && !Operand.getValueType().isVector() && - VT.getVectorElementType() == Operand.getValueType() && + (VT.getVectorElementType() == Operand.getValueType() || + (VT.getVectorElementType().isInteger() && + Operand.getValueType().isInteger() && + VT.getVectorElementType().bitsLE(Operand.getValueType()))) && "Illegal SCALAR_TO_VECTOR node!"); if (OpOpcode == ISD::UNDEF) return getUNDEF(VT); diff --git a/test/CodeGen/PowerPC/vec_splat.ll b/test/CodeGen/PowerPC/vec_splat.ll index bc860cbf024..a6311370003 100644 --- a/test/CodeGen/PowerPC/vec_splat.ll +++ b/test/CodeGen/PowerPC/vec_splat.ll @@ -1,7 +1,7 @@ ; Test that vectors are scalarized/lowered correctly. ; RUN: llvm-as < %s | llc -march=ppc32 -mcpu=g3 | \ ; RUN: grep stfs | count 4 -; RUN: llvm-as < %s | llc -march=ppc32 -mcpu=g5 -o %t -f -disable-legalize-types +; RUN: llvm-as < %s | llc -march=ppc32 -mcpu=g5 -o %t -f ; RUN: grep vspltw %t | count 2 ; RUN: grep vsplti %t | count 3 ; RUN: grep vsplth %t | count 1