[compiler-rt] r356529 - [builtins] Divide shouldn't underflow if rounded result would be normal.

Eli Friedman via llvm-commits llvm-commits at lists.llvm.org
Tue Mar 19 14:55:58 PDT 2019


Author: efriedma
Date: Tue Mar 19 14:55:58 2019
New Revision: 356529

URL: http://llvm.org/viewvc/llvm-project?rev=356529&view=rev
Log:
[builtins] Divide shouldn't underflow if rounded result would be normal.

We were treating certain edge cases that are actually normal as denormal
results, and flushing them to zero; we shouldn't do that. Not sure this
is the cleanest way to implement this edge case, but I wanted to avoid
adding any code on the common path.

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


Added:
    compiler-rt/trunk/test/builtins/Unit/divdf3_test.c
    compiler-rt/trunk/test/builtins/Unit/divsf3_test.c
Modified:
    compiler-rt/trunk/lib/builtins/divdf3.c
    compiler-rt/trunk/lib/builtins/divsf3.c
    compiler-rt/trunk/lib/builtins/divtf3.c
    compiler-rt/trunk/test/builtins/Unit/divtf3_test.c

Modified: compiler-rt/trunk/lib/builtins/divdf3.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/divdf3.c?rev=356529&r1=356528&r2=356529&view=diff
==============================================================================
--- compiler-rt/trunk/lib/builtins/divdf3.c (original)
+++ compiler-rt/trunk/lib/builtins/divdf3.c Tue Mar 19 14:55:58 2019
@@ -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);

Modified: compiler-rt/trunk/lib/builtins/divsf3.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/divsf3.c?rev=356529&r1=356528&r2=356529&view=diff
==============================================================================
--- compiler-rt/trunk/lib/builtins/divsf3.c (original)
+++ compiler-rt/trunk/lib/builtins/divsf3.c Tue Mar 19 14:55:58 2019
@@ -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);

Modified: compiler-rt/trunk/lib/builtins/divtf3.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/builtins/divtf3.c?rev=356529&r1=356528&r2=356529&view=diff
==============================================================================
--- compiler-rt/trunk/lib/builtins/divtf3.c (original)
+++ compiler-rt/trunk/lib/builtins/divtf3.c Tue Mar 19 14:55:58 2019
@@ -181,6 +181,18 @@ COMPILER_RT_ABI fp_t __divtf3(fp_t a, fp
         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);

Added: compiler-rt/trunk/test/builtins/Unit/divdf3_test.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/builtins/Unit/divdf3_test.c?rev=356529&view=auto
==============================================================================
--- compiler-rt/trunk/test/builtins/Unit/divdf3_test.c (added)
+++ compiler-rt/trunk/test/builtins/Unit/divdf3_test.c Tue Mar 19 14:55:58 2019
@@ -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;
+}

Added: compiler-rt/trunk/test/builtins/Unit/divsf3_test.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/builtins/Unit/divsf3_test.c?rev=356529&view=auto
==============================================================================
--- compiler-rt/trunk/test/builtins/Unit/divsf3_test.c (added)
+++ compiler-rt/trunk/test/builtins/Unit/divsf3_test.c Tue Mar 19 14:55:58 2019
@@ -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;
+}

Modified: compiler-rt/trunk/test/builtins/Unit/divtf3_test.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/builtins/Unit/divtf3_test.c?rev=356529&r1=356528&r2=356529&view=diff
==============================================================================
--- compiler-rt/trunk/test/builtins/Unit/divtf3_test.c (original)
+++ compiler-rt/trunk/test/builtins/Unit/divtf3_test.c Tue Mar 19 14:55:58 2019
@@ -28,8 +28,8 @@ int test__divtf3(long double a, long dou
     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");




More information about the llvm-commits mailing list