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]

rs6000 long double canonicalisation


This patch fixes a number of bugs.  For one thing,
execute/conversion.c finally completely passes with this patch; so
does ieee/inf-1.c.

There are two classes of problems fixed:
- There were typos in _xlqadd and _xlqmul
- Various bits of the compiler disagreed on the proper representation
  of a 'long double', which led to equality comparison failures.  I've
  documented what I think it should be, and made the compiler comply.

Bootstrapped & tested on powerpc-darwin, plus -mlong-double-128.

-- 
- Geoffrey Keating <geoffk@apple.com>

===File ~/patches/rs6000-longdouble-canon.patch=============
2004-01-09  Geoffrey Keating  <geoffk@apple.com>

	* config/rs6000/darwin-ldouble.c: Add big comment explaining
	exactly what is expected as a 'long double'.
	(_xlqadd): When a value to be returned is representable as a
	'double', just return it directly, do not construct it using a union.
	Also, correct final fixup.
	(_xlqmul): Likewise.
	(_xlqdiv): Likewise.
	* real.c (encode_ibm_extended): Make consistent with darwin-ldouble.c.

Index: real.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/real.c,v
retrieving revision 1.133
diff -u -p -c -p -r1.133 real.c
*** real.c	3 Nov 2003 23:27:51 -0000	1.133
--- real.c	10 Jan 2004 05:24:43 -0000
*************** encode_ibm_extended (const struct real_f
*** 3235,3287 ****
  
    base_fmt = fmt->qnan_msb_set ? &ieee_double_format : &mips_double_format;
  
!   switch (r->class)
!     {
!     case rvc_zero:
!       /* Both doubles have sign bit set.  */
!       buf[0] = FLOAT_WORDS_BIG_ENDIAN ? r->sign << 31 : 0;
!       buf[1] = FLOAT_WORDS_BIG_ENDIAN ? 0 : r->sign << 31;
!       buf[2] = buf[0];
!       buf[3] = buf[1];
!       break;
! 
!     case rvc_inf:
!     case rvc_nan:
!       /* Both doubles set to Inf / NaN.  */
!       encode_ieee_double (base_fmt, &buf[0], r);
!       buf[2] = buf[0];
!       buf[3] = buf[1];
!       return;
! 
!     case rvc_normal:
!       /* u = IEEE double precision portion of significand.  */
!       u = *r;
!       clear_significand_below (&u, SIGNIFICAND_BITS - 53);
! 
!       normalize (&u);
!       /* If the upper double is zero, we have a denormal double, so
! 	 move it to the first double and leave the second as zero.  */
!       if (u.class == rvc_zero)
! 	{
! 	  v = u;
! 	  u = *r;
! 	  normalize (&u);
! 	}
!       else
! 	{
! 	  /* v = remainder containing additional 53 bits of significand.  */
! 	  do_add (&v, r, &u, 1);
! 	  round_for_format (base_fmt, &v);
! 	}
  
!       round_for_format (base_fmt, &u);
! 
!       encode_ieee_double (base_fmt, &buf[0], &u);
        encode_ieee_double (base_fmt, &buf[2], &v);
!       break;
! 
!     default:
!       abort ();
      }
  }
  
--- 3235,3257 ----
  
    base_fmt = fmt->qnan_msb_set ? &ieee_double_format : &mips_double_format;
  
!   /* u = IEEE double precision portion of significand.  */
!   u = *r;
!   round_for_format (base_fmt, &u);
!   encode_ieee_double (base_fmt, &buf[0], &u);
  
!   if (r->class == rvc_normal)
!     {
!       do_add (&v, r, &u, 1);
!       round_for_format (base_fmt, &v);
        encode_ieee_double (base_fmt, &buf[2], &v);
!     }
!   else
!     {
!       /* Inf, NaN, 0 are all representable as doubles, so the
! 	 least-significant part can be 0.0.  */
!       buf[2] = 0;
!       buf[3] = 0;
      }
  }
  
Index: config/rs6000/darwin-ldouble.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/darwin-ldouble.c,v
retrieving revision 1.1
diff -u -p -c -p -r1.1 darwin-ldouble.c
*** config/rs6000/darwin-ldouble.c	6 Jan 2004 23:49:39 -0000	1.1
--- config/rs6000/darwin-ldouble.c	10 Jan 2004 05:24:43 -0000
*************** Software Foundation, 59 Temple Place - S
*** 37,42 ****
--- 37,53 ----
     Floating-Point Computations", by Seppo Linnainmaa, ACM TOMS vol 7
     no 3, September 1961, pages 272-283.  */
  
+ /* 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.  No other requirements are made; so, for example, 1.0 may be
+    represented as (1.0, +0.0) or (1.0, -0.0), and the low part of a
+    NaN is don't-care.
+ 
+    This code currently assumes big-endian.  */
+ 
  #define fabs(x) __builtin_fabs(x)
  
  #define unlikely(x) __builtin_expect ((x), 0)
*************** _xlqadd (double a, double b, double c, d
*** 68,78 ****
    FPR_zero = 0.0;
    FPR_PosInf = FPKINF;
  
!   if (unlikely (a != a) || unlikely (c != c)) {
!     z.dval[0] = a + c;		/* NaN result.	*/
!     z.dval[1] = a + c;		/* NaN result.	*/
!     return z.ldval;
!   }
  
    /* Ordered operands are arranged in order of their magnitudes.  */
  
--- 79,86 ----
    FPR_zero = 0.0;
    FPR_PosInf = FPKINF;
  
!   if (unlikely (a != a) || unlikely (c != c)) 
!     return a + c;  /* NaN result.  */
  
    /* Ordered operands are arranged in order of their magnitudes.  */
  
*************** _xlqadd (double a, double b, double c, d
*** 110,127 ****
    t = (tau + b) + a;	     /* Sum values in ascending magnitude order.  */
  
    /* Infinite or zero result.  */
!   if (unlikely (fabs (t) == FPR_PosInf) || unlikely (t == FPR_zero))
!     {
!       z.dval[0] = t;
!       z.dval[1] = t >= 0.0 ? (fabs (t) >= 0.0 ? t : 0.0) : -0.0;
!       return z.ldval;
!     }
  
    /* Usual case.  */
    tau = (((a-t) + b) + c) + d;
    u = t + tau;
    z.dval[0] = u;	       /* Final fixup for long double result.  */
!   z.dval[1] = (u - t) + tau;
    return z.ldval;
  }
  
--- 118,131 ----
    t = (tau + b) + a;	     /* Sum values in ascending magnitude order.  */
  
    /* Infinite or zero result.  */
!   if (unlikely (t == FPR_zero) || unlikely (fabs (t) == FPR_PosInf))
!     return t;
  
    /* Usual case.  */
    tau = (((a-t) + b) + c) + d;
    u = t + tau;
    z.dval[0] = u;	       /* Final fixup for long double result.  */
!   z.dval[1] = (t - u) + tau;
    return z.ldval;
  }
  
*************** _xlqmul (double a, double b, double c, d
*** 142,163 ****
  
    t = a * c;			/* Highest order double term.  */
  
!   if (unlikely (t != t) || unlikely (t == FPR_zero)) 
!     {
!       /* NaN or zero result.  */
!       z.dval[0] = t;
!       z.dval[1] = t;
!       return z.ldval;
!     }
  
-   if (unlikely (fabs(t) == FPR_PosInf))
-     {
-       /* Infinite result.  */
-       z.dval[0] = t;
-       z.dval[1] = t >= 0 ? 0.0 : -0.0;
-       return z.ldval;
-     }
-   
    /* Finite nonzero result requires summing of terms of two highest
       orders.	*/
    
--- 146,155 ----
  
    t = a * c;			/* Highest order double term.  */
  
!   if (unlikely (t != t) || unlikely (t == FPR_zero) 
!       || unlikely (fabs (t) == FPR_PosInf))
!     return t;
  
    /* Finite nonzero result requires summing of terms of two highest
       orders.	*/
    
*************** _xlqmul (double a, double b, double c, d
*** 170,176 ****
  
    /* Construct long double result.  */
    z.dval[0] = u;
!   z.dval[1] = (u - t) + tau;
    return z.ldval;
  }
  
--- 162,168 ----
  
    /* Construct long double result.  */
    z.dval[0] = u;
!   z.dval[1] = (t - u) + tau;
    return z.ldval;
  }
  
*************** _xlqdiv (double a, double b, double c, d
*** 185,205 ****
    
    t = a / c;                    /* highest order double term */
    
!   if (unlikely (t != t) || unlikely (t == FPR_zero))
!     {
!       /* NaN or zero result.  */
!       z.dval[0] = t;
!       z.dval[1] = t;
!       return z.ldval;
!     }
! 
!   if (unlikely (fabs (t) == FPR_PosInf))
!     {
!       /* Infinite result.  */
!       z.dval[0] = t;
!       z.dval[1] = t >= 0.0 ? 0.0 : -0.0;
!       return z.ldval;
!     }
  
    /* Finite nonzero result requires corrections to the highest order term.  */
  
--- 177,185 ----
    
    t = a / c;                    /* highest order double term */
    
!   if (unlikely (t != t) || unlikely (t == FPR_zero) 
!       || unlikely (fabs (t) == FPR_PosInf))
!     return t;
  
    /* Finite nonzero result requires corrections to the highest order term.  */
  
============================================================


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