Convert sqrt functions into sqrt instructions when -ffast-math is in effect.
authorPreston Gurd <preston.gurd@intel.com>
Mon, 27 May 2013 15:44:35 +0000 (15:44 +0000)
committerPreston Gurd <preston.gurd@intel.com>
Mon, 27 May 2013 15:44:35 +0000 (15:44 +0000)
When -ffast-math is in effect (on Linux, at least), clang defines
__FINITE_MATH_ONLY__ > 0 when including <math.h>. This causes the
preprocessor to include <bits/math-finite.h>, which renames the sqrt functions.
For instance, "sqrt" is renamed as "__sqrt_finite".

This patch adds the 3 new names in such a way that they will be treated
as equivalent to their respective original names.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@182739 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Target/TargetLibraryInfo.h
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
lib/Target/TargetLibraryInfo.cpp
test/CodeGen/X86/sqrt-fastmath.ll [new file with mode: 0644]

index 5f01c8d8351af8c682f9d64636be9bb2df237906..4b9c0442dc97b1ae81b257a5029e50df4146f3b2 100644 (file)
@@ -57,6 +57,12 @@ namespace llvm {
       dunder_isoc99_sscanf,
       /// void *__memcpy_chk(void *s1, const void *s2, size_t n, size_t s1size);
       memcpy_chk,
+      /// double __sqrt_finite(double x);
+      sqrt_finite,
+      /// float __sqrt_finite(float x);
+      sqrtf_finite,
+      /// long double __sqrt_finite(long double x);
+      sqrtl_finite,
       /// char * __strdup(const char *s);
       dunder_strdup,
       /// char *__strndup(const char *s, size_t n);
@@ -677,6 +683,8 @@ public:
     case LibFunc::sin:       case LibFunc::sinf:       case LibFunc::sinl:
     case LibFunc::cos:       case LibFunc::cosf:       case LibFunc::cosl:
     case LibFunc::sqrt:      case LibFunc::sqrtf:      case LibFunc::sqrtl:
+    case LibFunc::sqrt_finite: case LibFunc::sqrtf_finite:
+                                                  case LibFunc::sqrtl_finite:
     case LibFunc::floor:     case LibFunc::floorf:     case LibFunc::floorl:
     case LibFunc::nearbyint: case LibFunc::nearbyintf: case LibFunc::nearbyintl:
     case LibFunc::ceil:      case LibFunc::ceilf:      case LibFunc::ceill:
index aae11794eb041e25a740f5d30a45a9e5b11e8de0..f6867840aee0c102eeb2519f37e51be58742161b 100644 (file)
@@ -5562,6 +5562,9 @@ void SelectionDAGBuilder::visitCall(const CallInst &I) {
       case LibFunc::sqrt:
       case LibFunc::sqrtf:
       case LibFunc::sqrtl:
+      case LibFunc::sqrt_finite:
+      case LibFunc::sqrtf_finite:
+      case LibFunc::sqrtl_finite:
         if (visitUnaryFloatCall(I, ISD::FSQRT))
           return;
         break;
index ee88ce77c09fc3d525059588cca13442979f34b2..d2967d929d851399ba0f19dddd75fb52f0abdc39 100644 (file)
@@ -43,6 +43,9 @@ const char* TargetLibraryInfo::StandardNames[LibFunc::NumLibFuncs] =
     "__isoc99_scanf",
     "__isoc99_sscanf",
     "__memcpy_chk",
+    "__sqrt_finite",
+    "__sqrtf_finite",
+    "__sqrtl_finite",
     "__strdup",
     "__strndup",
     "__strtok_r",
diff --git a/test/CodeGen/X86/sqrt-fastmath.ll b/test/CodeGen/X86/sqrt-fastmath.ll
new file mode 100644 (file)
index 0000000..9b5179e
--- /dev/null
@@ -0,0 +1,60 @@
+; RUN: llc < %s -mcpu=core2 | FileCheck %s
+
+; generated using "clang -S -O2 -ffast-math -emit-llvm sqrt.c" from
+; #include <math.h>
+; 
+; double fd(double d){
+;   return sqrt(d);
+; }
+; 
+; float ff(float f){
+;   return sqrtf(f);
+; }
+; 
+; long double fld(long double ld){
+;   return sqrtl(ld);
+; }
+;
+; Tests conversion of sqrt function calls into sqrt instructions when
+; -ffast-math is in effect.
+
+; ModuleID = 'sqrt.c'
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: nounwind readnone uwtable
+define double @fd(double %d) #0 {
+entry:
+; CHECK: sqrtsd
+  %call = tail call double @__sqrt_finite(double %d) #2
+  ret double %call
+}
+
+; Function Attrs: nounwind readnone
+declare double @__sqrt_finite(double) #1
+
+; Function Attrs: nounwind readnone uwtable
+define float @ff(float %f) #0 {
+entry:
+; CHECK: sqrtss
+  %call = tail call float @__sqrtf_finite(float %f) #2
+  ret float %call
+}
+
+; Function Attrs: nounwind readnone
+declare float @__sqrtf_finite(float) #1
+
+; Function Attrs: nounwind readnone uwtable
+define x86_fp80 @fld(x86_fp80 %ld) #0 {
+entry:
+; CHECK: fsqrt
+  %call = tail call x86_fp80 @__sqrtl_finite(x86_fp80 %ld) #2
+  ret x86_fp80 %call
+}
+
+; Function Attrs: nounwind readnone
+declare x86_fp80 @__sqrtl_finite(x86_fp80) #1
+
+attributes #0 = { nounwind readnone uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="false" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "unsafe-fp-math"="true" "use-soft-float"="false" }
+attributes #1 = { nounwind readnone "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-frame-pointer-elim-non-leaf"="false" "no-infs-fp-math"="true" "no-nans-fp-math"="true" "unsafe-fp-math"="true" "use-soft-float"="false" }
+attributes #2 = { nounwind readnone }