Bug 20269 - Optimizer problem with aliasing floating point variable
Summary: Optimizer problem with aliasing floating point variable
Status: RESOLVED DUPLICATE of bug 21920
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 3.4.3
: P2 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2005-03-01 23:50 UTC by Bob van Manen
Modified: 2005-07-23 22:49 UTC (History)
1 user (show)

See Also:
Host: i686-pc-linux-gnu
Target: i686-pc-linux-gnu
Build: i686-pc-linux-gnu
Known to work:
Known to fail:
Last reconfirmed:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Bob van Manen 2005-03-01 23:50:57 UTC
gcc -v output:
Reading specs from /opt/gcc-3.4/lib/gcc/i686-pc-linux-gnu/3.4.3/specs
Configured with: ./configure --prefix=/opt/gcc-3.4 --enable-languages=c,c++
Thread model: posix
gcc version 3.4.3

See following preprocessed output:

extern "C" {
extern void __assert_fail (__const char *__assertion, __const char *__file,
            unsigned int __line, __const char *__function)
throw () __attribute__ ((__noreturn__));
}

static void DoTest()
{
        double doubleOne = 1.0;
        float floatOne = 1.0F;

        unsigned int *intDptr = (unsigned int *) &doubleOne;
        unsigned int *intFptr = (unsigned int *) &floatOne;

        (static_cast<void> (__builtin_expect (!!((intDptr[1] == 0x3ff00000) &&
(intDptr[0] == 0)), 1)? 0 : (__assert_fail ("(intDptr[1] == 0x3ff00000) &&
(intDptr[0] == 0)", "fptest.cpp", 12, __PRETTY_FUNCTION__), 0)));
        (static_cast<void> (__builtin_expect (!!(*intFptr == 0x3f800000), 1) ? 0
: (__assert_fail ("*intFptr == 0x3f800000", "fptest.cpp", 13,
__PRETTY_FUNCTION__), 0)));
}

int main()
{
        DoTest();
}

This compiles fine up to -O1, but with -O2 the test fails. When looking at the
generated assembler it seems to me that the compiler first issues the compare
before putting a value in it. Generated assembler:

gcc -O2 -S -o fptest.S fptest.cpp
main:
.LFB3:
        pushl   %ebp
.LCFI0:
        fld1
        movl    %esp, %ebp
.LCFI1:
        subl    $24, %esp
.LCFI2:
        andl    $-16, %esp
        subl    $16, %esp
        cmpl    $1072693248, -4(%ebp)
        fstpl   -8(%ebp)
        jne     .L4
        movl    -8(%ebp), %eax
        testl   %eax, %eax
        jne     .L4
        leave
        xorl    %eax, %eax
        ret
        .p2align 4,,7
.L4:
        movl    $.LC2, (%esp)
        movl    $_ZZ6DoTestvE19__PRETTY_FUNCTION__, %ecx
        movl    $12, %edx
        movl    %ecx, 12(%esp)
        movl    $.LC1, %eax
        movl    %edx, 8(%esp)
        movl    %eax, 4(%esp)
        call    __assert_fail

Specifying volatile for all the local variables fixes it.
Comment 1 Wolfgang Bangerth 2005-03-02 00:04:39 UTC
You can't access a floating point variable through a pointer to integer. 
Read up on -fstrict-aliasing, or its negative -fno-strict-aliasing. 
 
W. 
Comment 2 Andrew Pinski 2005-03-02 00:21:35 UTC
This is called a violation of aliasing rules by the way.
Comment 3 Bob van Manen 2005-03-02 00:33:18 UTC
I read the documentation on -fstrict-aliasing and it makes sense to me why this
code breaks those rules. I just wonder why the compiler didn't warn about it,
since this seems to be a pretty straight forward case of aliasing happening.

Thanks for responding so quickly.
Comment 4 Giovanni Bajo 2005-03-02 11:36:32 UTC
-Wstrict-aliasing can catch some, but you should not rely on it, because it 
can't possibly catch all of them. You should read and understand how aliasing 
works in ISO C and keep it in mind while writing the code.
Comment 5 Bob van Manen 2005-03-02 18:03:51 UTC
Ok, thank you for your explanation. We have a huge codebase and we just
increased the optimization level from -O to -O2 (together with -march=pentium3),
that's when this came up. Since most of this code has been around for a long
time (and not written by me) there is no way to guarantee that I caught all
these cases. 

So I guess I'll just have to disable the strict aliasing option for now. Thanks
for all your help.

Comment 6 Wolfgang Bangerth 2005-03-02 19:24:59 UTC
The problem with the compiler not warning about these cases is that it is 
perfectly legal to cast a double* to an int* -- the problem is that it is 
not legal to access a double through an int*, but to flag this as a warning 
would mean that the compiler has to keep track of what each pointer points 
to, a task it cannot do in general. We just have to ask our users to write 
decent code... 
 
W. 
Comment 7 Andrew Pinski 2005-06-05 09:08:28 UTC
Reopening to ...
Comment 8 Andrew Pinski 2005-06-05 09:08:46 UTC
Mark as a dup of bug 21920.

*** This bug has been marked as a duplicate of 21920 ***