X-Git-Url: http://demsky.eecs.uci.edu/git/?a=blobdiff_plain;f=lib%2FCodeGen%2FSelectionDAG%2FLegalizeIntegerTypes.cpp;h=20cfc77e022a60e40e7b95e29ef38f6c542be630;hb=9bed0f58eb7f5e9e22d062f3880a5fabfdd0dfdd;hp=4b927fec0822959ad4d777142353bc6d34419b5b;hpb=69b01e92a29ce6d7e435171aeea3fbc987b81586;p=oota-llvm.git diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index 4b927fec082..20cfc77e022 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -12,14 +12,13 @@ // computation in a larger type. For example, implementing i8 arithmetic in an // i32 register (often needed on powerpc). // Expansion is the act of changing a computation in an illegal type into a -// computation in multiple registers of a smaller type. For example, +// computation in two identical registers of a smaller type. For example, // implementing i64 arithmetic in two i32 registers (often needed on 32-bit // targets). // //===----------------------------------------------------------------------===// #include "LegalizeTypes.h" -#include "llvm/Constants.h" using namespace llvm; //===----------------------------------------------------------------------===// @@ -34,6 +33,18 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) { DEBUG(cerr << "Promote integer result: "; N->dump(&DAG); cerr << "\n"); SDOperand Result = SDOperand(); + // See if the target wants to custom expand this node. + if (TLI.getOperationAction(N->getOpcode(), N->getValueType(ResNo)) == + TargetLowering::Custom) { + // If the target wants to, allow it to lower this itself. + if (SDNode *P = TLI.ReplaceNodeResults(N, DAG)) { + // Everything that once used N now uses P. We are guaranteed that the + // result value types of N and the result value types of P match. + ReplaceNodeWith(N, P); + return; + } + } + switch (N->getOpcode()) { default: #ifndef NDEBUG @@ -49,7 +60,6 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) { case ISD::SIGN_EXTEND: case ISD::ZERO_EXTEND: case ISD::ANY_EXTEND: Result = PromoteIntRes_INT_EXTEND(N); break; - case ISD::FP_ROUND: Result = PromoteIntRes_FP_ROUND(N); break; case ISD::FP_TO_SINT: case ISD::FP_TO_UINT: Result = PromoteIntRes_FP_TO_XINT(N); break; case ISD::SETCC: Result = PromoteIntRes_SETCC(N); break; @@ -84,6 +94,8 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) { case ISD::EXTRACT_VECTOR_ELT: Result = PromoteIntRes_EXTRACT_VECTOR_ELT(N); break; + + case ISD::VAARG : Result = PromoteIntRes_VAARG(N); break; } // If Result is null, the sub-method took care of registering the result. @@ -156,15 +168,6 @@ SDOperand DAGTypeLegalizer::PromoteIntRes_INT_EXTEND(SDNode *N) { return DAG.getNode(N->getOpcode(), NVT, N->getOperand(0)); } -SDOperand DAGTypeLegalizer::PromoteIntRes_FP_ROUND(SDNode *N) { - // NOTE: Assumes input is legal. - if (N->getConstantOperandVal(1) == 0) - return DAG.getNode(ISD::FP_ROUND_INREG, N->getOperand(0).getValueType(), - N->getOperand(0), DAG.getValueType(N->getValueType(0))); - // If the precision discard isn't needed, just return the operand unrounded. - return N->getOperand(0); -} - SDOperand DAGTypeLegalizer::PromoteIntRes_FP_TO_XINT(SDNode *N) { unsigned NewOpc = N->getOpcode(); MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); @@ -192,7 +195,7 @@ SDOperand DAGTypeLegalizer::PromoteIntRes_SETCC(SDNode *N) { } SDOperand DAGTypeLegalizer::PromoteIntRes_LOAD(LoadSDNode *N) { - // FIXME: Add support for indexed loads. + assert(ISD::isUNINDEXEDLoad(N) && "Indexed load during type legalization!"); MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); ISD::LoadExtType ExtType = ISD::isNON_EXTLoad(N) ? ISD::EXTLOAD : N->getExtensionType(); @@ -232,17 +235,17 @@ SDOperand DAGTypeLegalizer::PromoteIntRes_BIT_CONVERT(SDNode *N) { // The input promotes to the same size. Convert the promoted value. return DAG.getNode(ISD::BIT_CONVERT, OutVT, GetPromotedInteger(InOp)); break; - case PromoteFloat: + case SoftenFloat: // Promote the integer operand by hand. - return DAG.getNode(ISD::ANY_EXTEND, OutVT, GetPromotedFloat(InOp)); + return DAG.getNode(ISD::ANY_EXTEND, OutVT, GetSoftenedFloat(InOp)); case ExpandInteger: case ExpandFloat: break; - case Scalarize: + case ScalarizeVector: // Convert the element to an integer and promote it by hand. return DAG.getNode(ISD::ANY_EXTEND, OutVT, BitConvertToInteger(GetScalarizedVector(InOp))); - case Split: + case SplitVector: // For example, i32 = BIT_CONVERT v2i16 on alpha. Convert the split // pieces of the input into integers and reassemble in the final type. SDOperand Lo, Hi; @@ -360,9 +363,9 @@ SDOperand DAGTypeLegalizer::PromoteIntRes_CTTZ(SDNode *N) { // The count is the same in the promoted type except if the original // value was zero. This can be handled by setting the bit just off // the top of the original type. - Op = DAG.getNode(ISD::OR, NVT, Op, - // FIXME: Do this using an APINT constant. - DAG.getConstant(1UL << OVT.getSizeInBits(), NVT)); + APInt TopBit(NVT.getSizeInBits(), 0); + TopBit.set(OVT.getSizeInBits()); + Op = DAG.getNode(ISD::OR, NVT, Op, DAG.getConstant(TopBit, NVT)); return DAG.getNode(ISD::CTTZ, NVT, Op); } @@ -411,6 +414,37 @@ SDOperand DAGTypeLegalizer::PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N) { return DAG.getNode(ISD::SELECT, NewVT, Odd, Hi, Lo); } +SDOperand DAGTypeLegalizer::PromoteIntRes_VAARG(SDNode *N) { + SDOperand Chain = N->getOperand(0); // Get the chain. + SDOperand Ptr = N->getOperand(1); // Get the pointer. + MVT VT = N->getValueType(0); + + const Value *V = cast(N->getOperand(2))->getValue(); + SDOperand VAList = DAG.getLoad(TLI.getPointerTy(), Chain, Ptr, V, 0); + + // Increment the arg pointer, VAList, to the next vaarg + // FIXME: should the ABI size be used for the increment? Think of + // x86 long double (10 bytes long, but aligned on 4 or 8 bytes) or + // integers of unusual size (such MVT::i1, which gives an increment + // of zero here!). + unsigned Increment = VT.getSizeInBits() / 8; + SDOperand Tmp = DAG.getNode(ISD::ADD, TLI.getPointerTy(), VAList, + DAG.getConstant(Increment, TLI.getPointerTy())); + + // Store the incremented VAList to the pointer. + Tmp = DAG.getStore(VAList.getValue(1), Tmp, Ptr, V, 0); + + // Load the actual argument out of the arg pointer VAList. + Tmp = DAG.getExtLoad(ISD::EXTLOAD, TLI.getTypeToTransformTo(VT), Tmp, + VAList, NULL, 0, VT); + + // Legalized the chain result - switch anything that used the old chain to + // use the new one. + ReplaceValueWith(SDOperand(N, 1), Tmp.getValue(1)); + return Tmp; +} + + //===----------------------------------------------------------------------===// // Integer Operand Promotion //===----------------------------------------------------------------------===// @@ -421,40 +455,48 @@ SDOperand DAGTypeLegalizer::PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N) { /// node may need promotion or expansion as well as the specified one. bool DAGTypeLegalizer::PromoteIntegerOperand(SDNode *N, unsigned OpNo) { DEBUG(cerr << "Promote integer operand: "; N->dump(&DAG); cerr << "\n"); - SDOperand Res; - switch (N->getOpcode()) { - default: -#ifndef NDEBUG - cerr << "PromoteIntegerOperand Op #" << OpNo << ": "; - N->dump(&DAG); cerr << "\n"; -#endif - assert(0 && "Do not know how to promote this operator's operand!"); - abort(); + SDOperand Res = SDOperand(); - case ISD::ANY_EXTEND: Res = PromoteIntOp_ANY_EXTEND(N); break; - case ISD::ZERO_EXTEND: Res = PromoteIntOp_ZERO_EXTEND(N); break; - case ISD::SIGN_EXTEND: Res = PromoteIntOp_SIGN_EXTEND(N); break; - case ISD::TRUNCATE: Res = PromoteIntOp_TRUNCATE(N); break; - case ISD::FP_EXTEND: Res = PromoteIntOp_FP_EXTEND(N); break; - case ISD::FP_ROUND: Res = PromoteIntOp_FP_ROUND(N); break; - case ISD::SINT_TO_FP: - case ISD::UINT_TO_FP: Res = PromoteIntOp_INT_TO_FP(N); break; - case ISD::BUILD_PAIR: Res = PromoteIntOp_BUILD_PAIR(N); break; - - case ISD::SELECT: Res = PromoteIntOp_SELECT(N, OpNo); break; - case ISD::BRCOND: Res = PromoteIntOp_BRCOND(N, OpNo); break; - case ISD::BR_CC: Res = PromoteIntOp_BR_CC(N, OpNo); break; - case ISD::SETCC: Res = PromoteIntOp_SETCC(N, OpNo); break; - - case ISD::STORE: Res = PromoteIntOp_STORE(cast(N), - OpNo); break; - - case ISD::BUILD_VECTOR: Res = PromoteIntOp_BUILD_VECTOR(N); break; - case ISD::INSERT_VECTOR_ELT: - Res = PromoteIntOp_INSERT_VECTOR_ELT(N, OpNo); - break; + if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType()) + == TargetLowering::Custom) + Res = TLI.LowerOperation(SDOperand(N, OpNo), DAG); + + if (Res.Val == 0) { + switch (N->getOpcode()) { + default: + #ifndef NDEBUG + cerr << "PromoteIntegerOperand Op #" << OpNo << ": "; + N->dump(&DAG); cerr << "\n"; + #endif + assert(0 && "Do not know how to promote this operator's operand!"); + abort(); - case ISD::MEMBARRIER: Res = PromoteIntOp_MEMBARRIER(N); break; + case ISD::ANY_EXTEND: Res = PromoteIntOp_ANY_EXTEND(N); break; + case ISD::ZERO_EXTEND: Res = PromoteIntOp_ZERO_EXTEND(N); break; + case ISD::SIGN_EXTEND: Res = PromoteIntOp_SIGN_EXTEND(N); break; + case ISD::TRUNCATE: Res = PromoteIntOp_TRUNCATE(N); break; + case ISD::FP_EXTEND: Res = PromoteIntOp_FP_EXTEND(N); break; + case ISD::FP_ROUND: Res = PromoteIntOp_FP_ROUND(N); break; + case ISD::SINT_TO_FP: + case ISD::UINT_TO_FP: Res = PromoteIntOp_INT_TO_FP(N); break; + case ISD::BUILD_PAIR: Res = PromoteIntOp_BUILD_PAIR(N); break; + + case ISD::BRCOND: Res = PromoteIntOp_BRCOND(N, OpNo); break; + case ISD::BR_CC: Res = PromoteIntOp_BR_CC(N, OpNo); break; + case ISD::SELECT: Res = PromoteIntOp_SELECT(N, OpNo); break; + case ISD::SELECT_CC: Res = PromoteIntOp_SELECT_CC(N, OpNo); break; + case ISD::SETCC: Res = PromoteIntOp_SETCC(N, OpNo); break; + + case ISD::STORE: Res = PromoteIntOp_STORE(cast(N), + OpNo); break; + + case ISD::BUILD_VECTOR: Res = PromoteIntOp_BUILD_VECTOR(N); break; + case ISD::INSERT_VECTOR_ELT: + Res = PromoteIntOp_INSERT_VECTOR_ELT(N, OpNo); + break; + + case ISD::MEMBARRIER: Res = PromoteIntOp_MEMBARRIER(N); break; + } } // If the result is null, the sub-method took care of registering results etc. @@ -568,7 +610,7 @@ SDOperand DAGTypeLegalizer::PromoteIntOp_BRCOND(SDNode *N, unsigned OpNo) { } SDOperand DAGTypeLegalizer::PromoteIntOp_BR_CC(SDNode *N, unsigned OpNo) { - assert(OpNo == 2 && "Don't know how to promote this operand"); + assert(OpNo == 2 && "Don't know how to promote this operand!"); SDOperand LHS = N->getOperand(2); SDOperand RHS = N->getOperand(3); @@ -580,8 +622,20 @@ SDOperand DAGTypeLegalizer::PromoteIntOp_BR_CC(SDNode *N, unsigned OpNo) { N->getOperand(1), LHS, RHS, N->getOperand(4)); } +SDOperand DAGTypeLegalizer::PromoteIntOp_SELECT_CC(SDNode *N, unsigned OpNo) { + assert(OpNo == 0 && "Don't know how to promote this operand!"); + + SDOperand LHS = N->getOperand(0); + SDOperand RHS = N->getOperand(1); + PromoteSetCCOperands(LHS, RHS, cast(N->getOperand(4))->get()); + + // The CC (#4) and the possible return values (#2 and #3) have legal types. + return DAG.UpdateNodeOperands(SDOperand(N, 0), LHS, RHS, N->getOperand(2), + N->getOperand(3), N->getOperand(4)); +} + SDOperand DAGTypeLegalizer::PromoteIntOp_SETCC(SDNode *N, unsigned OpNo) { - assert(OpNo == 0 && "Don't know how to promote this operand"); + assert(OpNo == 0 && "Don't know how to promote this operand!"); SDOperand LHS = N->getOperand(0); SDOperand RHS = N->getOperand(1); @@ -601,10 +655,6 @@ void DAGTypeLegalizer::PromoteSetCCOperands(SDOperand &NewLHS,SDOperand &NewRHS, NewLHS = GetPromotedInteger(NewLHS); NewRHS = GetPromotedInteger(NewRHS); - // If this is an FP compare, the operands have already been extended. - if (!NewLHS.getValueType().isInteger()) - return; - // Otherwise, we have to insert explicit sign or zero extends. Note // that we could insert sign extends for ALL conditions, but zero extend // is cheaper on many machines (an AND instead of two shifts), so prefer @@ -622,7 +672,7 @@ void DAGTypeLegalizer::PromoteSetCCOperands(SDOperand &NewLHS,SDOperand &NewRHS, // usually a simpler/cheaper operation, so prefer it. NewLHS = DAG.getZeroExtendInReg(NewLHS, VT); NewRHS = DAG.getZeroExtendInReg(NewRHS, VT); - return; + break; case ISD::SETGE: case ISD::SETGT: case ISD::SETLT: @@ -631,12 +681,12 @@ void DAGTypeLegalizer::PromoteSetCCOperands(SDOperand &NewLHS,SDOperand &NewRHS, DAG.getValueType(VT)); NewRHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, NewRHS.getValueType(), NewRHS, DAG.getValueType(VT)); - return; + break; } } SDOperand DAGTypeLegalizer::PromoteIntOp_STORE(StoreSDNode *N, unsigned OpNo){ - // FIXME: Add support for indexed stores. + assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!"); SDOperand Ch = N->getChain(), Ptr = N->getBasePtr(); int SVOffset = N->getSrcValueOffset(); unsigned Alignment = N->getAlignment(); @@ -736,10 +786,10 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) { Lo = Hi = SDOperand(); // See if the target wants to custom expand this node. - if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) == - TargetLowering::Custom) { + if (TLI.getOperationAction(N->getOpcode(), N->getValueType(ResNo)) == + TargetLowering::Custom) { // If the target wants to, allow it to lower this itself. - if (SDNode *P = TLI.ExpandOperationResult(N, DAG)) { + if (SDNode *P = TLI.ReplaceNodeResults(N, DAG)) { // Everything that once used N now uses P. We are guaranteed that the // result value types of N and the result value types of P match. ReplaceNodeWith(N, P); @@ -753,19 +803,25 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) { cerr << "ExpandIntegerResult #" << ResNo << ": "; N->dump(&DAG); cerr << "\n"; #endif - assert(0&&"Do not know how to expand the result of this operator!"); + assert(0 && "Do not know how to expand the result of this operator!"); abort(); - case ISD::UNDEF: ExpandIntRes_UNDEF(N, Lo, Hi); break; + case ISD::MERGE_VALUES: SplitRes_MERGE_VALUES(N, Lo, Hi); break; + case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break; + case ISD::SELECT_CC: SplitRes_SELECT_CC(N, Lo, Hi); break; + case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break; + + case ISD::BIT_CONVERT: ExpandRes_BIT_CONVERT(N, Lo, Hi); break; + case ISD::BUILD_PAIR: ExpandRes_BUILD_PAIR(N, Lo, Hi); break; + case ISD::EXTRACT_ELEMENT: ExpandRes_EXTRACT_ELEMENT(N, Lo, Hi); break; + case ISD::EXTRACT_VECTOR_ELT: ExpandRes_EXTRACT_VECTOR_ELT(N, Lo, Hi); break; + case ISD::Constant: ExpandIntRes_Constant(N, Lo, Hi); break; - case ISD::BUILD_PAIR: ExpandIntRes_BUILD_PAIR(N, Lo, Hi); break; - case ISD::MERGE_VALUES: ExpandIntRes_MERGE_VALUES(N, Lo, Hi); break; case ISD::ANY_EXTEND: ExpandIntRes_ANY_EXTEND(N, Lo, Hi); break; case ISD::ZERO_EXTEND: ExpandIntRes_ZERO_EXTEND(N, Lo, Hi); break; case ISD::SIGN_EXTEND: ExpandIntRes_SIGN_EXTEND(N, Lo, Hi); break; case ISD::AssertZext: ExpandIntRes_AssertZext(N, Lo, Hi); break; case ISD::TRUNCATE: ExpandIntRes_TRUNCATE(N, Lo, Hi); break; - case ISD::BIT_CONVERT: ExpandIntRes_BIT_CONVERT(N, Lo, Hi); break; case ISD::SIGN_EXTEND_INREG: ExpandIntRes_SIGN_EXTEND_INREG(N, Lo, Hi); break; case ISD::FP_TO_SINT: ExpandIntRes_FP_TO_SINT(N, Lo, Hi); break; case ISD::FP_TO_UINT: ExpandIntRes_FP_TO_UINT(N, Lo, Hi); break; @@ -781,8 +837,6 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) { case ISD::SUBC: ExpandIntRes_ADDSUBC(N, Lo, Hi); break; case ISD::ADDE: case ISD::SUBE: ExpandIntRes_ADDSUBE(N, Lo, Hi); break; - case ISD::SELECT: ExpandIntRes_SELECT(N, Lo, Hi); break; - case ISD::SELECT_CC: ExpandIntRes_SELECT_CC(N, Lo, Hi); break; case ISD::MUL: ExpandIntRes_MUL(N, Lo, Hi); break; case ISD::SDIV: ExpandIntRes_SDIV(N, Lo, Hi); break; case ISD::SREM: ExpandIntRes_SREM(N, Lo, Hi); break; @@ -795,10 +849,6 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) { case ISD::CTLZ: ExpandIntRes_CTLZ(N, Lo, Hi); break; case ISD::CTPOP: ExpandIntRes_CTPOP(N, Lo, Hi); break; case ISD::CTTZ: ExpandIntRes_CTTZ(N, Lo, Hi); break; - - case ISD::EXTRACT_VECTOR_ELT: - ExpandIntRes_EXTRACT_VECTOR_ELT(N, Lo, Hi); - break; } // If Lo/Hi is null, the sub-method took care of registering results etc. @@ -806,12 +856,6 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) { SetExpandedInteger(SDOperand(N, ResNo), Lo, Hi); } -void DAGTypeLegalizer::ExpandIntRes_UNDEF(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - Lo = Hi = DAG.getNode(ISD::UNDEF, NVT); -} - void DAGTypeLegalizer::ExpandIntRes_Constant(SDNode *N, SDOperand &Lo, SDOperand &Hi) { MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); @@ -821,34 +865,6 @@ void DAGTypeLegalizer::ExpandIntRes_Constant(SDNode *N, Hi = DAG.getConstant(Cst.lshr(NBitWidth).trunc(NBitWidth), NVT); } -void DAGTypeLegalizer::ExpandIntRes_BUILD_PAIR(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - // Return the operands. - Lo = N->getOperand(0); - Hi = N->getOperand(1); -} - -void DAGTypeLegalizer::ExpandIntRes_MERGE_VALUES(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - // A MERGE_VALUES node can produce any number of values. We know that the - // first illegal one needs to be expanded into Lo/Hi. - unsigned i; - - // The string of legal results gets turns into the input operands, which have - // the same type. - for (i = 0; isTypeLegal(N->getValueType(i)); ++i) - ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i))); - - // The first illegal result must be the one that needs to be expanded. - GetExpandedInteger(N->getOperand(i), Lo, Hi); - - // Legalize the rest of the results into the input operands whether they are - // legal or not. - unsigned e = N->getNumValues(); - for (++i; i != e; ++i) - ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i))); -} - void DAGTypeLegalizer::ExpandIntRes_ANY_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi) { MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); @@ -950,61 +966,6 @@ void DAGTypeLegalizer::ExpandIntRes_TRUNCATE(SDNode *N, Hi = DAG.getNode(ISD::TRUNCATE, NVT, Hi); } -void DAGTypeLegalizer::ExpandIntRes_BIT_CONVERT(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0)); - SDOperand InOp = N->getOperand(0); - MVT InVT = InOp.getValueType(); - - // Handle some special cases efficiently. - switch (getTypeAction(InVT)) { - default: - assert(false && "Unknown type action!"); - case Legal: - case PromoteInteger: - break; - case PromoteFloat: - // Convert the integer operand instead. - SplitInteger(GetPromotedFloat(InOp), Lo, Hi); - Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); - Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); - return; - case ExpandInteger: - // Convert the expanded pieces of the input. - GetExpandedInteger(InOp, Lo, Hi); - Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo); - Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi); - return; - case ExpandFloat: - // Convert the expanded pieces of the input. - GetExpandedFloat(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. - GetSplitVector(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. - SplitInteger(BitConvertToInteger(GetScalarizedVector(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. - SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0)); - ExpandIntRes_LOAD(cast(Op.Val), Lo, Hi); -} - void DAGTypeLegalizer:: ExpandIntRes_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi) { GetExpandedInteger(N->getOperand(0), Lo, Hi); @@ -1035,7 +996,17 @@ void DAGTypeLegalizer::ExpandIntRes_FP_TO_SINT(SDNode *N, SDOperand &Lo, MVT VT = N->getValueType(0); SDOperand Op = N->getOperand(0); RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; - if (VT == MVT::i64) { + + if (VT == MVT::i32) { + if (Op.getValueType() == MVT::f32) + LC = RTLIB::FPTOSINT_F32_I32; + else if (Op.getValueType() == MVT::f64) + LC = RTLIB::FPTOSINT_F64_I32; + else if (Op.getValueType() == MVT::f80) + LC = RTLIB::FPTOSINT_F80_I32; + else if (Op.getValueType() == MVT::ppcf128) + LC = RTLIB::FPTOSINT_PPCF128_I32; + } else if (VT == MVT::i64) { if (Op.getValueType() == MVT::f32) LC = RTLIB::FPTOSINT_F32_I64; else if (Op.getValueType() == MVT::f64) @@ -1053,9 +1024,8 @@ void DAGTypeLegalizer::ExpandIntRes_FP_TO_SINT(SDNode *N, SDOperand &Lo, LC = RTLIB::FPTOSINT_F80_I128; else if (Op.getValueType() == MVT::ppcf128) LC = RTLIB::FPTOSINT_PPCF128_I128; - } else { - assert(0 && "Unexpected fp-to-sint conversion!"); } + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected fp-to-sint conversion!"); SplitInteger(MakeLibCall(LC, VT, &Op, 1, true/*sign irrelevant*/), Lo, Hi); } @@ -1064,7 +1034,16 @@ void DAGTypeLegalizer::ExpandIntRes_FP_TO_UINT(SDNode *N, SDOperand &Lo, MVT VT = N->getValueType(0); SDOperand Op = N->getOperand(0); RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; - if (VT == MVT::i64) { + if (VT == MVT::i32) { + if (Op.getValueType() == MVT::f32) + LC = RTLIB::FPTOUINT_F32_I32; + else if (Op.getValueType() == MVT::f64) + LC = RTLIB::FPTOUINT_F64_I32; + else if (Op.getValueType() == MVT::f80) + LC = RTLIB::FPTOUINT_F80_I32; + else if (Op.getValueType() == MVT::ppcf128) + LC = RTLIB::FPTOUINT_PPCF128_I32; + } else if (VT == MVT::i64) { if (Op.getValueType() == MVT::f32) LC = RTLIB::FPTOUINT_F32_I64; else if (Op.getValueType() == MVT::f64) @@ -1082,45 +1061,32 @@ void DAGTypeLegalizer::ExpandIntRes_FP_TO_UINT(SDNode *N, SDOperand &Lo, LC = RTLIB::FPTOUINT_F80_I128; else if (Op.getValueType() == MVT::ppcf128) LC = RTLIB::FPTOUINT_PPCF128_I128; - } else { - assert(0 && "Unexpected fp-to-uint conversion!"); } + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unexpected fp-to-uint conversion!"); SplitInteger(MakeLibCall(LC, VT, &Op, 1, false/*sign irrelevant*/), Lo, Hi); } void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N, SDOperand &Lo, SDOperand &Hi) { - // FIXME: Add support for indexed loads. + if (ISD::isNormalLoad(N)) { + ExpandRes_NormalLoad(N, Lo, Hi); + return; + } + + assert(ISD::isUNINDEXEDLoad(N) && "Indexed load during type legalization!"); + MVT VT = N->getValueType(0); MVT NVT = TLI.getTypeToTransformTo(VT); - SDOperand Ch = N->getChain(); // Legalize the chain. - SDOperand Ptr = N->getBasePtr(); // Legalize the pointer. + SDOperand Ch = N->getChain(); + SDOperand Ptr = N->getBasePtr(); ISD::LoadExtType ExtType = N->getExtensionType(); int SVOffset = N->getSrcValueOffset(); unsigned Alignment = N->getAlignment(); bool isVolatile = N->isVolatile(); - assert(!(NVT.getSizeInBits() & 7) && "Expanded type not byte sized!"); + assert(NVT.isByteSized() && "Expanded type not byte sized!"); - if (ExtType == ISD::NON_EXTLOAD) { - Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset, - isVolatile, Alignment); - // Increment the pointer to the other half. - unsigned IncrementSize = NVT.getSizeInBits()/8; - Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, - DAG.getIntPtrConstant(IncrementSize)); - Hi = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset+IncrementSize, - isVolatile, MinAlign(Alignment, IncrementSize)); - - // Build a factor node to remember that this load is independent of the - // other one. - Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1), - Hi.getValue(1)); - - // Handle endianness of the load. - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - } else if (N->getMemoryVT().bitsLE(NVT)) { + if (N->getMemoryVT().bitsLE(NVT)) { MVT EVT = N->getMemoryVT(); Lo = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), SVOffset, EVT, @@ -1225,26 +1191,6 @@ void DAGTypeLegalizer::ExpandIntRes_BSWAP(SDNode *N, Hi = DAG.getNode(ISD::BSWAP, Hi.getValueType(), Hi); } -void DAGTypeLegalizer::ExpandIntRes_SELECT(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - SDOperand LL, LH, RL, RH; - GetExpandedInteger(N->getOperand(1), LL, LH); - GetExpandedInteger(N->getOperand(2), RL, RH); - Lo = DAG.getNode(ISD::SELECT, LL.getValueType(), N->getOperand(0), LL, RL); - Hi = DAG.getNode(ISD::SELECT, LL.getValueType(), N->getOperand(0), LH, RH); -} - -void DAGTypeLegalizer::ExpandIntRes_SELECT_CC(SDNode *N, - SDOperand &Lo, SDOperand &Hi) { - SDOperand LL, LH, RL, RH; - GetExpandedInteger(N->getOperand(2), LL, LH); - GetExpandedInteger(N->getOperand(3), RL, RH); - Lo = DAG.getNode(ISD::SELECT_CC, LL.getValueType(), N->getOperand(0), - N->getOperand(1), LL, RL, N->getOperand(4)); - Hi = DAG.getNode(ISD::SELECT_CC, LL.getValueType(), N->getOperand(0), - N->getOperand(1), LH, RH, N->getOperand(4)); -} - void DAGTypeLegalizer::ExpandIntRes_ADDSUB(SDNode *N, SDOperand &Lo, SDOperand &Hi) { // Expand the subcomponents. @@ -1324,14 +1270,13 @@ void DAGTypeLegalizer::ExpandIntRes_MUL(SDNode *N, GetExpandedInteger(N->getOperand(0), LL, LH); GetExpandedInteger(N->getOperand(1), RL, RH); unsigned OuterBitSize = VT.getSizeInBits(); - unsigned BitSize = NVT.getSizeInBits(); + unsigned InnerBitSize = NVT.getSizeInBits(); unsigned LHSSB = DAG.ComputeNumSignBits(N->getOperand(0)); unsigned RHSSB = DAG.ComputeNumSignBits(N->getOperand(1)); - if (DAG.MaskedValueIsZero(N->getOperand(0), - APInt::getHighBitsSet(OuterBitSize, LHSSB)) && - DAG.MaskedValueIsZero(N->getOperand(1), - APInt::getHighBitsSet(OuterBitSize, RHSSB))) { + APInt HighMask = APInt::getHighBitsSet(OuterBitSize, InnerBitSize); + if (DAG.MaskedValueIsZero(N->getOperand(0), HighMask) && + DAG.MaskedValueIsZero(N->getOperand(1), HighMask)) { // The inputs are both zero-extended. if (HasUMUL_LOHI) { // We can emit a umul_lohi. @@ -1346,7 +1291,7 @@ void DAGTypeLegalizer::ExpandIntRes_MUL(SDNode *N, return; } } - if (LHSSB > BitSize && RHSSB > BitSize) { + if (LHSSB > InnerBitSize && RHSSB > InnerBitSize) { // The input values are both sign-extended. if (HasSMUL_LOHI) { // We can emit a smul_lohi. @@ -1373,44 +1318,97 @@ void DAGTypeLegalizer::ExpandIntRes_MUL(SDNode *N, Hi = DAG.getNode(ISD::ADD, NVT, Hi, LH); return; } + if (HasMULHU) { + Lo = DAG.getNode(ISD::MUL, NVT, LL, RL); + Hi = DAG.getNode(ISD::MULHU, NVT, LL, RL); + RH = DAG.getNode(ISD::MUL, NVT, LL, RH); + LH = DAG.getNode(ISD::MUL, NVT, LH, RL); + Hi = DAG.getNode(ISD::ADD, NVT, Hi, RH); + Hi = DAG.getNode(ISD::ADD, NVT, Hi, LH); + return; + } } // If nothing else, we can make a libcall. + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (VT == MVT::i32) + LC = RTLIB::MUL_I32; + else if (VT == MVT::i64) + LC = RTLIB::MUL_I64; + else if (VT == MVT::i128) + LC = RTLIB::MUL_I128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported MUL!"); + SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; - SplitInteger(MakeLibCall(RTLIB::MUL_I64, VT, Ops, 2, true/*sign irrelevant*/), - Lo, Hi); + SplitInteger(MakeLibCall(LC, VT, Ops, 2, true/*sign irrelevant*/), Lo, Hi); } void DAGTypeLegalizer::ExpandIntRes_SDIV(SDNode *N, SDOperand &Lo, SDOperand &Hi) { - assert(N->getValueType(0) == MVT::i64 && "Unsupported sdiv!"); + MVT VT = N->getValueType(0); + + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (VT == MVT::i32) + LC = RTLIB::SDIV_I32; + else if (VT == MVT::i64) + LC = RTLIB::SDIV_I64; + else if (VT == MVT::i128) + LC = RTLIB::SDIV_I128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SDIV!"); + SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; - SplitInteger(MakeLibCall(RTLIB::SDIV_I64, N->getValueType(0), Ops, 2, true), - Lo, Hi); + SplitInteger(MakeLibCall(LC, VT, Ops, 2, true), Lo, Hi); } void DAGTypeLegalizer::ExpandIntRes_SREM(SDNode *N, SDOperand &Lo, SDOperand &Hi) { - assert(N->getValueType(0) == MVT::i64 && "Unsupported srem!"); + MVT VT = N->getValueType(0); + + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (VT == MVT::i32) + LC = RTLIB::SREM_I32; + else if (VT == MVT::i64) + LC = RTLIB::SREM_I64; + else if (VT == MVT::i128) + LC = RTLIB::SREM_I128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported SREM!"); + SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; - SplitInteger(MakeLibCall(RTLIB::SREM_I64, N->getValueType(0), Ops, 2, true), - Lo, Hi); + SplitInteger(MakeLibCall(LC, VT, Ops, 2, true), Lo, Hi); } void DAGTypeLegalizer::ExpandIntRes_UDIV(SDNode *N, SDOperand &Lo, SDOperand &Hi) { - assert(N->getValueType(0) == MVT::i64 && "Unsupported udiv!"); + MVT VT = N->getValueType(0); + + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (VT == MVT::i32) + LC = RTLIB::UDIV_I32; + else if (VT == MVT::i64) + LC = RTLIB::UDIV_I64; + else if (VT == MVT::i128) + LC = RTLIB::UDIV_I128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported UDIV!"); + SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; - SplitInteger(MakeLibCall(RTLIB::UDIV_I64, N->getValueType(0), Ops, 2, false), - Lo, Hi); + SplitInteger(MakeLibCall(LC, VT, Ops, 2, false), Lo, Hi); } void DAGTypeLegalizer::ExpandIntRes_UREM(SDNode *N, SDOperand &Lo, SDOperand &Hi) { - assert(N->getValueType(0) == MVT::i64 && "Unsupported urem!"); + MVT VT = N->getValueType(0); + + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (VT == MVT::i32) + LC = RTLIB::UREM_I32; + else if (VT == MVT::i64) + LC = RTLIB::UREM_I64; + else if (VT == MVT::i128) + LC = RTLIB::UREM_I128; + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported UREM!"); + SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; - SplitInteger(MakeLibCall(RTLIB::UREM_I64, N->getValueType(0), Ops, 2, false), - Lo, Hi); + SplitInteger(MakeLibCall(LC, VT, Ops, 2, false), Lo, Hi); } void DAGTypeLegalizer::ExpandIntRes_Shift(SDNode *N, @@ -1456,21 +1454,35 @@ void DAGTypeLegalizer::ExpandIntRes_Shift(SDNode *N, } // Otherwise, emit a libcall. - assert(VT == MVT::i64 && "Unsupported shift!"); - - RTLIB::Libcall LC; + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; bool isSigned; if (N->getOpcode() == ISD::SHL) { - LC = RTLIB::SHL_I64; isSigned = false; /*sign irrelevant*/ + if (VT == MVT::i32) + LC = RTLIB::SHL_I32; + else if (VT == MVT::i64) + LC = RTLIB::SHL_I64; + else if (VT == MVT::i128) + LC = RTLIB::SHL_I128; } else if (N->getOpcode() == ISD::SRL) { - LC = RTLIB::SRL_I64; isSigned = false; + if (VT == MVT::i32) + LC = RTLIB::SRL_I32; + else if (VT == MVT::i64) + LC = RTLIB::SRL_I64; + else if (VT == MVT::i128) + LC = RTLIB::SRL_I128; } else { assert(N->getOpcode() == ISD::SRA && "Unknown shift!"); - LC = RTLIB::SRA_I64; isSigned = true; + if (VT == MVT::i32) + LC = RTLIB::SRA_I32; + else if (VT == MVT::i64) + LC = RTLIB::SRA_I64; + else if (VT == MVT::i128) + LC = RTLIB::SRA_I128; } + assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported shift!"); SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) }; SplitInteger(MakeLibCall(LC, VT, Ops, 2, isSigned), Lo, Hi); @@ -1522,41 +1534,6 @@ void DAGTypeLegalizer::ExpandIntRes_CTTZ(SDNode *N, Hi = DAG.getConstant(0, NVT); } -void DAGTypeLegalizer::ExpandIntRes_EXTRACT_VECTOR_ELT(SDNode *N, - SDOperand &Lo, - SDOperand &Hi) { - SDOperand OldVec = N->getOperand(0); - unsigned OldElts = OldVec.getValueType().getVectorNumElements(); - - // Convert to a vector of the expanded element type, for example - // <2 x i64> -> <4 x i32>. - MVT OldVT = N->getValueType(0); - MVT NewVT = TLI.getTypeToTransformTo(OldVT); - assert(OldVT.getSizeInBits() == 2 * NewVT.getSizeInBits() && - "Do not know how to handle this expansion!"); - - SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT, - MVT::getVectorVT(NewVT, 2*OldElts), - OldVec); - - // Extract the elements at 2 * Idx and 2 * Idx + 1 from the new vector. - SDOperand Idx = N->getOperand(1); - - // Make sure the type of Idx is big enough to hold the new values. - if (Idx.getValueType().bitsLT(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); - - Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, - DAG.getConstant(1, Idx.getValueType())); - Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx); - - if (TLI.isBigEndian()) - std::swap(Lo, Hi); -} - /// ExpandShiftByConstant - N is a shift by a value that needs to be expanded, /// and the shift amount is a constant 'Amt'. Expand the operation. void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt, @@ -1579,6 +1556,13 @@ void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt, } else if (Amt == NVTBits) { Lo = DAG.getConstant(0, NVT); Hi = InL; + } else if (Amt == 1) { + // Emit this X << 1 as X+X. + SDVTList VTList = DAG.getVTList(NVT, MVT::Flag); + SDOperand LoOps[2] = { InL, InL }; + Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2); + SDOperand HiOps[3] = { InH, InH, Lo.getValue(1) }; + Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3); } else { Lo = DAG.getNode(ISD::SHL, NVT, InL, DAG.getConstant(Amt, ShTy)); Hi = DAG.getNode(ISD::OR, NVT, @@ -1721,11 +1705,11 @@ ExpandShiftWithKnownAmountBit(SDNode *N, SDOperand &Lo, SDOperand &Hi) { /// node may need promotion or expansion as well as the specified one. bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) { DEBUG(cerr << "Expand integer operand: "; N->dump(&DAG); cerr << "\n"); - SDOperand Res(0, 0); + SDOperand Res = SDOperand(); if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType()) == TargetLowering::Custom) - Res = TLI.LowerOperation(SDOperand(N, 0), DAG); + Res = TLI.LowerOperation(SDOperand(N, OpNo), DAG); if (Res.Val == 0) { switch (N->getOpcode()) { @@ -1737,8 +1721,11 @@ bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) { assert(0 && "Do not know how to expand this operator's operand!"); abort(); + case ISD::BUILD_VECTOR: Res = ExpandOp_BUILD_VECTOR(N); break; + case ISD::BIT_CONVERT: Res = ExpandOp_BIT_CONVERT(N); break; + case ISD::EXTRACT_ELEMENT: Res = ExpandOp_EXTRACT_ELEMENT(N); break; + case ISD::TRUNCATE: Res = ExpandIntOp_TRUNCATE(N); break; - case ISD::BIT_CONVERT: Res = ExpandIntOp_BIT_CONVERT(N); break; case ISD::SINT_TO_FP: Res = ExpandIntOp_SINT_TO_FP(N->getOperand(0), N->getValueType(0)); @@ -1746,16 +1733,14 @@ bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) { case ISD::UINT_TO_FP: Res = ExpandIntOp_UINT_TO_FP(N->getOperand(0), N->getValueType(0)); break; - case ISD::EXTRACT_ELEMENT: Res = ExpandIntOp_EXTRACT_ELEMENT(N); break; - case ISD::BR_CC: Res = ExpandIntOp_BR_CC(N); break; - case ISD::SETCC: Res = ExpandIntOp_SETCC(N); break; + case ISD::BR_CC: Res = ExpandIntOp_BR_CC(N); break; + case ISD::SELECT_CC: Res = ExpandIntOp_SELECT_CC(N); break; + case ISD::SETCC: Res = ExpandIntOp_SETCC(N); break; case ISD::STORE: Res = ExpandIntOp_STORE(cast(N), OpNo); break; - - case ISD::BUILD_VECTOR: Res = ExpandIntOp_BUILD_VECTOR(N); break; } } @@ -1785,38 +1770,13 @@ SDOperand DAGTypeLegalizer::ExpandIntOp_TRUNCATE(SDNode *N) { return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), InL); } -SDOperand DAGTypeLegalizer::ExpandIntOp_BIT_CONVERT(SDNode *N) { - if (N->getValueType(0).isVector()) { - // An illegal integer type is being converted to a legal vector type. - // Make a two element vector out of the expanded parts and convert that - // instead, but only if the new vector type is legal (otherwise there - // is no point, and it might create expansion loops). For example, on - // x86 this turns v1i64 = BIT_CONVERT i64 into v1i64 = BIT_CONVERT v2i32. - MVT OVT = N->getOperand(0).getValueType(); - MVT NVT = MVT::getVectorVT(TLI.getTypeToTransformTo(OVT), 2); - - if (isTypeLegal(NVT)) { - SDOperand Parts[2]; - GetExpandedInteger(N->getOperand(0), Parts[0], Parts[1]); - - if (TLI.isBigEndian()) - std::swap(Parts[0], Parts[1]); - - SDOperand Vec = DAG.getNode(ISD::BUILD_VECTOR, NVT, Parts, 2); - return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Vec); - } - } - - // Otherwise, store to a temporary and load out again as the new type. - return CreateStackStoreLoad(N->getOperand(0), N->getValueType(0)); -} - SDOperand DAGTypeLegalizer::ExpandIntOp_SINT_TO_FP(SDOperand Source, - MVT DestTy) { + MVT DestTy) { // We know the destination is legal, but that the input needs to be expanded. MVT SourceVT = Source.getValueType(); // Check to see if the target has a custom way to lower this. If so, use it. + // This can trigger when called from ExpandIntOp_UINT_TO_FP. switch (TLI.getOperationAction(ISD::SINT_TO_FP, SourceVT)) { default: assert(0 && "This action not implemented for this operation!"); case TargetLowering::Legal: @@ -1830,13 +1790,24 @@ SDOperand DAGTypeLegalizer::ExpandIntOp_SINT_TO_FP(SDOperand Source, } RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; - if (SourceVT == MVT::i64) { + if (SourceVT == MVT::i32) { + if (DestTy == MVT::f32) + LC = RTLIB::SINTTOFP_I32_F32; + else if (DestTy == MVT::f64) + LC = RTLIB::SINTTOFP_I32_F64; + else if (DestTy == MVT::f80) + LC = RTLIB::SINTTOFP_I32_F80; + else if (DestTy == MVT::ppcf128) + LC = RTLIB::SINTTOFP_I32_PPCF128; + } else if (SourceVT == MVT::i64) { if (DestTy == MVT::f32) LC = RTLIB::SINTTOFP_I64_F32; - else { - assert(DestTy == MVT::f64 && "Unknown fp value type!"); + else if (DestTy == MVT::f64) LC = RTLIB::SINTTOFP_I64_F64; - } + else if (DestTy == MVT::f80) + LC = RTLIB::SINTTOFP_I64_F80; + else if (DestTy == MVT::ppcf128) + LC = RTLIB::SINTTOFP_I64_PPCF128; } else if (SourceVT == MVT::i128) { if (DestTy == MVT::f32) LC = RTLIB::SINTTOFP_I128_F32; @@ -1844,16 +1815,12 @@ SDOperand DAGTypeLegalizer::ExpandIntOp_SINT_TO_FP(SDOperand Source, LC = RTLIB::SINTTOFP_I128_F64; else if (DestTy == MVT::f80) LC = RTLIB::SINTTOFP_I128_F80; - else { - assert(DestTy == MVT::ppcf128 && "Unknown fp value type!"); + else if (DestTy == MVT::ppcf128) LC = RTLIB::SINTTOFP_I128_PPCF128; - } - } else { - assert(0 && "Unknown int value type!"); } - assert(LC != RTLIB::UNKNOWN_LIBCALL && "Don't know how to expand this SINT_TO_FP!"); + return MakeLibCall(LC, DestTy, &Source, 1, true); } @@ -1898,16 +1865,10 @@ SDOperand DAGTypeLegalizer::ExpandIntOp_UINT_TO_FP(SDOperand Source, return DAG.getNode(ISD::FADD, DestTy, SignedConv, FudgeInReg); } -SDOperand DAGTypeLegalizer::ExpandIntOp_EXTRACT_ELEMENT(SDNode *N) { - SDOperand Lo, Hi; - GetExpandedInteger(N->getOperand(0), Lo, Hi); - return cast(N->getOperand(1))->getValue() ? Hi : Lo; -} - SDOperand DAGTypeLegalizer::ExpandIntOp_BR_CC(SDNode *N) { SDOperand NewLHS = N->getOperand(2), NewRHS = N->getOperand(3); ISD::CondCode CCCode = cast(N->getOperand(1))->get(); - ExpandSetCCOperands(NewLHS, NewRHS, CCCode); + IntegerExpandSetCCOperands(NewLHS, NewRHS, CCCode); // If ExpandSetCCOperands returned a scalar, we need to compare the result // against zero to select between true and false values. @@ -1922,55 +1883,63 @@ SDOperand DAGTypeLegalizer::ExpandIntOp_BR_CC(SDNode *N) { N->getOperand(4)); } +SDOperand DAGTypeLegalizer::ExpandIntOp_SELECT_CC(SDNode *N) { + SDOperand NewLHS = N->getOperand(0), NewRHS = N->getOperand(1); + ISD::CondCode CCCode = cast(N->getOperand(4))->get(); + IntegerExpandSetCCOperands(NewLHS, NewRHS, CCCode); + + // If ExpandSetCCOperands returned a scalar, we need to compare the result + // against zero to select between true and false values. + if (NewRHS.Val == 0) { + NewRHS = DAG.getConstant(0, NewLHS.getValueType()); + CCCode = ISD::SETNE; + } + + // Update N to have the operands specified. + return DAG.UpdateNodeOperands(SDOperand(N, 0), NewLHS, NewRHS, + N->getOperand(2), N->getOperand(3), + DAG.getCondCode(CCCode)); +} + SDOperand DAGTypeLegalizer::ExpandIntOp_SETCC(SDNode *N) { SDOperand NewLHS = N->getOperand(0), NewRHS = N->getOperand(1); ISD::CondCode CCCode = cast(N->getOperand(2))->get(); - ExpandSetCCOperands(NewLHS, NewRHS, CCCode); + IntegerExpandSetCCOperands(NewLHS, NewRHS, CCCode); // If ExpandSetCCOperands returned a scalar, use it. - if (NewRHS.Val == 0) return NewLHS; + if (NewRHS.Val == 0) { + assert(NewLHS.getValueType() == N->getValueType(0) && + "Unexpected setcc expansion!"); + return NewLHS; + } // Otherwise, update N to have the operands specified. return DAG.UpdateNodeOperands(SDOperand(N, 0), NewLHS, NewRHS, DAG.getCondCode(CCCode)); } -/// ExpandSetCCOperands - Expand the operands of a comparison. This code is -/// shared among BR_CC, SELECT_CC, and SETCC handlers. -void DAGTypeLegalizer::ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS, - ISD::CondCode &CCCode) { +/// IntegerExpandSetCCOperands - Expand the operands of a comparison. This code +/// is shared among BR_CC, SELECT_CC, and SETCC handlers. +void DAGTypeLegalizer::IntegerExpandSetCCOperands(SDOperand &NewLHS, + SDOperand &NewRHS, + ISD::CondCode &CCCode) { SDOperand LHSLo, LHSHi, RHSLo, RHSHi; GetExpandedInteger(NewLHS, LHSLo, LHSHi); GetExpandedInteger(NewRHS, RHSLo, RHSHi); MVT VT = NewLHS.getValueType(); - if (VT == MVT::ppcf128) { - // FIXME: This generated code sucks. We want to generate - // FCMP crN, hi1, hi2 - // BNE crN, L: - // FCMP crN, lo1, lo2 - // The following can be improved, but not that much. - SDOperand Tmp1, Tmp2, Tmp3; - Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, ISD::SETEQ); - Tmp2 = DAG.getSetCC(TLI.getSetCCResultType(LHSLo), LHSLo, RHSLo, CCCode); - Tmp3 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2); - Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, ISD::SETNE); - Tmp2 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, CCCode); - Tmp1 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2); - NewLHS = DAG.getNode(ISD::OR, Tmp1.getValueType(), Tmp1, Tmp3); - NewRHS = SDOperand(); // LHS is the result, not a compare. - return; - } if (CCCode == ISD::SETEQ || CCCode == ISD::SETNE) { - if (RHSLo == RHSHi) - if (ConstantSDNode *RHSCST = dyn_cast(RHSLo)) + if (RHSLo == RHSHi) { + if (ConstantSDNode *RHSCST = dyn_cast(RHSLo)) { if (RHSCST->isAllOnesValue()) { // Equality comparison to -1. NewLHS = DAG.getNode(ISD::AND, LHSLo.getValueType(), LHSLo, LHSHi); NewRHS = RHSLo; return; } + } + } NewLHS = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSLo, RHSLo); NewRHS = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSHi, RHSHi); @@ -2049,7 +2018,10 @@ void DAGTypeLegalizer::ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS, } SDOperand DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) { - // FIXME: Add support for indexed stores. + if (ISD::isNormalStore(N)) + return ExpandOp_NormalStore(N, OpNo); + + assert(ISD::isUNINDEXEDStore(N) && "Indexed store during type legalization!"); assert(OpNo == 1 && "Can only expand the stored value so far"); MVT VT = N->getOperand(1).getValueType(); @@ -2061,26 +2033,9 @@ SDOperand DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) { bool isVolatile = N->isVolatile(); SDOperand Lo, Hi; - assert(!(NVT.getSizeInBits() & 7) && "Expanded type not byte sized!"); - - if (!N->isTruncatingStore()) { - unsigned IncrementSize = 0; - GetExpandedInteger(N->getValue(), Lo, Hi); - IncrementSize = Hi.getValueType().getSizeInBits()/8; - - if (TLI.isBigEndian()) - std::swap(Lo, Hi); - - Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), - SVOffset, isVolatile, Alignment); + assert(NVT.isByteSized() && "Expanded type not byte sized!"); - Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr, - DAG.getIntPtrConstant(IncrementSize)); - assert(isTypeLegal(Ptr.getValueType()) && "Pointers must be legal!"); - Hi = DAG.getStore(Ch, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize, - isVolatile, MinAlign(Alignment, IncrementSize)); - return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); - } else if (N->getMemoryVT().bitsLE(NVT)) { + if (N->getMemoryVT().bitsLE(NVT)) { GetExpandedInteger(N->getValue(), Lo, Hi); return DAG.getTruncStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset, N->getMemoryVT(), isVolatile, Alignment); @@ -2140,35 +2095,3 @@ SDOperand DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) { return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi); } } - -SDOperand DAGTypeLegalizer::ExpandIntOp_BUILD_VECTOR(SDNode *N) { - // The vector type is legal but the element type needs expansion. - MVT VecVT = N->getValueType(0); - unsigned NumElts = VecVT.getVectorNumElements(); - MVT OldVT = N->getOperand(0).getValueType(); - MVT NewVT = TLI.getTypeToTransformTo(OldVT); - - assert(OldVT.getSizeInBits() == 2 * NewVT.getSizeInBits() && - "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; - GetExpandedInteger(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::getVectorVT(NewVT, NewElts.size()), - &NewElts[0], NewElts.size()); - - // Convert the new vector to the old vector type. - return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec); -}