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?

Reply via email to