$ 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

Reply via email to