On Tue, Sep 28, 2021 at 11:33 AM Jakub Jelinek <ja...@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  <ja...@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
>

Reply via email to