GCC 4.7.2 and 4.8.0 miscompile the following code where UINT_MAX == 4294967295. $ cat bug.c int main(void) { unsigned x = 2; return ((unsigned) 0 - ( x / 2 ) ) / 2; } $ gcc bug.c $ ./a.out $ echo $? 0 Unsigned (0-(x/2))/2 should evaluate to 2147483647 instead of 0. The following code with variable x replaced by "(unsigned) 2" is correctly compiled. $ cat nobug.c int main(void) { return ((unsigned) 0 - ( (unsigned) 2 / 2 ) ) / 2; } $ gcc nobug.c $ ./a.out $ echo $? 255 The miscompile seems to occur on many versions of gcc (4.2 - 4.8, and even 4.0 and 3.1 on i686-apple-darwin, 4.4 - 4.6 on i686-linux-gnu-gcc, etc.)
When I do this: unsigned x = 2; unsigned t = (x/2); unsigned t1 = -t; unsigned t2 = t2/2; t2 is 0 which is correct. I don't see why 2147483647 is correct.
Actually I get the correct results with the split out one. The problem is division is being merged together over the negative which is not valid for wrapping cases.
(In reply to comment #1) > When I do this: > unsigned x = 2; > unsigned t = (x/2); > unsigned t1 = -t; > unsigned t2 = t2/2; > > t2 is 0 which is correct. I don't see why 2147483647 is correct. The last line should be unsigned t2 = t1/2;
Bug is in extract_muldiv_1.
Created attachment 29394 [details] gcc48-pr56250.patch Untested fix. I believe only division/modulus is problematic, not multiplication, and I think -fwrapv signed types are fine too. For *_DIV_EXPR/*_MOD_EXPR, I think wide_type is always NULL_TREE and ctype is always equal to type.
Author: jakub Date: Fri Feb 8 15:06:26 2013 New Revision: 195888 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=195888 Log: PR tree-optimization/56250 * fold-const.c (extract_muldiv_1) <case NEGATE_EXPR>: Don't optimize if type is unsigned and code isn't MULT_EXPR. * gcc.c-torture/execute/pr56250.c: New test. Added: trunk/gcc/testsuite/gcc.c-torture/execute/pr56250.c Modified: trunk/gcc/ChangeLog trunk/gcc/fold-const.c trunk/gcc/testsuite/ChangeLog
Fixed on the trunk so far.
Author: jakub Date: Tue Feb 19 17:26:04 2013 New Revision: 196147 URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=196147 Log: Backported from mainline 2013-02-08 Jakub Jelinek <jakub@redhat.com> PR tree-optimization/56250 * fold-const.c (extract_muldiv_1) <case NEGATE_EXPR>: Don't optimize if type is unsigned and code isn't MULT_EXPR. * gcc.c-torture/execute/pr56250.c: New test. Added: branches/gcc-4_7-branch/gcc/testsuite/gcc.c-torture/execute/pr56250.c Modified: branches/gcc-4_7-branch/gcc/ChangeLog branches/gcc-4_7-branch/gcc/fold-const.c branches/gcc-4_7-branch/gcc/testsuite/ChangeLog
Fixed for 4.7.3+.