Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 31 Oct 2002 23:36:13 +1100 (EST)
From:      Bruce Evans <bde@zeta.org.au>
To:        David Schultz <dschultz@uclink.Berkeley.EDU>
Cc:        "M. Warner Losh" <imp@bsdimp.com>, <tlambert2@mindspring.com>, <rittle@labs.mot.com>, <rittle@latour.rsch.comm.mot.com>, <current@FreeBSD.ORG>
Subject:   Re: Lack of real long double support
Message-ID:  <20021031225719.V11320-100000@gamplex.bde.org>
In-Reply-To: <20021031112623.GA28135@HAL9000.homeunix.com>

next in thread | previous in thread | raw e-mail | index | archive | help
On Thu, 31 Oct 2002, David Schultz wrote:

> Thus spake Bruce Evans <bde@zeta.org.au>:
> > $ 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 majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20021031225719.V11320-100000>