This is the mail archive of the
mailing list for the GCC project.
Re: Powerpc64 long double support
- From: Alan Modra <amodra at bigpond dot net dot au>
- To: Geoff Keating <geoffk at desire dot geoffk dot org>
- Cc: sjmunroe at us dot ibm dot com, gcc-patches at gcc dot gnu dot org, aj at suse dot de,dgm69 at us dot ibm dot com, dje at watson dot ibm dot com, meissner at suse dot de
- Date: Sun, 7 Mar 2004 17:07:08 +1030
- Subject: Re: Powerpc64 long double support
- References: <email@example.com> <20040306105033.GF2715@bubble.modra.org> <200403062313.i26NDipA015313@desire.geoffk.org>
On Sat, Mar 06, 2004 at 03:13:44PM -0800, Geoff Keating wrote:
> > From: Alan Modra <firstname.lastname@example.org>
> > On Fri, Mar 05, 2004 at 06:20:24PM -0600, Steve Munroe wrote:
> > > +/* Powerpc64 uses the AIX long double format.
> > > +
> > > + Each long double is 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, as specified by IEEE. For Inf
> > > + values, the least significant part is required to be one of +0.0 or
> > > + -0.0.
> > Do you know why this is required for Inf? If there is a reason,
> > then the patch I just posted to fix -0.0 is wrong.. (In any case,
> > the patch is incomplete, as rs6000.md extenddftf2 also needs looking
> > at.)
> > Hmm, I can see that if you represent +Inf by (+Inf + -Inf), you're
> > in trouble, because converting to double will result in a Nan.
> > Perhaps there is some sequence of operations that will result in
> > (+Inf + +Inf) being turned into (+Inf + -Inf)?
> If you represent +Inf by (+Inf, +/-Inf), then the code to convert a
> double to a long double becomes significantly more complicated. Right
> now, it's done by just loading +0.0 in the low double.
> You have to use the same value consistently, of course, or when you
> compare two Inf values for == you might get the wrong answer.
OK, I can see that it makes sense to load a zero in extenddftf2, and
like you say, comparisons then explain the need for zero in the low
double of Inf. Specifically, we need -0.0, so that conversion of
(-0.0 + -0.0) to double works using the existing trunctfdf2. Is there a
better trick than the following for extenddftf2's body?
* config/rs6000/rs6000.md (extenddftf2): Use -0.0 in low double.
* real.c (encode_ibm_extended): Use -0.0 in low double of Inf,
NaN, and zero. Update comment.
Patch against hammer branch, so expect a reject if applying mainline..
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 22.214.171.124
diff -u -p -r126.96.36.199 rs6000.md
--- gcc/config/rs6000/rs6000.md 6 Feb 2004 07:17:40 -0000 188.8.131.52
+++ gcc/config/rs6000/rs6000.md 7 Mar 2004 04:13:46 -0000
@@ -8170,7 +8175,11 @@
"(DEFAULT_ABI == ABI_AIX || DEFAULT_ABI == ABI_DARWIN)
&& TARGET_HARD_FLOAT && TARGET_FPRS && TARGET_LONG_DOUBLE_128"
- operands = CONST0_RTX (DFmode);
+ REAL_VALUE_TYPE rv;
+ /* Make a -0.0 */
+ memset (&rv, 0, sizeof (rv));
+ rv.sign = 1;
+ operands = CONST_DOUBLE_FROM_REAL_VALUE (rv, DFmode);
RCS file: /cvs/gcc/gcc/gcc/real.c,v
retrieving revision 184.108.40.206
diff -u -p -r220.127.116.11 real.c
--- gcc/real.c 5 Mar 2004 15:06:08 -0000 18.104.22.168
+++ gcc/real.c 7 Mar 2004 06:26:02 -0000
@@ -3296,10 +3296,9 @@ const struct real_format ieee_extended_i
numbers whose sum is equal to the extended precision value. The number
with greater magnitude is first. This format has the same magnitude
range as an IEEE double precision value, but effectively 106 bits of
- significand precision. Infinity and NaN are represented by their IEEE
- double precision value stored in the first number, the second number is
- ignored. Zeroes, Infinities, and NaNs are set in both doubles
- due to precedent. */
+ significand precision. Zero, Infinity and NaN are represented by their
+ IEEE double precision value stored in the first number, the second
+ number is -0.0. */
static void encode_ibm_extended PARAMS ((const struct real_format *fmt,
long *, const REAL_VALUE_TYPE *));
@@ -3338,9 +3337,21 @@ encode_ibm_extended (fmt, buf, r)
/* Inf, NaN, 0 are all representable as doubles, so the
- least-significant part can be 0.0. */
- buf = 0;
- buf = 0;
+ least-significant part can be zero. We choose -0.0 because
+ conversion of IBM extended precision to double is done by
+ adding the two component doubles. -0.0 is the only value that
+ will result in a long double -0.0 correctly converting to a
+ -0.0 double. */
+ if (FLOAT_WORDS_BIG_ENDIAN)
+ buf = 0x80000000;
+ buf = 0;
+ buf = 0;
+ buf = 0x80000000;
IBM OzLabs - Linux Technology Centre