17581 – [3.4 Regression] Long long arithmetic fails inside a switch/case statement when compiled with -O2 (original) (raw)
Description Avner Lottem 2004-09-21 08:45:29 UTC
Inside a case statement, the following code gives an incorrect result: case 21: ctl_bitvec |= 1; ctl_bitvec |= 2; ctl_bitvec |= 8; break;
By the end of the calculation, ctl_bitvec contains 8 instead of 0xb.
This is a complete listing that exhibits the problem:
--------------------------------------- cut here -------------------------- #include <stdio.h>
void f(long unsigned *x1) { int stack_ctl; unsigned long long ctl_bitvec;
stack_ctl = *x1;
ctl_bitvec = 0;
switch(stack_ctl) {
case 8:
ctl_bitvec |= 1;
ctl_bitvec |= 2;
break;
case 12:
ctl_bitvec |= 1;
ctl_bitvec |= 2;
ctl_bitvec |= 0x10;
break;
case 15:
ctl_bitvec |= 2;
ctl_bitvec |= 0x10;
break;
case 16:
ctl_bitvec |= 1;
ctl_bitvec |= 0x20;
ctl_bitvec |= 8;
break;
case 20:
ctl_bitvec |= 1;
ctl_bitvec |= 8;
break;
case 21:
ctl_bitvec |= 1;
ctl_bitvec |= 2;
ctl_bitvec |= 8;
break;
case 22:
ctl_bitvec |= 8;
break;
case 30:
ctl_bitvec |= 0x40;
break;
default:
break;}
printf("%x\n", ctl_bitvec);
(*x1) |= ((ctl_bitvec & 7) << 0);}
main() { long unsigned i = 21; f(&i); }
--------------------------------------- cut here --------------------------
This is the a sample compile and run:
% make && make run /usr/intel/pkgs/gcc/3.4/bin/g++ -O2 -march=pentium3 test.c -o test_o2 /usr/intel/pkgs/gcc/3.4/bin/g++ -O -march=pentium3 test.c -o test_o ./test_o2 8 ./test_o b
% /usr/intel/pkgs/gcc/3.4/bin/g++ -v Reading specs from /a/nfs/iil/itools/i386_linux24/pkgs/gcc/3.4/bin/../lib/gcc/i686-pc-linux- gnu/3.4.0/specs Configured with: ../gcc-3.4.0/configure --prefix=/usr/intel/pkgs/gcc/3.4 --with- gnu-as --with-as=/usr/intel/pkgs/gcc/3.4/bin/gas --with-gnu-ld --with- ld=/usr/intel/pkgs/gcc/3.4/bin/gld --enable-shared Thread model: posix gcc version 3.4.0
% /usr/intel/pkgs/gcc/3.4/bin/g++ -v -save-temps -O2 -march=pentium3 test.c -o test_o2 Reading specs from /a/nfs/iil/itools/i386_linux24/pkgs/gcc/3.4/bin/../lib/gcc/i686-pc-linux- gnu/3.4.0/specs Configured with: ../gcc-3.4.0/configure --prefix=/usr/intel/pkgs/gcc/3.4 --with- gnu-as --with-as=/usr/intel/pkgs/gcc/3.4/bin/gas --with-gnu-ld --with- ld=/usr/intel/pkgs/gcc/3.4/bin/gld --enable-shared Thread model: posix gcc version 3.4.0 /a/nfs/iil/itools/i386_linux24/pkgs/gcc/3.4/bin/../libexec/gcc/i686-pc-linux- gnu/3.4.0/cc1plus -E -quiet -v - iprefix /a/nfs/iil/itools/i386_linux24/pkgs/gcc/3.4/bin/../lib/gcc/i686-pc- linux-gnu/3.4.0/ -D_GNU_SOURCE test.c -march=pentium3 -O2 -o test.ii ignoring nonexistent directory "/a/nfs/iil/itools/i386_linux24/pkgs/gcc/3.4/bin/../lib/gcc/i686-pc- linux-gnu/3.4.0/../../../../i686-pc-linux-gnu/include" ignoring duplicate directory "/usr/intel/pkgs/gcc/3.4/lib/gcc/i686-pc-linux- gnu/3.4.0/../../../../include/c++/3.4.0" ignoring duplicate directory "/usr/intel/pkgs/gcc/3.4/lib/gcc/i686-pc-linux- gnu/3.4.0/../../../../include/c++/3.4.0/i686-pc-linux-gnu" ignoring duplicate directory "/usr/intel/pkgs/gcc/3.4/lib/gcc/i686-pc-linux- gnu/3.4.0/../../../../include/c++/3.4.0/backward" ignoring duplicate directory "/usr/intel/pkgs/gcc/3.4/lib/gcc/i686-pc-linux- gnu/3.4.0/include" ignoring nonexistent directory "/usr/intel/pkgs/gcc/3.4/lib/gcc/i686-pc-linux- gnu/3.4.0/../../../../i686-pc-linux-gnu/include" #include "..." search starts here: #include <...> search starts here: /a/nfs/iil/itools/i386_linux24/pkgs/gcc/3.4/bin/../lib/gcc/i686-pc-linux- gnu/3.4.0/../../../../include/c++/3.4.0 /a/nfs/iil/itools/i386_linux24/pkgs/gcc/3.4/bin/../lib/gcc/i686-pc-linux- gnu/3.4.0/../../../../include/c++/3.4.0/i686-pc-linux-gnu /a/nfs/iil/itools/i386_linux24/pkgs/gcc/3.4/bin/../lib/gcc/i686-pc-linux- gnu/3.4.0/../../../../include/c++/3.4.0/backward /a/nfs/iil/itools/i386_linux24/pkgs/gcc/3.4/bin/../lib/gcc/i686-pc-linux- gnu/3.4.0/include /usr/local/include /usr/intel/pkgs/gcc/3.4/include /usr/include End of search list. /a/nfs/iil/itools/i386_linux24/pkgs/gcc/3.4/bin/../libexec/gcc/i686-pc-linux- gnu/3.4.0/cc1plus -fpreprocessed test.ii -quiet -dumpbase test.c - march=pentium3 -auxbase test -O2 -version -o test.s GNU C++ version 3.4.0 (i686-pc-linux-gnu) compiled by GNU C version 3.4.0. GGC heuristics: --param ggc-min-expand=98 --param ggc-min-heapsize=128512 /usr/intel/pkgs/gcc/3.4/bin/gas -V -Qy -o test.o test.s GNU assembler version 2.14 (i686-pc-linux-gnu) using BFD version 2.14 20030612 /a/nfs/iil/itools/i386_linux24/pkgs/gcc/3.4/bin/../libexec/gcc/i686-pc-linux- gnu/3.4.0/collect2 -rpath=/usr/intel/pkgs/gcc/3.4/lib --eh-frame-hdr -m elf_i386 -dynamic-linker /lib/ld-linux.so.2 -o test_o2 /usr/lib/crt1.o /usr/lib/crti.o /a/nfs/iil/itools/i386_linux24/pkgs/gcc/ 3.4/bin/../lib/gcc/i686-pc-linux-gnu/3.4.0/crtbegin.o - L/a/nfs/iil/itools/i386_linux24/pkgs/gcc/3.4/bin/../lib/gcc/i686-pc-linux- gnu/3.4.0 -L/a/nfs/iil/itools/i386_linux24/pkgs/gcc/3.4/bin/../lib/gcc - L/usr/intel/pkgs/gcc/3.4/lib/gcc/i686-pc-linux-gnu/3.4.0 - L/a/nfs/iil/itools/i386_linux24/pkgs/gcc/3.4/bin/../lib/gcc/i686-pc-linux- gnu/3.4.0/../../../../i686-pc-linux-gnu/lib - L/usr/intel/pkgs/gcc/3.4/lib/gcc/i686-pc-linux-gnu/3.4.0/../../../../i686-pc- linux-gnu/lib -L/a/nfs/iil/itools/i386_linux24/pkgs/gcc/3.4/bin/../lib/gcc/i686- pc-linux-gnu/3.4.0/../../.. -L/usr/intel/pkgs/gcc/3.4/lib/gcc/i686-pc-linux- gnu/3.4.0/../../.. test.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s - lgcc /a/nfs/iil/itools/i386_linux24/pkgs/gcc/3.4/bin/../lib/gcc/i686-pc-linux- gnu/3.4.0/crtend.o /usr/lib/crtn.o
Comment 1 Andreas Schwab 2004-09-21 08:53:46 UTC
Note that the correct printf format for long long is "%llx", not "%x".
Comment 2 Avner Lottem 2004-09-21 08:56:13 UTC
Oooops, right. Thanks. But the bug still holds, even with %llx.
Comment 3 Avner Lottem 2004-09-21 12:22:46 UTC
The test case was further minimized to the following:
------------------------ cut here ------------------------ #include <stdio.h>
int f(long unsigned x1) { unsigned long long ctl_bitvec = 0;
switch(x1) {
case 21:
ctl_bitvec |= 1;
ctl_bitvec |= 2;
ctl_bitvec |= 8;
break;
default:
break;
}
printf("%llx\n", ctl_bitvec);
return ctl_bitvec;}
main() { f(21); } ------------------------ cut here ------------------------
And running: % make && make run /usr/intel/pkgs/gcc/3.4/bin/g++ -O2 test.c -o test_o2 /usr/intel/pkgs/gcc/3.4/bin/g++ -O test.c -o test_o ./test_o2 8 ./test_o b
It does not fail with gcc 3.3.2. unfortunately, I was not able to test with versions later than 3.4.
Comment 4 Drea Pinski 2004-09-21 13:03:41 UTC
Confirmed with the last example in 3.4.0.
Comment 8 Drea Pinski 2004-10-30 18:12:08 UTC
Fixed.
Comment 9 Drea Pinski 2004-10-30 23:06:26 UTC
*** Bug 18084 has been marked as a duplicate of this bug. ***