diff options
-rw-r--r-- | include/llvm/CodeGen/SelectionDAGNodes.h | 5 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 11 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 50 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp | 22 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeTypesGeneric.cpp | 2 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp | 8 | ||||
-rw-r--r-- | lib/CodeGen/SelectionDAG/SelectionDAG.cpp | 5 | ||||
-rw-r--r-- | 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 3ae26fdd24..56706689fd 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 dd4fda1e84..d1ef0815c8 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 5932aebf5c..5ea1ce3430 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<ConstantSDNode>(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<FrameIndexSDNode>(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<SDValue, 16> 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 115c9f8924..2dfe0e3b7d 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 f1d1f5b077..7826270a8f 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<SDValue, 16> Ops(NumElts); Ops[0] = N->getOperand(0); diff --git a/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp index 935f420912..eec328f52f 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 4b8591eb85..0b2ef855fd 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 bc860cbf02..a631137000 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 |