]> granicus.if.org Git - clang/commitdiff
[CodeGen] fix mapping from fmod calls to frem instruction
authorSanjay Patel <spatel@rotateright.com>
Sat, 2 Dec 2017 17:52:00 +0000 (17:52 +0000)
committerSanjay Patel <spatel@rotateright.com>
Sat, 2 Dec 2017 17:52:00 +0000 (17:52 +0000)
Similar to D40044 and discussed in D40594.

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

lib/CodeGen/CGBuiltin.cpp
test/CodeGen/math-builtins.c
test/CodeGen/math-libcalls.c

index 962f5d8a517a89cb066aee9091bf09a69745e6bc..6324520350b876e4c1a5b7a93682450a7d5e47d7 100644 (file)
@@ -854,12 +854,11 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
                                                Result.Val.getFloat()));
   }
 
-  // Math builtins have the same semantics as their math library twins.
-  // There are LLVM math intrinsics corresponding to math library functions
-  // except the intrinsic will never set errno while the math library might.
-  // Thus, we can transform math library and builtin calls to their
-  // semantically-equivalent LLVM intrinsic counterparts if the call is marked
-  // 'const' (it is known to never set errno).
+  // There are LLVM math intrinsics/instructions corresponding to math library
+  // functions except the LLVM op will never set errno while the math library
+  // might. Also, math builtins have the same semantics as their math library
+  // twins. Thus, we can transform math library and builtin calls to their
+  // LLVM counterparts if the call is marked 'const' (known to never set errno).
   if (FD->hasAttr<ConstAttr>()) {
     switch (BuiltinID) {
     case Builtin::BIceil:
@@ -942,6 +941,19 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
     case Builtin::BI__builtin_fminl:
       return RValue::get(emitBinaryBuiltin(*this, E, Intrinsic::minnum));
 
+    // fmod() is a special-case. It maps to the frem instruction rather than an
+    // LLVM intrinsic.
+    case Builtin::BIfmod:
+    case Builtin::BIfmodf:
+    case Builtin::BIfmodl:
+    case Builtin::BI__builtin_fmod:
+    case Builtin::BI__builtin_fmodf:
+    case Builtin::BI__builtin_fmodl: {
+      Value *Arg1 = EmitScalarExpr(E->getArg(0));
+      Value *Arg2 = EmitScalarExpr(E->getArg(1));
+      return RValue::get(Builder.CreateFRem(Arg1, Arg2, "fmod"));
+    }
+
     case Builtin::BIlog:
     case Builtin::BIlogf:
     case Builtin::BIlogl:
@@ -1067,14 +1079,6 @@ RValue CodeGenFunction::EmitBuiltinExpr(const FunctionDecl *FD,
 
     return RValue::get(Result);
   }
-  case Builtin::BI__builtin_fmod:
-  case Builtin::BI__builtin_fmodf:
-  case Builtin::BI__builtin_fmodl: {
-    Value *Arg1 = EmitScalarExpr(E->getArg(0));
-    Value *Arg2 = EmitScalarExpr(E->getArg(1));
-    Value *Result = Builder.CreateFRem(Arg1, Arg2, "fmod");
-    return RValue::get(Result);
-  }
   case Builtin::BI__builtin_conj:
   case Builtin::BI__builtin_conjf:
   case Builtin::BI__builtin_conjl: {
index 805babe1cb0c198f59533b9947534cb7938e5843..799d91b4ec0036af94663f7f8d550c89cabecb8a 100644 (file)
@@ -6,12 +6,21 @@
 // Test attributes and codegen of math builtins.
 
 void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
+  f = __builtin_fmod(f,f);    f = __builtin_fmodf(f,f);   f =  __builtin_fmodl(f,f);
+
+// NO__ERRNO: frem double
+// NO__ERRNO: frem float
+// NO__ERRNO: frem x86_fp80
+// HAS_ERRNO: declare double @fmod(double, double) [[NOT_READNONE:#[0-9]+]]
+// HAS_ERRNO: declare float @fmodf(float, float) [[NOT_READNONE]]
+// HAS_ERRNO: declare x86_fp80 @fmodl(x86_fp80, x86_fp80) [[NOT_READNONE]]
+
   __builtin_atan2(f,f);    __builtin_atan2f(f,f) ;  __builtin_atan2l(f, f);
 
 // NO__ERRNO: declare double @atan2(double, double) [[READNONE:#[0-9]+]]
 // NO__ERRNO: declare float @atan2f(float, float) [[READNONE]]
 // NO__ERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[READNONE]]
-// HAS_ERRNO: declare double @atan2(double, double) [[NOT_READNONE:#[0-9]+]]
+// HAS_ERRNO: declare double @atan2(double, double) [[NOT_READNONE]]
 // HAS_ERRNO: declare float @atan2f(float, float) [[NOT_READNONE]]
 // HAS_ERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[NOT_READNONE]]
 
@@ -33,13 +42,6 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
 // HAS_ERRNO: declare float @llvm.fabs.f32(float) [[READNONE_INTRINSIC]]
 // HAS_ERRNO: declare x86_fp80 @llvm.fabs.f80(x86_fp80) [[READNONE_INTRINSIC]]
 
-  __builtin_fmod(f,f);     __builtin_fmodf(f,f);    __builtin_fmodl(f,f);
-
-// NO__ERRNO-NOT: .fmod
-// NO__ERRNO-NOT: @fmod
-// HAS_ERRNO-NOT: .fmod
-// HAS_ERRNO-NOT: @fmod
-
   __builtin_frexp(f,i);    __builtin_frexpf(f,i);   __builtin_frexpl(f,i);
 
 // NO__ERRNO: declare double @frexp(double, i32*) [[NOT_READNONE:#[0-9]+]]
index be9481cea4597c3b88e3f636b6e1c213a81cb0c3..39bcb4454d7c187a7fb7a684b19fb8271c516161 100644 (file)
@@ -6,12 +6,21 @@
 // Test attributes and builtin codegen of math library calls.
 
 void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
+  f = fmod(f,f);     f = fmodf(f,f);    f = fmodl(f,f);
+
+// NO__ERRNO: frem double
+// NO__ERRNO: frem float
+// NO__ERRNO: frem x86_fp80
+// HAS_ERRNO: declare double @fmod(double, double) [[NOT_READNONE:#[0-9]+]]
+// HAS_ERRNO: declare float @fmodf(float, float) [[NOT_READNONE]]
+// HAS_ERRNO: declare x86_fp80 @fmodl(x86_fp80, x86_fp80) [[NOT_READNONE]]
+
   atan2(f,f);    atan2f(f,f) ;  atan2l(f, f);
 
 // NO__ERRNO: declare double @atan2(double, double) [[READNONE:#[0-9]+]]
 // NO__ERRNO: declare float @atan2f(float, float) [[READNONE]]
 // NO__ERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[READNONE]]
-// HAS_ERRNO: declare double @atan2(double, double) [[NOT_READNONE:#[0-9]+]]
+// HAS_ERRNO: declare double @atan2(double, double) [[NOT_READNONE]]
 // HAS_ERRNO: declare float @atan2f(float, float) [[NOT_READNONE]]
 // HAS_ERRNO: declare x86_fp80 @atan2l(x86_fp80, x86_fp80) [[NOT_READNONE]]
 
@@ -33,15 +42,6 @@ void foo(double *d, float f, float *fp, long double *l, int *i, const char *c) {
 // HAS_ERRNO: declare float @llvm.fabs.f32(float) [[READNONE_INTRINSIC]]
 // HAS_ERRNO: declare x86_fp80 @llvm.fabs.f80(x86_fp80) [[READNONE_INTRINSIC]]
 
-  fmod(f,f);     fmodf(f,f);    fmodl(f,f);
-
-// NO__ERRNO: declare double @fmod(double, double) [[READNONE]]
-// NO__ERRNO: declare float @fmodf(float, float) [[READNONE]]
-// NO__ERRNO: declare x86_fp80 @fmodl(x86_fp80, x86_fp80) [[READNONE]]
-// HAS_ERRNO: declare double @fmod(double, double) [[NOT_READNONE]]
-// HAS_ERRNO: declare float @fmodf(float, float) [[NOT_READNONE]]
-// HAS_ERRNO: declare x86_fp80 @fmodl(x86_fp80, x86_fp80) [[NOT_READNONE]]
-
   frexp(f,i);    frexpf(f,i);   frexpl(f,i);
 
 // NO__ERRNO: declare double @frexp(double, i32*) [[NOT_READNONE:#[0-9]+]]