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. ***