http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53857
Bug #: 53857 Summary: Possible problem with arithmetic overflow in optimizer Classification: Unclassified Product: gcc Version: 4.7.1 Status: UNCONFIRMED Severity: major Priority: P3 Component: c AssignedTo: unassig...@gcc.gnu.org ReportedBy: 00w...@gmail.com Created attachment 27743 --> http://gcc.gnu.org/bugzilla/attachment.cgi?id=27743 Program showing the problem Hi We found unusual behaviour of compilator which probably assumes there is no arithmetic overflow and then simplifies the code too much. We attach the simplest code which illustrates the problem. Make will create several binaries including: "testo1" and "testo2". The first is compiled with -O1 option, the other with -O2. For the gcc 4.6 (or clang'a 3.1) everything is fine. Both programs write: x: 2147483648, y: 2147483648 For gcc 4.7.1 (also 4.7) program "testo1" writes the same as above but "testo2" will write: x: 18446744071562067968, y: 18446744071562067968 What is interesting the problem appears on both architectures: x86_64 (Intel 64-bit) and i386 (Intel 32-bit). We made tests with options "-fno-strict-overflow" and "-fwrapv". Compilation with only "-fno-strict-overflow" option still generates the code which gives wrong results. Compilation with "-fwrapv" gived the proper code. But still the behaviour differs from 4.6 version. According to us code "x64|=(uint32_t)(some_arithmetic_operations_on_signed_integers_with_overflow)" should in no case set high 32 bits of x64 variable independently of options used. Even if overflow result in "some_arithmetic_operations_on_signed_integers_with_overflow" fragment is not specified, then type casting to uint32_t should never return negative number, which expanded to 64 bits will cause setting high 32 bits of x64 variable. We need to take into account that "some_arithmetic_operations_on_signed_integers_with_overflow" may return a negative number (even without any overflows), so treatment of overflows should not change anything here - after casting to uint32_t we should always get a 32-bit unsigned number which by the "|=" operation with 64-bit number with no sign should also expand to 64-bit number with no sign by adding 32 high bits filled with zeros. Even when we assume that the result of "some_arithmetic_operations_on_signed_integers_with_overflow" has "undefined behavior", then after casting it to uint32_t only lower 32 bits should remain undefined but here we can see that the result has also impact on the high bits (even without any warning). What is suspicious compilation behaves in very unpredictable way. The same expression compiled with the same options may give different results. When we change this fragment "y = get64bit(&rp);" to: "y = 0;" then the second variable "x" will return proper results. MooseFS Team http://www.moosefs.org/