From 14fd63cae875b8e41c70f4408b2185abf82d1d60 Mon Sep 17 00:00:00 2001 From: Duncan Sands Date: Sun, 24 Feb 2008 07:36:03 +0000 Subject: [PATCH] Add support to LegalizeTypes for building legal vectors out of illegal elements (BUILD_VECTOR). Uses and beefs up BUILD_PAIR, though it didn't really have to. Like most of LegalizeTypes, does not support soft-float. This cures all "make check" vector building failures. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@47537 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/LegalizeTypes.h | 4 ++ .../SelectionDAG/LegalizeTypesExpand.cpp | 33 +++++++++ .../SelectionDAG/LegalizeTypesPromote.cpp | 67 ++++++++++++++++++- 3 files changed, 103 insertions(+), 1 deletion(-) diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/lib/CodeGen/SelectionDAG/LegalizeTypes.h index 3ebc2110587..047c0582d47 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -159,6 +159,7 @@ private: // Result Promotion. void PromoteResult(SDNode *N, unsigned ResNo); + SDOperand PromoteResult_BUILD_PAIR(SDNode *N); SDOperand PromoteResult_Constant(SDNode *N); SDOperand PromoteResult_CTLZ(SDNode *N); SDOperand PromoteResult_CTPOP(SDNode *N); @@ -182,8 +183,10 @@ private: // Operand Promotion. bool PromoteOperand(SDNode *N, unsigned OperandNo); SDOperand PromoteOperand_ANY_EXTEND(SDNode *N); + SDOperand PromoteOperand_BUILD_PAIR(SDNode *N); SDOperand PromoteOperand_BR_CC(SDNode *N, unsigned OpNo); SDOperand PromoteOperand_BRCOND(SDNode *N, unsigned OpNo); + SDOperand PromoteOperand_BUILD_VECTOR(SDNode *N); SDOperand PromoteOperand_FP_EXTEND(SDNode *N); SDOperand PromoteOperand_FP_ROUND(SDNode *N); SDOperand PromoteOperand_INT_TO_FP(SDNode *N); @@ -240,6 +243,7 @@ private: bool ExpandOperand(SDNode *N, unsigned OperandNo); SDOperand ExpandOperand_BIT_CONVERT(SDNode *N); SDOperand ExpandOperand_BR_CC(SDNode *N); + SDOperand ExpandOperand_BUILD_VECTOR(SDNode *N); SDOperand ExpandOperand_EXTRACT_ELEMENT(SDNode *N); SDOperand ExpandOperand_SETCC(SDNode *N); SDOperand ExpandOperand_SINT_TO_FP(SDOperand Source, MVT::ValueType DestTy); diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp index 58beefa440a..f8bed687625 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp @@ -865,6 +865,8 @@ bool DAGTypeLegalizer::ExpandOperand(SDNode *N, unsigned OpNo) { case ISD::MEMSET: case ISD::MEMCPY: case ISD::MEMMOVE: Res = HandleMemIntrinsic(N); break; + + case ISD::BUILD_VECTOR: Res = ExpandOperand_BUILD_VECTOR(N); break; } } @@ -1224,3 +1226,34 @@ SDOperand DAGTypeLegalizer::ExpandOperand_STORE(StoreSDNode *N, unsigned OpNo) { } } +SDOperand DAGTypeLegalizer::ExpandOperand_BUILD_VECTOR(SDNode *N) { + // The vector type is legal but the element type needs expansion. + MVT::ValueType VecVT = N->getValueType(0); + unsigned NumElts = MVT::getVectorNumElements(VecVT); + MVT::ValueType OldVT = N->getOperand(0).getValueType(); + MVT::ValueType NewVT = TLI.getTypeToTransformTo(OldVT); + + assert(MVT::getSizeInBits(OldVT) == 2 * MVT::getSizeInBits(NewVT) && + "Do not know how to expand this operand!"); + + // Build a vector of twice the length out of the expanded elements. + // For example <2 x i64> -> <4 x i32>. + std::vector NewElts; + NewElts.reserve(NumElts*2); + + for (unsigned i = 0; i < NumElts; ++i) { + SDOperand Lo, Hi; + GetExpandedOp(N->getOperand(i), Lo, Hi); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + NewElts.push_back(Lo); + NewElts.push_back(Hi); + } + + SDOperand NewVec = DAG.getNode(ISD::BUILD_VECTOR, + MVT::getVectorType(NewVT, NewElts.size()), + &NewElts[0], NewElts.size()); + + // Convert the new vector to the old vector type. + return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec); +} diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp b/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp index 870501c9a7c..5e94d7bbb97 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp @@ -49,6 +49,7 @@ void DAGTypeLegalizer::PromoteResult(SDNode *N, unsigned ResNo) { case ISD::FP_TO_UINT: Result = PromoteResult_FP_TO_XINT(N); break; case ISD::SETCC: Result = PromoteResult_SETCC(N); break; case ISD::LOAD: Result = PromoteResult_LOAD(cast(N)); break; + case ISD::BUILD_PAIR: Result = PromoteResult_BUILD_PAIR(N); break; case ISD::AND: case ISD::OR: @@ -200,6 +201,19 @@ SDOperand DAGTypeLegalizer::PromoteResult_LOAD(LoadSDNode *N) { return Res; } +SDOperand DAGTypeLegalizer::PromoteResult_BUILD_PAIR(SDNode *N) { + // The pair element type may be legal, or may not promote to the same type as + // the result, for example i16 = BUILD_PAIR (i8, i8) when i8 is legal but i16 + // is not. Handle all cases. + MVT::ValueType LVT = N->getOperand(0).getValueType(); + MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + SDOperand Lo = DAG.getNode(ISD::ZERO_EXTEND, NVT, N->getOperand(0)); + SDOperand Hi = DAG.getNode(ISD::ANY_EXTEND, NVT, N->getOperand(1)); + Hi = DAG.getNode(ISD::SHL, NVT, Hi, DAG.getConstant(MVT::getSizeInBits(LVT), + TLI.getShiftAmountTy())); + return DAG.getNode(ISD::OR, NVT, Lo, Hi); +} + SDOperand DAGTypeLegalizer::PromoteResult_SimpleIntBinOp(SDNode *N) { // The input may have strange things in the top bits of the registers, but // these operations don't care. They may have weird bits going out, but @@ -329,7 +343,8 @@ bool DAGTypeLegalizer::PromoteOperand(SDNode *N, unsigned OpNo) { case ISD::FP_ROUND: Res = PromoteOperand_FP_ROUND(N); break; case ISD::SINT_TO_FP: case ISD::UINT_TO_FP: Res = PromoteOperand_INT_TO_FP(N); break; - + case ISD::BUILD_PAIR: Res = PromoteOperand_BUILD_PAIR(N); break; + case ISD::SELECT: Res = PromoteOperand_SELECT(N, OpNo); break; case ISD::BRCOND: Res = PromoteOperand_BRCOND(N, OpNo); break; case ISD::BR_CC: Res = PromoteOperand_BR_CC(N, OpNo); break; @@ -341,6 +356,8 @@ bool DAGTypeLegalizer::PromoteOperand(SDNode *N, unsigned OpNo) { case ISD::MEMCPY: case ISD::MEMMOVE: Res = HandleMemIntrinsic(N); break; + case ISD::BUILD_VECTOR: Res = PromoteOperand_BUILD_VECTOR(N); break; + case ISD::RET: Res = PromoteOperand_RET(N, OpNo); break; } @@ -409,6 +426,20 @@ SDOperand DAGTypeLegalizer::PromoteOperand_INT_TO_FP(SDNode *N) { return DAG.UpdateNodeOperands(SDOperand(N, 0), In); } +SDOperand DAGTypeLegalizer::PromoteOperand_BUILD_PAIR(SDNode *N) { + // Since the result type is legal, the operands must promote to it. + MVT::ValueType OVT = N->getOperand(0).getValueType(); + SDOperand Lo = GetPromotedOp(N->getOperand(0)); + SDOperand Hi = GetPromotedOp(N->getOperand(1)); + assert(Lo.getValueType() == N->getValueType(0) && "Operand over promoted?"); + + Lo = DAG.getZeroExtendInReg(Lo, OVT); + Hi = DAG.getNode(ISD::SHL, N->getValueType(0), Hi, + DAG.getConstant(MVT::getSizeInBits(OVT), + TLI.getShiftAmountTy())); + return DAG.getNode(ISD::OR, N->getValueType(0), Lo, Hi); +} + SDOperand DAGTypeLegalizer::PromoteOperand_SELECT(SDNode *N, unsigned OpNo) { assert(OpNo == 0 && "Only know how to promote condition"); SDOperand Cond = GetPromotedOp(N->getOperand(0)); // Promote the condition. @@ -527,6 +558,40 @@ SDOperand DAGTypeLegalizer::PromoteOperand_STORE(StoreSDNode *N, unsigned OpNo){ isVolatile, Alignment); } +SDOperand DAGTypeLegalizer::PromoteOperand_BUILD_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::ValueType VecVT = N->getValueType(0); + unsigned NumElts = MVT::getVectorNumElements(VecVT); + assert(!(NumElts & 1) && "Legal vector of one illegal element?"); + + // Build a vector of half the length out of elements of twice the bitwidth. + // For example <4 x i16> -> <2 x i32>. + MVT::ValueType OldVT = N->getOperand(0).getValueType(); + MVT::ValueType NewVT = MVT::getIntegerType(2 * MVT::getSizeInBits(OldVT)); + assert(!MVT::isExtendedVT(OldVT) && !MVT::isExtendedVT(NewVT)); + + std::vector NewElts; + NewElts.reserve(NumElts/2); + + for (unsigned i = 0; i < NumElts; i += 2) { + // Combine two successive elements into one promoted element. + SDOperand Lo = N->getOperand(i); + SDOperand Hi = N->getOperand(i+1); + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + NewElts.push_back(DAG.getNode(ISD::BUILD_PAIR, NewVT, Lo, Hi)); + } + + SDOperand NewVec = DAG.getNode(ISD::BUILD_VECTOR, + MVT::getVectorType(NewVT, NewElts.size()), + &NewElts[0], NewElts.size()); + + // Convert the new vector to the old vector type. + return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec); +} + 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!");