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>