From mboxrd@z Thu Jan 1 00:00:00 1970 From: Alan Modra To: hjl@lucon.org (H.J. Lu) Cc: mikeg@weiden.de, gas2@cygnus.com, egcs@cygnus.com, gcc2@cygnus.com Subject: Re: gcc generates invalid i386 fmulp Date: Wed, 15 Apr 1998 07:18:00 -0000 Message-id: <199804151416.XAA08842@mullet.Levels.UniSA.Edu.Au> References: X-SW-Source: 1998/msg00128.html I fiddled around with the glibc source that generated the invalid `fmulp %st(1),%st', and came up with the following test case. It's not all that small, but reducing the complexity seems to make the problem go away. ------------------ fop_pop_bug.c ------------------ /* * inspired by glibc-2.0.6/sysdeps/libm-ieee754/s_nextafterf.c * * gcc -O2 -S -DOP=+ gives faddp %st(1),%st * gcc -O2 -S -DOP=* gives fmulp %st(1),%st * gcc -O2 -S -DOP=- gives fsubrp %st(1),%st * gcc -O2 -S -DOP=/ gives fdivrp %st(1),%st */ #ifndef OP #define OP * #endif typedef int int32_t __attribute__ ((__mode__ ( __SI__ ))) ; typedef unsigned int u_int32_t __attribute__ ((__mode__ ( __SI__ ))) ; typedef union { float value; u_int32_t word; } ieee_float_shape_type; float __nextafterf(float x, float y) { int32_t hx,hy,ix,iy; { ieee_float_shape_type gf_u; gf_u.value = x; hx = gf_u.word; } { ieee_float_shape_type gf_u; gf_u.value = y; hy = gf_u.word; } ix = hx&0x7fffffff; iy = hy&0x7fffffff; if ( ix > 0x7f800000 || iy > 0x7f800000 ) return x+y; if (x == y) return x; if (ix == 0) { { ieee_float_shape_type sf_u; sf_u.word = (hy&0x80000000) | 1; x = sf_u.value; } y = x*x; if (y == x) return y; else return x; } if (hx >= 0) { if (hx > hy) hx -= 1; else hx += 1; } else { if (hy >= 0 || hx > hy) hx -= 1; else hx += 1; } hy = hx & 0x7f800000; if (hy >= 0x7f800000) return x+x; if (hy < 0x00800000) { y = x OP x; if (y != x) { ieee_float_shape_type sf_u; sf_u.word = hx; y = sf_u.value; return y; } } { ieee_float_shape_type sf_u; sf_u.word = hx; x = sf_u.value; } return x; }