http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55939
--- Comment #12 from Jeffrey A. Law <law at redhat dot com> 2013-01-29 17:37:12 UTC --- On 01/29/2013 10:26 AM, aldyh at gcc dot gnu.org wrote: > > http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55939 > > --- Comment #11 from Aldy Hernandez <aldyh at gcc dot gnu.org> 2013-01-29 > 17:26:46 UTC --- > In adding debugging printfs throughout a locally reduced testcase, I ran into > something peculiar, that may or may not be related to this PR. Perhaps some > floating point savvy person comment? > > double d, d2; > ... > if (d != d2) { > dumpd(d,d2); > return -1; > } > > By this point, "d" and "d2" are in fp2/fp3, and we compare them in > extended-precision real mode (fcmp.x) below: At this point alarm bells are already ringing... When I see EQ/NE comparisons of floating points, there's a good bet something is wrong. > > (gdb) si > 0x80000670 154 if (d != d2) > 1: x/i $pc > => 0x80000670 <check_random+260>: fcmpx %fp3,%fp2 > (gdb) info reg fp2 > fp2 9.5869038983080764131982923476680188e-94 (raw > 0x3ec90000fff801fffff84000) > (gdb) info reg fp3 > fp3 9.5869038983080764090401284414100591e-94 (raw > 0x3ec90000fff801fffff83ff8) > > Notice above that the registers are slightly different, so d != d2. Right. > > (gdb) si > 0x80000674 154 if (d != d2) > 1: x/i $pc > => 0x80000674 <check_random+264>: fbne 0x80000692 <check_random+294> > (gdb) > 156 dumpd(d,d2); > 1: x/i $pc > => 0x80000692 <check_random+294>: fmoved %fp2,%sp@- > (gdb) si > 0x80000696 156 dumpd(d,d2); > 1: x/i $pc > => 0x80000696 <check_random+298>: fmoved %fp3,%sp@- > (gdb) > 0x8000069a 156 dumpd(d,d2); > 1: x/i $pc > => 0x8000069a <check_random+302>: jsr 0x80000508 <dumpd> > > Notice we pass fp2/fp3 in the stack as arguments to dumpd(). Interestingly, > we > move them with fmove.d which is double-precision (instead of the compare we > did > prior in .x mode). > > With dumpd() implemented as below, "a" will be the same as "b", since we > chopped off some bits with the fmove.d explained above. Right. This is very similar to the problems with the 80bit FP precision on i387. The in-register format is 80 bits, but in memory the values are just 64 bits. So a value can change simply by storing it into memory and reading it back out. This causes all kinds of subtle problems -- think reload. A programmer can't predict what the allocator is going to do, so a small change in the source might lead to changes in register allocation and a value which previously lived in a register might now be on the stack and reloaded. And if the code is not tolerant of those extra bits appearing/disappearing causes problems. A great example was Dreamworks where this extra precision suddenly appearing/disappearing was causing a single pixel to unexpectedly change color in one of their frame renders. > Is this one of those FP quirks, and I'm horrendously misguided? Yup, this is definitely one of those FP quirks. It might be helpful to see the entire function. Jeff