summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler-rt/lib/builtins/divdf3.c12
-rw-r--r--compiler-rt/lib/builtins/divsf3.c12
-rw-r--r--compiler-rt/lib/builtins/divtf3.c12
-rw-r--r--compiler-rt/test/builtins/Unit/divdf3_test.c45
-rw-r--r--compiler-rt/test/builtins/Unit/divsf3_test.c45
-rw-r--r--compiler-rt/test/builtins/Unit/divtf3_test.c9
6 files changed, 133 insertions, 2 deletions
diff --git a/compiler-rt/lib/builtins/divdf3.c b/compiler-rt/lib/builtins/divdf3.c
index 3993507a0f7..9132f83813b 100644
--- a/compiler-rt/lib/builtins/divdf3.c
+++ b/compiler-rt/lib/builtins/divdf3.c
@@ -162,6 +162,18 @@ __divdf3(fp_t a, fp_t b) {
}
else if (writtenExponent < 1) {
+ if (writtenExponent == 0) {
+ // Check whether the rounded result is normal.
+ const bool round = (residual << 1) > bSignificand;
+ // Clear the implicit bit.
+ rep_t absResult = quotient & significandMask;
+ // Round.
+ absResult += round;
+ if (absResult & ~significandMask) {
+ // The rounded result is normal; return it.
+ return fromRep(absResult | quotientSign);
+ }
+ }
// Flush denormals to zero. In the future, it would be nice to add
// code to round them correctly.
return fromRep(quotientSign);
diff --git a/compiler-rt/lib/builtins/divsf3.c b/compiler-rt/lib/builtins/divsf3.c
index 97cbcc1960b..944524749e9 100644
--- a/compiler-rt/lib/builtins/divsf3.c
+++ b/compiler-rt/lib/builtins/divsf3.c
@@ -147,6 +147,18 @@ __divsf3(fp_t a, fp_t b) {
}
else if (writtenExponent < 1) {
+ if (writtenExponent == 0) {
+ // Check whether the rounded result is normal.
+ const bool round = (residual << 1) > bSignificand;
+ // Clear the implicit bit.
+ rep_t absResult = quotient & significandMask;
+ // Round.
+ absResult += round;
+ if (absResult & ~significandMask) {
+ // The rounded result is normal; return it.
+ return fromRep(absResult | quotientSign);
+ }
+ }
// Flush denormals to zero. In the future, it would be nice to add
// code to round them correctly.
return fromRep(quotientSign);
diff --git a/compiler-rt/lib/builtins/divtf3.c b/compiler-rt/lib/builtins/divtf3.c
index 17273749b5b..ba5de99f995 100644
--- a/compiler-rt/lib/builtins/divtf3.c
+++ b/compiler-rt/lib/builtins/divtf3.c
@@ -181,6 +181,18 @@ COMPILER_RT_ABI fp_t __divtf3(fp_t a, fp_t b) {
return fromRep(infRep | quotientSign);
}
else if (writtenExponent < 1) {
+ if (writtenExponent == 0) {
+ // Check whether the rounded result is normal.
+ const bool round = (residual << 1) > bSignificand;
+ // Clear the implicit bit.
+ rep_t absResult = quotient & significandMask;
+ // Round.
+ absResult += round;
+ if (absResult & ~significandMask) {
+ // The rounded result is normal; return it.
+ return fromRep(absResult | quotientSign);
+ }
+ }
// Flush denormals to zero. In the future, it would be nice to add
// code to round them correctly.
return fromRep(quotientSign);
diff --git a/compiler-rt/test/builtins/Unit/divdf3_test.c b/compiler-rt/test/builtins/Unit/divdf3_test.c
new file mode 100644
index 00000000000..00b021f4ec7
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/divdf3_test.c
@@ -0,0 +1,45 @@
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+//===--------------- divdf3_test.c - Test __divdf3 ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file tests __divdf3 for the compiler_rt library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "int_lib.h"
+#include <stdio.h>
+
+#include "fp_test.h"
+
+// Returns: a / b
+COMPILER_RT_ABI double __divdf3(double a, double b);
+
+int test__divdf3(double a, double b, uint64_t expected)
+{
+ double x = __divdf3(a, b);
+ int ret = compareResultD(x, expected);
+
+ if (ret){
+ printf("error in test__divdf3(%.20e, %.20e) = %.20e, "
+ "expected %.20e\n", a, b, x,
+ fromRep64(expected));
+ }
+ return ret;
+}
+
+int main()
+{
+ // 1/3
+ if (test__divdf3(1., 3., 0x3fd5555555555555ULL))
+ return 1;
+ // smallest normal result
+ if (test__divdf3(4.450147717014403e-308, 2., 0x10000000000000ULL))
+ return 1;
+
+ return 0;
+}
diff --git a/compiler-rt/test/builtins/Unit/divsf3_test.c b/compiler-rt/test/builtins/Unit/divsf3_test.c
new file mode 100644
index 00000000000..4b14c81b322
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/divsf3_test.c
@@ -0,0 +1,45 @@
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+//===--------------- divsf3_test.c - Test __divsf3 ------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file tests __divsf3 for the compiler_rt library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "int_lib.h"
+#include <stdio.h>
+
+#include "fp_test.h"
+
+// Returns: a / b
+COMPILER_RT_ABI float __divsf3(float a, float b);
+
+int test__divsf3(float a, float b, uint32_t expected)
+{
+ float x = __divsf3(a, b);
+ int ret = compareResultF(x, expected);
+
+ if (ret){
+ printf("error in test__divsf3(%.20e, %.20e) = %.20e, "
+ "expected %.20e\n", a, b, x,
+ fromRep32(expected));
+ }
+ return ret;
+}
+
+int main()
+{
+ // 1/3
+ if (test__divsf3(1.f, 3.f, 0x3EAAAAABU))
+ return 1;
+ // smallest normal result
+ if (test__divsf3(2.3509887e-38, 2., 0x00800000U))
+ return 1;
+
+ return 0;
+}
diff --git a/compiler-rt/test/builtins/Unit/divtf3_test.c b/compiler-rt/test/builtins/Unit/divtf3_test.c
index a9ff43e3885..23e1b5580b8 100644
--- a/compiler-rt/test/builtins/Unit/divtf3_test.c
+++ b/compiler-rt/test/builtins/Unit/divtf3_test.c
@@ -28,8 +28,8 @@ int test__divtf3(long double a, long double b,
int ret = compareResultLD(x, expectedHi, expectedLo);
if (ret){
- printf("error in test__divtf3(%.20Lf, %.20Lf) = %.20Lf, "
- "expected %.20Lf\n", a, b, x,
+ printf("error in test__divtf3(%.20Le, %.20Le) = %.20Le, "
+ "expected %.20Le\n", a, b, x,
fromRep128(expectedHi, expectedLo));
}
return ret;
@@ -86,6 +86,11 @@ int main()
UINT64_C(0x50bf2e02f0798d36),
UINT64_C(0x5e6fcb6b60044078)))
return 1;
+ if (test__divtf3(6.72420628622418701252535563464350521E-4932L,
+ 2.L,
+ UINT64_C(0x0001000000000000),
+ UINT64_C(0)))
+ return 1;
#else
printf("skipped\n");
OpenPOWER on IntegriCloud