On Thu, 31 Oct 2002, David Schultz wrote:

> Thus spake Bruce Evans <[EMAIL PROTECTED]>:
> > $ cc -o z z.c
> > $ ./z
> > LDBL_EPSILON failed test 1 with prec 2
> > $ cc -O -o z z.c.
> > $ ./z
> > LDBL_EPSILON failed test 1 with prec 2
> > DBL_EPSILON failed test 2 with prec 3
> > %%%
> >
> > The full brokenness only shows up with -O.
>
> Actually, the _full_ brokenness of floating point in FreeBSD shows
> up only with -O2.  :-(  A number of library functions
> (e.g. isinf()) use unions for type punning, which violates C's
> aliasing rules.
>
> It turns out that there's a bad interaction
> between gcc3's -fschedule-insns and -fstrict-aliasing (both
> implied by -O2) that can cause problems.  The best fix I know of
> is to use unions in the limited way that gcc's optimizer knows how
> to handle in a reasonable way.

Eeek.

gcc.info says one version is required to work even with -fstrict-aliasing.
The problems seems to be limited, since msun was fixed before rev.1.1
to use this version.  From msun/src/math_private.h:

%%%
/*
 * The original fdlibm code used statements like:
 *      n0 = ((*(int*)&one)>>29)^1;             * index of high word *
 *      ix0 = *(n0+(int*)&x);                   * high word of x *
 *      ix1 = *((1-n0)+(int*)&x);               * low word of x *
 * to dig two 32 bit words out of the 64 bit IEEE floating point
 * value.  That is non-ANSI, and, moreover, the gcc instruction
 * scheduler gets it wrong.  We instead use the following macros.
 * Unlike the original code, we determine the endianness at compile
 * time, not at run time; I don't see much benefit to selecting
 * endianness at run time.
 */
...
#define EXTRACT_WORDS(ix0,ix1,d)                                \
do {                                                            \
  ieee_double_shape_type ew_u;                                  \
  ew_u.value = (d);                                             \
  (ix0) = ew_u.parts.msw;                                       \
  (ix1) = ew_u.parts.lsw;                                       \
} while (0)
...
%%%

This stores the double into the union and doesn't use any pointers to
access the results, so it should work.  isinf.c and even the "fixed"
version of strtod.c uses a dubious cast to pun the double to a union.
I think the store gets optimized away as far as possible.

Bruce


To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-current" in the body of the message

Reply via email to