diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 56645f708eb..c467967b0fc 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -283,7 +283,8 @@ namespace ISD { BUILD_VECTOR, /// INSERT_VECTOR_ELT(VECTOR, VAL, IDX) - Returns VECTOR with the element - /// at IDX replaced with VAL. + /// at IDX replaced with VAL. If the type of VAL is larger than the vector + /// element type then VAL is truncated before replacement. INSERT_VECTOR_ELT, /// EXTRACT_VECTOR_ELT(VECTOR, IDX) - Returns a single element from VECTOR diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/lib/CodeGen/SelectionDAG/LegalizeTypes.h index 1947673dd8c..d480fe707a2 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -190,6 +190,7 @@ private: SDOperand PromoteOperand_FP_EXTEND(SDNode *N); SDOperand PromoteOperand_FP_ROUND(SDNode *N); SDOperand PromoteOperand_INT_TO_FP(SDNode *N); + SDOperand PromoteOperand_INSERT_VECTOR_ELT(SDNode *N, unsigned OpNo); SDOperand PromoteOperand_MEMBARRIER(SDNode *N); SDOperand PromoteOperand_RET(SDNode *N, unsigned OpNo); SDOperand PromoteOperand_SELECT(SDNode *N, unsigned OpNo); @@ -269,15 +270,17 @@ private: // Result Vector Scalarization: <1 x ty> -> ty. void ScalarizeResult(SDNode *N, unsigned OpNo); - SDOperand ScalarizeRes_UNDEF(SDNode *N); - SDOperand ScalarizeRes_LOAD(LoadSDNode *N); SDOperand ScalarizeRes_BinOp(SDNode *N); SDOperand ScalarizeRes_UnaryOp(SDNode *N); - SDOperand ScalarizeRes_FPOWI(SDNode *N); - SDOperand ScalarizeRes_VECTOR_SHUFFLE(SDNode *N); + SDOperand ScalarizeRes_BIT_CONVERT(SDNode *N); + SDOperand ScalarizeRes_FPOWI(SDNode *N); + SDOperand ScalarizeRes_INSERT_VECTOR_ELT(SDNode *N); + SDOperand ScalarizeRes_LOAD(LoadSDNode *N); SDOperand ScalarizeRes_SELECT(SDNode *N); - + SDOperand ScalarizeRes_UNDEF(SDNode *N); + SDOperand ScalarizeRes_VECTOR_SHUFFLE(SDNode *N); + // Operand Vector Scalarization: <1 x ty> -> ty. bool ScalarizeOperand(SDNode *N, unsigned OpNo); SDOperand ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N); diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp index 41501398f2e..c4eb0593805 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp @@ -357,6 +357,9 @@ bool DAGTypeLegalizer::PromoteOperand(SDNode *N, unsigned OpNo) { case ISD::MEMMOVE: Res = HandleMemIntrinsic(N); break; case ISD::BUILD_VECTOR: Res = PromoteOperand_BUILD_VECTOR(N); break; + case ISD::INSERT_VECTOR_ELT: + Res = PromoteOperand_INSERT_VECTOR_ELT(N, OpNo); + break; case ISD::RET: Res = PromoteOperand_RET(N, OpNo); break; @@ -591,6 +594,30 @@ SDOperand DAGTypeLegalizer::PromoteOperand_BUILD_VECTOR(SDNode *N) { return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec); } +SDOperand DAGTypeLegalizer::PromoteOperand_INSERT_VECTOR_ELT(SDNode *N, + unsigned OpNo) { + if (OpNo == 1) { + // Promote the inserted value. This is valid because the type does not + // have to match the vector element type. + + // Check that any extra bits introduced will be truncated away. + assert(MVT::getSizeInBits(N->getOperand(1).getValueType()) >= + MVT::getSizeInBits(MVT::getVectorElementType(N->getValueType(0))) && + "Type of inserted value narrower than vector element type!"); + return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), + GetPromotedOp(N->getOperand(1)), + N->getOperand(2)); + } + + assert(OpNo == 2 && "Different operand and result vector types?"); + + // Promote the index. + SDOperand Idx = N->getOperand(2); + Idx = DAG.getZeroExtendInReg(GetPromotedOp(Idx), Idx.getValueType()); + return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), + N->getOperand(1), Idx); +} + SDOperand DAGTypeLegalizer::PromoteOperand_RET(SDNode *N, unsigned OpNo) { assert(!(OpNo & 1) && "Return values should be legally typed!"); assert((N->getNumOperands() & 1) && "Wrong number of operands!"); diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp index d386feb2607..72c1f484db4 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp @@ -77,7 +77,7 @@ void DAGTypeLegalizer::ScalarizeResult(SDNode *N, unsigned ResNo) { case ISD::FCOS: R = ScalarizeRes_UnaryOp(N); break; case ISD::FPOWI: R = ScalarizeRes_FPOWI(N); break; case ISD::BUILD_VECTOR: R = N->getOperand(0); break; - case ISD::INSERT_VECTOR_ELT: R = N->getOperand(1); break; + case ISD::INSERT_VECTOR_ELT: R = ScalarizeRes_INSERT_VECTOR_ELT(N); break; case ISD::VECTOR_SHUFFLE: R = ScalarizeRes_VECTOR_SHUFFLE(N); break; case ISD::BIT_CONVERT: R = ScalarizeRes_BIT_CONVERT(N); break; case ISD::SELECT: R = ScalarizeRes_SELECT(N); break; @@ -120,6 +120,17 @@ SDOperand DAGTypeLegalizer::ScalarizeRes_FPOWI(SDNode *N) { return DAG.getNode(ISD::FPOWI, Op.getValueType(), Op, N->getOperand(1)); } +SDOperand DAGTypeLegalizer::ScalarizeRes_INSERT_VECTOR_ELT(SDNode *N) { + // The value to insert may have a wider type than the vector element type, + // so be sure to truncate it to the element type if necessary. + SDOperand Op = N->getOperand(1); + MVT::ValueType EltVT = MVT::getVectorElementType(N->getValueType(0)); + if (MVT::getSizeInBits(Op.getValueType()) > MVT::getSizeInBits(EltVT)) + Op = DAG.getNode(ISD::TRUNCATE, EltVT, Op); + assert(Op.getValueType() == EltVT && "Invalid type for inserted value!"); + return Op; +} + SDOperand DAGTypeLegalizer::ScalarizeRes_VECTOR_SHUFFLE(SDNode *N) { // Figure out if the scalar is the LHS or RHS and return it. SDOperand EltNum = N->getOperand(2).getOperand(0);