diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp @@ -1108,36 +1108,61 @@ case ISD::ConstantFP: ExpandFloatRes_ConstantFP(N, Lo, Hi); break; case ISD::FABS: ExpandFloatRes_FABS(N, Lo, Hi); break; + case ISD::STRICT_FMINNUM: case ISD::FMINNUM: ExpandFloatRes_FMINNUM(N, Lo, Hi); break; + case ISD::STRICT_FMAXNUM: case ISD::FMAXNUM: ExpandFloatRes_FMAXNUM(N, Lo, Hi); break; + case ISD::STRICT_FADD: case ISD::FADD: ExpandFloatRes_FADD(N, Lo, Hi); break; case ISD::FCBRT: ExpandFloatRes_FCBRT(N, Lo, Hi); break; + case ISD::STRICT_FCEIL: case ISD::FCEIL: ExpandFloatRes_FCEIL(N, Lo, Hi); break; case ISD::FCOPYSIGN: ExpandFloatRes_FCOPYSIGN(N, Lo, Hi); break; + case ISD::STRICT_FCOS: case ISD::FCOS: ExpandFloatRes_FCOS(N, Lo, Hi); break; + case ISD::STRICT_FDIV: case ISD::FDIV: ExpandFloatRes_FDIV(N, Lo, Hi); break; + case ISD::STRICT_FEXP: case ISD::FEXP: ExpandFloatRes_FEXP(N, Lo, Hi); break; + case ISD::STRICT_FEXP2: case ISD::FEXP2: ExpandFloatRes_FEXP2(N, Lo, Hi); break; + case ISD::STRICT_FFLOOR: case ISD::FFLOOR: ExpandFloatRes_FFLOOR(N, Lo, Hi); break; + case ISD::STRICT_FLOG: case ISD::FLOG: ExpandFloatRes_FLOG(N, Lo, Hi); break; + case ISD::STRICT_FLOG2: case ISD::FLOG2: ExpandFloatRes_FLOG2(N, Lo, Hi); break; + case ISD::STRICT_FLOG10: case ISD::FLOG10: ExpandFloatRes_FLOG10(N, Lo, Hi); break; + case ISD::STRICT_FMA: case ISD::FMA: ExpandFloatRes_FMA(N, Lo, Hi); break; + case ISD::STRICT_FMUL: case ISD::FMUL: ExpandFloatRes_FMUL(N, Lo, Hi); break; + case ISD::STRICT_FNEARBYINT: case ISD::FNEARBYINT: ExpandFloatRes_FNEARBYINT(N, Lo, Hi); break; case ISD::FNEG: ExpandFloatRes_FNEG(N, Lo, Hi); break; + case ISD::STRICT_FP_EXTEND: case ISD::FP_EXTEND: ExpandFloatRes_FP_EXTEND(N, Lo, Hi); break; + case ISD::STRICT_FPOW: case ISD::FPOW: ExpandFloatRes_FPOW(N, Lo, Hi); break; + case ISD::STRICT_FPOWI: case ISD::FPOWI: ExpandFloatRes_FPOWI(N, Lo, Hi); break; + case ISD::STRICT_FRINT: case ISD::FRINT: ExpandFloatRes_FRINT(N, Lo, Hi); break; + case ISD::STRICT_FROUND: case ISD::FROUND: ExpandFloatRes_FROUND(N, Lo, Hi); break; + case ISD::STRICT_FSIN: case ISD::FSIN: ExpandFloatRes_FSIN(N, Lo, Hi); break; + case ISD::STRICT_FSQRT: case ISD::FSQRT: ExpandFloatRes_FSQRT(N, Lo, Hi); break; + case ISD::STRICT_FSUB: case ISD::FSUB: ExpandFloatRes_FSUB(N, Lo, Hi); break; + case ISD::STRICT_FTRUNC: case ISD::FTRUNC: ExpandFloatRes_FTRUNC(N, Lo, Hi); break; case ISD::LOAD: ExpandFloatRes_LOAD(N, Lo, Hi); break; case ISD::SINT_TO_FP: case ISD::UINT_TO_FP: ExpandFloatRes_XINT_TO_FP(N, Lo, Hi); break; + case ISD::STRICT_FREM: case ISD::FREM: ExpandFloatRes_FREM(N, Lo, Hi); break; } @@ -1161,6 +1186,36 @@ dl, NVT); } +void DAGTypeLegalizer::ExpandFloatRes_Unary(SDNode *N, RTLIB::Libcall LC, + SDValue &Lo, SDValue &Hi) { + bool IsStrict = N->isStrictFPOpcode(); + unsigned Offset = IsStrict ? 1 : 0; + SDValue Op = N->getOperand(0 + Offset); + SDValue Chain = IsStrict ? N->getOperand(0) : SDValue(); + TargetLowering::MakeLibCallOptions CallOptions; + std::pair Tmp = TLI.makeLibCall(DAG, LC, N->getValueType(0), + Op, CallOptions, SDLoc(N), + Chain); + if (IsStrict) + ReplaceValueWith(SDValue(N, 1), Tmp.second); + GetPairElements(Tmp.first, Lo, Hi); +} + +void DAGTypeLegalizer::ExpandFloatRes_Binary(SDNode *N, RTLIB::Libcall LC, + SDValue &Lo, SDValue &Hi) { + bool IsStrict = N->isStrictFPOpcode(); + unsigned Offset = IsStrict ? 1 : 0; + SDValue Ops[] = { N->getOperand(0 + Offset), N->getOperand(1 + Offset) }; + SDValue Chain = IsStrict ? N->getOperand(0) : SDValue(); + TargetLowering::MakeLibCallOptions CallOptions; + std::pair Tmp = TLI.makeLibCall(DAG, LC, N->getValueType(0), + Ops, CallOptions, SDLoc(N), + Chain); + if (IsStrict) + ReplaceValueWith(SDValue(N, 1), Tmp.second); + GetPairElements(Tmp.first, Lo, Hi); +} + void DAGTypeLegalizer::ExpandFloatRes_FABS(SDNode *N, SDValue &Lo, SDValue &Hi) { assert(N->getValueType(0) == MVT::ppcf128 && @@ -1177,190 +1232,159 @@ void DAGTypeLegalizer::ExpandFloatRes_FMINNUM(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::FMIN_F32, RTLIB::FMIN_F64, - RTLIB::FMIN_F80, RTLIB::FMIN_F128, - RTLIB::FMIN_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), + RTLIB::FMIN_F32, RTLIB::FMIN_F64, + RTLIB::FMIN_F80, RTLIB::FMIN_F128, + RTLIB::FMIN_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FMAXNUM(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::FMAX_F32, RTLIB::FMAX_F64, - RTLIB::FMAX_F80, RTLIB::FMAX_F128, - RTLIB::FMAX_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0), + RTLIB::FMAX_F32, RTLIB::FMAX_F64, + RTLIB::FMAX_F80, RTLIB::FMAX_F128, + RTLIB::FMAX_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FADD(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::ADD_F32, RTLIB::ADD_F64, - RTLIB::ADD_F80, RTLIB::ADD_F128, - RTLIB::ADD_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0), + RTLIB::ADD_F32, RTLIB::ADD_F64, + RTLIB::ADD_F80, RTLIB::ADD_F128, + RTLIB::ADD_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FCBRT(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), RTLIB::CBRT_F32, - RTLIB::CBRT_F64, RTLIB::CBRT_F80, - RTLIB::CBRT_F128, RTLIB::CBRT_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), RTLIB::CBRT_F32, + RTLIB::CBRT_F64, RTLIB::CBRT_F80, + RTLIB::CBRT_F128, + RTLIB::CBRT_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FCEIL(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::CEIL_F32, RTLIB::CEIL_F64, - RTLIB::CEIL_F80, RTLIB::CEIL_F128, - RTLIB::CEIL_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), + RTLIB::CEIL_F32, RTLIB::CEIL_F64, + RTLIB::CEIL_F80, RTLIB::CEIL_F128, + RTLIB::CEIL_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FCOPYSIGN(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::COPYSIGN_F32, - RTLIB::COPYSIGN_F64, - RTLIB::COPYSIGN_F80, - RTLIB::COPYSIGN_F128, - RTLIB::COPYSIGN_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0), + RTLIB::COPYSIGN_F32, + RTLIB::COPYSIGN_F64, + RTLIB::COPYSIGN_F80, + RTLIB::COPYSIGN_F128, + RTLIB::COPYSIGN_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FCOS(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::COS_F32, RTLIB::COS_F64, - RTLIB::COS_F80, RTLIB::COS_F128, - RTLIB::COS_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), + RTLIB::COS_F32, RTLIB::COS_F64, + RTLIB::COS_F80, RTLIB::COS_F128, + RTLIB::COS_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FDIV(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; - TargetLowering::MakeLibCallOptions CallOptions; - SDValue Call = TLI.makeLibCall(DAG, GetFPLibCall(N->getValueType(0), - RTLIB::DIV_F32, - RTLIB::DIV_F64, - RTLIB::DIV_F80, - RTLIB::DIV_F128, - RTLIB::DIV_PPCF128), - N->getValueType(0), Ops, CallOptions, - SDLoc(N)).first; - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0), + RTLIB::DIV_F32, + RTLIB::DIV_F64, + RTLIB::DIV_F80, + RTLIB::DIV_F128, + RTLIB::DIV_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FEXP(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::EXP_F32, RTLIB::EXP_F64, - RTLIB::EXP_F80, RTLIB::EXP_F128, - RTLIB::EXP_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), + RTLIB::EXP_F32, RTLIB::EXP_F64, + RTLIB::EXP_F80, RTLIB::EXP_F128, + RTLIB::EXP_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FEXP2(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::EXP2_F32, RTLIB::EXP2_F64, - RTLIB::EXP2_F80, RTLIB::EXP2_F128, - RTLIB::EXP2_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), + RTLIB::EXP2_F32, RTLIB::EXP2_F64, + RTLIB::EXP2_F80, RTLIB::EXP2_F128, + RTLIB::EXP2_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FFLOOR(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::FLOOR_F32, RTLIB::FLOOR_F64, - RTLIB::FLOOR_F80, RTLIB::FLOOR_F128, - RTLIB::FLOOR_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), + RTLIB::FLOOR_F32, RTLIB::FLOOR_F64, + RTLIB::FLOOR_F80, RTLIB::FLOOR_F128, + RTLIB::FLOOR_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FLOG(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::LOG_F32, RTLIB::LOG_F64, - RTLIB::LOG_F80, RTLIB::LOG_F128, - RTLIB::LOG_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), + RTLIB::LOG_F32, RTLIB::LOG_F64, + RTLIB::LOG_F80, RTLIB::LOG_F128, + RTLIB::LOG_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FLOG2(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::LOG2_F32, RTLIB::LOG2_F64, - RTLIB::LOG2_F80, RTLIB::LOG2_F128, - RTLIB::LOG2_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), + RTLIB::LOG2_F32, RTLIB::LOG2_F64, + RTLIB::LOG2_F80, RTLIB::LOG2_F128, + RTLIB::LOG2_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FLOG10(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::LOG10_F32, RTLIB::LOG10_F64, - RTLIB::LOG10_F80, RTLIB::LOG10_F128, - RTLIB::LOG10_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), + RTLIB::LOG10_F32, RTLIB::LOG10_F64, + RTLIB::LOG10_F80, RTLIB::LOG10_F128, + RTLIB::LOG10_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FMA(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Ops[3] = { N->getOperand(0), N->getOperand(1), N->getOperand(2) }; + bool IsStrict = N->isStrictFPOpcode(); + unsigned Offset = IsStrict ? 1 : 0; + SDValue Ops[3] = { N->getOperand(0 + Offset), N->getOperand(1 + Offset), + N->getOperand(2 + Offset) }; + SDValue Chain = IsStrict ? N->getOperand(0) : SDValue(); TargetLowering::MakeLibCallOptions CallOptions; - SDValue Call = TLI.makeLibCall(DAG, GetFPLibCall(N->getValueType(0), + std::pair Tmp = TLI.makeLibCall(DAG, GetFPLibCall(N->getValueType(0), RTLIB::FMA_F32, RTLIB::FMA_F64, RTLIB::FMA_F80, RTLIB::FMA_F128, RTLIB::FMA_PPCF128), N->getValueType(0), Ops, CallOptions, - SDLoc(N)).first; - GetPairElements(Call, Lo, Hi); + SDLoc(N), Chain); + if (IsStrict) + ReplaceValueWith(SDValue(N, 1), Tmp.second); + GetPairElements(Tmp.first, Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FMUL(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; - TargetLowering::MakeLibCallOptions CallOptions; - SDValue Call = TLI.makeLibCall(DAG, GetFPLibCall(N->getValueType(0), + ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0), RTLIB::MUL_F32, RTLIB::MUL_F64, RTLIB::MUL_F80, RTLIB::MUL_F128, - RTLIB::MUL_PPCF128), - N->getValueType(0), Ops, CallOptions, - SDLoc(N)).first; - GetPairElements(Call, Lo, Hi); + RTLIB::MUL_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FNEARBYINT(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::NEARBYINT_F32, - RTLIB::NEARBYINT_F64, - RTLIB::NEARBYINT_F80, - RTLIB::NEARBYINT_F128, - RTLIB::NEARBYINT_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), + RTLIB::NEARBYINT_F32, + RTLIB::NEARBYINT_F64, + RTLIB::NEARBYINT_F80, + RTLIB::NEARBYINT_F128, + RTLIB::NEARBYINT_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FNEG(SDNode *N, SDValue &Lo, @@ -1375,106 +1399,105 @@ SDValue &Hi) { EVT NVT = TLI.getTypeToTransformTo(*DAG.getContext(), N->getValueType(0)); SDLoc dl(N); - Hi = DAG.getNode(ISD::FP_EXTEND, dl, NVT, N->getOperand(0)); + bool IsStrict = N->isStrictFPOpcode(); + + SDValue Chain; + if (IsStrict) { + // If the expanded type is the same as the input type, just bypass the node. + if (NVT == N->getOperand(1).getValueType()) { + Hi = N->getOperand(1); + Chain = N->getOperand(0); + } else { + // Other we need to extend. + Hi = DAG.getNode(ISD::STRICT_FP_EXTEND, dl, { NVT, MVT::Other }, + { N->getOperand(0), N->getOperand(1) }); + Chain = Hi.getValue(1); + } + } else { + Hi = DAG.getNode(ISD::FP_EXTEND, dl, NVT, N->getOperand(0)); + } + Lo = DAG.getConstantFP(APFloat(DAG.EVTToAPFloatSemantics(NVT), APInt(NVT.getSizeInBits(), 0)), dl, NVT); + + if (IsStrict) + ReplaceValueWith(SDValue(N, 1), Chain); } void DAGTypeLegalizer::ExpandFloatRes_FPOW(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::POW_F32, RTLIB::POW_F64, - RTLIB::POW_F80, RTLIB::POW_F128, - RTLIB::POW_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0), + RTLIB::POW_F32, RTLIB::POW_F64, + RTLIB::POW_F80, RTLIB::POW_F128, + RTLIB::POW_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FPOWI(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::POWI_F32, RTLIB::POWI_F64, - RTLIB::POWI_F80, RTLIB::POWI_F128, - RTLIB::POWI_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0), + RTLIB::POWI_F32, RTLIB::POWI_F64, + RTLIB::POWI_F80, RTLIB::POWI_F128, + RTLIB::POWI_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FREM(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::REM_F32, RTLIB::REM_F64, - RTLIB::REM_F80, RTLIB::REM_F128, - RTLIB::REM_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0), + RTLIB::REM_F32, RTLIB::REM_F64, + RTLIB::REM_F80, RTLIB::REM_F128, + RTLIB::REM_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FRINT(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::RINT_F32, RTLIB::RINT_F64, - RTLIB::RINT_F80, RTLIB::RINT_F128, - RTLIB::RINT_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), + RTLIB::RINT_F32, RTLIB::RINT_F64, + RTLIB::RINT_F80, RTLIB::RINT_F128, + RTLIB::RINT_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FROUND(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::ROUND_F32, - RTLIB::ROUND_F64, - RTLIB::ROUND_F80, - RTLIB::ROUND_F128, - RTLIB::ROUND_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), + RTLIB::ROUND_F32, + RTLIB::ROUND_F64, + RTLIB::ROUND_F80, + RTLIB::ROUND_F128, + RTLIB::ROUND_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FSIN(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::SIN_F32, RTLIB::SIN_F64, - RTLIB::SIN_F80, RTLIB::SIN_F128, - RTLIB::SIN_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), + RTLIB::SIN_F32, RTLIB::SIN_F64, + RTLIB::SIN_F80, RTLIB::SIN_F128, + RTLIB::SIN_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FSQRT(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::SQRT_F32, RTLIB::SQRT_F64, - RTLIB::SQRT_F80, RTLIB::SQRT_F128, - RTLIB::SQRT_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), + RTLIB::SQRT_F32, RTLIB::SQRT_F64, + RTLIB::SQRT_F80, RTLIB::SQRT_F128, + RTLIB::SQRT_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FSUB(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; - TargetLowering::MakeLibCallOptions CallOptions; - SDValue Call = TLI.makeLibCall(DAG, GetFPLibCall(N->getValueType(0), - RTLIB::SUB_F32, - RTLIB::SUB_F64, - RTLIB::SUB_F80, - RTLIB::SUB_F128, - RTLIB::SUB_PPCF128), - N->getValueType(0), Ops, CallOptions, - SDLoc(N)).first; - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Binary(N, GetFPLibCall(N->getValueType(0), + RTLIB::SUB_F32, + RTLIB::SUB_F64, + RTLIB::SUB_F80, + RTLIB::SUB_F128, + RTLIB::SUB_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_FTRUNC(SDNode *N, SDValue &Lo, SDValue &Hi) { - SDValue Call = LibCallify(GetFPLibCall(N->getValueType(0), - RTLIB::TRUNC_F32, RTLIB::TRUNC_F64, - RTLIB::TRUNC_F80, RTLIB::TRUNC_F128, - RTLIB::TRUNC_PPCF128), - N, false); - GetPairElements(Call, Lo, Hi); + ExpandFloatRes_Unary(N, GetFPLibCall(N->getValueType(0), + RTLIB::TRUNC_F32, RTLIB::TRUNC_F64, + RTLIB::TRUNC_F80, RTLIB::TRUNC_F128, + RTLIB::TRUNC_PPCF128), Lo, Hi); } void DAGTypeLegalizer::ExpandFloatRes_LOAD(SDNode *N, SDValue &Lo, @@ -1615,8 +1638,11 @@ case ISD::BR_CC: Res = ExpandFloatOp_BR_CC(N); break; case ISD::FCOPYSIGN: Res = ExpandFloatOp_FCOPYSIGN(N); break; + 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::LROUND: Res = ExpandFloatOp_LROUND(N); break; case ISD::LLROUND: Res = ExpandFloatOp_LLROUND(N); break; @@ -1705,34 +1731,72 @@ } SDValue DAGTypeLegalizer::ExpandFloatOp_FP_ROUND(SDNode *N) { - assert(N->getOperand(0).getValueType() == MVT::ppcf128 && + bool IsStrict = N->isStrictFPOpcode(); + assert(N->getOperand(IsStrict ? 1 : 0).getValueType() == MVT::ppcf128 && "Logic only correct for ppcf128!"); SDValue Lo, Hi; - GetExpandedFloat(N->getOperand(0), Lo, Hi); - // Round it the rest of the way (e.g. to f32) if needed. - return DAG.getNode(ISD::FP_ROUND, SDLoc(N), - N->getValueType(0), Hi, N->getOperand(1)); + GetExpandedFloat(N->getOperand(IsStrict ? 1 : 0), Lo, Hi); + + if (!IsStrict) + // Round it the rest of the way (e.g. to f32) if needed. + return DAG.getNode(ISD::FP_ROUND, SDLoc(N), + N->getValueType(0), Hi, N->getOperand(1)); + + // Eliminate the node if the input float type is the same as the output float + // type. + if (Hi.getValueType() == N->getValueType(0)) { + // Connect the output chain to the input chain, unlinking the node. + ReplaceValueWith(SDValue(N, 1), N->getOperand(0)); + ReplaceValueWith(SDValue(N, 0), Hi); + return SDValue(); + } + + SDValue Expansion = DAG.getNode(ISD::STRICT_FP_ROUND, SDLoc(N), + {N->getValueType(0), MVT::Other}, + {N->getOperand(0), Hi, N->getOperand(2)}); + ReplaceValueWith(SDValue(N, 1), Expansion.getValue(1)); + ReplaceValueWith(SDValue(N, 0), Expansion); + return SDValue(); } SDValue DAGTypeLegalizer::ExpandFloatOp_FP_TO_SINT(SDNode *N) { EVT RVT = N->getValueType(0); SDLoc dl(N); - RTLIB::Libcall LC = RTLIB::getFPTOSINT(N->getOperand(0).getValueType(), RVT); + 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; - return TLI.makeLibCall(DAG, LC, RVT, N->getOperand(0), CallOptions, dl).first; + 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) { EVT RVT = N->getValueType(0); SDLoc dl(N); - RTLIB::Libcall LC = RTLIB::getFPTOUINT(N->getOperand(0).getValueType(), RVT); + 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!"); TargetLowering::MakeLibCallOptions CallOptions; - return TLI.makeLibCall(DAG, LC, N->getValueType(0), N->getOperand(0), - CallOptions, dl).first; + 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_SELECT_CC(SDNode *N) { diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.h @@ -215,7 +215,6 @@ SDValue DisintegrateMERGE_VALUES(SDNode *N, unsigned ResNo); SDValue JoinIntegers(SDValue Lo, SDValue Hi); - SDValue LibCallify(RTLIB::Libcall LC, SDNode *N, bool isSigned); std::pair ExpandAtomic(SDNode *Node); @@ -560,6 +559,10 @@ // Float Result Expansion. void ExpandFloatResult(SDNode *N, unsigned ResNo); void ExpandFloatRes_ConstantFP(SDNode *N, SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_Unary(SDNode *N, RTLIB::Libcall LC, + SDValue &Lo, SDValue &Hi); + void ExpandFloatRes_Binary(SDNode *N, RTLIB::Libcall LC, + SDValue &Lo, SDValue &Hi); void ExpandFloatRes_FABS (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandFloatRes_FMINNUM (SDNode *N, SDValue &Lo, SDValue &Hi); void ExpandFloatRes_FMAXNUM (SDNode *N, SDValue &Lo, SDValue &Hi); diff --git a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp --- a/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp @@ -974,32 +974,6 @@ return DAG.getNode(ISD::OR, dlHi, NVT, Lo, Hi); } -/// Convert the node into a libcall with the same prototype. -SDValue DAGTypeLegalizer::LibCallify(RTLIB::Libcall LC, SDNode *N, - bool isSigned) { - TargetLowering::MakeLibCallOptions CallOptions; - CallOptions.setSExt(isSigned); - unsigned NumOps = N->getNumOperands(); - SDLoc dl(N); - if (NumOps == 0) { - return TLI.makeLibCall(DAG, LC, N->getValueType(0), None, CallOptions, - dl).first; - } else if (NumOps == 1) { - SDValue Op = N->getOperand(0); - return TLI.makeLibCall(DAG, LC, N->getValueType(0), Op, CallOptions, - dl).first; - } else if (NumOps == 2) { - SDValue Ops[2] = { N->getOperand(0), N->getOperand(1) }; - return TLI.makeLibCall(DAG, LC, N->getValueType(0), Ops, CallOptions, - dl).first; - } - SmallVector Ops(NumOps); - for (unsigned i = 0; i < NumOps; ++i) - Ops[i] = N->getOperand(i); - - return TLI.makeLibCall(DAG, LC, N->getValueType(0), Ops, CallOptions, dl).first; -} - /// Promote the given target boolean to a target boolean of the given type. /// A target boolean is an integer value, not necessarily of type i1, the bits /// of which conform to getBooleanContents. diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp --- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -7322,8 +7322,40 @@ if (VTList.NumVTs == 1) return getNode(Opcode, DL, VTList.VTs[0], Ops); -#if 0 switch (Opcode) { + case ISD::STRICT_FP_EXTEND: + assert(VTList.NumVTs == 2 && Ops.size() == 2 && + "Invalid STRICT_FP_EXTEND!"); + assert(VTList.VTs[0].isFloatingPoint() && + Ops[1].getValueType().isFloatingPoint() && "Invalid FP cast!"); + assert(VTList.VTs[0].isVector() == Ops[1].getValueType().isVector() && + "STRICT_FP_EXTEND result type should be vector iff the operand " + "type is vector!"); + assert((!VTList.VTs[0].isVector() || + VTList.VTs[0].getVectorNumElements() == + Ops[1].getValueType().getVectorNumElements()) && + "Vector element count mismatch!"); + assert(Ops[1].getValueType().bitsLT(VTList.VTs[0]) && + "Invalid fpext node, dst <= src!"); + break; + case ISD::STRICT_FP_ROUND: + assert(VTList.NumVTs == 2 && Ops.size() == 3 && "Invalid STRICT_FP_ROUND!"); + assert(VTList.VTs[0].isVector() == Ops[1].getValueType().isVector() && + "STRICT_FP_ROUND result type should be vector iff the operand " + "type is vector!"); + assert((!VTList.VTs[0].isVector() || + VTList.VTs[0].getVectorNumElements() == + Ops[1].getValueType().getVectorNumElements()) && + "Vector element count mismatch!"); + assert(VTList.VTs[0].isFloatingPoint() && + Ops[1].getValueType().isFloatingPoint() && + VTList.VTs[0].bitsLT(Ops[1].getValueType()) && + isa(Ops[2]) && + (cast(Ops[2])->getZExtValue() == 0 || + cast(Ops[2])->getZExtValue() == 1) && + "Invalid STRICT_FP_ROUND!"); + break; +#if 0 // FIXME: figure out how to safely handle things like // int foo(int x) { return 1 << (x & 255); } // int bar() { return foo(256); } @@ -7342,8 +7374,8 @@ return getNode(Opcode, DL, VT, N1, N2, N3.getOperand(0)); } break; - } #endif + } // Memoize the node unless it returns a flag. SDNode *N; diff --git a/llvm/test/CodeGen/PowerPC/ppcf128-constrained-fp-intrinsics.ll b/llvm/test/CodeGen/PowerPC/ppcf128-constrained-fp-intrinsics.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/PowerPC/ppcf128-constrained-fp-intrinsics.ll @@ -0,0 +1,1569 @@ +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py +; RUN: llc -O3 -mtriple=powerpc64le-linux-gnu < %s | FileCheck --check-prefix=PC64LE %s +; RUN: llc -O3 -mtriple=powerpc64le-linux-gnu -mcpu=pwr9 < %s | FileCheck --check-prefix=PC64LE9 %s +; RUN: llc -O3 -mtriple=powerpc64-linux-gnu < %s | FileCheck --check-prefix=PC64 %s + +define ppc_fp128 @test_fadd_ppc_fp128(ppc_fp128 %first, ppc_fp128 %second) nounwind { +; PC64LE-LABEL: test_fadd_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl __gcc_qadd +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_fadd_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl __gcc_qadd +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_fadd_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl __gcc_qadd +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %add = call ppc_fp128 @llvm.experimental.constrained.fadd.ppcf128( + ppc_fp128 %first, + ppc_fp128 %second, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %add +} + +define ppc_fp128 @test_fsub_ppc_fp128(ppc_fp128 %first, ppc_fp128 %second) nounwind { +; PC64LE-LABEL: test_fsub_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl __gcc_qsub +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_fsub_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl __gcc_qsub +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_fsub_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl __gcc_qsub +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %sub = call ppc_fp128 @llvm.experimental.constrained.fsub.ppcf128( + ppc_fp128 %first, + ppc_fp128 %second, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %sub +} + +define ppc_fp128 @test_fmul_ppc_fp128(ppc_fp128 %first, ppc_fp128 %second) nounwind { +; PC64LE-LABEL: test_fmul_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl __gcc_qmul +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_fmul_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl __gcc_qmul +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_fmul_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl __gcc_qmul +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %mul = call ppc_fp128 @llvm.experimental.constrained.fmul.ppcf128( + ppc_fp128 %first, + ppc_fp128 %second, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %mul +} + +define ppc_fp128 @test_fdiv_ppc_fp128(ppc_fp128 %first, ppc_fp128 %second) nounwind { +; PC64LE-LABEL: test_fdiv_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl __gcc_qdiv +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_fdiv_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl __gcc_qdiv +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_fdiv_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl __gcc_qdiv +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %div = call ppc_fp128 @llvm.experimental.constrained.fdiv.ppcf128( + ppc_fp128 %first, + ppc_fp128 %second, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %div +} + +define ppc_fp128 @test_frem_ppc_fp128(ppc_fp128 %first, ppc_fp128 %second) nounwind { +; PC64LE-LABEL: test_frem_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl fmodl +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_frem_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl fmodl +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_frem_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl fmodl +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %rem = call ppc_fp128 @llvm.experimental.constrained.frem.ppcf128( + ppc_fp128 %first, + ppc_fp128 %second, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %rem +} + +define ppc_fp128 @test_fma_ppc_fp128(ppc_fp128 %first, ppc_fp128 %second, ppc_fp128 %third) nounwind { +; PC64LE-LABEL: test_fma_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl fmal +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_fma_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl fmal +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_fma_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl fmal +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %add = call ppc_fp128 @llvm.experimental.constrained.fma.ppcf128( + ppc_fp128 %first, + ppc_fp128 %second, + ppc_fp128 %third, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %add +} + +define ppc_fp128 @test_sqrt_ppc_fp128(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_sqrt_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl sqrtl +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_sqrt_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl sqrtl +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_sqrt_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl sqrtl +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %sqrt = call ppc_fp128 @llvm.experimental.constrained.sqrt.ppcf128( + ppc_fp128 %first, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %sqrt +} + +define ppc_fp128 @test_pow_ppc_fp128(ppc_fp128 %first, ppc_fp128 %second) nounwind { +; PC64LE-LABEL: test_pow_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl powl +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_pow_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl powl +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_pow_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl powl +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %pow = call ppc_fp128 @llvm.experimental.constrained.pow.ppcf128( + ppc_fp128 %first, + ppc_fp128 %second, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %pow +} + +define ppc_fp128 @test_powi_ppc_fp128(ppc_fp128 %first, i32 %second) nounwind { +; PC64LE-LABEL: test_powi_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: clrldi 5, 5, 32 +; PC64LE-NEXT: bl __powitf2 +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_powi_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: clrldi 5, 5, 32 +; PC64LE9-NEXT: bl __powitf2 +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_powi_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: clrldi 5, 5, 32 +; PC64-NEXT: bl __powitf2 +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +; PC64LE9 : clrldi 5, 5, 32 +entry: + %powi = call ppc_fp128 @llvm.experimental.constrained.powi.ppcf128( + ppc_fp128 %first, + i32 %second, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %powi +} + +define ppc_fp128 @test_sin_ppc_fp128(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_sin_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl sinl +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_sin_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl sinl +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_sin_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl sinl +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %sin = call ppc_fp128 @llvm.experimental.constrained.sin.ppcf128( + ppc_fp128 %first, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %sin +} + +define ppc_fp128 @test_cos_ppc_fp128(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_cos_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl cosl +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_cos_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl cosl +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_cos_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl cosl +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %cos = call ppc_fp128 @llvm.experimental.constrained.cos.ppcf128( + ppc_fp128 %first, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %cos +} + +define ppc_fp128 @test_exp_ppc_fp128(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_exp_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl expl +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_exp_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl expl +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_exp_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl expl +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %exp = call ppc_fp128 @llvm.experimental.constrained.exp.ppcf128( + ppc_fp128 %first, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %exp +} + +define ppc_fp128 @test_exp2_ppc_fp128(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_exp2_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl exp2l +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_exp2_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl exp2l +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_exp2_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl exp2l +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %exp2 = call ppc_fp128 @llvm.experimental.constrained.exp2.ppcf128( + ppc_fp128 %first, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %exp2 +} + +define ppc_fp128 @test_log_ppc_fp128(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_log_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl logl +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_log_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl logl +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_log_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl logl +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %log = call ppc_fp128 @llvm.experimental.constrained.log.ppcf128( + ppc_fp128 %first, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %log +} + +define ppc_fp128 @test_log2_ppc_fp128(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_log2_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl log2l +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_log2_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl log2l +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_log2_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl log2l +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %log2 = call ppc_fp128 @llvm.experimental.constrained.log2.ppcf128( + ppc_fp128 %first, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %log2 +} + +define ppc_fp128 @test_log10_ppc_fp128(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_log10_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl log10l +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_log10_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl log10l +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_log10_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl log10l +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %log10 = call ppc_fp128 @llvm.experimental.constrained.log10.ppcf128( + ppc_fp128 %first, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %log10 +} + +define ppc_fp128 @test_rint_ppc_fp128(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_rint_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl rintl +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_rint_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl rintl +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_rint_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl rintl +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %rint = call ppc_fp128 @llvm.experimental.constrained.rint.ppcf128( + ppc_fp128 %first, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %rint +} + +define ppc_fp128 @test_nearbyint_ppc_fp128(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_nearbyint_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl nearbyintl +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_nearbyint_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl nearbyintl +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_nearbyint_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl nearbyintl +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %nearbyint = call ppc_fp128 @llvm.experimental.constrained.nearbyint.ppcf128( + ppc_fp128 %first, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %nearbyint +} + +define ppc_fp128 @test_maxnum_ppc_fp128(ppc_fp128 %first, ppc_fp128 %second) nounwind { +; PC64LE-LABEL: test_maxnum_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl fmaxl +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_maxnum_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl fmaxl +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_maxnum_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl fmaxl +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %maxnum = call ppc_fp128 @llvm.experimental.constrained.maxnum.ppcf128( + ppc_fp128 %first, + ppc_fp128 %second, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %maxnum +} + +define ppc_fp128 @test_minnum_ppc_fp128(ppc_fp128 %first, ppc_fp128 %second) nounwind { +; PC64LE-LABEL: test_minnum_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl fminl +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_minnum_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl fminl +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_minnum_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl fminl +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %minnum = call ppc_fp128 @llvm.experimental.constrained.minnum.ppcf128( + ppc_fp128 %first, + ppc_fp128 %second, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %minnum +} + +define ppc_fp128 @test_ceil_ppc_fp128(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_ceil_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl ceill +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_ceil_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl ceill +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_ceil_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl ceill +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %ceil = call ppc_fp128 @llvm.experimental.constrained.ceil.ppcf128( + ppc_fp128 %first, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %ceil +} + +define ppc_fp128 @test_floor_ppc_fp128(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_floor_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl floorl +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_floor_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl floorl +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_floor_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl floorl +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %floor = call ppc_fp128 @llvm.experimental.constrained.floor.ppcf128( + ppc_fp128 %first, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %floor +} + +define ppc_fp128 @test_round_ppc_fp128(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_round_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl roundl +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_round_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl roundl +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_round_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl roundl +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %round = call ppc_fp128 @llvm.experimental.constrained.round.ppcf128( + ppc_fp128 %first, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %round +} + +define ppc_fp128 @test_trunc_ppc_fp128(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_trunc_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl truncl +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_trunc_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl truncl +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_trunc_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl truncl +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %trunc = call ppc_fp128 @llvm.experimental.constrained.trunc.ppcf128( + ppc_fp128 %first, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret ppc_fp128 %trunc +} + +define float @test_fptrunc_ppc_fp128_f32(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_fptrunc_ppc_fp128_f32: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: frsp 1, 1 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_fptrunc_ppc_fp128_f32: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: frsp 1, 1 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_fptrunc_ppc_fp128_f32: +; PC64: # %bb.0: # %entry +; PC64-NEXT: frsp 1, 1 +; PC64-NEXT: blr +entry: + %fptrunc = call float @llvm.experimental.constrained.fptrunc.ppcf128.f32( + ppc_fp128 %first, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret float %fptrunc +} + +define double @test_fptrunc_ppc_fp128_f64(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_fptrunc_ppc_fp128_f64: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_fptrunc_ppc_fp128_f64: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_fptrunc_ppc_fp128_f64: +; PC64: # %bb.0: # %entry +; PC64-NEXT: blr +entry: + %fptrunc = call double @llvm.experimental.constrained.fptrunc.ppcf128.f64( + ppc_fp128 %first, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + ret double %fptrunc +} + +define ppc_fp128 @test_fpext_ppc_fp128_f32(float %first) nounwind { +; PC64LE-LABEL: test_fpext_ppc_fp128_f32: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: xxlxor 2, 2, 2 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_fpext_ppc_fp128_f32: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: xxlxor 2, 2, 2 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_fpext_ppc_fp128_f32: +; PC64: # %bb.0: # %entry +; PC64-NEXT: addis 3, 2, .LCPI26_0@toc@ha +; PC64-NEXT: lfs 2, .LCPI26_0@toc@l(3) +; PC64-NEXT: blr +entry: + %fpext = call ppc_fp128 @llvm.experimental.constrained.fpext.f32.ppcf128( + float %first, + metadata !"fpexcept.strict") + ret ppc_fp128 %fpext +} + +define ppc_fp128 @test_fpext_ppc_fp128_f64(double %first) nounwind { +; PC64LE-LABEL: test_fpext_ppc_fp128_f64: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: xxlxor 2, 2, 2 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_fpext_ppc_fp128_f64: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: xxlxor 2, 2, 2 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_fpext_ppc_fp128_f64: +; PC64: # %bb.0: # %entry +; PC64-NEXT: addis 3, 2, .LCPI27_0@toc@ha +; PC64-NEXT: lfs 2, .LCPI27_0@toc@l(3) +; PC64-NEXT: blr +entry: + %fpext = call ppc_fp128 @llvm.experimental.constrained.fpext.f64.ppcf128( + double %first, + metadata !"fpexcept.strict") + ret ppc_fp128 %fpext +} + +define i64 @test_fptosi_ppc_i64_ppc_fp128(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_fptosi_ppc_i64_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl __fixtfdi +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_fptosi_ppc_i64_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl __fixtfdi +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_fptosi_ppc_i64_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl __fixtfdi +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %fpext = call i64 @llvm.experimental.constrained.fptosi.i64.ppcf128( + ppc_fp128 %first, + metadata !"fpexcept.strict") + ret i64 %fpext +} + +define i32 @test_fptosi_ppc_i32_ppc_fp128(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_fptosi_ppc_i32_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; 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: test_fptosi_ppc_i32_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; 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: test_fptosi_ppc_i32_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; 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: + %fpext = call i32 @llvm.experimental.constrained.fptosi.i32.ppcf128( + ppc_fp128 %first, + metadata !"fpexcept.strict") + ret i32 %fpext +} + +define i64 @test_fptoui_ppc_i64_ppc_fp128(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_fptoui_ppc_i64_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; PC64LE-NEXT: bl __fixunstfdi +; PC64LE-NEXT: nop +; PC64LE-NEXT: addi 1, 1, 32 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_fptoui_ppc_i64_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; PC64LE9-NEXT: bl __fixunstfdi +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: addi 1, 1, 32 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_fptoui_ppc_i64_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; PC64-NEXT: bl __fixunstfdi +; PC64-NEXT: nop +; PC64-NEXT: addi 1, 1, 112 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr +entry: + %fpext = call i64 @llvm.experimental.constrained.fptoui.i64.ppcf128( + ppc_fp128 %first, + metadata !"fpexcept.strict") + ret i64 %fpext +} + +define i32 @test_fptoui_ppc_i32_ppc_fp128(ppc_fp128 %first) nounwind { +; PC64LE-LABEL: test_fptoui_ppc_i32_ppc_fp128: +; PC64LE: # %bb.0: # %entry +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -32(1) +; 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: test_fptoui_ppc_i32_ppc_fp128: +; PC64LE9: # %bb.0: # %entry +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -32(1) +; 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: test_fptoui_ppc_i32_ppc_fp128: +; PC64: # %bb.0: # %entry +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -112(1) +; 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: + %fpext = call i32 @llvm.experimental.constrained.fptoui.i32.ppcf128( + ppc_fp128 %first, + metadata !"fpexcept.strict") + ret i32 %fpext +} + +; Test that resultant libcalls retain order even when their non-strict FLOP form could be +; trivially optimized into differing sequences. +define void @test_constrained_libcall_multichain(float* %firstptr, ppc_fp128* %result) nounwind { +; PC64LE-LABEL: test_constrained_libcall_multichain: +; PC64LE: # %bb.0: +; PC64LE-NEXT: mflr 0 +; PC64LE-NEXT: std 29, -48(1) # 8-byte Folded Spill +; PC64LE-NEXT: std 30, -40(1) # 8-byte Folded Spill +; PC64LE-NEXT: stfd 29, -24(1) # 8-byte Folded Spill +; PC64LE-NEXT: stfd 30, -16(1) # 8-byte Folded Spill +; PC64LE-NEXT: stfd 31, -8(1) # 8-byte Folded Spill +; PC64LE-NEXT: std 0, 16(1) +; PC64LE-NEXT: stdu 1, -80(1) +; PC64LE-NEXT: mr 29, 3 +; PC64LE-NEXT: xxlxor 2, 2, 2 +; PC64LE-NEXT: li 3, 0 +; PC64LE-NEXT: mr 30, 4 +; PC64LE-NEXT: lfsx 31, 0, 29 +; PC64LE-NEXT: xxlxor 4, 4, 4 +; PC64LE-NEXT: std 3, 8(4) +; PC64LE-NEXT: fmr 1, 31 +; PC64LE-NEXT: fmr 3, 31 +; PC64LE-NEXT: stfdx 31, 0, 4 +; PC64LE-NEXT: bl __gcc_qadd +; PC64LE-NEXT: nop +; PC64LE-NEXT: fmr 3, 1 +; PC64LE-NEXT: fmr 4, 2 +; PC64LE-NEXT: fmr 30, 1 +; PC64LE-NEXT: fmr 29, 2 +; PC64LE-NEXT: stfd 1, 16(30) +; PC64LE-NEXT: stfd 2, 24(30) +; PC64LE-NEXT: bl __gcc_qmul +; PC64LE-NEXT: nop +; PC64LE-NEXT: fmr 1, 31 +; PC64LE-NEXT: xxlxor 2, 2, 2 +; PC64LE-NEXT: li 5, 2 +; PC64LE-NEXT: stfd 30, 32(30) +; PC64LE-NEXT: stfd 29, 40(30) +; PC64LE-NEXT: bl __powitf2 +; PC64LE-NEXT: nop +; PC64LE-NEXT: frsp 0, 1 +; PC64LE-NEXT: stfsx 0, 0, 29 +; PC64LE-NEXT: stfd 2, -8(30) +; PC64LE-NEXT: stfd 1, -16(30) +; PC64LE-NEXT: addi 1, 1, 80 +; PC64LE-NEXT: ld 0, 16(1) +; PC64LE-NEXT: mtlr 0 +; PC64LE-NEXT: lfd 31, -8(1) # 8-byte Folded Reload +; PC64LE-NEXT: lfd 30, -16(1) # 8-byte Folded Reload +; PC64LE-NEXT: ld 30, -40(1) # 8-byte Folded Reload +; PC64LE-NEXT: ld 29, -48(1) # 8-byte Folded Reload +; PC64LE-NEXT: lfd 29, -24(1) # 8-byte Folded Reload +; PC64LE-NEXT: blr +; +; PC64LE9-LABEL: test_constrained_libcall_multichain: +; PC64LE9: # %bb.0: +; PC64LE9-NEXT: mflr 0 +; PC64LE9-NEXT: std 29, -48(1) # 8-byte Folded Spill +; PC64LE9-NEXT: std 30, -40(1) # 8-byte Folded Spill +; PC64LE9-NEXT: stfd 29, -24(1) # 8-byte Folded Spill +; PC64LE9-NEXT: stfd 30, -16(1) # 8-byte Folded Spill +; PC64LE9-NEXT: stfd 31, -8(1) # 8-byte Folded Spill +; PC64LE9-NEXT: std 0, 16(1) +; PC64LE9-NEXT: stdu 1, -80(1) +; PC64LE9-NEXT: lfs 31, 0(3) +; PC64LE9-NEXT: mr 29, 3 +; PC64LE9-NEXT: li 3, 0 +; PC64LE9-NEXT: xxlxor 2, 2, 2 +; PC64LE9-NEXT: xxlxor 4, 4, 4 +; PC64LE9-NEXT: std 3, 8(4) +; PC64LE9-NEXT: fmr 1, 31 +; PC64LE9-NEXT: fmr 3, 31 +; PC64LE9-NEXT: mr 30, 4 +; PC64LE9-NEXT: stfd 31, 0(4) +; PC64LE9-NEXT: bl __gcc_qadd +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: fmr 3, 1 +; PC64LE9-NEXT: fmr 4, 2 +; PC64LE9-NEXT: fmr 30, 2 +; PC64LE9-NEXT: fmr 29, 1 +; PC64LE9-NEXT: stfd 1, 16(30) +; PC64LE9-NEXT: stfd 2, 24(30) +; PC64LE9-NEXT: bl __gcc_qmul +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: fmr 1, 31 +; PC64LE9-NEXT: xxlxor 2, 2, 2 +; PC64LE9-NEXT: li 5, 2 +; PC64LE9-NEXT: stfd 29, 32(30) +; PC64LE9-NEXT: stfd 30, 40(30) +; PC64LE9-NEXT: bl __powitf2 +; PC64LE9-NEXT: nop +; PC64LE9-NEXT: frsp 0, 1 +; PC64LE9-NEXT: stfs 0, 0(29) +; PC64LE9-NEXT: stfd 2, -8(30) +; PC64LE9-NEXT: stfd 1, -16(30) +; PC64LE9-NEXT: addi 1, 1, 80 +; PC64LE9-NEXT: ld 0, 16(1) +; PC64LE9-NEXT: mtlr 0 +; PC64LE9-NEXT: lfd 31, -8(1) # 8-byte Folded Reload +; PC64LE9-NEXT: lfd 30, -16(1) # 8-byte Folded Reload +; PC64LE9-NEXT: lfd 29, -24(1) # 8-byte Folded Reload +; PC64LE9-NEXT: ld 30, -40(1) # 8-byte Folded Reload +; PC64LE9-NEXT: ld 29, -48(1) # 8-byte Folded Reload +; PC64LE9-NEXT: blr +; +; PC64-LABEL: test_constrained_libcall_multichain: +; PC64: # %bb.0: +; PC64-NEXT: mflr 0 +; PC64-NEXT: std 0, 16(1) +; PC64-NEXT: stdu 1, -176(1) +; PC64-NEXT: std 29, 120(1) # 8-byte Folded Spill +; PC64-NEXT: mr 29, 3 +; PC64-NEXT: li 3, 0 +; PC64-NEXT: stfd 31, 168(1) # 8-byte Folded Spill +; PC64-NEXT: stfd 30, 160(1) # 8-byte Folded Spill +; PC64-NEXT: std 30, 128(1) # 8-byte Folded Spill +; PC64-NEXT: stfd 28, 144(1) # 8-byte Folded Spill +; PC64-NEXT: stfd 29, 152(1) # 8-byte Folded Spill +; PC64-NEXT: mr 30, 4 +; PC64-NEXT: lfs 31, 0(29) +; PC64-NEXT: std 3, 8(4) +; PC64-NEXT: addis 3, 2, .LCPI32_0@toc@ha +; PC64-NEXT: lfs 30, .LCPI32_0@toc@l(3) +; PC64-NEXT: fmr 1, 31 +; PC64-NEXT: fmr 3, 31 +; PC64-NEXT: fmr 2, 30 +; PC64-NEXT: fmr 4, 30 +; PC64-NEXT: stfd 31, 0(4) +; PC64-NEXT: bl __gcc_qadd +; PC64-NEXT: nop +; PC64-NEXT: fmr 3, 1 +; PC64-NEXT: fmr 4, 2 +; PC64-NEXT: fmr 29, 1 +; PC64-NEXT: fmr 28, 2 +; PC64-NEXT: stfd 1, 16(30) +; PC64-NEXT: stfd 2, 24(30) +; PC64-NEXT: bl __gcc_qmul +; PC64-NEXT: nop +; PC64-NEXT: fmr 1, 31 +; PC64-NEXT: fmr 2, 30 +; PC64-NEXT: li 5, 2 +; PC64-NEXT: stfd 29, 32(30) +; PC64-NEXT: stfd 28, 40(30) +; PC64-NEXT: bl __powitf2 +; PC64-NEXT: nop +; PC64-NEXT: frsp 0, 1 +; PC64-NEXT: stfs 0, 0(29) +; PC64-NEXT: lfd 31, 168(1) # 8-byte Folded Reload +; PC64-NEXT: lfd 30, 160(1) # 8-byte Folded Reload +; PC64-NEXT: lfd 29, 152(1) # 8-byte Folded Reload +; PC64-NEXT: lfd 28, 144(1) # 8-byte Folded Reload +; PC64-NEXT: ld 29, 120(1) # 8-byte Folded Reload +; PC64-NEXT: stfd 2, -8(30) +; PC64-NEXT: stfd 1, -16(30) +; PC64-NEXT: ld 30, 128(1) # 8-byte Folded Reload +; PC64-NEXT: addi 1, 1, 176 +; PC64-NEXT: ld 0, 16(1) +; PC64-NEXT: mtlr 0 +; PC64-NEXT: blr + %load = load float, float* %firstptr + %first = call ppc_fp128 @llvm.experimental.constrained.fpext.f32.ppcf128( + float %load, + metadata !"fpexcept.strict") + store ppc_fp128 %first, ppc_fp128* %result + + ; For unconstrained FLOPs, these next two FP instructions would necessarily + ; be executed in series with one another. + %fadd = call ppc_fp128 @llvm.experimental.constrained.fadd.ppcf128( + ppc_fp128 %first, + ppc_fp128 %first, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + %stridx1 = getelementptr ppc_fp128, ppc_fp128* %result, i32 1 + store ppc_fp128 %fadd, ppc_fp128* %stridx1 + %fmul = call ppc_fp128 @llvm.experimental.constrained.fmul.ppcf128( + ppc_fp128 %fadd, + ppc_fp128 %fadd, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + %stridx2 = getelementptr ppc_fp128, ppc_fp128* %stridx1, i32 1 + store ppc_fp128 %fadd, ppc_fp128* %stridx2 + + ; For unconstrained FLOPs, these next two FP instructions could be reordered + ; or even executed in parallel with respect to the previous two instructions. + ; However, strict floating point rules would not allow this. + %powi = call ppc_fp128 @llvm.experimental.constrained.powi.ppcf128( + ppc_fp128 %first, + i32 2, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + %tinypow = call float @llvm.experimental.constrained.fptrunc.ppcf128.f32( + ppc_fp128 %powi, + metadata !"round.dynamic", + metadata !"fpexcept.strict") + store float %tinypow, float* %firstptr + %stridxn1 = getelementptr ppc_fp128, ppc_fp128* %result, i32 -1 + store ppc_fp128 %powi, ppc_fp128* %stridxn1 + ret void +} + +declare ppc_fp128 @llvm.experimental.constrained.fadd.ppcf128(ppc_fp128, ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.ceil.ppcf128(ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.cos.ppcf128(ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.fdiv.ppcf128(ppc_fp128, ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.exp.ppcf128(ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.exp2.ppcf128(ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.floor.ppcf128(ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.fma.ppcf128(ppc_fp128, ppc_fp128, ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.fpext.f32.ppcf128(float, metadata) +declare ppc_fp128 @llvm.experimental.constrained.fpext.f64.ppcf128(double, metadata) +declare float @llvm.experimental.constrained.fptrunc.ppcf128.f32(ppc_fp128, metadata, metadata) +declare double @llvm.experimental.constrained.fptrunc.ppcf128.f64(ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.log.ppcf128(ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.log10.ppcf128(ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.log2.ppcf128(ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.maxnum.ppcf128(ppc_fp128, ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.minnum.ppcf128(ppc_fp128, ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.fmul.ppcf128(ppc_fp128, ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.nearbyint.ppcf128(ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.pow.ppcf128(ppc_fp128, ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.powi.ppcf128(ppc_fp128, i32, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.frem.ppcf128(ppc_fp128, ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.rint.ppcf128(ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.round.ppcf128(ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.sin.ppcf128(ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.sqrt.ppcf128(ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.fsub.ppcf128(ppc_fp128, ppc_fp128, metadata, metadata) +declare ppc_fp128 @llvm.experimental.constrained.trunc.ppcf128(ppc_fp128, metadata, metadata) +declare i64 @llvm.experimental.constrained.fptosi.i64.ppcf128(ppc_fp128, metadata) +declare i32 @llvm.experimental.constrained.fptosi.i32.ppcf128(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)