Message ID | 20210928093312.GV304296@tucnak |
---|---|
State | New |
Headers | show |
Series | i386: Don't emit fldpi etc. if -frounding-math [PR102498] | expand |
On Tue, Sep 28, 2021 at 11:33 AM Jakub Jelinek <jakub@redhat.com> wrote: > > Hi! > > 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. > > Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? > > 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. OK. Thanks, Uros. > > --- gcc/config/i386/i386.c.jj 2021-09-18 09:44:31.720743823 +0200 > +++ gcc/config/i386/i386.c 2021-09-27 16:55:37.928072249 +0200 > @@ -5035,7 +5035,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; > > --- gcc/testsuite/gcc.target/i386/pr102498.c.jj 2021-09-27 17:09:30.387509264 +0200 > +++ gcc/testsuite/gcc.target/i386/pr102498.c 2021-09-27 17:09:22.548618148 +0200 > @@ -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; > +} > > Jakub >
--- gcc/config/i386/i386.c.jj 2021-09-18 09:44:31.720743823 +0200 +++ gcc/config/i386/i386.c 2021-09-27 16:55:37.928072249 +0200 @@ -5035,7 +5035,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; --- gcc/testsuite/gcc.target/i386/pr102498.c.jj 2021-09-27 17:09:30.387509264 +0200 +++ gcc/testsuite/gcc.target/i386/pr102498.c 2021-09-27 17:09:22.548618148 +0200 @@ -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; +}