[llvm] r322087 - [SelectionDAG] lower math intrinsics to finite version of libcalls when possible (PR35672)

Sanjay Patel via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 9 07:41:00 PST 2018


Author: spatel
Date: Tue Jan  9 07:41:00 2018
New Revision: 322087

URL: http://llvm.org/viewvc/llvm-project?rev=322087&view=rev
Log:
[SelectionDAG] lower math intrinsics to finite version of libcalls when possible (PR35672)

Ingredients in this patch:
1. Add HANDLE_LIBCALL defs for finite mathlib functions that correspond to LLVM intrinsics.
2. Plumbing to send TargetLibraryInfo down to SelectionDAGLegalize.
3. Relaxed math and library checking in SelectionDAGLegalize::ConvertNodeToLibcall() to choose finite libcalls.

There was a bug about determining the availability of the finite calls that should be fixed with:
rL322010

Not in this patch:
This doesn't resolve the question/bug of clang creating the intrinsic IR in the first place.
There's likely follow-up work needed to support the long double variants better.
There's room for improvement to reduce the code duplication.
Create finite calls that don't originate from a corresponding intrinsic or DAG node?

Differential Revision: https://reviews.llvm.org/D41338


Modified:
    llvm/trunk/include/llvm/CodeGen/RuntimeLibcalls.def
    llvm/trunk/include/llvm/CodeGen/SelectionDAG.h
    llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
    llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
    llvm/trunk/test/CodeGen/X86/finite-libcalls.ll

Modified: llvm/trunk/include/llvm/CodeGen/RuntimeLibcalls.def
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/RuntimeLibcalls.def?rev=322087&r1=322086&r2=322087&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/RuntimeLibcalls.def (original)
+++ llvm/trunk/include/llvm/CodeGen/RuntimeLibcalls.def Tue Jan  9 07:41:00 2018
@@ -130,26 +130,51 @@ HANDLE_LIBCALL(LOG_F64, "log")
 HANDLE_LIBCALL(LOG_F80, "logl")
 HANDLE_LIBCALL(LOG_F128, "logl")
 HANDLE_LIBCALL(LOG_PPCF128, "logl")
+HANDLE_LIBCALL(LOG_FINITE_F32, "__logf_finite")
+HANDLE_LIBCALL(LOG_FINITE_F64, "__log_finite")
+HANDLE_LIBCALL(LOG_FINITE_F80, "__logl_finite")
+HANDLE_LIBCALL(LOG_FINITE_F128, "__logl_finite")
+HANDLE_LIBCALL(LOG_FINITE_PPCF128, "__logl_finite")
 HANDLE_LIBCALL(LOG2_F32, "log2f")
 HANDLE_LIBCALL(LOG2_F64, "log2")
 HANDLE_LIBCALL(LOG2_F80, "log2l")
 HANDLE_LIBCALL(LOG2_F128, "log2l")
 HANDLE_LIBCALL(LOG2_PPCF128, "log2l")
+HANDLE_LIBCALL(LOG2_FINITE_F32, "__log2f_finite")
+HANDLE_LIBCALL(LOG2_FINITE_F64, "__log2_finite")
+HANDLE_LIBCALL(LOG2_FINITE_F80, "__log2l_finite")
+HANDLE_LIBCALL(LOG2_FINITE_F128, "__log2l_finite")
+HANDLE_LIBCALL(LOG2_FINITE_PPCF128, "__log2l_finite")
 HANDLE_LIBCALL(LOG10_F32, "log10f")
 HANDLE_LIBCALL(LOG10_F64, "log10")
 HANDLE_LIBCALL(LOG10_F80, "log10l")
 HANDLE_LIBCALL(LOG10_F128, "log10l")
 HANDLE_LIBCALL(LOG10_PPCF128, "log10l")
+HANDLE_LIBCALL(LOG10_FINITE_F32, "__log10f_finite")
+HANDLE_LIBCALL(LOG10_FINITE_F64, "__log10_finite")
+HANDLE_LIBCALL(LOG10_FINITE_F80, "__log10l_finite")
+HANDLE_LIBCALL(LOG10_FINITE_F128, "__log10l_finite")
+HANDLE_LIBCALL(LOG10_FINITE_PPCF128, "__log10l_finite")
 HANDLE_LIBCALL(EXP_F32, "expf")
 HANDLE_LIBCALL(EXP_F64, "exp")
 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")
 HANDLE_LIBCALL(EXP2_F128, "exp2l")
 HANDLE_LIBCALL(EXP2_PPCF128, "exp2l")
+HANDLE_LIBCALL(EXP2_FINITE_F32, "__exp2f_finite")
+HANDLE_LIBCALL(EXP2_FINITE_F64, "__exp2_finite")
+HANDLE_LIBCALL(EXP2_FINITE_F80, "__exp2l_finite")
+HANDLE_LIBCALL(EXP2_FINITE_F128, "__exp2l_finite")
+HANDLE_LIBCALL(EXP2_FINITE_PPCF128, "__exp2l_finite")
 HANDLE_LIBCALL(SIN_F32, "sinf")
 HANDLE_LIBCALL(SIN_F64, "sin")
 HANDLE_LIBCALL(SIN_F80, "sinl")
@@ -172,6 +197,11 @@ HANDLE_LIBCALL(POW_F64, "pow")
 HANDLE_LIBCALL(POW_F80, "powl")
 HANDLE_LIBCALL(POW_F128, "powl")
 HANDLE_LIBCALL(POW_PPCF128, "powl")
+HANDLE_LIBCALL(POW_FINITE_F32, "__powf_finite")
+HANDLE_LIBCALL(POW_FINITE_F64, "__pow_finite")
+HANDLE_LIBCALL(POW_FINITE_F80, "__powl_finite")
+HANDLE_LIBCALL(POW_FINITE_F128, "__powl_finite")
+HANDLE_LIBCALL(POW_FINITE_PPCF128, "__powl_finite")
 HANDLE_LIBCALL(CEIL_F32, "ceilf")
 HANDLE_LIBCALL(CEIL_F64, "ceil")
 HANDLE_LIBCALL(CEIL_F80, "ceill")

Modified: llvm/trunk/include/llvm/CodeGen/SelectionDAG.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/SelectionDAG.h?rev=322087&r1=322086&r2=322087&view=diff
==============================================================================
--- llvm/trunk/include/llvm/CodeGen/SelectionDAG.h (original)
+++ llvm/trunk/include/llvm/CodeGen/SelectionDAG.h Tue Jan  9 07:41:00 2018
@@ -73,6 +73,7 @@ class OptimizationRemarkEmitter;
 class SDDbgValue;
 class SelectionDAG;
 class SelectionDAGTargetInfo;
+class TargetLibraryInfo;
 class TargetLowering;
 class TargetMachine;
 class TargetSubtargetInfo;
@@ -210,6 +211,7 @@ class SelectionDAG {
   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 @@ public:
 
   /// 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 @@ public:
   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; }

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp?rev=322087&r1=322086&r2=322087&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Tue Jan  9 07:41:00 2018
@@ -3932,6 +3932,8 @@ void SelectionDAGLegalize::ConvertNodeTo
   DEBUG(dbgs() << "Trying to convert node to libcall\n");
   SmallVector<SDValue, 8> 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: {
@@ -4026,33 +4028,68 @@ void SelectionDAGLegalize::ConvertNodeTo
     break;
   case ISD::FLOG:
   case ISD::STRICT_FLOG:
-    Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG_F32, RTLIB::LOG_F64,
-                                      RTLIB::LOG_F80, RTLIB::LOG_F128,
-                                      RTLIB::LOG_PPCF128));
+    if (CanUseFiniteLibCall && DAG.getLibInfo().has(LibFunc_log_finite))
+      Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG_FINITE_F32,
+                                        RTLIB::LOG_FINITE_F64,
+                                        RTLIB::LOG_FINITE_F80,
+                                        RTLIB::LOG_FINITE_F128,
+                                        RTLIB::LOG_FINITE_PPCF128));
+    else
+      Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG_F32, RTLIB::LOG_F64,
+                                        RTLIB::LOG_F80, RTLIB::LOG_F128,
+                                        RTLIB::LOG_PPCF128));
     break;
   case ISD::FLOG2:
   case ISD::STRICT_FLOG2:
-    Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG2_F32, RTLIB::LOG2_F64,
-                                      RTLIB::LOG2_F80, RTLIB::LOG2_F128,
-                                      RTLIB::LOG2_PPCF128));
+    if (CanUseFiniteLibCall && DAG.getLibInfo().has(LibFunc_log2_finite))
+      Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG2_FINITE_F32,
+                                        RTLIB::LOG2_FINITE_F64,
+                                        RTLIB::LOG2_FINITE_F80,
+                                        RTLIB::LOG2_FINITE_F128,
+                                        RTLIB::LOG2_FINITE_PPCF128));
+    else
+      Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG2_F32, RTLIB::LOG2_F64,
+                                        RTLIB::LOG2_F80, RTLIB::LOG2_F128,
+                                        RTLIB::LOG2_PPCF128));
     break;
   case ISD::FLOG10:
   case ISD::STRICT_FLOG10:
-    Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG10_F32, RTLIB::LOG10_F64,
-                                      RTLIB::LOG10_F80, RTLIB::LOG10_F128,
-                                      RTLIB::LOG10_PPCF128));
+    if (CanUseFiniteLibCall && DAG.getLibInfo().has(LibFunc_log10_finite))
+      Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG10_FINITE_F32,
+                                        RTLIB::LOG10_FINITE_F64,
+                                        RTLIB::LOG10_FINITE_F80,
+                                        RTLIB::LOG10_FINITE_F128,
+                                        RTLIB::LOG10_FINITE_PPCF128));
+    else
+      Results.push_back(ExpandFPLibCall(Node, RTLIB::LOG10_F32, RTLIB::LOG10_F64,
+                                        RTLIB::LOG10_F80, RTLIB::LOG10_F128,
+                                        RTLIB::LOG10_PPCF128));
     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:
-    Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP2_F32, RTLIB::EXP2_F64,
-                                      RTLIB::EXP2_F80, RTLIB::EXP2_F128,
-                                      RTLIB::EXP2_PPCF128));
+    if (CanUseFiniteLibCall && DAG.getLibInfo().has(LibFunc_exp2_finite))
+      Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP2_FINITE_F32,
+                                        RTLIB::EXP2_FINITE_F64,
+                                        RTLIB::EXP2_FINITE_F80,
+                                        RTLIB::EXP2_FINITE_F128,
+                                        RTLIB::EXP2_FINITE_PPCF128));
+    else
+      Results.push_back(ExpandFPLibCall(Node, RTLIB::EXP2_F32, RTLIB::EXP2_F64,
+                                        RTLIB::EXP2_F80, RTLIB::EXP2_F128,
+                                        RTLIB::EXP2_PPCF128));
     break;
   case ISD::FTRUNC:
     Results.push_back(ExpandFPLibCall(Node, RTLIB::TRUNC_F32, RTLIB::TRUNC_F64,
@@ -4098,9 +4135,16 @@ void SelectionDAGLegalize::ConvertNodeTo
     break;
   case ISD::FPOW:
   case ISD::STRICT_FPOW:
-    Results.push_back(ExpandFPLibCall(Node, RTLIB::POW_F32, RTLIB::POW_F64,
-                                      RTLIB::POW_F80, RTLIB::POW_F128,
-                                      RTLIB::POW_PPCF128));
+    if (CanUseFiniteLibCall && DAG.getLibInfo().has(LibFunc_pow_finite))
+      Results.push_back(ExpandFPLibCall(Node, RTLIB::POW_FINITE_F32,
+                                        RTLIB::POW_FINITE_F64,
+                                        RTLIB::POW_FINITE_F80,
+                                        RTLIB::POW_FINITE_F128,
+                                        RTLIB::POW_FINITE_PPCF128));
+    else
+      Results.push_back(ExpandFPLibCall(Node, RTLIB::POW_F32, RTLIB::POW_F64,
+                                        RTLIB::POW_F80, RTLIB::POW_F128,
+                                        RTLIB::POW_PPCF128));
     break;
   case ISD::FDIV:
     Results.push_back(ExpandFPLibCall(Node, RTLIB::DIV_F32, RTLIB::DIV_F64,

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp?rev=322087&r1=322086&r2=322087&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAG.cpp Tue Jan  9 07:41:00 2018
@@ -903,12 +903,13 @@ SelectionDAG::SelectionDAG(const TargetM
 
 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();
 }
 

Modified: llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp?rev=322087&r1=322086&r2=322087&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp Tue Jan  9 07:41:00 2018
@@ -414,7 +414,7 @@ bool SelectionDAGISel::runOnMachineFunct
 
   SplitCriticalSideEffectEdges(const_cast<Function &>(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.

Modified: llvm/trunk/test/CodeGen/X86/finite-libcalls.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/finite-libcalls.ll?rev=322087&r1=322086&r2=322087&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/X86/finite-libcalls.ll (original)
+++ llvm/trunk/test/CodeGen/X86/finite-libcalls.ll Tue Jan  9 07:41:00 2018
@@ -1,24 +1,41 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc < %s -mtriple=x86_64-pc-linux-gnu     | FileCheck %s --check-prefix=CHECK --check-prefix=GNU
 ; RUN: llc < %s -mtriple=x86_64-pc-windows-msvc  | FileCheck %s --check-prefix=CHECK --check-prefix=WIN
+; RUN: llc < %s -mtriple=x86_64-apple-darwin     | FileCheck %s --check-prefix=CHECK --check-prefix=MAC
 
 ; PR35672 - https://bugs.llvm.org/show_bug.cgi?id=35672
 ; 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
-  %exp = tail call nnan ninf float @llvm.exp.f32(float %x)
-  ret float %exp
+; 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
+;
+; MAC-LABEL: exp_f32:
+; MAC:       ## %bb.0:
+; MAC-NEXT:    jmp _expf ## TAILCALL
+  %r = tail call nnan ninf float @llvm.exp.f32(float %x)
+  ret float %r
 }
 
 define double @exp_f64(double %x) #0 {
-; CHECK-LABEL: exp_f64:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    jmp exp # TAILCALL
-  %exp = tail call nnan ninf double @llvm.exp.f64(double %x)
-  ret double %exp
+; 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
+;
+; MAC-LABEL: exp_f64:
+; MAC:       ## %bb.0:
+; MAC-NEXT:    jmp _exp ## TAILCALL
+  %r = tail call nnan ninf double @llvm.exp.f64(double %x)
+  ret double %r
 }
 
 define x86_fp80 @exp_f80(x86_fp80 %x) #0 {
@@ -27,7 +44,7 @@ define x86_fp80 @exp_f80(x86_fp80 %x) #0
 ; 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
 ;
@@ -39,14 +56,370 @@ define x86_fp80 @exp_f80(x86_fp80 %x) #0
 ; WIN-NEXT:    callq expl
 ; WIN-NEXT:    addq $56, %rsp
 ; WIN-NEXT:    retq
-  %exp = tail call nnan ninf x86_fp80 @llvm.exp.f80(x86_fp80 %x)
-  ret x86_fp80 %exp
+;
+; MAC-LABEL: exp_f80:
+; MAC:       ## %bb.0:
+; MAC-NEXT:    subq $24, %rsp
+; MAC-NEXT:    fldt {{[0-9]+}}(%rsp)
+; MAC-NEXT:    fstpt (%rsp)
+; MAC-NEXT:    callq _expl
+; MAC-NEXT:    addq $24, %rsp
+; MAC-NEXT:    retq
+  %r = tail call nnan ninf x86_fp80 @llvm.exp.f80(x86_fp80 %x)
+  ret x86_fp80 %r
+}
+
+define float @exp2_f32(float %x) #0 {
+; GNU-LABEL: exp2_f32:
+; GNU:       # %bb.0:
+; GNU-NEXT:    jmp __exp2f_finite # TAILCALL
+;
+; WIN-LABEL: exp2_f32:
+; WIN:       # %bb.0:
+; WIN-NEXT:    jmp exp2f # TAILCALL
+;
+; MAC-LABEL: exp2_f32:
+; MAC:       ## %bb.0:
+; MAC-NEXT:    jmp _exp2f ## TAILCALL
+  %r = tail call nnan ninf float @llvm.exp2.f32(float %x)
+  ret float %r
+}
+
+define double @exp2_f64(double %x) #0 {
+; GNU-LABEL: exp2_f64:
+; GNU:       # %bb.0:
+; GNU-NEXT:    jmp __exp2_finite # TAILCALL
+;
+; WIN-LABEL: exp2_f64:
+; WIN:       # %bb.0:
+; WIN-NEXT:    jmp exp2 # TAILCALL
+;
+; MAC-LABEL: exp2_f64:
+; MAC:       ## %bb.0:
+; MAC-NEXT:    jmp _exp2 ## TAILCALL
+  %r = tail call nnan ninf double @llvm.exp2.f64(double %x)
+  ret double %r
+}
+
+define x86_fp80 @exp2_f80(x86_fp80 %x) #0 {
+; GNU-LABEL: exp2_f80:
+; GNU:       # %bb.0:
+; GNU-NEXT:    subq $24, %rsp
+; GNU-NEXT:    fldt {{[0-9]+}}(%rsp)
+; GNU-NEXT:    fstpt (%rsp)
+; GNU-NEXT:    callq __exp2l_finite
+; GNU-NEXT:    addq $24, %rsp
+; GNU-NEXT:    retq
+;
+; WIN-LABEL: exp2_f80:
+; WIN:       # %bb.0:
+; WIN-NEXT:    subq $56, %rsp
+; WIN-NEXT:    fldt {{[0-9]+}}(%rsp)
+; WIN-NEXT:    fstpt {{[0-9]+}}(%rsp)
+; WIN-NEXT:    callq exp2l
+; WIN-NEXT:    addq $56, %rsp
+; WIN-NEXT:    retq
+;
+; MAC-LABEL: exp2_f80:
+; MAC:       ## %bb.0:
+; MAC-NEXT:    subq $24, %rsp
+; MAC-NEXT:    fldt {{[0-9]+}}(%rsp)
+; MAC-NEXT:    fstpt (%rsp)
+; MAC-NEXT:    callq _exp2l
+; MAC-NEXT:    addq $24, %rsp
+; MAC-NEXT:    retq
+  %r = tail call nnan ninf x86_fp80 @llvm.exp2.f80(x86_fp80 %x)
+  ret x86_fp80 %r
+}
+
+define float @log_f32(float %x) #0 {
+; GNU-LABEL: log_f32:
+; GNU:       # %bb.0:
+; GNU-NEXT:    jmp __logf_finite # TAILCALL
+;
+; WIN-LABEL: log_f32:
+; WIN:       # %bb.0:
+; WIN-NEXT:    jmp logf # TAILCALL
+;
+; MAC-LABEL: log_f32:
+; MAC:       ## %bb.0:
+; MAC-NEXT:    jmp _logf ## TAILCALL
+  %r = tail call nnan ninf float @llvm.log.f32(float %x)
+  ret float %r
+}
+
+define double @log_f64(double %x) #0 {
+; GNU-LABEL: log_f64:
+; GNU:       # %bb.0:
+; GNU-NEXT:    jmp __log_finite # TAILCALL
+;
+; WIN-LABEL: log_f64:
+; WIN:       # %bb.0:
+; WIN-NEXT:    jmp log # TAILCALL
+;
+; MAC-LABEL: log_f64:
+; MAC:       ## %bb.0:
+; MAC-NEXT:    jmp _log ## TAILCALL
+  %r = tail call nnan ninf double @llvm.log.f64(double %x)
+  ret double %r
+}
+
+define x86_fp80 @log_f80(x86_fp80 %x) #0 {
+; GNU-LABEL: log_f80:
+; GNU:       # %bb.0:
+; GNU-NEXT:    subq $24, %rsp
+; GNU-NEXT:    fldt {{[0-9]+}}(%rsp)
+; GNU-NEXT:    fstpt (%rsp)
+; GNU-NEXT:    callq __logl_finite
+; GNU-NEXT:    addq $24, %rsp
+; GNU-NEXT:    retq
+;
+; WIN-LABEL: log_f80:
+; WIN:       # %bb.0:
+; WIN-NEXT:    subq $56, %rsp
+; WIN-NEXT:    fldt {{[0-9]+}}(%rsp)
+; WIN-NEXT:    fstpt {{[0-9]+}}(%rsp)
+; WIN-NEXT:    callq logl
+; WIN-NEXT:    addq $56, %rsp
+; WIN-NEXT:    retq
+;
+; MAC-LABEL: log_f80:
+; MAC:       ## %bb.0:
+; MAC-NEXT:    subq $24, %rsp
+; MAC-NEXT:    fldt {{[0-9]+}}(%rsp)
+; MAC-NEXT:    fstpt (%rsp)
+; MAC-NEXT:    callq _logl
+; MAC-NEXT:    addq $24, %rsp
+; MAC-NEXT:    retq
+  %r = tail call nnan ninf x86_fp80 @llvm.log.f80(x86_fp80 %x)
+  ret x86_fp80 %r
+}
+
+define float @log2_f32(float %x) #0 {
+; GNU-LABEL: log2_f32:
+; GNU:       # %bb.0:
+; GNU-NEXT:    jmp __log2f_finite # TAILCALL
+;
+; WIN-LABEL: log2_f32:
+; WIN:       # %bb.0:
+; WIN-NEXT:    jmp log2f # TAILCALL
+;
+; MAC-LABEL: log2_f32:
+; MAC:       ## %bb.0:
+; MAC-NEXT:    jmp _log2f ## TAILCALL
+  %r = tail call nnan ninf float @llvm.log2.f32(float %x)
+  ret float %r
+}
+
+define double @log2_f64(double %x) #0 {
+; GNU-LABEL: log2_f64:
+; GNU:       # %bb.0:
+; GNU-NEXT:    jmp __log2_finite # TAILCALL
+;
+; WIN-LABEL: log2_f64:
+; WIN:       # %bb.0:
+; WIN-NEXT:    jmp log2 # TAILCALL
+;
+; MAC-LABEL: log2_f64:
+; MAC:       ## %bb.0:
+; MAC-NEXT:    jmp _log2 ## TAILCALL
+  %r = tail call nnan ninf double @llvm.log2.f64(double %x)
+  ret double %r
+}
+
+define x86_fp80 @log2_f80(x86_fp80 %x) #0 {
+; GNU-LABEL: log2_f80:
+; GNU:       # %bb.0:
+; GNU-NEXT:    subq $24, %rsp
+; GNU-NEXT:    fldt {{[0-9]+}}(%rsp)
+; GNU-NEXT:    fstpt (%rsp)
+; GNU-NEXT:    callq __log2l_finite
+; GNU-NEXT:    addq $24, %rsp
+; GNU-NEXT:    retq
+;
+; WIN-LABEL: log2_f80:
+; WIN:       # %bb.0:
+; WIN-NEXT:    subq $56, %rsp
+; WIN-NEXT:    fldt {{[0-9]+}}(%rsp)
+; WIN-NEXT:    fstpt {{[0-9]+}}(%rsp)
+; WIN-NEXT:    callq log2l
+; WIN-NEXT:    addq $56, %rsp
+; WIN-NEXT:    retq
+;
+; MAC-LABEL: log2_f80:
+; MAC:       ## %bb.0:
+; MAC-NEXT:    subq $24, %rsp
+; MAC-NEXT:    fldt {{[0-9]+}}(%rsp)
+; MAC-NEXT:    fstpt (%rsp)
+; MAC-NEXT:    callq _log2l
+; MAC-NEXT:    addq $24, %rsp
+; MAC-NEXT:    retq
+  %r = tail call nnan ninf x86_fp80 @llvm.log2.f80(x86_fp80 %x)
+  ret x86_fp80 %r
+}
+
+define float @log10_f32(float %x) #0 {
+; GNU-LABEL: log10_f32:
+; GNU:       # %bb.0:
+; GNU-NEXT:    jmp __log10f_finite # TAILCALL
+;
+; WIN-LABEL: log10_f32:
+; WIN:       # %bb.0:
+; WIN-NEXT:    jmp log10f # TAILCALL
+;
+; MAC-LABEL: log10_f32:
+; MAC:       ## %bb.0:
+; MAC-NEXT:    jmp _log10f ## TAILCALL
+  %r = tail call nnan ninf float @llvm.log10.f32(float %x)
+  ret float %r
+}
+
+define double @log10_f64(double %x) #0 {
+; GNU-LABEL: log10_f64:
+; GNU:       # %bb.0:
+; GNU-NEXT:    jmp __log10_finite # TAILCALL
+;
+; WIN-LABEL: log10_f64:
+; WIN:       # %bb.0:
+; WIN-NEXT:    jmp log10 # TAILCALL
+;
+; MAC-LABEL: log10_f64:
+; MAC:       ## %bb.0:
+; MAC-NEXT:    jmp _log10 ## TAILCALL
+  %r = tail call nnan ninf double @llvm.log10.f64(double %x)
+  ret double %r
+}
+
+define x86_fp80 @log10_f80(x86_fp80 %x) #0 {
+; GNU-LABEL: log10_f80:
+; GNU:       # %bb.0:
+; GNU-NEXT:    subq $24, %rsp
+; GNU-NEXT:    fldt {{[0-9]+}}(%rsp)
+; GNU-NEXT:    fstpt (%rsp)
+; GNU-NEXT:    callq __log10l_finite
+; GNU-NEXT:    addq $24, %rsp
+; GNU-NEXT:    retq
+;
+; WIN-LABEL: log10_f80:
+; WIN:       # %bb.0:
+; WIN-NEXT:    subq $56, %rsp
+; WIN-NEXT:    fldt {{[0-9]+}}(%rsp)
+; WIN-NEXT:    fstpt {{[0-9]+}}(%rsp)
+; WIN-NEXT:    callq log10l
+; WIN-NEXT:    addq $56, %rsp
+; WIN-NEXT:    retq
+;
+; MAC-LABEL: log10_f80:
+; MAC:       ## %bb.0:
+; MAC-NEXT:    subq $24, %rsp
+; MAC-NEXT:    fldt {{[0-9]+}}(%rsp)
+; MAC-NEXT:    fstpt (%rsp)
+; MAC-NEXT:    callq _log10l
+; MAC-NEXT:    addq $24, %rsp
+; MAC-NEXT:    retq
+  %r = tail call nnan ninf x86_fp80 @llvm.log10.f80(x86_fp80 %x)
+  ret x86_fp80 %r
+}
+
+define float @pow_f32(float %x) #0 {
+; GNU-LABEL: pow_f32:
+; GNU:       # %bb.0:
+; GNU-NEXT:    movaps %xmm0, %xmm1
+; GNU-NEXT:    jmp __powf_finite # TAILCALL
+;
+; WIN-LABEL: pow_f32:
+; WIN:       # %bb.0:
+; WIN-NEXT:    movaps %xmm0, %xmm1
+; WIN-NEXT:    jmp powf # TAILCALL
+;
+; MAC-LABEL: pow_f32:
+; MAC:       ## %bb.0:
+; MAC-NEXT:    movaps %xmm0, %xmm1
+; MAC-NEXT:    jmp _powf ## TAILCALL
+  %r = tail call nnan ninf float @llvm.pow.f32(float %x, float %x)
+  ret float %r
+}
+
+define double @pow_f64(double %x) #0 {
+; GNU-LABEL: pow_f64:
+; GNU:       # %bb.0:
+; GNU-NEXT:    movaps %xmm0, %xmm1
+; GNU-NEXT:    jmp __pow_finite # TAILCALL
+;
+; WIN-LABEL: pow_f64:
+; WIN:       # %bb.0:
+; WIN-NEXT:    movaps %xmm0, %xmm1
+; WIN-NEXT:    jmp pow # TAILCALL
+;
+; MAC-LABEL: pow_f64:
+; MAC:       ## %bb.0:
+; MAC-NEXT:    movaps %xmm0, %xmm1
+; MAC-NEXT:    jmp _pow ## TAILCALL
+  %r = tail call nnan ninf double @llvm.pow.f64(double %x, double %x)
+  ret double %r
+}
+
+define x86_fp80 @pow_f80(x86_fp80 %x) #0 {
+; GNU-LABEL: pow_f80:
+; GNU:       # %bb.0:
+; GNU-NEXT:    subq $40, %rsp
+; GNU-NEXT:    fldt {{[0-9]+}}(%rsp)
+; GNU-NEXT:    fld %st(0)
+; GNU-NEXT:    fstpt {{[0-9]+}}(%rsp)
+; GNU-NEXT:    fstpt (%rsp)
+; GNU-NEXT:    callq __powl_finite
+; GNU-NEXT:    addq $40, %rsp
+; GNU-NEXT:    retq
+;
+; WIN-LABEL: pow_f80:
+; WIN:       # %bb.0:
+; WIN-NEXT:    subq $72, %rsp
+; WIN-NEXT:    fldt {{[0-9]+}}(%rsp)
+; WIN-NEXT:    fld %st(0)
+; WIN-NEXT:    fstpt {{[0-9]+}}(%rsp)
+; WIN-NEXT:    fstpt {{[0-9]+}}(%rsp)
+; WIN-NEXT:    callq powl
+; WIN-NEXT:    addq $72, %rsp
+; WIN-NEXT:    retq
+;
+; MAC-LABEL: pow_f80:
+; MAC:       ## %bb.0:
+; MAC-NEXT:    subq $40, %rsp
+; MAC-NEXT:    fldt {{[0-9]+}}(%rsp)
+; MAC-NEXT:    fld %st(0)
+; MAC-NEXT:    fstpt {{[0-9]+}}(%rsp)
+; MAC-NEXT:    fstpt (%rsp)
+; MAC-NEXT:    callq _powl
+; MAC-NEXT:    addq $40, %rsp
+; MAC-NEXT:    retq
+  %r = tail call nnan ninf x86_fp80 @llvm.pow.f80(x86_fp80 %x, x86_fp80 %x)
+  ret x86_fp80 %r
 }
 
 declare float @llvm.exp.f32(float) #1
 declare double @llvm.exp.f64(double) #1
 declare x86_fp80 @llvm.exp.f80(x86_fp80) #1
 
+declare float @llvm.exp2.f32(float) #1
+declare double @llvm.exp2.f64(double) #1
+declare x86_fp80 @llvm.exp2.f80(x86_fp80) #1
+
+declare float @llvm.log.f32(float) #1
+declare double @llvm.log.f64(double) #1
+declare x86_fp80 @llvm.log.f80(x86_fp80) #1
+
+declare float @llvm.log2.f32(float) #1
+declare double @llvm.log2.f64(double) #1
+declare x86_fp80 @llvm.log2.f80(x86_fp80) #1
+
+declare float @llvm.log10.f32(float) #1
+declare double @llvm.log10.f64(double) #1
+declare x86_fp80 @llvm.log10.f80(x86_fp80) #1
+
+declare float @llvm.pow.f32(float, float) #1
+declare double @llvm.pow.f64(double, double) #1
+declare x86_fp80 @llvm.pow.f80(x86_fp80, x86_fp80) #1
+
 attributes #0 = { nounwind "no-infs-fp-math"="true" "no-nans-fp-math"="true" }
 attributes #1 = { nounwind readnone speculatable }
 




More information about the llvm-commits mailing list