This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
rs6000 LDBL_MAX converts to infinity
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Geoff Keating <geoffk at geoffk dot org>, aoliva at redhat dot com,rsandifo at redhat dot com
- Date: Wed, 3 Mar 2004 11:40:41 +1030
- Subject: rs6000 LDBL_MAX converts to infinity
This patch corrects a problem with -mlong-double-128 on powerpc*-linux,
where converting numbers some delta larger than DBL_MAX but smaller
than LDBL_MAX results in infinity.
http://gcc.gnu.org/ml/gcc-patches/2004-02/msg00073.html touched this
area, with Richard noting
> While there, I noticed that the code didn't deal correctly with normal
> values of the form 0x1.FFFFFFFFFFFFFx....P1023, where the high bit of "x"
> is set. The high part double will round to infinity, and so the extended
> precision number will also be infinite. However, at the moment, the low
> part of this number will have a nonzero (negative) lowpart.
LDBL_MAX is a number of the above form, in fact x.... is a bunch of
F's. It's obvious that gcc's own value for LDBL_MAX ought to convert to
a finite number! So either LDBL_MAX needs adjusting or
encode_ibm_extended needs to convert these numbers to finite values.
I think the latter is the correct course.
* real.c (encode_ibm_extended): Handle LDBL_MAX and other large
numbers. Don't round before converting low double.
While looking at this code, I noticed that the value is rounded to
double after the high double has been subtracted. I think this is
unnecessary since real_to_target_fmt rounds before calling the
encode function. No other encode_* function does this rounding.
Digging through the history, I see that Alexandre Oliva added the
round_for_format call in version 1.109,
http://gcc.gnu.org/ml/gcc-patches/2003-01/msg02039.html
I couldn't see any explanation in the thread on the mailing list.
Bootstrap and regression test powerpc64-linux in progress. A better
test would be on some mips target with 128-bit long doubles enabled,
since powerpc64-linux doesn't yet have 128-bit long double in glibc.
Would one of the mips crowd please run a bootstrap with this patch?
Assuming testing shows no regressions, OK mainline and 3.4?
Index: gcc/real.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/real.c,v
retrieving revision 1.138
diff -u -p -r1.138 real.c
--- gcc/real.c 10 Feb 2004 23:05:58 -0000 1.138
+++ gcc/real.c 3 Mar 2004 00:13:35 -0000
@@ -3245,10 +3245,16 @@ encode_ibm_extended (const struct real_f
round_for_format (base_fmt, &u);
encode_ieee_double (base_fmt, &buf[0], &u);
- if (u.class == rvc_normal)
+ if (normr.class == rvc_normal)
{
+ if (u.class == rvc_inf)
+ {
+ /* Rounding caused an overflow. Convert without rounding so
+ we can handle LDBL_MAX. */
+ encode_ieee_double (base_fmt, &buf[0], &normr);
+ decode_ieee_double (base_fmt, &u, &buf[0]);
+ }
do_add (&v, &normr, &u, 1);
- round_for_format (base_fmt, &v);
encode_ieee_double (base_fmt, &buf[2], &v);
}
else
--
Alan Modra
IBM OzLabs - Linux Technology Centre