[compiler-rt] [compiler-rt] Don't raise Inexact exception in C FP add implementation (PR #111211)

Keith Packard via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 4 14:28:30 PDT 2024


https://github.com/keith-packard updated https://github.com/llvm/llvm-project/pull/111211

>From 05be7cdd836643b47dbcf92a48992526a679d8be Mon Sep 17 00:00:00 2001
From: Keith Packard <keithp at keithp.com>
Date: Fri, 4 Oct 2024 13:13:35 -0700
Subject: [PATCH] [compiler-rt] Don't raise Inexact exception in C FP add
 implementation

It would be lovely if the soft float implementation were extended to
fully support all IEEE exceptions and rounding modes. However, at
present, there is only a single place where one exception might be
raised: the C version of addition raises Inexact when the result
differs from the precise value.

This affects targets which have hardware support for some formats and
rely on software for other formats; those will expose an
implementation of __fe_raise_inexact() that modifies the FPU status
register.

Removing the Inexact exception generation from the C version of FP
addition makes the implementation consistent across all operations and
formats on all targets. In addition, it makes the implementation match
the semantics of libgcc.

Signed-off-by: Keith Packard <keithp at keithp.com>
---
 compiler-rt/lib/builtins/fp_add_impl.inc      |  2 -
 .../test/builtins/Unit/adddf3inexact_test.c   | 81 +++++++++++++++++++
 2 files changed, 81 insertions(+), 2 deletions(-)
 create mode 100644 compiler-rt/test/builtins/Unit/adddf3inexact_test.c

diff --git a/compiler-rt/lib/builtins/fp_add_impl.inc b/compiler-rt/lib/builtins/fp_add_impl.inc
index d20599921e7d88..1b52c163d7a3f6 100644
--- a/compiler-rt/lib/builtins/fp_add_impl.inc
+++ b/compiler-rt/lib/builtins/fp_add_impl.inc
@@ -166,7 +166,5 @@ static __inline fp_t __addXf3__(fp_t a, fp_t b) {
   case CRT_FE_TOWARDZERO:
     break;
   }
-  if (roundGuardSticky)
-    __fe_raise_inexact();
   return fromRep(result);
 }
diff --git a/compiler-rt/test/builtins/Unit/adddf3inexact_test.c b/compiler-rt/test/builtins/Unit/adddf3inexact_test.c
new file mode 100644
index 00000000000000..a417281ba70dbc
--- /dev/null
+++ b/compiler-rt/test/builtins/Unit/adddf3inexact_test.c
@@ -0,0 +1,81 @@
+// RUN: %clang_builtins %s %librt -o %t && %run %t
+// REQUIRES: librt_has_adddf3
+
+#include "int_lib.h"
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if defined(__arm__) && (__ARM_FP & 0xc) == 4
+
+/* Run test on arm hardware with 32-bit only FPU */
+#  define PERFORM_TEST
+
+#  define ARM_INVALID 0x0001
+#  define ARM_DIVBYZERO 0x0002
+#  define ARM_OVERFLOW 0x0004
+#  define ARM_UNDERFLOW 0x0008
+#  define ARM_INEXACT 0x0010
+#  define ARM_DENORMAL 0x0080
+#  define ARM_ALL_EXCEPT                                                       \
+    (ARM_DIVBYZERO | ARM_INEXACT | ARM_INVALID | ARM_OVERFLOW |                \
+     ARM_UNDERFLOW | ARM_DENORMAL)
+
+static void clear_except(void) {
+  uint32_t fpscr;
+
+  /* Clear all exception bits */
+  __asm__ __volatile__("vmrs  %0, fpscr" : "=r"(fpscr));
+  fpscr &= ~(ARM_ALL_EXCEPT);
+  __asm__ __volatile__("vmsr  fpscr, %0" : : "ri"(fpscr));
+}
+
+static int get_except(void) {
+  uint32_t fpscr;
+
+  /* Test exception bits */
+  __asm__ __volatile__("vmrs  %0, fpscr" : "=r"(fpscr));
+  return (int)(fpscr & ARM_ALL_EXCEPT);
+}
+
+#endif
+
+#ifdef PERFORM_TEST
+int test__adddf3inexact(volatile double a, volatile double b,
+                        volatile double expected) {
+  volatile double actual;
+  int ret = 0;
+  int except;
+
+  clear_except();
+  actual = a + b;
+  if (actual != expected && isnan(actual) != isnan(expected)) {
+    printf("error in test__adddf3inexact(%a, %a) = %a, expected %a\n", a, b,
+           actual, expected);
+    ret = 1;
+  }
+
+  except = get_except();
+  if (except != 0) {
+    printf("error in test__adddf3inexact(%a, %a). raised exceptions 0x%x\n", a,
+           b, except);
+    ret = 1;
+  }
+
+  return ret;
+}
+#endif
+
+int main() {
+#ifdef PERFORM_TEST
+  if (test__adddf3inexact(0x1p+0, 0x1p-53, 0x1p+0))
+    return 1;
+  if (test__adddf3inexact(0x1p+0, 0x1p-52, 0x1.0000000000001p+0))
+    return 1;
+  if (test__adddf3inexact(0x1p+0, NAN, NAN))
+    return 1;
+#else
+  printf("skipped\n");
+#endif
+  return 0;
+}



More information about the llvm-commits mailing list