Index: include/llvm/CodeGen/RuntimeLibcalls.def =================================================================== --- include/llvm/CodeGen/RuntimeLibcalls.def +++ include/llvm/CodeGen/RuntimeLibcalls.def @@ -145,6 +145,11 @@ HANDLE_LIBCALL(EXP_F80, "expl") HANDLE_LIBCALL(EXP_F128, "expl") HANDLE_LIBCALL(EXP_PPCF128, "expl") +HANDLE_LIBCALL(EXP_FINITE_F32, "__expf_finite") +HANDLE_LIBCALL(EXP_FINITE_F64, "__exp_finite") +HANDLE_LIBCALL(EXP_FINITE_F80, "__expl_finite") +HANDLE_LIBCALL(EXP_FINITE_F128, "__expl_finite") +HANDLE_LIBCALL(EXP_FINITE_PPCF128, "__expl_finite") HANDLE_LIBCALL(EXP2_F32, "exp2f") HANDLE_LIBCALL(EXP2_F64, "exp2") HANDLE_LIBCALL(EXP2_F80, "exp2l") Index: include/llvm/CodeGen/SelectionDAG.h =================================================================== --- include/llvm/CodeGen/SelectionDAG.h +++ include/llvm/CodeGen/SelectionDAG.h @@ -73,6 +73,7 @@ class SDDbgValue; class SelectionDAG; class SelectionDAGTargetInfo; +class TargetLibraryInfo; class TargetLowering; class TargetMachine; class TargetSubtargetInfo; @@ -210,6 +211,7 @@ const TargetMachine &TM; const SelectionDAGTargetInfo *TSI = nullptr; const TargetLowering *TLI = nullptr; + const TargetLibraryInfo *LibInfo = nullptr; MachineFunction *MF; Pass *SDAGISelPass = nullptr; LLVMContext *Context; @@ -376,7 +378,7 @@ /// Prepare this SelectionDAG to process code in the given MachineFunction. void init(MachineFunction &NewMF, OptimizationRemarkEmitter &NewORE, - Pass *PassPtr); + Pass *PassPtr, const TargetLibraryInfo *LibraryInfo); /// Clear state and free memory necessary to make this /// SelectionDAG ready to process a new block. @@ -389,6 +391,7 @@ const TargetMachine &getTarget() const { return TM; } const TargetSubtargetInfo &getSubtarget() const { return MF->getSubtarget(); } const TargetLowering &getTargetLoweringInfo() const { return *TLI; } + const TargetLibraryInfo &getLibInfo() const { return *LibInfo; } const SelectionDAGTargetInfo &getSelectionDAGInfo() const { return *TSI; } LLVMContext *getContext() const {return Context; } OptimizationRemarkEmitter &getORE() const { return *ORE; } Index: lib/CodeGen/SelectionDAG/LegalizeDAG.cpp =================================================================== --- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -3932,6 +3932,8 @@ DEBUG(dbgs() << "Trying to convert node to libcall\n"); SmallVector Results; SDLoc dl(Node); + // FIXME: Check flags on the node to see if we can use a finite call. + bool CanUseFiniteLibCall = TM.Options.NoInfsFPMath && TM.Options.NoNaNsFPMath; unsigned Opc = Node->getOpcode(); switch (Opc) { case ISD::ATOMIC_FENCE: { @@ -4044,9 +4046,16 @@ break; case ISD::FEXP: case ISD::STRICT_FEXP: - Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP_F32, RTLIB::EXP_F64, - RTLIB::EXP_F80, RTLIB::EXP_F128, - RTLIB::EXP_PPCF128)); + if (CanUseFiniteLibCall && DAG.getLibInfo().has(LibFunc_exp_finite)) + Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP_FINITE_F32, + RTLIB::EXP_FINITE_F64, + RTLIB::EXP_FINITE_F80, + RTLIB::EXP_FINITE_F128, + RTLIB::EXP_FINITE_PPCF128)); + else + Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP_F32, RTLIB::EXP_F64, + RTLIB::EXP_F80, RTLIB::EXP_F128, + RTLIB::EXP_PPCF128)); break; case ISD::FEXP2: case ISD::STRICT_FEXP2: Index: lib/CodeGen/SelectionDAG/SelectionDAG.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -903,12 +903,13 @@ void SelectionDAG::init(MachineFunction &NewMF, OptimizationRemarkEmitter &NewORE, - Pass *PassPtr) { + Pass *PassPtr, const TargetLibraryInfo *LibraryInfo) { MF = &NewMF; SDAGISelPass = PassPtr; ORE = &NewORE; TLI = getSubtarget().getTargetLowering(); TSI = getSubtarget().getSelectionDAGInfo(); + LibInfo = LibraryInfo; Context = &MF->getFunction().getContext(); } Index: lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp =================================================================== --- lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -414,7 +414,7 @@ SplitCriticalSideEffectEdges(const_cast(Fn), DT, LI); - CurDAG->init(*MF, *ORE, this); + CurDAG->init(*MF, *ORE, this, LibInfo); FuncInfo->set(Fn, *MF, CurDAG); // Now get the optional analyzes if we want to. Index: test/CodeGen/X86/finite-libcalls.ll =================================================================== --- test/CodeGen/X86/finite-libcalls.ll +++ test/CodeGen/X86/finite-libcalls.ll @@ -6,17 +6,25 @@ ; FIXME: We would not need the function-level attributes if FMF were propagated to DAG nodes for this case. define float @exp_f32(float %x) #0 { -; CHECK-LABEL: exp_f32: -; CHECK: # %bb.0: -; CHECK-NEXT: jmp expf # TAILCALL +; GNU-LABEL: exp_f32: +; GNU: # %bb.0: +; GNU-NEXT: jmp __expf_finite # TAILCALL +; +; WIN-LABEL: exp_f32: +; WIN: # %bb.0: +; WIN-NEXT: jmp expf # TAILCALL %exp = tail call nnan ninf float @llvm.exp.f32(float %x) ret float %exp } define double @exp_f64(double %x) #0 { -; CHECK-LABEL: exp_f64: -; CHECK: # %bb.0: -; CHECK-NEXT: jmp exp # TAILCALL +; GNU-LABEL: exp_f64: +; GNU: # %bb.0: +; GNU-NEXT: jmp __exp_finite # TAILCALL +; +; WIN-LABEL: exp_f64: +; WIN: # %bb.0: +; WIN-NEXT: jmp exp # TAILCALL %exp = tail call nnan ninf double @llvm.exp.f64(double %x) ret double %exp } @@ -27,7 +35,7 @@ ; GNU-NEXT: subq $24, %rsp ; GNU-NEXT: fldt {{[0-9]+}}(%rsp) ; GNU-NEXT: fstpt (%rsp) -; GNU-NEXT: callq expl +; GNU-NEXT: callq __expl_finite ; GNU-NEXT: addq $24, %rsp ; GNU-NEXT: retq ;