summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorErich Keane <erich.keane@intel.com>2019-12-16 07:18:18 -0800
committerErich Keane <erich.keane@intel.com>2019-12-16 07:20:29 -0800
commitf02d6dd6c7afc08f871a623c0411f2d77ed6acf8 (patch)
treefc23ef1efd956f83119a79c289f842965703cfd5
parent9f99aba1cfeb603f368c45ef78ba9795bab16d47 (diff)
downloadbcm5719-llvm-f02d6dd6c7afc08f871a623c0411f2d77ed6acf8.tar.gz
bcm5719-llvm-f02d6dd6c7afc08f871a623c0411f2d77ed6acf8.zip
Fix floating point builtins to not promote float->double
As brought up in D71467, a group of floating point builtins automatically promoted floats to doubles because they used the variadic builtin tag to support an overload set. The result is that the parameters were treated as a variadic pack, which always promots float->double. This resulted in the wrong answer being given in cases with certain values of NaN.
-rw-r--r--clang/include/clang/Basic/Builtins.def12
-rw-r--r--clang/test/CodeGen/arm-float-helpers.c2
-rw-r--r--clang/test/CodeGen/builtin_float.c71
3 files changed, 78 insertions, 7 deletions
diff --git a/clang/include/clang/Basic/Builtins.def b/clang/include/clang/Basic/Builtins.def
index 8a102744700..29dec78e4b9 100644
--- a/clang/include/clang/Basic/Builtins.def
+++ b/clang/include/clang/Basic/Builtins.def
@@ -391,12 +391,12 @@ BUILTIN(__builtin_ctanhf, "XfXf", "Fne")
BUILTIN(__builtin_ctanhl, "XLdXLd", "Fne")
// FP Comparisons.
-BUILTIN(__builtin_isgreater , "i.", "Fnc")
-BUILTIN(__builtin_isgreaterequal, "i.", "Fnc")
-BUILTIN(__builtin_isless , "i.", "Fnc")
-BUILTIN(__builtin_islessequal , "i.", "Fnc")
-BUILTIN(__builtin_islessgreater , "i.", "Fnc")
-BUILTIN(__builtin_isunordered , "i.", "Fnc")
+BUILTIN(__builtin_isgreater , "i.", "Fnct")
+BUILTIN(__builtin_isgreaterequal, "i.", "Fnct")
+BUILTIN(__builtin_isless , "i.", "Fnct")
+BUILTIN(__builtin_islessequal , "i.", "Fnct")
+BUILTIN(__builtin_islessgreater , "i.", "Fnct")
+BUILTIN(__builtin_isunordered , "i.", "Fnct")
// Unary FP classification
BUILTIN(__builtin_fpclassify, "iiiiii.", "Fnc")
diff --git a/clang/test/CodeGen/arm-float-helpers.c b/clang/test/CodeGen/arm-float-helpers.c
index 30363304bcf..b2e65805cc7 100644
--- a/clang/test/CodeGen/arm-float-helpers.c
+++ b/clang/test/CodeGen/arm-float-helpers.c
@@ -79,7 +79,7 @@ int fcmpgt(float a, float b) { return a > b; }
int fcmpun(float a, float b) { return __builtin_isunordered(a, b); }
// CHECK-LABEL: define i32 @fcmpun(float %a, float %b)
// CHECK-NOT: __aeabi_fcmpun
-// CHECK: %cmp = fcmp uno double %conv, %conv1
+// CHECK: %cmp = fcmp uno float {{.*}}, {{.*}}
double dadd(double a, double b) { return a + b; }
// CHECK-LABEL: define double @dadd(double %a, double %b)
diff --git a/clang/test/CodeGen/builtin_float.c b/clang/test/CodeGen/builtin_float.c
new file mode 100644
index 00000000000..b97cf1be348
--- /dev/null
+++ b/clang/test/CodeGen/builtin_float.c
@@ -0,0 +1,71 @@
+// RUN: %clang_cc1 -emit-llvm -o - %s | FileCheck %s
+
+// test to ensure that these builtins don't do the variadic promotion of float->double.
+void test_floats(float f1, float f2) {
+ (void)__builtin_isgreater(f1, f2);
+ // CHECK: fcmp ogt float
+ // CHECK-NEXT: zext i1
+ (void)__builtin_isgreaterequal(f1, f2);
+ // CHECK: fcmp oge float
+ // CHECK-NEXT: zext i1
+ (void)__builtin_isless(f1, f2);
+ // CHECK: fcmp olt float
+ // CHECK-NEXT: zext i1
+ (void)__builtin_islessequal(f1, f2);
+ // CHECK: fcmp ole float
+ // CHECK-NEXT: zext i1
+ (void)__builtin_islessgreater(f1, f2);
+ // CHECK: fcmp one float
+ // CHECK-NEXT: zext i1
+ (void)__builtin_isunordered(f1, f2);
+ // CHECK: fcmp uno float
+ // CHECK-NEXT: zext i1
+}
+
+void test_doubles(double d1, double f2) {
+ (void)__builtin_isgreater(d1, f2);
+ // CHECK: fcmp ogt double
+ // CHECK-NEXT: zext i1
+ (void)__builtin_isgreaterequal(d1, f2);
+ // CHECK: fcmp oge double
+ // CHECK-NEXT: zext i1
+ (void)__builtin_isless(d1, f2);
+ // CHECK: fcmp olt double
+ // CHECK-NEXT: zext i1
+ (void)__builtin_islessequal(d1, f2);
+ // CHECK: fcmp ole double
+ // CHECK-NEXT: zext i1
+ (void)__builtin_islessgreater(d1, f2);
+ // CHECK: fcmp one double
+ // CHECK-NEXT: zext i1
+ (void)__builtin_isunordered(d1, f2);
+ // CHECK: fcmp uno double
+ // CHECK-NEXT: zext i1
+}
+
+void test_mixed(double d1, float f2) {
+ (void)__builtin_isgreater(d1, f2);
+ // CHECK: fpext float {{.*}} to double
+ // CHECK-NEXT: fcmp ogt double
+ // CHECK-NEXT: zext i1
+ (void)__builtin_isgreaterequal(d1, f2);
+ // CHECK: fpext float {{.*}} to double
+ // CHECK-NEXT: fcmp oge double
+ // CHECK-NEXT: zext i1
+ (void)__builtin_isless(d1, f2);
+ // CHECK: fpext float {{.*}} to double
+ // CHECK-NEXT: fcmp olt double
+ // CHECK-NEXT: zext i1
+ (void)__builtin_islessequal(d1, f2);
+ // CHECK: fpext float {{.*}} to double
+ // CHECK-NEXT: fcmp ole double
+ // CHECK-NEXT: zext i1
+ (void)__builtin_islessgreater(d1, f2);
+ // CHECK: fpext float {{.*}} to double
+ // CHECK-NEXT: fcmp one double
+ // CHECK-NEXT: zext i1
+ (void)__builtin_isunordered(d1, f2);
+ // CHECK: fpext float {{.*}} to double
+ // CHECK-NEXT: fcmp uno double
+ // CHECK-NEXT: zext i1
+}
OpenPOWER on IntegriCloud