diff --git a/include/llvm/CodeGen/RuntimeLibcalls.h b/include/llvm/CodeGen/RuntimeLibcalls.h index 36b96e11ff9..acbaa1a1ec1 100644 --- a/include/llvm/CodeGen/RuntimeLibcalls.h +++ b/include/llvm/CodeGen/RuntimeLibcalls.h @@ -137,8 +137,16 @@ namespace RTLIB { SINTTOFP_I128_PPCF128, UINTTOFP_I32_F32, UINTTOFP_I32_F64, + UINTTOFP_I32_F80, + UINTTOFP_I32_PPCF128, UINTTOFP_I64_F32, UINTTOFP_I64_F64, + UINTTOFP_I64_F80, + UINTTOFP_I64_PPCF128, + UINTTOFP_I128_F32, + UINTTOFP_I128_F64, + UINTTOFP_I128_F80, + UINTTOFP_I128_PPCF128, // COMPARISON OEQ_F32, diff --git a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp index 20cfc77e022..699ba604e6a 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp @@ -1727,12 +1727,8 @@ bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) { case ISD::TRUNCATE: Res = ExpandIntOp_TRUNCATE(N); break; - case ISD::SINT_TO_FP: - Res = ExpandIntOp_SINT_TO_FP(N->getOperand(0), N->getValueType(0)); - break; - case ISD::UINT_TO_FP: - Res = ExpandIntOp_UINT_TO_FP(N->getOperand(0), N->getValueType(0)); - break; + case ISD::SINT_TO_FP: Res = ExpandIntOp_SINT_TO_FP(N); break; + case ISD::UINT_TO_FP: Res = ExpandIntOp_UINT_TO_FP(N); break; case ISD::BR_CC: Res = ExpandIntOp_BR_CC(N); break; case ISD::SELECT_CC: Res = ExpandIntOp_SELECT_CC(N); break; @@ -1770,99 +1766,134 @@ SDOperand DAGTypeLegalizer::ExpandIntOp_TRUNCATE(SDNode *N) { return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), InL); } -SDOperand DAGTypeLegalizer::ExpandIntOp_SINT_TO_FP(SDOperand Source, - 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: - case TargetLowering::Expand: - break; // This case is handled below. - case TargetLowering::Custom: - SDOperand NV = TLI.LowerOperation(DAG.getNode(ISD::SINT_TO_FP, DestTy, - Source), DAG); - if (NV.Val) return NV; - break; // The target lowered this. - } +SDOperand DAGTypeLegalizer::ExpandIntOp_SINT_TO_FP(SDNode *N) { + SDOperand Op = N->getOperand(0); + MVT SrcVT = Op.getValueType(); + MVT DstVT = N->getValueType(0); RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; - if (SourceVT == MVT::i32) { - if (DestTy == MVT::f32) + if (SrcVT == MVT::i32) { + if (DstVT == MVT::f32) LC = RTLIB::SINTTOFP_I32_F32; - else if (DestTy == MVT::f64) + else if (DstVT == MVT::f64) LC = RTLIB::SINTTOFP_I32_F64; - else if (DestTy == MVT::f80) + else if (DstVT == MVT::f80) LC = RTLIB::SINTTOFP_I32_F80; - else if (DestTy == MVT::ppcf128) + else if (DstVT == MVT::ppcf128) LC = RTLIB::SINTTOFP_I32_PPCF128; - } else if (SourceVT == MVT::i64) { - if (DestTy == MVT::f32) + } else if (SrcVT == MVT::i64) { + if (DstVT == MVT::f32) LC = RTLIB::SINTTOFP_I64_F32; - else if (DestTy == MVT::f64) + else if (DstVT == MVT::f64) LC = RTLIB::SINTTOFP_I64_F64; - else if (DestTy == MVT::f80) + else if (DstVT == MVT::f80) LC = RTLIB::SINTTOFP_I64_F80; - else if (DestTy == MVT::ppcf128) + else if (DstVT == MVT::ppcf128) LC = RTLIB::SINTTOFP_I64_PPCF128; - } else if (SourceVT == MVT::i128) { - if (DestTy == MVT::f32) + } else if (SrcVT == MVT::i128) { + if (DstVT == MVT::f32) LC = RTLIB::SINTTOFP_I128_F32; - else if (DestTy == MVT::f64) + else if (DstVT == MVT::f64) LC = RTLIB::SINTTOFP_I128_F64; - else if (DestTy == MVT::f80) + else if (DstVT == MVT::f80) LC = RTLIB::SINTTOFP_I128_F80; - else if (DestTy == MVT::ppcf128) + else if (DstVT == MVT::ppcf128) LC = RTLIB::SINTTOFP_I128_PPCF128; } assert(LC != RTLIB::UNKNOWN_LIBCALL && "Don't know how to expand this SINT_TO_FP!"); - return MakeLibCall(LC, DestTy, &Source, 1, true); + return MakeLibCall(LC, DstVT, &Op, 1, true); } -SDOperand DAGTypeLegalizer::ExpandIntOp_UINT_TO_FP(SDOperand Source, - MVT DestTy) { - // We know the destination is legal, but that the input needs to be expanded. - assert(getTypeAction(Source.getValueType()) == ExpandInteger && - "This is not an expansion!"); +SDOperand DAGTypeLegalizer::ExpandIntOp_UINT_TO_FP(SDNode *N) { + SDOperand Op = N->getOperand(0); + MVT SrcVT = Op.getValueType(); + MVT DstVT = N->getValueType(0); - // If this is unsigned, and not supported, first perform the conversion to - // signed, then adjust the result if the sign bit is set. - SDOperand SignedConv = ExpandIntOp_SINT_TO_FP(Source, DestTy); + if (TLI.getOperationAction(ISD::SINT_TO_FP, SrcVT) == TargetLowering::Custom){ + // Do a signed conversion then adjust the result. + SDOperand SignedConv = DAG.getNode(ISD::SINT_TO_FP, DstVT, Op); + SignedConv = TLI.LowerOperation(SignedConv, DAG); - // The 64-bit value loaded will be incorrectly if the 'sign bit' of the - // incoming integer is set. To handle this, we dynamically test to see if - // it is set, and, if so, add a fudge factor. - SDOperand Lo, Hi; - GetExpandedInteger(Source, Lo, Hi); + // The result of the signed conversion needs adjusting if the 'sign bit' of + // the incoming integer was set. To handle this, we dynamically test to see + // if it is set, and, if so, add a fudge factor. - SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultType(Hi), Hi, - DAG.getConstant(0, Hi.getValueType()), - ISD::SETLT); - SDOperand Zero = DAG.getIntPtrConstant(0), Four = DAG.getIntPtrConstant(4); - SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(), - SignSet, Four, Zero); - uint64_t FF = 0x5f800000ULL; - if (TLI.isLittleEndian()) FF <<= 32; - Constant *FudgeFactor = ConstantInt::get((Type*)Type::Int64Ty, FF); + const uint64_t F32TwoE32 = 0x4F800000ULL; + const uint64_t F32TwoE64 = 0x5F800000ULL; + const uint64_t F32TwoE128 = 0x7F800000ULL; - SDOperand CPIdx = DAG.getConstantPool(FudgeFactor, TLI.getPointerTy()); - CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset); - SDOperand FudgeInReg; - if (DestTy == MVT::f32) - FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, NULL, 0); - else if (DestTy.bitsGT(MVT::f32)) - // FIXME: Avoid the extend by construction the right constantpool? - FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, DestTy, DAG.getEntryNode(), - CPIdx, NULL, 0, MVT::f32); - else - assert(0 && "Unexpected conversion"); + APInt FF(32, 0); + if (SrcVT == MVT::i32) + FF = APInt(32, F32TwoE32); + else if (SrcVT == MVT::i64) + FF = APInt(32, F32TwoE64); + else if (SrcVT == MVT::i128) + FF = APInt(32, F32TwoE128); + else + assert(false && "Unsupported UINT_TO_FP!"); - return DAG.getNode(ISD::FADD, DestTy, SignedConv, FudgeInReg); + // Check whether the sign bit is set. + SDOperand Lo, Hi; + GetExpandedInteger(Op, Lo, Hi); + SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultType(Hi), Hi, + DAG.getConstant(0, Hi.getValueType()), + ISD::SETLT); + + // Build a 64 bit pair (0, FF) in the constant pool, with FF in the lo bits. + SDOperand FudgePtr = DAG.getConstantPool(ConstantInt::get(FF.zext(64)), + TLI.getPointerTy()); + + // Get a pointer to FF if the sign bit was set, or to 0 otherwise. + SDOperand Zero = DAG.getIntPtrConstant(0); + SDOperand Four = DAG.getIntPtrConstant(4); + if (TLI.isBigEndian()) std::swap(Zero, Four); + SDOperand Offset = DAG.getNode(ISD::SELECT, Zero.getValueType(), SignSet, + Zero, Four); + FudgePtr = DAG.getNode(ISD::ADD, TLI.getPointerTy(), FudgePtr, Offset); + + // Load the value out, extending it from f32 to the destination float type. + // FIXME: Avoid the extend by constructing the right constant pool? + SDOperand Fudge = DAG.getExtLoad(ISD::EXTLOAD, DstVT, DAG.getEntryNode(), + FudgePtr, NULL, 0, MVT::f32); + return DAG.getNode(ISD::FADD, DstVT, SignedConv, Fudge); + } + + // Otherwise, use a libcall. + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + if (SrcVT == MVT::i32) { + if (DstVT == MVT::f32) + LC = RTLIB::UINTTOFP_I32_F32; + else if (DstVT == MVT::f64) + LC = RTLIB::UINTTOFP_I32_F64; + else if (DstVT == MVT::f80) + LC = RTLIB::UINTTOFP_I32_F80; + else if (DstVT == MVT::ppcf128) + LC = RTLIB::UINTTOFP_I32_PPCF128; + } else if (SrcVT == MVT::i64) { + if (DstVT == MVT::f32) + LC = RTLIB::UINTTOFP_I64_F32; + else if (DstVT == MVT::f64) + LC = RTLIB::UINTTOFP_I64_F64; + else if (DstVT == MVT::f80) + LC = RTLIB::UINTTOFP_I64_F80; + else if (DstVT == MVT::ppcf128) + LC = RTLIB::UINTTOFP_I64_PPCF128; + } else if (SrcVT == MVT::i128) { + if (DstVT == MVT::f32) + LC = RTLIB::UINTTOFP_I128_F32; + else if (DstVT == MVT::f64) + LC = RTLIB::UINTTOFP_I128_F64; + else if (DstVT == MVT::f80) + LC = RTLIB::UINTTOFP_I128_F80; + else if (DstVT == MVT::ppcf128) + LC = RTLIB::UINTTOFP_I128_PPCF128; + } + assert(LC != RTLIB::UNKNOWN_LIBCALL && + "Don't know how to expand this UINT_TO_FP!"); + + return MakeLibCall(LC, DstVT, &Op, 1, true); } SDOperand DAGTypeLegalizer::ExpandIntOp_BR_CC(SDNode *N) { diff --git a/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/lib/CodeGen/SelectionDAG/LegalizeTypes.h index f23e5a5ce70..f1ecd2a9730 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -299,10 +299,10 @@ private: SDOperand ExpandIntOp_EXTRACT_ELEMENT(SDNode *N); SDOperand ExpandIntOp_SELECT_CC(SDNode *N); SDOperand ExpandIntOp_SETCC(SDNode *N); - SDOperand ExpandIntOp_SINT_TO_FP(SDOperand Source, MVT DestTy); + SDOperand ExpandIntOp_SINT_TO_FP(SDNode *N); SDOperand ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo); SDOperand ExpandIntOp_TRUNCATE(SDNode *N); - SDOperand ExpandIntOp_UINT_TO_FP(SDOperand Source, MVT DestTy); + SDOperand ExpandIntOp_UINT_TO_FP(SDNode *N); void IntegerExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS, ISD::CondCode &CCCode); diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index b19686820bf..692158e87b2 100644 --- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -135,8 +135,16 @@ static void InitLibcallNames(const char **Names) { Names[RTLIB::SINTTOFP_I128_PPCF128] = "__floattitf"; Names[RTLIB::UINTTOFP_I32_F32] = "__floatunsisf"; Names[RTLIB::UINTTOFP_I32_F64] = "__floatunsidf"; + Names[RTLIB::UINTTOFP_I32_F80] = "__floatunsixf"; + Names[RTLIB::UINTTOFP_I32_PPCF128] = "__floatunsitf"; Names[RTLIB::UINTTOFP_I64_F32] = "__floatundisf"; Names[RTLIB::UINTTOFP_I64_F64] = "__floatundidf"; + Names[RTLIB::UINTTOFP_I64_F80] = "__floatundixf"; + Names[RTLIB::UINTTOFP_I64_PPCF128] = "__floatunditf"; + Names[RTLIB::UINTTOFP_I128_F32] = "__floatuntisf"; + Names[RTLIB::UINTTOFP_I128_F64] = "__floatuntidf"; + Names[RTLIB::UINTTOFP_I128_F80] = "__floatuntixf"; + Names[RTLIB::UINTTOFP_I128_PPCF128] = "__floatuntitf"; Names[RTLIB::OEQ_F32] = "__eqsf2"; Names[RTLIB::OEQ_F64] = "__eqdf2"; Names[RTLIB::UNE_F32] = "__nesf2";