Index: llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp +++ llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp @@ -910,6 +910,27 @@ 0); } +// If the result is not legal, eg: fp -> i1, then it needs to be promoted to +// a larger type, eg: fp -> i32. Even if it is legal, no libcall may exactly +// match, eg. we don't have fp -> i8 conversions. +// Look for an appropriate libcall. +static bool findConversionLibcall(RTLIB::Libcall &LC, EVT SrcVT, EVT &RetVT, + bool Signed) { + EVT NVT; + for (unsigned IntVT = MVT::FIRST_INTEGER_VALUETYPE; + IntVT <= MVT::LAST_INTEGER_VALUETYPE && LC == RTLIB::UNKNOWN_LIBCALL; + ++IntVT) { + NVT = (MVT::SimpleValueType)IntVT; + // The type needs to big enough to hold the result. + if (NVT.bitsGE(RetVT)) { + RetVT = NVT; + LC = Signed ? RTLIB::getFPTOSINT(SrcVT, NVT) + : RTLIB::getFPTOUINT(SrcVT, NVT); + } + } + return LC != RTLIB::UNKNOWN_LIBCALL; +} + SDValue DAGTypeLegalizer::SoftenFloatOp_FP_TO_XINT(SDNode *N) { bool IsStrict = N->isStrictFPOpcode(); bool Signed = N->getOpcode() == ISD::FP_TO_SINT || @@ -918,29 +939,16 @@ SDValue Op = N->getOperand(IsStrict ? 1 : 0); EVT SVT = Op.getValueType(); EVT RVT = N->getValueType(0); - EVT NVT = EVT(); SDLoc dl(N); - - // If the result is not legal, eg: fp -> i1, then it needs to be promoted to - // a larger type, eg: fp -> i32. Even if it is legal, no libcall may exactly - // match, eg. we don't have fp -> i8 conversions. - // Look for an appropriate libcall. RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; - for (unsigned IntVT = MVT::FIRST_INTEGER_VALUETYPE; - IntVT <= MVT::LAST_INTEGER_VALUETYPE && LC == RTLIB::UNKNOWN_LIBCALL; - ++IntVT) { - NVT = (MVT::SimpleValueType)IntVT; - // The type needs to big enough to hold the result. - if (NVT.bitsGE(RVT)) - LC = Signed ? RTLIB::getFPTOSINT(SVT, NVT) : RTLIB::getFPTOUINT(SVT, NVT); - } - assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_TO_XINT!"); + assert(findConversionLibcall(LC, SVT, RVT, Signed) && + "Unsupported FP_TO_XINT!"); Op = GetSoftenedFloat(Op); SDValue Chain = IsStrict ? N->getOperand(0) : SDValue(); TargetLowering::MakeLibCallOptions CallOptions; CallOptions.setTypeListBeforeSoften(SVT, RVT, true); - std::pair Tmp = TLI.makeLibCall(DAG, LC, NVT, Op, + std::pair Tmp = TLI.makeLibCall(DAG, LC, RVT, Op, CallOptions, dl, Chain); // Truncate the result if the libcall returns a larger type. @@ -1750,9 +1758,9 @@ case ISD::STRICT_FP_ROUND: case ISD::FP_ROUND: Res = ExpandFloatOp_FP_ROUND(N); break; case ISD::STRICT_FP_TO_SINT: - case ISD::FP_TO_SINT: Res = ExpandFloatOp_FP_TO_SINT(N); break; case ISD::STRICT_FP_TO_UINT: - case ISD::FP_TO_UINT: Res = ExpandFloatOp_FP_TO_UINT(N); break; + case ISD::FP_TO_SINT: + case ISD::FP_TO_UINT: Res = ExpandFloatOp_FP_TO_XINT(N); break; case ISD::LROUND: Res = ExpandFloatOp_LROUND(N); break; case ISD::LLROUND: Res = ExpandFloatOp_LLROUND(N); break; case ISD::LRINT: Res = ExpandFloatOp_LRINT(N); break; @@ -1878,35 +1886,18 @@ return SDValue(); } -SDValue DAGTypeLegalizer::ExpandFloatOp_FP_TO_SINT(SDNode *N) { - EVT RVT = N->getValueType(0); - SDLoc dl(N); - - bool IsStrict = N->isStrictFPOpcode(); - SDValue Op = N->getOperand(IsStrict ? 1 : 0); - SDValue Chain = IsStrict ? N->getOperand(0) : SDValue(); - RTLIB::Libcall LC = RTLIB::getFPTOSINT(Op.getValueType(), RVT); - assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_TO_SINT!"); - TargetLowering::MakeLibCallOptions CallOptions; - std::pair Tmp = TLI.makeLibCall(DAG, LC, RVT, Op, - CallOptions, dl, Chain); - if (!IsStrict) - return Tmp.first; - - ReplaceValueWith(SDValue(N, 1), Tmp.second); - ReplaceValueWith(SDValue(N, 0), Tmp.first); - return SDValue(); -} - -SDValue DAGTypeLegalizer::ExpandFloatOp_FP_TO_UINT(SDNode *N) { +SDValue DAGTypeLegalizer::ExpandFloatOp_FP_TO_XINT(SDNode *N) { EVT RVT = N->getValueType(0); SDLoc dl(N); + bool Signed = N->getOpcode() == ISD::FP_TO_SINT || + N->getOpcode() == ISD::STRICT_FP_TO_SINT; bool IsStrict = N->isStrictFPOpcode(); SDValue Op = N->getOperand(IsStrict ? 1 : 0); SDValue Chain = IsStrict ? N->getOperand(0) : SDValue(); - RTLIB::Libcall LC = RTLIB::getFPTOUINT(Op.getValueType(), RVT); - assert(LC != RTLIB::UNKNOWN_LIBCALL && "Unsupported FP_TO_UINT!"); + RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL; + assert(findConversionLibcall(LC, Op.getValueType(), RVT, Signed) && + "Unsupported FP_TO_XINT!"); TargetLowering::MakeLibCallOptions CallOptions; std::pair Tmp = TLI.makeLibCall(DAG, LC, RVT, Op, CallOptions, dl, Chain); Index: llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h =================================================================== --- llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -629,8 +629,7 @@ SDValue ExpandFloatOp_BR_CC(SDNode *N); SDValue ExpandFloatOp_FCOPYSIGN(SDNode *N); SDValue ExpandFloatOp_FP_ROUND(SDNode *N); - SDValue ExpandFloatOp_FP_TO_SINT(SDNode *N); - SDValue ExpandFloatOp_FP_TO_UINT(SDNode *N); + SDValue ExpandFloatOp_FP_TO_XINT(SDNode *N); SDValue ExpandFloatOp_LROUND(SDNode *N); SDValue ExpandFloatOp_LLROUND(SDNode *N); SDValue ExpandFloatOp_LRINT(SDNode *N); Index: llvm/test/CodeGen/PowerPC/ppcf128-constrained-fp-intrinsics.ll =================================================================== --- llvm/test/CodeGen/PowerPC/ppcf128-constrained-fp-intrinsics.ll +++ llvm/test/CodeGen/PowerPC/ppcf128-constrained-fp-intrinsics.ll @@ -1975,6 +1975,100 @@ ret ppc_fp128 %conv } +define i1 @ppcq_to_s1(ppc_fp128 %a) { +; PC64LE-LABEL: ppcq_to_s1: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: .cfi_def_cfa_offset 32 +; PC64LE-NEXT: .cfi_offset lr, 16 +; PC64LE-NEXT: bl __gcc_qtou +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: ppcq_to_s1: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: .cfi_def_cfa_offset 32 +; PC64LE9-NEXT: .cfi_offset lr, 16 +; PC64LE9-NEXT: bl __gcc_qtou +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: ppcq_to_s1: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: .cfi_def_cfa_offset 112 +; PC64-NEXT: .cfi_offset lr, 16 +; PC64-NEXT: bl __gcc_qtou +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %conv = tail call i1 @llvm.experimental.constrained.fptosi.ppcf128.i1(ppc_fp128 %a, metadata !"fpexcept.strict") #1 + ret i1 %conv +} + +define i1 @ppcq_to_u1(ppc_fp128 %a) { +; PC64LE-LABEL: ppcq_to_u1: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: .cfi_def_cfa_offset 32 +; PC64LE-NEXT: .cfi_offset lr, 16 +; PC64LE-NEXT: bl __fixunstfsi +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: ppcq_to_u1: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: .cfi_def_cfa_offset 32 +; PC64LE9-NEXT: .cfi_offset lr, 16 +; PC64LE9-NEXT: bl __fixunstfsi +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: ppcq_to_u1: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: .cfi_def_cfa_offset 112 +; PC64-NEXT: .cfi_offset lr, 16 +; PC64-NEXT: bl __fixunstfsi +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %conv = tail call i1 @llvm.experimental.constrained.fptoui.ppcf128.i1(ppc_fp128 %a, metadata !"fpexcept.strict") #1 + ret i1 %conv +} + attributes #0 = { nounwind strictfp } attributes #1 = { strictfp } @@ -2008,8 +2102,10 @@ declare ppc_fp128 @llvm.experimental.constrained.trunc.ppcf128(ppc_fp128, metadata) declare i64 @llvm.experimental.constrained.fptosi.i64.ppcf128(ppc_fp128, metadata) declare i32 @llvm.experimental.constrained.fptosi.i32.ppcf128(ppc_fp128, metadata) +declare i1 @llvm.experimental.constrained.fptosi.ppcf128.i1(ppc_fp128, metadata) declare i64 @llvm.experimental.constrained.fptoui.i64.ppcf128(ppc_fp128, metadata) declare i32 @llvm.experimental.constrained.fptoui.i32.ppcf128(ppc_fp128, metadata) +declare i1 @llvm.experimental.constrained.fptoui.ppcf128.i1(ppc_fp128, metadata) declare ppc_fp128 @llvm.experimental.constrained.sitofp.ppcf128.i32(i32, metadata, metadata) declare ppc_fp128 @llvm.experimental.constrained.uitofp.ppcf128.i32(i32, metadata, metadata) declare ppc_fp128 @llvm.experimental.constrained.sitofp.ppcf128.i64(i64, metadata, metadata)