I have write a very simple program to test gcc -O2 option, it will generate a wrong behavior. Is it a bug of gcc?
My C program:
#include <stdio.h>
int main(int argc, char **argv)
{
unsigned long i = 0;
while (1) {
if (++i > 0x1fffffffUL) {
printf("hello\n");
i = 0;
}
}
}
When I compile it with -O1, everything is right, i is added 1 in each loop. But when I compile it with -O2, i is ignored, "hello" is output in each loop. Why -O2 will cause this wrong behavior? Is obvious bug of gcc? My gcc version is 4.8.3 for cygwin, and I have tried a new one, it also has the same problem.
Compile with -O1, the assembly code is:
Disassembly of section .text:
00000000 <_main>:
#include <stdio.h>
int main(int argc, char **argv)
{
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 e4 f0 and $0xfffffff0,%esp
6: 83 ec 10 sub $0x10,%esp
9: e8 00 00 00 00 call e <_main+0xe>
e: b8 00 00 00 20 mov $0x20000000,%eax
unsigned long i = 0;
while (1) {
if (++i > 0x1fffffffUL) {
13: 83 e8 01 sub $0x1,%eax
16: 75 fb jne 13 <_main+0x13>
printf("hello\n");
18: c7 04 24 00 00 00 00 movl $0x0,(%esp)
1f: e8 00 00 00 00 call 24 <_main+0x24>
24: eb e8 jmp e <_main+0xe>
26: 90 nop
27: 90 nop
Compile with -O2, the assembly code is:
Disassembly of section .text.startup:
00000000 <_main>:
#include <stdio.h>
int main(int argc, char **argv)
{
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 83 e4 f0 and $0xfffffff0,%esp
6: 83 ec 10 sub $0x10,%esp
9: e8 00 00 00 00 call e <_main+0xe>
e: 66 90 xchg %ax,%ax
10: c7 04 24 00 00 00 00 movl $0x0,(%esp)
17: e8 00 00 00 00 call 1c <_main+0x1c>
1c: eb f2 jmp 10 <_main+0x10>
1e: 90 nop
1f: 90 nop