$ cat test.c #include <stdio.h> int main() { _Decimal128 const a=1.111111111111111111111111111111111dl; _Decimal128 const b=1.1111111e-6158dl; _Decimal128 volatile x=a; _Decimal128 volatile y=b; double ab=a*b*1.0e6000dl; double xy=x*y*1.0e6000dl; printf("ab=%g\n",ab); printf("xy=%g\n",xy); } $ gcc test.c && ./a.out ab=9.64506e-159 xy=9.64506e-159 $ gcc -O test.c && ./a.out ab=1.23457e-158 xy=9.64506e-159 $ gcc --version | head -1 gcc (GCC) 4.5.1 20100418 (prerelease) The correct value is 1.23457e-158: $ echo "1.111111111111111111111111111111111*1.1111111" | bc 1.234567888888888888888888888888888 A simple modification of test.c can show that it is x*y and a*b, when computed by libbid, are incorrect. The a*b expression, when computed by gcc (with -O), is correct. To further diagnose, I extracted libbid from the gcc source tree and compiled it outside of gcc to link it with the above test.c program. I added some #defines to compile the library and renamed some functions to call them directly from the test. I found that if compiled with -O only, libbid multiplies correctly. With -O -ftree-pre, it multiplies incorrectly. The real job is done by bid128_ext_fma() (about 3000 C lines).
This needs a testcase. The libdecnumber code is a mess (and I can't find an implementation for bid128_ext_fma()).
(In reply to comment #1) > This needs a testcase. The libdecnumber code is a mess (and I can't find > an implementation for bid128_ext_fma()). > bid128_ext_fma() is in libgcc/config/libbid/bid128_fma.c
Starting from r150519 gcc compiles its own internal libbid wrong. With the previous revision of gcc, the output of the above test.c is correct: $ gcc -O test.c && ./a.out ab=1.23457e-158 xy=1.23457e-158
Confirmed (libbid result is incorrect, GCC constant-folded result is correct).
It's not bid128_ext_fma that is miscompiled but bid_round.c, building that with -O1 [-ftree-pre] works [fails]. __bid_round192_39_57 is miscompiled by PRE.
Testcase: typedef __attribute__((aligned(16))) struct { unsigned long w[3]; } UINT192; UINT192 __bid_Kx192[32]; extern void abort (void); int main() { int i = 0; unsigned long x = 0; for (i = 0; i < 32; ++i) __bid_Kx192[i].w[1] = i == 1; for (i = 0; i < 32; ++i) x += __bid_Kx192[1].w[1]; if (x != 32) abort (); return 0; }
The array element alignment is not properly visible, but instead loads of random crap alignments appear in trees.
Subject: Bug 43783 Author: rguenth Date: Mon Apr 19 13:36:54 2010 New Revision: 158517 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=158517 Log: 2010-04-19 Richard Guenther <rguenther@suse.de> PR tree-optimization/43783 * tree-ssa-pre.c (create_component_ref_by_pieces_1): Drop constant ARRAY_REF operands two and three if possible. * gcc.c-torture/execute/pr43783.c: New testcase. Added: trunk/gcc/testsuite/gcc.c-torture/execute/pr43783.c Modified: trunk/gcc/ChangeLog trunk/gcc/testsuite/ChangeLog trunk/gcc/tree-ssa-pre.c
The 4.5 branch works for me if patched this way. Thanks.
Fixed.
Subject: Bug 43783 Author: rguenth Date: Tue Apr 20 09:05:33 2010 New Revision: 158549 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=158549 Log: 2010-04-20 Richard Guenther <rguenther@suse.de> PR tree-optimization/43783 * tree-ssa-pre.c (create_component_ref_by_pieces_1): Drop constant ARRAY_REF operands two and three if possible. * gcc.c-torture/execute/pr43783.c: New testcase. Added: branches/gcc-4_5-branch/gcc/testsuite/gcc.c-torture/execute/pr43783.c Modified: branches/gcc-4_5-branch/gcc/ChangeLog branches/gcc-4_5-branch/gcc/testsuite/ChangeLog branches/gcc-4_5-branch/gcc/tree-ssa-pre.c