aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2021-09-28 13:02:51 +0200
committerJakub Jelinek <jakub@redhat.com>2021-09-28 13:02:51 +0200
commit3b7041e8345c2f1030e58620f28e22d64b2c196b (patch)
tree261386b7393d54006d01f91dd7bca2098f5166a0
parent34b1e44e166c58df20a15cb35b6cc8d4d299d415 (diff)
downloadgcc-3b7041e8345c2f1030e58620f28e22d64b2c196b.zip
gcc-3b7041e8345c2f1030e58620f28e22d64b2c196b.tar.gz
gcc-3b7041e8345c2f1030e58620f28e22d64b2c196b.tar.bz2
i386: Don't emit fldpi etc. if -frounding-math [PR102498]
i387 has instructions to store some transcedental numbers into the top of stack. The problem is that what exact bit in the last place one gets for those depends on the current rounding mode, the CPU knows the number with slightly higher precision. The compiler assumes rounding to nearest when comparing them against constants in the IL, but at runtime the rounding can be different and so some of these depending on rounding mode and the constant could be 1 ulp higher or smaller than expected. We only support changing the rounding mode at runtime if the non-default -frounding-mode option is used, so the following patch just disables using those constants if that flag is on. 2021-09-28 Jakub Jelinek <jakub@redhat.com> PR target/102498 * config/i386/i386.c (standard_80387_constant_p): Don't recognize special 80387 instruction XFmode constants if flag_rounding_math. * gcc.target/i386/pr102498.c: New test.
-rw-r--r--gcc/config/i386/i386.c3
-rw-r--r--gcc/testsuite/gcc.target/i386/pr102498.c59
2 files changed, 61 insertions, 1 deletions
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index b3e4add..5aeb44c 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -5039,7 +5039,8 @@ standard_80387_constant_p (rtx x)
/* For XFmode constants, try to find a special 80387 instruction when
optimizing for size or on those CPUs that benefit from them. */
if (mode == XFmode
- && (optimize_function_for_size_p (cfun) || TARGET_EXT_80387_CONSTANTS))
+ && (optimize_function_for_size_p (cfun) || TARGET_EXT_80387_CONSTANTS)
+ && !flag_rounding_math)
{
int i;
diff --git a/gcc/testsuite/gcc.target/i386/pr102498.c b/gcc/testsuite/gcc.target/i386/pr102498.c
new file mode 100644
index 0000000..44161c5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/pr102498.c
@@ -0,0 +1,59 @@
+/* PR target/102498 */
+/* { dg-do run { target fenv } } */
+/* { dg-options "-frounding-math" } */
+
+#include <fenv.h>
+#include <stdlib.h>
+
+__attribute__((noipa)) long double
+fldlg2 (void)
+{
+ return 0.3010299956639811952256464283594894482L;
+}
+
+__attribute__((noipa)) long double
+fldln2 (void)
+{
+ return 0.6931471805599453094286904741849753009L;
+}
+
+__attribute__((noipa)) long double
+fldl2e (void)
+{
+ return 1.4426950408889634073876517827983434472L;
+}
+
+__attribute__((noipa)) long double
+fldl2t (void)
+{
+ return 3.3219280948873623478083405569094566090L;
+}
+
+__attribute__((noipa)) long double
+fldpi (void)
+{
+ return 3.1415926535897932385128089594061862044L;
+}
+
+int
+main ()
+{
+ long double a = fldlg2 ();
+ long double b = fldln2 ();
+ long double c = fldl2e ();
+ long double d = fldl2t ();
+ long double e = fldpi ();
+ static int f[] = { FE_TONEAREST, FE_TOWARDZERO, FE_UPWARD, FE_DOWNWARD };
+ int i;
+ for (i = 0; i < 4; i++)
+ {
+ fesetround (f[i]);
+ if (a != fldlg2 ()
+ || b != fldln2 ()
+ || c != fldl2e ()
+ || d != fldl2t ()
+ || e != fldpi ())
+ abort ();
+ }
+ return 0;
+}