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.