@@ -140,12 +140,19 @@ class SelectionDAGLegalize {
140140 RTLIB::Libcall Call_F128,
141141 RTLIB::Libcall Call_PPCF128,
142142 SmallVectorImpl<SDValue> &Results);
143- SDValue ExpandIntLibCall (SDNode *Node, bool isSigned,
144- RTLIB::Libcall Call_I8,
145- RTLIB::Libcall Call_I16,
146- RTLIB::Libcall Call_I32,
147- RTLIB::Libcall Call_I64,
148- RTLIB::Libcall Call_I128);
143+
144+ void
145+ ExpandFastFPLibCall (SDNode *Node, bool IsFast,
146+ std::pair<RTLIB::Libcall, RTLIB::Libcall> Call_F32,
147+ std::pair<RTLIB::Libcall, RTLIB::Libcall> Call_F64,
148+ std::pair<RTLIB::Libcall, RTLIB::Libcall> Call_F80,
149+ std::pair<RTLIB::Libcall, RTLIB::Libcall> Call_F128,
150+ std::pair<RTLIB::Libcall, RTLIB::Libcall> Call_PPCF128,
151+ SmallVectorImpl<SDValue> &Results);
152+
153+ SDValue ExpandIntLibCall (SDNode *Node, bool isSigned, RTLIB::Libcall Call_I8,
154+ RTLIB::Libcall Call_I16, RTLIB::Libcall Call_I32,
155+ RTLIB::Libcall Call_I64, RTLIB::Libcall Call_I128);
149156 void ExpandArgFPLibCall (SDNode *Node,
150157 RTLIB::Libcall Call_F32, RTLIB::Libcall Call_F64,
151158 RTLIB::Libcall Call_F80, RTLIB::Libcall Call_F128,
@@ -2228,6 +2235,37 @@ void SelectionDAGLegalize::ExpandFPLibCall(SDNode* Node,
22282235 ExpandFPLibCall (Node, LC, Results);
22292236}
22302237
2238+ void SelectionDAGLegalize::ExpandFastFPLibCall (
2239+ SDNode *Node, bool IsFast,
2240+ std::pair<RTLIB::Libcall, RTLIB::Libcall> Call_F32,
2241+ std::pair<RTLIB::Libcall, RTLIB::Libcall> Call_F64,
2242+ std::pair<RTLIB::Libcall, RTLIB::Libcall> Call_F80,
2243+ std::pair<RTLIB::Libcall, RTLIB::Libcall> Call_F128,
2244+ std::pair<RTLIB::Libcall, RTLIB::Libcall> Call_PPCF128,
2245+ SmallVectorImpl<SDValue> &Results) {
2246+
2247+ EVT VT = Node->getSimpleValueType (0 );
2248+
2249+ RTLIB::Libcall LC;
2250+
2251+ // FIXME: Probably should define fast to respect nan/inf and only be
2252+ // approximate functions.
2253+
2254+ if (IsFast) {
2255+ LC = RTLIB::getFPLibCall (VT, Call_F32.first , Call_F64.first , Call_F80.first ,
2256+ Call_F128.first , Call_PPCF128.first );
2257+ }
2258+
2259+ if (!IsFast || TLI.getLibcallImpl (LC) == RTLIB::Unsupported) {
2260+ // Fall back if we don't have a fast implementation.
2261+ LC = RTLIB::getFPLibCall (VT, Call_F32.second , Call_F64.second ,
2262+ Call_F80.second , Call_F128.second ,
2263+ Call_PPCF128.second );
2264+ }
2265+
2266+ ExpandFPLibCall (Node, LC, Results);
2267+ }
2268+
22312269SDValue SelectionDAGLegalize::ExpandIntLibCall (SDNode* Node, bool isSigned,
22322270 RTLIB::Libcall Call_I8,
22332271 RTLIB::Libcall Call_I16,
@@ -4514,6 +4552,18 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
45144552 return true ;
45154553}
45164554
4555+ // / Return if we can use the FAST_* variant of a math libcall for the node.
4556+ // / FIXME: This is just guessing, we probably should have unique specific sets
4557+ // / flags required per libcall.
4558+ static bool canUseFastMathLibcall (const SDNode *Node) {
4559+ // FIXME: Probably should define fast to respect nan/inf and only be
4560+ // approximate functions.
4561+
4562+ SDNodeFlags Flags = Node->getFlags ();
4563+ return Flags.hasApproximateFuncs () && Flags.hasNoNaNs () &&
4564+ Flags.hasNoInfs () && Flags.hasNoSignedZeros ();
4565+ }
4566+
45174567void SelectionDAGLegalize::ConvertNodeToLibcall (SDNode *Node) {
45184568 LLVM_DEBUG (dbgs () << " Trying to convert node to libcall\n " );
45194569 SmallVector<SDValue, 8 > Results;
@@ -4634,11 +4684,18 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
46344684 RTLIB::FMAXIMUM_NUM_PPCF128, Results);
46354685 break ;
46364686 case ISD::FSQRT:
4637- case ISD::STRICT_FSQRT:
4638- ExpandFPLibCall (Node, RTLIB::SQRT_F32, RTLIB::SQRT_F64,
4639- RTLIB::SQRT_F80, RTLIB::SQRT_F128,
4640- RTLIB::SQRT_PPCF128, Results);
4687+ case ISD::STRICT_FSQRT: {
4688+ // FIXME: Probably should define fast to respect nan/inf and only be
4689+ // approximate functions.
4690+ ExpandFastFPLibCall (Node, canUseFastMathLibcall (Node),
4691+ {RTLIB::FAST_SQRT_F32, RTLIB::SQRT_F32},
4692+ {RTLIB::FAST_SQRT_F64, RTLIB::SQRT_F64},
4693+ {RTLIB::FAST_SQRT_F80, RTLIB::SQRT_F80},
4694+ {RTLIB::FAST_SQRT_F128, RTLIB::SQRT_F128},
4695+ {RTLIB::FAST_SQRT_PPCF128, RTLIB::SQRT_PPCF128},
4696+ Results);
46414697 break ;
4698+ }
46424699 case ISD::FCBRT:
46434700 ExpandFPLibCall (Node, RTLIB::CBRT_F32, RTLIB::CBRT_F64,
46444701 RTLIB::CBRT_F80, RTLIB::CBRT_F128,
@@ -4875,11 +4932,15 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
48754932 RTLIB::LLRINT_PPCF128, Results);
48764933 break ;
48774934 case ISD::FDIV:
4878- case ISD::STRICT_FDIV:
4879- ExpandFPLibCall (Node, RTLIB::DIV_F32, RTLIB::DIV_F64,
4880- RTLIB::DIV_F80, RTLIB::DIV_F128,
4881- RTLIB::DIV_PPCF128, Results);
4935+ case ISD::STRICT_FDIV: {
4936+ ExpandFastFPLibCall (Node, canUseFastMathLibcall (Node),
4937+ {RTLIB::FAST_DIV_F32, RTLIB::DIV_F32},
4938+ {RTLIB::FAST_DIV_F64, RTLIB::DIV_F64},
4939+ {RTLIB::FAST_DIV_F80, RTLIB::DIV_F80},
4940+ {RTLIB::FAST_DIV_F128, RTLIB::DIV_F128},
4941+ {RTLIB::FAST_DIV_PPCF128, RTLIB::DIV_PPCF128}, Results);
48824942 break ;
4943+ }
48834944 case ISD::FREM:
48844945 case ISD::STRICT_FREM:
48854946 ExpandFPLibCall (Node, RTLIB::REM_F32, RTLIB::REM_F64,
@@ -4893,17 +4954,25 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
48934954 RTLIB::FMA_PPCF128, Results);
48944955 break ;
48954956 case ISD::FADD:
4896- case ISD::STRICT_FADD:
4897- ExpandFPLibCall (Node, RTLIB::ADD_F32, RTLIB::ADD_F64,
4898- RTLIB::ADD_F80, RTLIB::ADD_F128,
4899- RTLIB::ADD_PPCF128, Results);
4957+ case ISD::STRICT_FADD: {
4958+ ExpandFastFPLibCall (Node, canUseFastMathLibcall (Node),
4959+ {RTLIB::FAST_ADD_F32, RTLIB::ADD_F32},
4960+ {RTLIB::FAST_ADD_F64, RTLIB::ADD_F64},
4961+ {RTLIB::FAST_ADD_F80, RTLIB::ADD_F80},
4962+ {RTLIB::FAST_ADD_F128, RTLIB::ADD_F128},
4963+ {RTLIB::FAST_ADD_PPCF128, RTLIB::ADD_PPCF128}, Results);
49004964 break ;
4965+ }
49014966 case ISD::FMUL:
4902- case ISD::STRICT_FMUL:
4903- ExpandFPLibCall (Node, RTLIB::MUL_F32, RTLIB::MUL_F64,
4904- RTLIB::MUL_F80, RTLIB::MUL_F128,
4905- RTLIB::MUL_PPCF128, Results);
4967+ case ISD::STRICT_FMUL: {
4968+ ExpandFastFPLibCall (Node, canUseFastMathLibcall (Node),
4969+ {RTLIB::FAST_MUL_F32, RTLIB::MUL_F32},
4970+ {RTLIB::FAST_MUL_F64, RTLIB::MUL_F64},
4971+ {RTLIB::FAST_MUL_F80, RTLIB::MUL_F80},
4972+ {RTLIB::FAST_MUL_F128, RTLIB::MUL_F128},
4973+ {RTLIB::FAST_MUL_PPCF128, RTLIB::MUL_PPCF128}, Results);
49064974 break ;
4975+ }
49074976 case ISD::FP16_TO_FP:
49084977 if (Node->getValueType (0 ) == MVT::f32 ) {
49094978 Results.push_back (ExpandLibCall (RTLIB::FPEXT_F16_F32, Node, false ).first );
@@ -5076,11 +5145,15 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
50765145 break ;
50775146 }
50785147 case ISD::FSUB:
5079- case ISD::STRICT_FSUB:
5080- ExpandFPLibCall (Node, RTLIB::SUB_F32, RTLIB::SUB_F64,
5081- RTLIB::SUB_F80, RTLIB::SUB_F128,
5082- RTLIB::SUB_PPCF128, Results);
5148+ case ISD::STRICT_FSUB: {
5149+ ExpandFastFPLibCall (Node, canUseFastMathLibcall (Node),
5150+ {RTLIB::FAST_SUB_F32, RTLIB::SUB_F32},
5151+ {RTLIB::FAST_SUB_F64, RTLIB::SUB_F64},
5152+ {RTLIB::FAST_SUB_F80, RTLIB::SUB_F80},
5153+ {RTLIB::FAST_SUB_F128, RTLIB::SUB_F128},
5154+ {RTLIB::FAST_SUB_PPCF128, RTLIB::SUB_PPCF128}, Results);
50835155 break ;
5156+ }
50845157 case ISD::SREM:
50855158 Results.push_back (ExpandIntLibCall (Node, true ,
50865159 RTLIB::SREM_I8,
0 commit comments