rs6000 LDBL_MAX converts to infinity

Geoff Keating geoffk@desire.geoffk.org
Thu Mar 4 08:46:00 GMT 2004


> X-Original-To: geoffk@foam.wonderslug.com
> Date: Thu, 4 Mar 2004 18:38:31 +1030
> From: Alan Modra <amodra@bigpond.net.au>
> Mail-Followup-To: Geoff Keating <geoffk@desire.geoffk.org>,
> 	gcc-patches@gcc.gnu.org
> Content-Disposition: inline
> X-OriginalArrivalTime: 04 Mar 2004 08:08:40.0828 (UTC) FILETIME=[E78B8BC0:01C401BF]
> 
> On Thu, Mar 04, 2004 at 05:57:33PM +1030, Alan Modra wrote:
> > You mean c-cppbuiltins.c:builtin_define_float_constants, presumably,
> > possibly with some supporting changes to struct real_format.  Hmm, I
> > could detect ibm (and mips) format long doubles by looking at fmt->p
> > and fmt->pnan.  IBM format is the only one where they differ, and
> > fmt->pnan conveniently specifies the bit we need to zero.  Is that
> > too hacky?
> > 
> > > The second part looks right to me but should really leave a comment in
> > > the code saying why the value is already rounded.
> 
> 	* real.c (encode_ibm_extended): Don't bother rounding low double.
> 	* c-cppbuiltin.c (builtin_define_float_constants): Tweak MAX
> 	when fmt->pnan < fmt->p.

The fundamental problem is that real.c's model of the structure of a
real just isn't right for this particular 'long double'.  There are
lots of other problems where GCC believes that the type behaves one
way and it really behaves some other way.  For instance, the type has
a minimum of 107 bits of precision, not 106, because the sign bit of
the low double gives you an extra bit.

I guess the patch is OK for now.

> 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	4 Mar 2004 07:49:23 -0000
> @@ -3248,7 +3248,9 @@ encode_ibm_extended (const struct real_f
>    if (u.class == rvc_normal)
>      {
>        do_add (&v, &normr, &u, 1);
> -      round_for_format (base_fmt, &v);
> +      /* The low double won't need rounding, since we round to a 106 bit
> +	 mantissa before calling this function, and we've just
> +	 subtracted off the top 53 bits.  */
>        encode_ieee_double (base_fmt, &buf[2], &v);
>      }
>    else
> Index: gcc/c-cppbuiltin.c
> ===================================================================
> RCS file: /cvs/gcc/gcc/gcc/c-cppbuiltin.c,v
> retrieving revision 1.17
> diff -u -p -r1.17 c-cppbuiltin.c
> --- gcc/c-cppbuiltin.c	21 Jan 2004 20:39:51 -0000	1.17
> +++ gcc/c-cppbuiltin.c	4 Mar 2004 07:49:23 -0000
> @@ -193,6 +193,16 @@ builtin_define_float_constants (const ch
>      if (i < n)
>        *p++ = "08ce"[n - i];
>      sprintf (p, "p%d", fmt->emax * fmt->log2_b);
> +    if (fmt->pnan < fmt->p)
> +      {
> +	/* This is an IBM extended double format made up of two IEEE
> +	   doubles.  The value of the long double is the sum of the
> +	   values of the two parts.  The most significant part is
> +	   required to be the value of the long double rounded to the
> +	   nearest double.  Rounding means we need a slightly smaller
> +	   value for LDBL_MAX.  */
> +	buf[4 + fmt->pnan / 4] = "7bde"[fmt->pnan % 4];
> +      }
>    }
>    sprintf (name, "__%s_MAX__", name_prefix);
>    builtin_define_with_hex_fp_value (name, type, decimal_dig, buf, fp_suffix);
> 
> -- 
> Alan Modra
> IBM OzLabs - Linux Technology Centre
> 


-- 
- Geoffrey Keating <geoffk@geoffk.org>



More information about the Gcc-patches mailing list