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

             Bug #: 54550
           Summary: GCC -O3 breaks floating point equality comparison
    Classification: Unclassified
           Product: gcc
           Version: 4.6.3
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
        AssignedTo: unassig...@gcc.gnu.org
        ReportedBy: veio...@gmail.com


32-bit X86 on Linux.

First of all, this is not one of those "bug" reports that states that floating
point is implemented differently on different platforms. This is the same C
source on the same platform.

Secondly, this isn't a blanket statement. It happens in a very specific set of
circumstances. If there's interest from this forum, then I'll try to hack
together a demo. Doing so is nontrivial due to the sensitive (to surrounding
code) nature of the bug, and my inability to upload my entire source.

Here's the bug, from a high level perspective:

1. Fill a list with a bunch of random (but valid) 64-bit double-precision
values. 

2. Sort the list from negative to positive, to another list.

3. For each random value in the first list, scan through the second (sorted)
list to find it, using floating point comparison for equality. This should work
because numbers are bit-for-bit identical to the original list. (Only the order
of the numbers is different between the lists.)

4. If you find any value which is not on the list, print an error.

With -O2, it's fine. With -O3, it prints an error. However, if I use 80-bit
long double precision, it works again with -O3.

I suspect that, at higher optimization levels, GCC is caching doubles in X87
registers. That's great, but somehow equality comparison is getting messed up
under _some_ scenarios. When I print out the values that are "different",
they're identical, down to the bit. Again, no math is done on any of these
values after generating them. It's purely loads and stores.

It's worth noting that, if instead of -O3, I do -O2 and add all the command
line options that -O3 enables beyond -O2 _except_ for -finline_functions, then
it also works fine. I suspect that function inlining, in this case, causes the
above register caching issue to break equality comparison, probably because the
compiler is inlining the search function in step 3.

Maybe there's some subtle spec violation here, i.e. maybe floating point
equality is somehow illegitimate. If it is, sorry for submitting this bug.

Reply via email to