This is the mail archive of the gcc-bugs@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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


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:

(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.

(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.

void dumpd(double a, double b)
{
  ...
  if (a == b)
    dump_same();
  ...
  ...
}

dumpd() gets executed as follows:

1: x/i $pc
=> 0x8000050c <dumpd+4>:    fmoved %fp@(8),%fp1
(gdb) 
0x80000512    90    {
1: x/i $pc
=> 0x80000512 <dumpd+10>:    fmoved %fp@(16),%fp0
(gdb) info reg fp1
fp1            9.5869038983080764131982923476680188e-94    (raw
0x3ec90000fff801fffff84000)
(gdb) info reg fp0
fp0            9.5869038983080764131982923476680188e-94    (raw
0x3ec90000fff801fffff84000)

Notice fp0 and fp1 are now the same.

(gdb) 
93      if (a == b)
1: x/i $pc
=> 0x80000528 <dumpd+32>:    fcmpx %fp0,%fp1
(gdb) 
0x8000052c    93      if (a == b)
1: x/i $pc
=> 0x8000052c <dumpd+36>:    fbeq 0x80000538 <dumpd+48>
(gdb) 
110    }
1: x/i $pc
=> 0x80000538 <dumpd+48>:    unlk %fp

etc etc etc.

I'm a bit flaky as to FP standards, but it seems suspect that two values that
are different, suddenly become the same when passed to a function.

Is this one of those FP quirks, and I'm horrendously misguided?


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]