Bug 26824 - optimisation bug with -0x80000000
optimisation bug with -0x80000000
Status: RESOLVED DUPLICATE of bug 25329
Product: gcc
Classification: Unclassified
Component: c
4.1.0
: P3 major
: ---
Assigned To: Not yet assigned to anyone
:
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2006-03-23 11:37 UTC by Simon Marlow
Modified: 2006-03-23 15:17 UTC (History)
2 users (show)

See Also:
Host: x86_64-redhat-linux
Target: x86_64-redhat-linux
Build: x86_64-redhat-linux
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Simon Marlow 2006-03-23 11:37:22 UTC
The following code is compiled incorrectly with -O2:

#include <stdlib.h>

void f(int x) {
    if (x < 0) {
	if (-x > 0) {
	    exit(1);
	}
    }
}

int main() {
	f(-0x80000000);
	exit(0);
}

$ gcc foo.c; ./a.out         
$ gcc -O2 foo.c; ./a.out 
zsh: 4407 exit 1     ./a.out
$
Comment 1 Andrew Pinski 2006-03-23 14:12:46 UTC
-0x80000000 is going to overflow and for signed integers overflow is undefined.  If you want signed integers to be defined to be wrapping use -fwrapv.
Comment 2 Falk Hueffner 2006-03-23 14:44:46 UTC
Wait a minute. 0x80000000 is unsigned. So -0x80000000 is well-defined, and
is 0x80000000 (unsigned). This is then converted to signed. Since 0x80000000
cannot be represented in signed, the result is implementation specific.
We document it to be -0x80000000. So the call is just fine.
Comment 3 Andrew Pinski 2006-03-23 14:49:00 UTC
It is the -x in f where x = 0x80000000 which is undefined as it overflows.
Comment 4 Falk Hueffner 2006-03-23 14:57:09 UTC
(In reply to comment #3)
> It is the -x in f where x = 0x80000000 which is undefined as it overflows.

Oh. I see. Right.


Comment 5 Simon Marlow 2006-03-23 15:10:13 UTC
I see your point, but I still think there's a bug.  Let me change the code slightly:

#include <stdlib.h>
#include <stdio.h>

void f(int x) {
    long y;
    if (x < 0) {
	y = -x;
	if (y > 0) {
	    printf("%d\n",y);
	}
    }
}

int main() {
	f(-0x80000000);
	exit(0);
}

$ gcc -O2 foo.c
$ ./a.out      
-2147483648

so, we're in the y > 0 branch, but y is clearly < 0.
Comment 6 Richard Earnshaw 2006-03-23 15:14:09 UTC
Pinskia is right, and this is just as undefined as your previous example (negating INT_MIN is just undefined, however you do it).  All you've done is obfuscated things a bit more.
Comment 7 Andrew Pinski 2006-03-23 15:15:01 UTC
(In reply to comment #5)
> I see your point, but I still think there's a bug.  Let me change the code
> slightly:
The code is still undefined, as you are comparing an overflowed variable to something.

-x is still undefined for x being 0x80000000 as it overflows and overflow signed integer is undefined runtime code.
Comment 8 Andrew Pinski 2006-03-23 15:17:10 UTC
Reopening to ... 
Comment 9 Andrew Pinski 2006-03-23 15:17:24 UTC
Mark as a dup of bug 25329.

*** This bug has been marked as a duplicate of 25329 ***