[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