Bug 36026 - optimized code returns different results
Summary: optimized code returns different results
Status: RESOLVED INVALID
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.3.0
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2008-04-23 11:26 UTC by Lukas Jirkovsky
Modified: 2008-04-23 15:18 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed:


Attachments
test code from verse (977 bytes, application/octet-stream)
2008-04-23 11:28 UTC, Lukas Jirkovsky
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Lukas Jirkovsky 2008-04-23 11:26:46 UTC
Hi,
I've code from verse (http://verse.blender.org/) which returns different results when run with optimizations.

Steps to reproduce:
run gcc test_simple.c
then run compiled program and see what it prints.
compile it with gcc -O2 (or higher). Resulting executable returns different result.

Tested gcc versions:
3.4.6 - everything works there
4.3.0 - bug is reproducible
4.1.2 - the same as 4.3.0

I've tried to turn on optimization flags which are enabled by -O2 by parts (At first first half and then second half of flags) but in this case the problem is not present.
Comment 1 Lukas Jirkovsky 2008-04-23 11:28:05 UTC
Created attachment 15516 [details]
test code from verse
Comment 2 Lukas Jirkovsky 2008-04-23 11:37:38 UTC
thanks to Ketling (one guy who helps me with identifying the bug) there is more progress:
high = (uv & 0x80000000) != 0; is always zero.
Comment 3 Richard Biener 2008-04-23 14:15:43 UTC
What is correct, what is incorrect output?  I get the same output

0x91F915BFDFAA69101B4D0720E517E6EAFAF7B231ADFFBBCDA5D630F51644A3466EC239357DA5989680018670CAAA4CA9CF5383B2E71A933A5608E3155DFF5071

for 3.3, 4.1, 4.2 and 4.3 for x86_64 and i686.
Comment 4 Richard Biener 2008-04-23 14:16:34 UTC
ok, there are subtle differences (too large number to look at), but which is
correct, which is incorrect?
Comment 5 Jakub Jelinek 2008-04-23 14:26:00 UTC
Looking at it.
Comment 6 Richard Biener 2008-04-23 14:32:29 UTC
-fno-tree-vrp "fixes" it, but

D.2830_35: [0, 65535]
D.2839_49: [0, 65535]
D.2840_56: [0, +INF(OVF)]

  D.2829_34 = *D.2828_33;
  D.2830_35 = (int) D.2829_34;
...
  D.2838_48 = *D.2837_47; 
  D.2839_49 = (int) D.2838_48;
  D.2840_56 = D.2830_35 * D.2839_49;
  high_59 = D.2840_56 < 0;

looks suspiciously like a case of signed integer overflow undefinedness.

                        uv = x[1 + j] * x[1 + i];
                        high = (uv & 0x80000000) != 0;

the multiplication will be carried out in signed int because VBigDig, the
type of *x, unsigned short, promotes to int.  Thus the above is equivalent to

                       uv = (unsigned int)((int)x[1 + j] * (int)x[1 + i]);
                       high = (uv & 0x80000000) != 0;

at which the compiler can conclude that the result of the multiplication
is never negative.  Fix this by doing

                        uv = (VBigDigs)x[1 + j] * (VBigDigs)x[1 + i];
                        high = (uv & 0x80000000) != 0;

instead.
Comment 7 Richard Biener 2008-04-23 14:48:53 UTC
Btw:

gcc-4.3 -o t test_simple.c -O2 -Wstrict-overflow
test_simple.c: In function 'v_bignum_square_half':
test_simple.c:96: warning: assuming signed overflow does not occur when simplifying conditional to constant
Comment 8 Lukas Jirkovsky 2008-04-23 15:18:37 UTC
Thanks a lot. Actually I'm a very beginner in C++ and I don't understand this code a lot.