This is GCC Bugzilla
This is GCC Bugzilla Version 2.20+
View Bug Activity | Format For Printing | Clone This Bug
On FreeBSD/i386, FPU precision is set to 53 bits to avoid problems with extra precision and double rounding for doubles. gcc understands this and evaluates FP constants in 53-bit precision, even for long doubles. (See ieee_extended_intel_96_round_53_format in real.c.) However, gcc occasionally evaluates hexadecimal (and possibly decimal) floating-point constants incorrectly starting with version 3.4: das@VARK:~> cat bar.c #include <stdio.h> int main(int argc, char *argv[]) { volatile long double d = 0x3.243f6a8885a31p0L; printf("%La\n", d); d = 2.0 * d / 2.0; printf("%La\n", d); return (0); } das@VARK:~> gcc33 bar.c das@VARK:~> ./a.out 0xc.90fdaa22168cp-2 0xc.90fdaa22168cp-2 das@VARK:~> gcc bar.c das@VARK:~> ./a.out 0xc.90fdaa22168c4p-2 0xc.90fdaa22168cp-2 das@VARK:~> gcc --version gcc (GCC) 3.4.2 [FreeBSD] 20040728 das@VARK:~> gcc33 --version gcc33 (GCC) 3.3.5 20040630 (prerelease) [FreeBSD] In the tests I've tried, the symptoms were always setting the 57th mantissa bit, even when the number would not have that bit set when rounded to 57 bits. Given the position of the incorrect bit, I suspect that the bug is due to either a mistake in the way rounding is handled, or, more likely, an endianness mistake in the handling of the sign bit that doesn't show up in the 96-bit format since the 97th bit is ignored.
I cannot reproduce this on the mainline or on 3.4.0 on i686-pc-linux, maybe this is a difference between Linux and freebsd depending on the rounding mode (or precision set to 80bits). I really think this is OS problem rather than a GCC problem.
Subject: Re: regression in evaluating long double hexadecimal constants On Fri, Oct 01, 2004, pinskia at gcc dot gnu dot org wrote: > > ------- Additional Comments From pinskia at gcc dot gnu dot org 2004-10-01 17:04 ------- > I cannot reproduce this on the mainline or on 3.4.0 on i686-pc-linux, maybe this is a difference > between Linux and freebsd depending on the rounding mode (or precision set to 80bits). > > I really think this is OS problem rather than a GCC problem. Thanks for the quick response. Linux sets the i386 FPU to extended precision, which avoids this bug but leads to other problems. So you're right that the bug won't appear on Linux, but it isn't an OS problem, it's a gcc problem. gcc is supposed to understand the native precision used in the target environment and round floating-point constant expressions to that precision. This used to work, and it almost works now, but as of gcc 3.4, an extra bit is set in the mantissa of long doubles.
I could also reproduce it with 3.3.3 on openbsd (with a Linux binary) so this is not a regression from 3.3.3.
Subject: Re: regression in evaluating long double hexadecimal constants On Fri, Oct 01, 2004, pinskia at gcc dot gnu dot org wrote: > I could also reproduce it with 3.3.3 on openbsd (with a Linux > binary) so this is not a regression from 3.3.3. Yes it is. The ``I tried it for two test cases so it must be true'' argument does not apply here; OpenBSD and Linux set the FPU control word identically.
The bug is real, and it's not any of those proposed. The Real Problem is that the floating point format that is actually installed is NOT the 53-bit format that FreeBSD wants to use. I guess Zack's conversion to cpu-modes.def files was not 100% correct. In any case, the SUBTARGET_OVERRIDE_OPTIONS definition in freebsd.h is not effective. It probably happens too early. Seems like a cleaner solution here would be a TARGET_53_IN_96_LONG_DOUBLE macro to be used in the existing ADJUST_FLOAT_FORMAT directive that we already have.
Created an attachment (id=7524) [edit] proposed patch
Try that.
Subject: Re: [3.4/4.0 Regression] regression in evaluating long double hexadecimal constants Yes, this appears to fix the problem. Thanks! Your timing is impeccable, by the way. Over in FreeBSDland, this bug recently generated discussion about whether we really need to reduce the npx precision on i386 anymore. The precision was originally reduced because gcc didn't used to evaluate expressions involving doubles with the appropriate rounding when the FPU rounding mode was set to extended precision, but gcc seems to be somewhat better in this respect in 3.X. I think the consensus is that we would like to move to extended precision, but it's not yet clear how to do this without breaking older programs.
Subject: Bug 17778 CVSROOT: /cvs/gcc Module name: gcc Changes by: rth@gcc.gnu.org 2004-11-12 21:15:24 Modified files: gcc : ChangeLog gcc/config/i386: freebsd.h i386-modes.def i386.h Log message: PR 17778 * config/i386/i386.h (TARGET_96_ROUND_53_LONG_DOUBLE): New. * config/i386/freebsd.h (SUBTARGET_OVERRIDE_OPTIONS): Remove. (TARGET_96_ROUND_53_LONG_DOUBLE): New. * config/i386/i386-modes.def (XF): Use it. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&r1=2.6301&r2=2.6302 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/i386/freebsd.h.diff?cvsroot=gcc&r1=1.44&r2=1.45 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/i386/i386-modes.def.diff?cvsroot=gcc&r1=1.9&r2=1.10 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/i386/i386.h.diff?cvsroot=gcc&r1=1.402&r2=1.403
Subject: Bug 17778 CVSROOT: /cvs/gcc Module name: gcc Branch: gcc-3_4-branch Changes by: rth@gcc.gnu.org 2004-11-12 21:26:55 Modified files: gcc : ChangeLog gcc/config/i386: freebsd.h i386-modes.def i386.h Log message: PR 17778 * config/i386/i386.h (TARGET_96_ROUND_53_LONG_DOUBLE): New. * config/i386/freebsd.h (SUBTARGET_OVERRIDE_OPTIONS): Remove. (TARGET_96_ROUND_53_LONG_DOUBLE): New. * config/i386/i386-modes.def (XF): Use it. Patches: http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/ChangeLog.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=2.2326.2.688&r2=2.2326.2.689 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/i386/freebsd.h.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.41.10.1&r2=1.41.10.2 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/i386/i386-modes.def.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.6&r2=1.6.6.1 http://gcc.gnu.org/cgi-bin/cvsweb.cgi/gcc/gcc/config/i386/i386.h.diff?cvsroot=gcc&only_with_tag=gcc-3_4-branch&r1=1.368.2.4&r2=1.368.2.5
Fixed.