diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp index 43acb5ba3114..d13fefab430c 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp @@ -464,19 +464,42 @@ SDOperand DAGTypeLegalizer::HandleMemIntrinsic(SDNode *N) { return DAG.UpdateNodeOperands(SDOperand(N, 0), Ops, 6); } -/// SplitOp - Return the lower and upper halves of Op's bits in a value type -/// half the size of Op's. -void DAGTypeLegalizer::SplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) { - unsigned NVTBits = MVT::getSizeInBits(Op.getValueType())/2; - assert(MVT::getSizeInBits(Op.getValueType()) == 2*NVTBits && - "Cannot split odd sized integer type"); - MVT::ValueType NVT = MVT::getIntegerType(NVTBits); - Lo = DAG.getNode(ISD::TRUNCATE, NVT, Op); - Hi = DAG.getNode(ISD::SRL, Op.getValueType(), Op, - DAG.getConstant(NVTBits, TLI.getShiftAmountTy())); - Hi = DAG.getNode(ISD::TRUNCATE, NVT, Hi); +/// JoinIntegers - Build an integer with low bits Lo and high bits Hi. +SDOperand DAGTypeLegalizer::JoinIntegers(SDOperand Lo, SDOperand Hi) { + MVT::ValueType LVT = Lo.getValueType(); + MVT::ValueType HVT = Hi.getValueType(); + MVT::ValueType NVT = MVT::getIntegerType(MVT::getSizeInBits(LVT) + + MVT::getSizeInBits(HVT)); + + Lo = DAG.getNode(ISD::ZERO_EXTEND, NVT, Lo); + Hi = DAG.getNode(ISD::ANY_EXTEND, NVT, Hi); + Hi = DAG.getNode(ISD::SHL, NVT, Hi, DAG.getConstant(MVT::getSizeInBits(LVT), + TLI.getShiftAmountTy())); + return DAG.getNode(ISD::OR, NVT, Lo, Hi); } +/// SplitInteger - Return the lower LoVT bits of Op in Lo and the upper HiVT +/// bits in Hi. +void DAGTypeLegalizer::SplitInteger(SDOperand Op, + MVT::ValueType LoVT, MVT::ValueType HiVT, + SDOperand &Lo, SDOperand &Hi) { + assert(MVT::getSizeInBits(LoVT) + MVT::getSizeInBits(HiVT) == + MVT::getSizeInBits(Op.getValueType()) && "Invalid integer splitting!"); + Lo = DAG.getNode(ISD::TRUNCATE, LoVT, Op); + Hi = DAG.getNode(ISD::SRL, Op.getValueType(), Op, + DAG.getConstant(MVT::getSizeInBits(LoVT), + TLI.getShiftAmountTy())); + Hi = DAG.getNode(ISD::TRUNCATE, HiVT, Hi); +} + +/// SplitInteger - Return the lower and upper halves of Op's bits in a value type +/// half the size of Op's. +void DAGTypeLegalizer::SplitInteger(SDOperand Op, + SDOperand &Lo, SDOperand &Hi) { + MVT::ValueType HalfVT = + MVT::getIntegerType(MVT::getSizeInBits(Op.getValueType())/2); + SplitInteger(Op, HalfVT, HalfVT, Lo, Hi); +} //===----------------------------------------------------------------------===// // Entry Point diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h index 1c20969b9dca..35e72ddeab2a 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -154,7 +154,10 @@ private: // Common routines. SDOperand CreateStackStoreLoad(SDOperand Op, MVT::ValueType DestVT); SDOperand HandleMemIntrinsic(SDNode *N); - void SplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi); + SDOperand JoinIntegers(SDOperand Lo, SDOperand Hi); + void SplitInteger(SDOperand Op, SDOperand &Lo, SDOperand &Hi); + void SplitInteger(SDOperand Op, MVT::ValueType LoVT, MVT::ValueType HiVT, + SDOperand &Lo, SDOperand &Hi); //===--------------------------------------------------------------------===// // Promotion Support: LegalizeTypesPromote.cpp diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp index 9b2280068894..15d25e69280c 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp @@ -157,7 +157,7 @@ void DAGTypeLegalizer::ExpandResult_ANY_EXTEND(SDNode *N, assert(Res.getValueType() == N->getValueType(0) && "Operand over promoted?"); // Split the promoted operand. This will simplify when it is expanded. - SplitOp(Res, Lo, Hi); + SplitInteger(Res, Lo, Hi); } } @@ -178,7 +178,7 @@ void DAGTypeLegalizer::ExpandResult_ZERO_EXTEND(SDNode *N, assert(Res.getValueType() == N->getValueType(0) && "Operand over promoted?"); // Split the promoted operand. This will simplify when it is expanded. - SplitOp(Res, Lo, Hi); + SplitInteger(Res, Lo, Hi); unsigned ExcessBits = MVT::getSizeInBits(Op.getValueType()) - MVT::getSizeInBits(NVT); Hi = DAG.getZeroExtendInReg(Hi, MVT::getIntegerType(ExcessBits)); @@ -205,7 +205,7 @@ void DAGTypeLegalizer::ExpandResult_SIGN_EXTEND(SDNode *N, assert(Res.getValueType() == N->getValueType(0) && "Operand over promoted?"); // Split the promoted operand. This will simplify when it is expanded. - SplitOp(Res, Lo, Hi); + SplitInteger(Res, Lo, Hi); unsigned ExcessBits = MVT::getSizeInBits(Op.getValueType()) - MVT::getSizeInBits(NVT); Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, Hi.getValueType(), Hi, @@ -243,10 +243,47 @@ void DAGTypeLegalizer::ExpandResult_TRUNCATE(SDNode *N, void DAGTypeLegalizer::ExpandResult_BIT_CONVERT(SDNode *N, SDOperand &Lo, SDOperand &Hi) { + MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0)); + SDOperand InOp = N->getOperand(0); + MVT::ValueType InVT = InOp.getValueType(); + + // Handle some special cases efficiently. + switch (getTypeAction(InVT)) { + default: + assert(false && "Unknown type action!"); + case Legal: + case Promote: + break; + case Expand: + // Convert the expanded pieces of the input. + GetExpandedOp(InOp, Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); + return; + case Split: + // Convert the split parts of the input if it was split in two. + GetSplitOp(InOp, Lo, Hi); + if (Lo.getValueType() == Hi.getValueType()) { + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); + return; + } + break; + case Scalarize: + // Convert the element instead. + InOp = DAG.getNode(ISD::BIT_CONVERT, + MVT::getIntegerType(MVT::getSizeInBits(InVT)), + GetScalarizedOp(InOp)); + SplitInteger(InOp, Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); + return; + } + // Lower the bit-convert to a store/load from the stack, then expand the load. - // TODO: If the operand also needs expansion then this could be turned into - // conversion of the expanded pieces. But there needs to be a testcase first! - SDOperand Op = CreateStackStoreLoad(N->getOperand(0), N->getValueType(0)); + SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0)); ExpandResult_LOAD(cast(Op.Val), Lo, Hi); } @@ -694,8 +731,9 @@ void DAGTypeLegalizer::ExpandResult_EXTRACT_VECTOR_ELT(SDNode *N, SDOperand Idx = N->getOperand(1); // Make sure the type of Idx is big enough to hold the new values. - if (MVT::getSizeInBits(Idx.getValueType()) < 32) - Idx = DAG.getNode(ISD::ZERO_EXTEND, MVT::i32, Idx); + if (MVT::getSizeInBits(Idx.getValueType()) < + MVT::getSizeInBits(TLI.getPointerTy())) + Idx = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(), Idx); Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, Idx); Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx); diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp index 2b1a29d77ccc..1a0dfe755da6 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp @@ -209,15 +209,10 @@ SDOperand DAGTypeLegalizer::PromoteResult_LOAD(LoadSDNode *N) { 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); + // the result, for example i14 = BUILD_PAIR (i7, i7). Handle all cases. + return DAG.getNode(ISD::ANY_EXTEND, + TLI.getTypeToTransformTo(N->getValueType(0)), + JoinIntegers(N->getOperand(0), N->getOperand(1))); } SDOperand DAGTypeLegalizer::PromoteResult_BIT_CONVERT(SDNode *N) { @@ -262,15 +257,10 @@ SDOperand DAGTypeLegalizer::PromoteResult_BIT_CONVERT(SDNode *N) { if (TLI.isBigEndian()) std::swap(Lo, Hi); - MVT::ValueType TargetTy = MVT::getIntegerType(MVT::getSizeInBits(OutVT)); - Hi = DAG.getNode(ISD::ANY_EXTEND, TargetTy, Hi); - Hi = DAG.getNode(ISD::SHL, TargetTy, Hi, - DAG.getConstant(MVT::getSizeInBits(Lo.getValueType()), - TLI.getShiftAmountTy())); - Lo = DAG.getNode(ISD::ZERO_EXTEND, TargetTy, Lo); - - return DAG.getNode(ISD::BIT_CONVERT, OutVT, - DAG.getNode(ISD::OR, TargetTy, Lo, Hi)); + InOp = DAG.getNode(ISD::ANY_EXTEND, + MVT::getIntegerType(MVT::getSizeInBits(OutVT)), + JoinIntegers(Lo, Hi)); + return DAG.getNode(ISD::BIT_CONVERT, OutVT, InOp); } // Otherwise, lower the bit-convert to a store/load from the stack, then @@ -693,7 +683,7 @@ SDOperand DAGTypeLegalizer::PromoteOperand_BUILD_VECTOR(SDNode *N) { SDOperand Hi = N->getOperand(i+1); if (TLI.isBigEndian()) std::swap(Lo, Hi); - NewElts.push_back(DAG.getNode(ISD::BUILD_PAIR, NewVT, Lo, Hi)); + NewElts.push_back(JoinIntegers(Lo, Hi)); } SDOperand NewVec = DAG.getNode(ISD::BUILD_VECTOR, diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp index f6fdd2b8a3a1..2e76cebf1618 100644 --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp @@ -45,7 +45,7 @@ static void GetSplitDestVTs(MVT::ValueType InVT, /// legalization, we just know that (at least) one result needs vector /// splitting. void DAGTypeLegalizer::SplitResult(SDNode *N, unsigned ResNo) { - DEBUG(cerr << "Expand node result: "; N->dump(&DAG); cerr << "\n"); + DEBUG(cerr << "Split node result: "; N->dump(&DAG); cerr << "\n"); SDOperand Lo, Hi; #if 0 @@ -257,26 +257,20 @@ void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N, SDOperand InOp = N->getOperand(0); MVT::ValueType InVT = InOp.getValueType(); - MVT::ValueType NewInVT = TLI.getTypeToTransformTo(InVT); + // Handle some special cases efficiently. switch (getTypeAction(InVT)) { default: assert(false && "Unknown type action!"); case Legal: - break; case Promote: - break; case Scalarize: - // While it is tempting to extract the scalarized operand, check whether it - // needs expansion, and if so process it in the Expand case below, there is - // no guarantee that the scalarized operand has been processed yet. If it - // hasn't then the call to GetExpandedOp will abort. So just give up. break; case Expand: // A scalar to vector conversion, where the scalar needs expansion. - // Check that the vector is being split in two. - if (MVT::getSizeInBits(NewInVT) == MVT::getSizeInBits(LoVT)) { - // Convert each expanded piece of the scalar now. + // If the vector is being split in two then we can just convert the + // expanded pieces. + if (LoVT == HiVT) { GetExpandedOp(InOp, Lo, Hi); if (TLI.isBigEndian()) std::swap(Lo, Hi); @@ -294,9 +288,21 @@ void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N, return; } - // Lower the bit-convert to a store/load from the stack, then split the load. - SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0)); - SplitRes_LOAD(cast(Op.Val), Lo, Hi); + // In the general case, convert the input to an integer and split it by hand. + InVT = MVT::getIntegerType(MVT::getSizeInBits(InVT)); + InOp = DAG.getNode(ISD::BIT_CONVERT, InVT, InOp); + + MVT::ValueType LoIntVT = MVT::getIntegerType(MVT::getSizeInBits(LoVT)); + MVT::ValueType HiIntVT = MVT::getIntegerType(MVT::getSizeInBits(HiVT)); + if (TLI.isBigEndian()) + std::swap(LoIntVT, HiIntVT); + + SplitInteger(InOp, LoIntVT, HiIntVT, Lo, Hi); + + if (TLI.isBigEndian()) + std::swap(Lo, Hi); + Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo); + Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi); } void DAGTypeLegalizer::SplitRes_BinOp(SDNode *N, SDOperand &Lo, SDOperand &Hi) { @@ -448,11 +454,8 @@ SDOperand DAGTypeLegalizer::SplitOp_BIT_CONVERT(SDNode *N) { if (TLI.isBigEndian()) std::swap(Lo, Hi); - assert(LoBits == HiBits && "Do not know how to assemble odd sized vectors!"); - return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), - DAG.getNode(ISD::BUILD_PAIR, - MVT::getIntegerType(LoBits+HiBits), Lo, Hi)); + JoinIntegers(Lo, Hi)); } SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_VECTOR_ELT(SDNode *N) {