tests/mpq/t-get_d.c failure on m68k-linux
Aldy Hernandez
aldyh at redhat.com
Mon Feb 18 20:52:29 CET 2013
On 02/18/13 01:36, Niels Möller wrote:
> Aldy Hernandez <aldyh at redhat.com> writes:
>
>> [Disclaimer: I am not a 68k guru. Well, for that matter neither am I
>> an FP guru...:)].
>
> Neither am I...
>
>> This means that EQ/NE comparisons with FP values on 68k are extremely
>> problematic because the programmer has no way of knowing if the values
>> are in memory or in the FP registers. For example, the compiler may
>> have spilled an FPR to memory and read it back, thus losing some
>> precision, causing the equality to fail.
>>
>> I suggest running the testcase (and possibly all of GMP) with
>> -ffloat-store on m68k.
>
> I think I've seen other code which declares certain double variables as
> volatile, to force the compiler to store them in memory. Maybe that
> would be a more local and portable workaround?
Ugh, I seem to have responded just to you.
But yes, if you were really careful, you could probably use volatiles to
force the value into memory, thus chopping off the excess precision.
For the test in question, my_ldexp() could use the following change:
[guest at aranym2 gcc]$ diff -u a.c b.c
--- a.c 2013-02-18 20:37:23.000000000 +0100
+++ b.c 2013-02-18 20:36:42.000000000 +0100
@@ -404,7 +404,11 @@
e += 1;
}
} else
- return d;
+ {
+ volatile double force_round = d;
+ return force_round;
+
+ }
}
}
The problematic code in the test was:
d = my_ldexp (d, (int) (rp[LIMBS_PER_DOUBLE] % 1000) - 500);
__gmpq_set_d (q, d);
nd = __gmpz_get_d ((&((q)->_mp_num)));
dd = __gmpz_get_d ((&((q)->_mp_den)));
d2 = nd / dd;
if (d != d2) <-- boo hiss!
return -1;
__gmpz_get_d()* would have correct precision because all the munging is
done with a union (union ieee_double_extract). But my_ldexp() would
have the excess precision of having calculated "d" in the FPRs directly.
With the above patch, my_ldexp() would chop off the excess precision
before returning the value in the FPR.
I would personally prefer -ffloat-store, for a more complete solution,
since a cursory look at GCC source points at it using -ffloat-store to
inhibit all sorts of internal floating point internal temporaries being
passed around in FPRs (not just user defined variables like the above).
But Richard (cc'ed) differs and he's the resident expert, so I'd trust him.
That being said, I'd be careful keeping track of what you need to
declare volatile.
Aldy
More information about the gmp-bugs
mailing list