This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Powerpc64 long double support


On Sat, Mar 06, 2004 at 03:13:44PM -0800, Geoff Keating wrote:
> > From: Alan Modra <amodra@bigpond.net.au>
> > 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..
Index: gcc/config/rs6000/rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.221.4.12
diff -u -p -r1.221.4.12 rs6000.md
--- gcc/config/rs6000/rs6000.md	6 Feb 2004 07:17:40 -0000	1.221.4.12
+++ 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[2] = CONST0_RTX (DFmode);
+  REAL_VALUE_TYPE rv;
+  /* Make a -0.0 */
+  memset (&rv, 0, sizeof (rv));
+  rv.sign = 1;
+  operands[2] = CONST_DOUBLE_FROM_REAL_VALUE (rv, DFmode);
 })
 
 (define_insn_and_split "*extenddftf2_internal"
Index: gcc/real.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/real.c,v
retrieving revision 1.103.2.7
diff -u -p -r1.103.2.7 real.c
--- gcc/real.c	5 Mar 2004 15:06:08 -0000	1.103.2.7
+++ 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)
   else
     {
       /* Inf, NaN, 0 are all representable as doubles, so the
-	 least-significant part can be 0.0.  */
-      buf[2] = 0;
-      buf[3] = 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[2] = 0x80000000;
+	  buf[3] = 0;
+	}
+      else
+	{
+	  buf[2] = 0;
+	  buf[3] = 0x80000000;
+	}
     }
 }
 

-- 
Alan Modra
IBM OzLabs - Linux Technology Centre


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]