[Bug target/55939] [4.6/4.7/4.8 regression] gcc miscompiles gmp-5.0.5 on m68k-linux

law at redhat dot com gcc-bugzilla@gcc.gnu.org
Tue Jan 29 17:37:00 GMT 2013


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



More information about the Gcc-bugs mailing list