[Bug c++/23793] New: Unhealthy optimization. Accessing double with reinterpret_cast.

martsummsw at hotmail dot com gcc-bugzilla@gcc.gnu.org
Fri Sep 9 07:51:00 GMT 2005


This is an error-report. However I will provide some background 
for my little piece of code. (The code itself is very simple)

I will try to post on comp.std.c++ in order to make this a part of C++ 
(maybe c) otherwise I might come back too beck you to implement it just in your
compiler.

There are many reasons. (One and the best is to switch a double based on
intervals) Therefore I would like a VERY FAST FUNCTION to return the sign of a
double (and float and long double) ...

(And compare on a double d<=-0.0 (without branch) wont do the trick. And I can't
blame you because you will have to respect Nan. 

Since c/c++ does not have this fast function (skipping Nan)
(which I hope will come) I have no other no other options that to 
write it myself (and cheat!)

That means that my trick will only work on doubles in IEEE 754 - with a size of 2. 

The sizepart of double (in my case 8 bytes) and int (in my case 4 bytes) could
probably be fixed with the right macros. 

However my code will only work on x86 and other machines accepting the IEEE 754
standard. I think Motorola does not follow this - but nevermind.

The code with the bug is : (Read signbit a push it to be one or zero)
int is_not_positive(double v)
{
  return ((reinterpret_cast<unsigned int*>(&v)[1]) >> 31);
}

This works with option O1 (and below)
but fails with O2 (and above)

The O1 correct (but not fast fast code) looks like this:

    .file    "bug.cpp"
    .text
    .align 2
.globl _Z15is_not_positived
    .type    _Z15is_not_positived, @function
_Z15is_not_positived:
.LFB3:
    pushl    %ebp
.LCFI0:
    movl    %esp, %ebp
.LCFI1:
    subl    $8, %esp
.LCFI2:
    fldl    8(%ebp)
    fstpl    -8(%ebp)
    movl    -4(%ebp), %eax
    shrl    $31, %eax
    movl    %ebp, %esp
    popl    %ebp
    ret
.LFE3:
    .size    _Z15is_not_positived, .-_Z15is_not_positived
    .section    .note.GNU-stack,"",@progbits
    .ident    "GCC: (GNU) 3.3.5-20050130 (Gentoo 3.3.5.20050130-r1,
ssp-3.3.5.20050130-1, pie-8.7.7.1)"

The wrong optimization simply removes:
fldl    8(%ebp)
fstpl    -8(%ebp)
// I guess that it removes the store. 

---------------------------------------
The "wished optimized code" is (notice this is partly manually written so
I might be wrong. I am not an assembler expert)

.LFB4:
    pushl    %ebp
.LCFI0:
    movl    %esp, %ebp
.LCFI1:
    movl    12(%ebp), %eax
    popl    %ebp
    shrl    $31, %eax
    ret
.LFE4:

I am sorry that I have not testet it with a newer version. 
(However I am not to bright and last time I did emerge gcc (with accept newest
version I got problems with compiling my kernel))
I hope the answer is "just upgrade you stupid man..."

Regards 
Thorbjørn Martsum

PS: 
BTW...
I have found a workaround using unsigned long long. 
This works with O3 and has only one extra instruction compared to "my best"

    movl    12(%ebp), %eax
    popl    %ebp

expands to

    movl    12(%ebp), %ecx
    popl    %ebp
    movl    %ecx, %eax

(a missing peephole-pattern (?) ) 
But sill WAY WAY Better than what the MS VS6 gives =)

-- 
           Summary: Unhealthy optimization. Accessing double with
                    reinterpret_cast.
           Product: gcc
           Version: 3.3.5
            Status: UNCONFIRMED
          Severity: normal
          Priority: P2
         Component: c++
        AssignedTo: unassigned at gcc dot gnu dot org
        ReportedBy: martsummsw at hotmail dot com
                CC: gcc-bugs at gcc dot gnu dot org


http://gcc.gnu.org/bugzilla/show_bug.cgi?id=23793



More information about the Gcc-bugs mailing list