[epic] Re: epic100.c, gcc-2.95.2 compiler bug!

antirez antirez@invece.org
Fri, 7 Sep 2001 16:13:23 +0200


On Fri, Sep 07, 2001 at 04:03:15PM +0200, Ingo Rohloff wrote:
> BEWARE: DON'T USE gcc-2.95.2!
> I compiled the linux-2.4.9 version with gcc-2.95.2.
> And I can _definitely_ confirm that epic100.c triggers a compiler
> bug. (I have the erronous assembler code on my harddisk if anyone is
> interested.)

The following seems a gcc 3.0 bug, not sure it was fixed in gcc 3.01.

See the assembly generated with -O3 for the following code:

--------------------------------------------------------------
inline static long QInt(double inval)
{
        long *l;
        char *c = (char*) &inval;
        inval = 68719476991.99;

        l = (long*) (c+2);
        return *l;
}

int main(void)
{
        printf("%lu\n", QInt(OFFENDING_VALUE));
        return 0;
}
---------------------------------------------------------------

the above function is compiled as:

        .file   "test2.c"
        .section        .rodata
.LC0:
        .string "%lu\n"
        .text
        .align 16
.globl main
        .type   main,@function
main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $48, %esp
*       movl    $16776561, -32(%ebp)
*       movl    -30(%ebp), %eax
*       movl    $1110441984, -28(%ebp)
        pushl   %eax
        pushl   $.LC0
        call    printf
        addl    $16, %esp
        movl    %ebp, %esp
        xorl    %eax, %eax
        popl    %ebp
        ret
.Lfe1:
        .size   main,.Lfe1-main
        .ident  "GCC: (GNU) 3.0"

Note the line I marked with "*".
The double var is 8 byte, it is loaded
moving two 32 bit words in the -32 and -28 offset.
Unfortunatelly with -O3 the "*l" value get
computed between the two 'movl', and not after
the second movl.

This code is really unsane anyway but this seems
a clear gcc 3.0 bug.

I hope that the gcc folks here may report the
problem if not already known.

I didn't tested it but maybe the same problem
exists with other 8 byte types like 'long long'.

regards,
antirez