@@ -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,
@@ -2229,6 +2236,37 @@ void SelectionDAGLegalize::ExpandFPLibCall(SDNode* Node,
22292236 ExpandFPLibCall (Node, LC, Results);
22302237}
22312238
2239+ void SelectionDAGLegalize::ExpandFastFPLibCall (
2240+ SDNode *Node, bool IsFast,
2241+ std::pair<RTLIB::Libcall, RTLIB::Libcall> Call_F32,
2242+ std::pair<RTLIB::Libcall, RTLIB::Libcall> Call_F64,
2243+ std::pair<RTLIB::Libcall, RTLIB::Libcall> Call_F80,
2244+ std::pair<RTLIB::Libcall, RTLIB::Libcall> Call_F128,
2245+ std::pair<RTLIB::Libcall, RTLIB::Libcall> Call_PPCF128,
2246+ SmallVectorImpl<SDValue> &Results) {
2247+
2248+ EVT VT = Node->getSimpleValueType (0 );
2249+
2250+ RTLIB::Libcall LC;
2251+
2252+ // FIXME: Probably should define fast to respect nan/inf and only be
2253+ // approximate functions.
2254+
2255+ if (IsFast) {
2256+ LC = RTLIB::getFPLibCall (VT, Call_F32.first , Call_F64.first , Call_F80.first ,
2257+ Call_F128.first , Call_PPCF128.first );
2258+ }
2259+
2260+ if (!IsFast || TLI.getLibcallImpl (LC) == RTLIB::Unsupported) {
2261+ // Fall back if we don't have a fast implementation.
2262+ LC = RTLIB::getFPLibCall (VT, Call_F32.second , Call_F64.second ,
2263+ Call_F80.second , Call_F128.second ,
2264+ Call_PPCF128.second );
2265+ }
2266+
2267+ ExpandFPLibCall (Node, LC, Results);
2268+ }
2269+
22322270SDValue SelectionDAGLegalize::ExpandIntLibCall (SDNode* Node, bool isSigned,
22332271 RTLIB::Libcall Call_I8,
22342272 RTLIB::Libcall Call_I16,
@@ -4489,6 +4527,18 @@ bool SelectionDAGLegalize::ExpandNode(SDNode *Node) {
44894527 return true ;
44904528}
44914529
4530+ // / Return if we can use the FAST_* variant of a math libcall for the node.
4531+ // / FIXME: This is just guessing, we probably should have unique specific sets
4532+ // / flags required per libcall.
4533+ static bool canUseFastMathLibcall (const SDNode *Node) {
4534+ // FIXME: Probably should define fast to respect nan/inf and only be
4535+ // approximate functions.
4536+
4537+ SDNodeFlags Flags = Node->getFlags ();
4538+ return Flags.hasApproximateFuncs () && Flags.hasNoNaNs () &&
4539+ Flags.hasNoInfs () && Flags.hasNoSignedZeros ();
4540+ }
4541+
44924542void SelectionDAGLegalize::ConvertNodeToLibcall (SDNode *Node) {
44934543 LLVM_DEBUG (dbgs () << " Trying to convert node to libcall\n " );
44944544 SmallVector<SDValue, 8 > Results;
@@ -4609,11 +4659,18 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
46094659 RTLIB::FMAXIMUM_NUM_PPCF128, Results);
46104660 break ;
46114661 case ISD::FSQRT:
4612- case ISD::STRICT_FSQRT:
4613- ExpandFPLibCall (Node, RTLIB::SQRT_F32, RTLIB::SQRT_F64,
4614- RTLIB::SQRT_F80, RTLIB::SQRT_F128,
4615- RTLIB::SQRT_PPCF128, Results);
4662+ case ISD::STRICT_FSQRT: {
4663+ // FIXME: Probably should define fast to respect nan/inf and only be
4664+ // approximate functions.
4665+ ExpandFastFPLibCall (Node, canUseFastMathLibcall (Node),
4666+ {RTLIB::FAST_SQRT_F32, RTLIB::SQRT_F32},
4667+ {RTLIB::FAST_SQRT_F64, RTLIB::SQRT_F64},
4668+ {RTLIB::FAST_SQRT_F80, RTLIB::SQRT_F80},
4669+ {RTLIB::FAST_SQRT_F128, RTLIB::SQRT_F128},
4670+ {RTLIB::FAST_SQRT_PPCF128, RTLIB::SQRT_PPCF128},
4671+ Results);
46164672 break ;
4673+ }
46174674 case ISD::FCBRT:
46184675 ExpandFPLibCall (Node, RTLIB::CBRT_F32, RTLIB::CBRT_F64,
46194676 RTLIB::CBRT_F80, RTLIB::CBRT_F128,
@@ -4850,11 +4907,15 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
48504907 RTLIB::LLRINT_PPCF128, Results);
48514908 break ;
48524909 case ISD::FDIV:
4853- case ISD::STRICT_FDIV:
4854- ExpandFPLibCall (Node, RTLIB::DIV_F32, RTLIB::DIV_F64,
4855- RTLIB::DIV_F80, RTLIB::DIV_F128,
4856- RTLIB::DIV_PPCF128, Results);
4910+ case ISD::STRICT_FDIV: {
4911+ ExpandFastFPLibCall (Node, canUseFastMathLibcall (Node),
4912+ {RTLIB::FAST_DIV_F32, RTLIB::DIV_F32},
4913+ {RTLIB::FAST_DIV_F64, RTLIB::DIV_F64},
4914+ {RTLIB::FAST_DIV_F80, RTLIB::DIV_F80},
4915+ {RTLIB::FAST_DIV_F128, RTLIB::DIV_F128},
4916+ {RTLIB::FAST_DIV_PPCF128, RTLIB::DIV_PPCF128}, Results);
48574917 break ;
4918+ }
48584919 case ISD::FREM:
48594920 case ISD::STRICT_FREM:
48604921 ExpandFPLibCall (Node, RTLIB::REM_F32, RTLIB::REM_F64,
@@ -4868,17 +4929,25 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
48684929 RTLIB::FMA_PPCF128, Results);
48694930 break ;
48704931 case ISD::FADD:
4871- case ISD::STRICT_FADD:
4872- ExpandFPLibCall (Node, RTLIB::ADD_F32, RTLIB::ADD_F64,
4873- RTLIB::ADD_F80, RTLIB::ADD_F128,
4874- RTLIB::ADD_PPCF128, Results);
4932+ case ISD::STRICT_FADD: {
4933+ ExpandFastFPLibCall (Node, canUseFastMathLibcall (Node),
4934+ {RTLIB::FAST_ADD_F32, RTLIB::ADD_F32},
4935+ {RTLIB::FAST_ADD_F64, RTLIB::ADD_F64},
4936+ {RTLIB::FAST_ADD_F80, RTLIB::ADD_F80},
4937+ {RTLIB::FAST_ADD_F128, RTLIB::ADD_F128},
4938+ {RTLIB::FAST_ADD_PPCF128, RTLIB::ADD_PPCF128}, Results);
48754939 break ;
4940+ }
48764941 case ISD::FMUL:
4877- case ISD::STRICT_FMUL:
4878- ExpandFPLibCall (Node, RTLIB::MUL_F32, RTLIB::MUL_F64,
4879- RTLIB::MUL_F80, RTLIB::MUL_F128,
4880- RTLIB::MUL_PPCF128, Results);
4942+ case ISD::STRICT_FMUL: {
4943+ ExpandFastFPLibCall (Node, canUseFastMathLibcall (Node),
4944+ {RTLIB::FAST_MUL_F32, RTLIB::MUL_F32},
4945+ {RTLIB::FAST_MUL_F64, RTLIB::MUL_F64},
4946+ {RTLIB::FAST_MUL_F80, RTLIB::MUL_F80},
4947+ {RTLIB::FAST_MUL_F128, RTLIB::MUL_F128},
4948+ {RTLIB::FAST_MUL_PPCF128, RTLIB::MUL_PPCF128}, Results);
48814949 break ;
4950+ }
48824951 case ISD::FP16_TO_FP:
48834952 if (Node->getValueType (0 ) == MVT::f32 ) {
48844953 Results.push_back (ExpandLibCall (RTLIB::FPEXT_F16_F32, Node, false ).first );
@@ -5051,11 +5120,15 @@ void SelectionDAGLegalize::ConvertNodeToLibcall(SDNode *Node) {
50515120 break ;
50525121 }
50535122 case ISD::FSUB:
5054- case ISD::STRICT_FSUB:
5055- ExpandFPLibCall (Node, RTLIB::SUB_F32, RTLIB::SUB_F64,
5056- RTLIB::SUB_F80, RTLIB::SUB_F128,
5057- RTLIB::SUB_PPCF128, Results);
5123+ case ISD::STRICT_FSUB: {
5124+ ExpandFastFPLibCall (Node, canUseFastMathLibcall (Node),
5125+ {RTLIB::FAST_SUB_F32, RTLIB::SUB_F32},
5126+ {RTLIB::FAST_SUB_F64, RTLIB::SUB_F64},
5127+ {RTLIB::FAST_SUB_F80, RTLIB::SUB_F80},
5128+ {RTLIB::FAST_SUB_F128, RTLIB::SUB_F128},
5129+ {RTLIB::FAST_SUB_PPCF128, RTLIB::SUB_PPCF128}, Results);
50585130 break ;
5131+ }
50595132 case ISD::SREM:
50605133 Results.push_back (ExpandIntLibCall (Node, true ,
50615134 RTLIB::SREM_I8,
0 commit comments