$ cat bittest_64.c extern int puts(const char *s); typedef unsigned long long uint64; typedef unsigned uint32;
#define BITPOS (31) int bittest(uint64 in) { if ( ((uint32)(in >> BITPOS)) & 1 ) { puts("bit is set"); return 1; } return 0; } int main() { return bittest(0x0000100000000000ULL); } $ gcc-4.4 bittest_64.c $ ./bittest_64 $ gcc-4.4 -O2 bittest_64.c $ ./bittest_64 bit is set $ The assembly code generated with -O2 seems to have spurious OR-ing with the high-order word: bittest: pushl %ebp xorl %eax, %eax movl %esp, %ebp subl $24, %esp movl 8(%ebp), %edx andl $-2147483648, %edx orl 12(%ebp), %edx jne .L6 leave ret .p2align 4,,7 .p2align 3 .L6: movl $.LC0, (%esp) call puts movl $1, %eax leave ret - This problem only happens when BITPOS is 31; correct code is generated for other BITPOS values. - I got the same incorrect results from both gcc 4.4.0 and my RHEL5 gcc 4.1.2 20080704 (Red Hat 4.1.2-44). -- Summary: incorrect code generated when testing 31st bit of 64bit integer with optimiaztion on Product: gcc Version: 4.4.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: jisooy at gmail dot com GCC build triplet: i686-pc-linux-gnu GCC host triplet: i686-pc-linux-gnu GCC target triplet: i686-pc-linux-gnu http://gcc.gnu.org/bugzilla/show_bug.cgi?id=40279