Skip to content

Commit 05be7cd

Browse files
committed
[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 <[email protected]>
1 parent fda2fea commit 05be7cd

File tree

2 files changed

+81
-2
lines changed

2 files changed

+81
-2
lines changed

compiler-rt/lib/builtins/fp_add_impl.inc

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,5 @@ static __inline fp_t __addXf3__(fp_t a, fp_t b) {
166166
case CRT_FE_TOWARDZERO:
167167
break;
168168
}
169-
if (roundGuardSticky)
170-
__fe_raise_inexact();
171169
return fromRep(result);
172170
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
// RUN: %clang_builtins %s %librt -o %t && %run %t
2+
// REQUIRES: librt_has_adddf3
3+
4+
#include "int_lib.h"
5+
#include <math.h>
6+
#include <stdio.h>
7+
#include <stdlib.h>
8+
9+
#if defined(__arm__) && (__ARM_FP & 0xc) == 4
10+
11+
/* Run test on arm hardware with 32-bit only FPU */
12+
# define PERFORM_TEST
13+
14+
# define ARM_INVALID 0x0001
15+
# define ARM_DIVBYZERO 0x0002
16+
# define ARM_OVERFLOW 0x0004
17+
# define ARM_UNDERFLOW 0x0008
18+
# define ARM_INEXACT 0x0010
19+
# define ARM_DENORMAL 0x0080
20+
# define ARM_ALL_EXCEPT \
21+
(ARM_DIVBYZERO | ARM_INEXACT | ARM_INVALID | ARM_OVERFLOW | \
22+
ARM_UNDERFLOW | ARM_DENORMAL)
23+
24+
static void clear_except(void) {
25+
uint32_t fpscr;
26+
27+
/* Clear all exception bits */
28+
__asm__ __volatile__("vmrs %0, fpscr" : "=r"(fpscr));
29+
fpscr &= ~(ARM_ALL_EXCEPT);
30+
__asm__ __volatile__("vmsr fpscr, %0" : : "ri"(fpscr));
31+
}
32+
33+
static int get_except(void) {
34+
uint32_t fpscr;
35+
36+
/* Test exception bits */
37+
__asm__ __volatile__("vmrs %0, fpscr" : "=r"(fpscr));
38+
return (int)(fpscr & ARM_ALL_EXCEPT);
39+
}
40+
41+
#endif
42+
43+
#ifdef PERFORM_TEST
44+
int test__adddf3inexact(volatile double a, volatile double b,
45+
volatile double expected) {
46+
volatile double actual;
47+
int ret = 0;
48+
int except;
49+
50+
clear_except();
51+
actual = a + b;
52+
if (actual != expected && isnan(actual) != isnan(expected)) {
53+
printf("error in test__adddf3inexact(%a, %a) = %a, expected %a\n", a, b,
54+
actual, expected);
55+
ret = 1;
56+
}
57+
58+
except = get_except();
59+
if (except != 0) {
60+
printf("error in test__adddf3inexact(%a, %a). raised exceptions 0x%x\n", a,
61+
b, except);
62+
ret = 1;
63+
}
64+
65+
return ret;
66+
}
67+
#endif
68+
69+
int main() {
70+
#ifdef PERFORM_TEST
71+
if (test__adddf3inexact(0x1p+0, 0x1p-53, 0x1p+0))
72+
return 1;
73+
if (test__adddf3inexact(0x1p+0, 0x1p-52, 0x1.0000000000001p+0))
74+
return 1;
75+
if (test__adddf3inexact(0x1p+0, NAN, NAN))
76+
return 1;
77+
#else
78+
printf("skipped\n");
79+
#endif
80+
return 0;
81+
}

0 commit comments

Comments
 (0)