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.
This commit is contained in:
Jakub Jelinek 2021-09-28 13:02:51 +02:00
parent 34b1e44e16
commit 3b7041e834
2 changed files with 61 additions and 1 deletions

View file

@ -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;

View file

@ -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;
}