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: libgcc2 __fixsfdi


On Tue, Oct 29, 2002 at 05:01:29PM -0800, Geoff Keating wrote:
> Did this get approved?

No.  And to do the job properly I need quite a few more changes.  This
patch makes gcc follow the Java conventions for floating point
conversions.

	* defaults.h (FLOAT_FIX_BOUND_OVERFLOW): Define
	(FLOAT_FIX_NANS_TO_ZERO): Define.
	* fold-const.c (fold_convert): Handle FLOAT_FIX_BOUND_OVERFLOW.
	* simplify-rtx.c (simplify_unary_operation): Likewise.
	* optabs.c (expand_fix): Likewise, also FLOAT_FIX_NANS_TO_ZERO.
	* config/rs6000/rs6000.h (FLOAT_FIX_BOUND_OVERFLOW): Define
	(FLOAT_FIX_NANS_TO_ZERO): Define.
	* libgcc2.c (__fixunstfDI): Reorganize so that NaNs convert to zero.
	(__fixunsxfDI, __fixunsdfDI, __fixunssfDI): Likewise.
	(__fixunsxfSI, __fixunsdfSI, __fixunssfSI): Likewise.
	(__fixtfdi): Handle FLOAT_FIX_BOUND_OVERFLOW.
	(__fixxfdi, __fixdfdi, __fixsfdi): Likewise.

Unfortunately, this tickles a problem which caused me to lose interest.

.../libgcc2.c: In function `__fixdfti':
.../libgcc2.c:1013: internal compiler error: in output_toc, at
 config/rs6000/rs6000.c:11824

I suppose I ought to post a bugreport..

Index: gcc/defaults.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/defaults.h,v
retrieving revision 1.96
diff -c -p -r1.96 defaults.h
*** gcc/defaults.h	22 Sep 2002 14:09:30 -0000	1.96
--- gcc/defaults.h	4 Nov 2002 22:58:46 -0000
*************** You Lose!  You must define PREFERRED_DEB
*** 535,540 ****
--- 535,557 ----
  #define	TARGET_FLOAT_FORMAT	IEEE_FLOAT_FORMAT
  #endif
  
+ /* For floating point to integer conversions, defines the result for
+    conversions of values (including +/-inf) that overflow the
+    destination integer type.  If set, gcc generates extra code to
+    return the max/min value.  The "destination integer type" is
+    considered to be "int" or "unsigned int" for types smaller than an
+    "int".  */
+ #ifndef FLOAT_FIX_BOUND_OVERFLOW
+ #define FLOAT_FIX_BOUND_OVERFLOW 0
+ #endif
+ 
+ /* For floating point to integer conversions, defines the result for
+    conversions of NaNs.  If set, gcc generates extra code to convert
+    NaNs to zero.  */
+ #ifndef FLOAT_FIX_NANS_TO_ZERO
+ #define FLOAT_FIX_NANS_TO_ZERO 0
+ #endif
+ 
  /* Determine the register class for registers suitable to be the base
     address register in a MEM.  Allow the choice to be dependent upon
     the mode of the memory access.  */
Index: gcc/fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.225
diff -c -p -r1.225 fold-const.c
*** gcc/fold-const.c	30 Oct 2002 23:07:47 -0000	1.225
--- gcc/fold-const.c	4 Nov 2002 22:58:51 -0000
*************** fold_convert (t, arg1)
*** 1549,1589 ****
  	}
        else if (TREE_CODE (arg1) == REAL_CST)
  	{
! 	  /* Don't initialize these, use assignments.
  	     Initialized local aggregates don't work on old compilers.  */
  	  REAL_VALUE_TYPE x;
! 	  REAL_VALUE_TYPE l;
! 	  REAL_VALUE_TYPE u;
! 	  tree type1 = TREE_TYPE (arg1);
! 	  int no_upper_bound;
  
  	  x = TREE_REAL_CST (arg1);
- 	  l = real_value_from_int_cst (type1, TYPE_MIN_VALUE (type));
  
- 	  no_upper_bound = (TYPE_MAX_VALUE (type) == NULL);
- 	  if (!no_upper_bound)
- 	    u = real_value_from_int_cst (type1, TYPE_MAX_VALUE (type));
- 
- 	  /* See if X will be in range after truncation towards 0.
- 	     To compensate for truncation, move the bounds away from 0,
- 	     but reject if X exactly equals the adjusted bounds.  */
- 	  REAL_ARITHMETIC (l, MINUS_EXPR, l, dconst1);
- 	  if (!no_upper_bound)
- 	    REAL_ARITHMETIC (u, PLUS_EXPR, u, dconst1);
  	  /* If X is a NaN, use zero instead and show we have an overflow.
  	     Otherwise, range check.  */
  	  if (REAL_VALUE_ISNAN (x))
! 	    overflow = 1, x = dconst0;
! 	  else if (! (REAL_VALUES_LESS (l, x)
! 		      && !no_upper_bound
! 		      && REAL_VALUES_LESS (x, u)))
! 	    overflow = 1;
! 
! 	  {
! 	    HOST_WIDE_INT low, high;
! 	    REAL_VALUE_TO_INT (&low, &high, x);
! 	    t = build_int_2 (low, high);
! 	  }
  	  TREE_TYPE (t) = type;
  	  TREE_OVERFLOW (t)
  	    = TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);
--- 1549,1655 ----
  	}
        else if (TREE_CODE (arg1) == REAL_CST)
  	{
! 	  /* Don't initialize REAL_VALUE_TYPE vars, use assignments.
  	     Initialized local aggregates don't work on old compilers.  */
  	  REAL_VALUE_TYPE x;
! 	  HOST_WIDE_INT low = 0, high = 0;
! 	  int converted = 0;
  
  	  x = TREE_REAL_CST (arg1);
  
  	  /* If X is a NaN, use zero instead and show we have an overflow.
  	     Otherwise, range check.  */
  	  if (REAL_VALUE_ISNAN (x))
! 	    {
! 	      overflow = 1;
! 	      converted = 1;
! 	    }
! 	  else
! 	    {
! 	      REAL_VALUE_TYPE l;
! 	      REAL_VALUE_TYPE u;
! 	      tree type1 = TREE_TYPE (arg1);
! 	      int no_upper_bound, too_small, too_big;
! 
! 	      l = real_value_from_int_cst (type1, TYPE_MIN_VALUE (type));
! 
! 	      no_upper_bound = TYPE_MAX_VALUE (type) == NULL;
! 	      if (!no_upper_bound)
! 		u = real_value_from_int_cst (type1, TYPE_MAX_VALUE (type));
! 
! 	      /* See if X will be in range after truncation towards 0.
! 		 To compensate for truncation, move the bounds away from 0,
! 		 but reject if X exactly equals the adjusted bounds.  */
! 	      REAL_ARITHMETIC (l, MINUS_EXPR, l, dconst1);
! 	      if (!no_upper_bound)
! 		REAL_ARITHMETIC (u, PLUS_EXPR, u, dconst1);
! 
! 	      too_big = 0;
! 	      too_small = !REAL_VALUES_LESS (l, x);
! 	      if (too_small)
! 		overflow = 1;
! 	      else
! 		{
! 		  too_big = !no_upper_bound && !REAL_VALUES_LESS (x, u);
! 		  if (too_big)
! 		    overflow = 1;
! 		}
! 
! 	      if (FLOAT_FIX_BOUND_OVERFLOW)
! 		{
! 		  /* We want to peg overflows to the min/max values in
! 		     the target integer representation, except when
! 		     the target integer is smaller than an int.  In
! 		     that case, we peg to int min/max.  */
! 		  tree bound = type;
! 		  tree utype = integer_types[itk_unsigned_int];
! 		  tree stype = integer_types[itk_int];
! 
! 		  if (TREE_UNSIGNED (type) && !no_upper_bound
! 		      && INT_CST_LT_UNSIGNED (TYPE_MAX_VALUE (type),
! 					      TYPE_MAX_VALUE (utype)))
! 		    bound = utype;
! 
! 		  if (!TREE_UNSIGNED (type)
! 		      && INT_CST_LT (TYPE_MAX_VALUE (type),
! 				     TYPE_MAX_VALUE (stype)))
! 		    bound = stype;
! 
! 		  if (bound != type)
! 		    {
! 		      l = real_value_from_int_cst (type1,
! 						   TYPE_MIN_VALUE (bound));
! 		      u = real_value_from_int_cst (type1,
! 						   TYPE_MAX_VALUE (bound));
! 		      REAL_ARITHMETIC (l, MINUS_EXPR, l, dconst1);
! 		      REAL_ARITHMETIC (u, PLUS_EXPR, u, dconst1);
! 		      too_big = 0;
! 		      too_small = !REAL_VALUES_LESS (l, x);
! 		      if (!too_small)
! 			too_big = !REAL_VALUES_LESS (x, u);
! 		    }
! 
! 		  if (too_small)
! 		    {
! 		      low = TREE_INT_CST_LOW (TYPE_MIN_VALUE (bound));
! 		      high = TREE_INT_CST_HIGH (TYPE_MIN_VALUE (bound));
! 		      converted = 1;
! 		    }
! 		  else if (too_big)
! 		    {
! 		      low = TREE_INT_CST_LOW (TYPE_MAX_VALUE (bound));
! 		      high = TREE_INT_CST_HIGH (TYPE_MAX_VALUE (bound));
! 		      converted = 1;
! 		    }
! 		}
! 	    }
! 
! 	  if (!converted)
! 	    {
! 	      REAL_VALUE_TO_INT (&low, &high, x);
! 	    }
! 
! 	  t = build_int_2 (low, high);
  	  TREE_TYPE (t) = type;
  	  TREE_OVERFLOW (t)
  	    = TREE_OVERFLOW (arg1) | force_fit_type (t, overflow);
Index: gcc/libgcc2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/libgcc2.c,v
retrieving revision 1.153
diff -c -p -r1.153 libgcc2.c
*** gcc/libgcc2.c	23 Oct 2002 10:47:24 -0000	1.153
--- gcc/libgcc2.c	4 Nov 2002 22:58:52 -0000
*************** DWtype
*** 850,886 ****
  __fixunstfDI (TFtype a)
  {
    TFtype b;
!   UDWtype v;
  
!   if (a < 0)
!     return 0;
! 
!   /* Compute high word of result, as a flonum.  */
!   b = (a / HIGH_WORD_COEFF);
!   /* Convert that to fixed (but not to DWtype!),
!      and shift it into the high word.  */
!   v = (UWtype) b;
!   v <<= WORD_SIZE;
!   /* Remove high part from the TFtype, leaving the low part as flonum.  */
!   a -= (TFtype)v;
!   /* Convert that to fixed (but not to DWtype!) and add it in.
!      Sometimes A comes out negative.  This is significant, since
!      A has more bits than a long int does.  */
!   if (a < 0)
!     v -= (UWtype) (- a);
!   else
!     v += (UWtype) a;
    return v;
  }
  #endif
  
  #if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
  DWtype
  __fixtfdi (TFtype a)
  {
!   if (a < 0)
!     return - __fixunstfDI (-a);
!   return __fixunstfDI (a);
  }
  #endif
  
--- 850,901 ----
  __fixunstfDI (TFtype a)
  {
    TFtype b;
!   UDWtype v = 0;
  
!   if (a > 0)
!     {
!       /* Compute high word of result, as a flonum.  */
!       b = (a / HIGH_WORD_COEFF);
!       /* Convert that to fixed (but not to DWtype!),
! 	 and shift it into the high word.  */
!       v = (UWtype) b;
!       v <<= WORD_SIZE;
!       /* Remove high part from the TFtype, leaving the low part as flonum.  */
!       a -= (TFtype) v;
!       /* Convert that to fixed (but not to DWtype!) and add it in.
! 	 Sometimes A comes out negative.  This is significant, since
! 	 A has more bits than a long int does.  */
!       if (a < 0)
! 	v -= (UWtype) (- a);
!       else
! 	v += (UWtype) a;
!     }
    return v;
  }
  #endif
  
  #if defined(L_fixtfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
+ #define DWORD_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
+ #define MAXDWtype ((DWtype) (((UDWtype) 1 << (DWORD_SIZE - 1)) - 1))
+ 
  DWtype
  __fixtfdi (TFtype a)
  {
!   DWtype tmp;
! 
!   if (a >= 0)
!     {
!       tmp = __fixunstfDI (a);
!       if (FLOAT_FIX_BOUND_OVERFLOW && tmp < 0)
! 	tmp = MAXDWtype;
!       return tmp;
!     }
! 
!   tmp = __fixunstfDI (-a);
!   tmp = -tmp;
!   if (FLOAT_FIX_BOUND_OVERFLOW && tmp > 0)
!     tmp = -MAXDWtype - 1;
!   return tmp;
  }
  #endif
  
*************** DWtype
*** 892,928 ****
  __fixunsxfDI (XFtype a)
  {
    XFtype b;
!   UDWtype v;
! 
!   if (a < 0)
!     return 0;
  
!   /* Compute high word of result, as a flonum.  */
!   b = (a / HIGH_WORD_COEFF);
!   /* Convert that to fixed (but not to DWtype!),
!      and shift it into the high word.  */
!   v = (UWtype) b;
!   v <<= WORD_SIZE;
!   /* Remove high part from the XFtype, leaving the low part as flonum.  */
!   a -= (XFtype)v;
!   /* Convert that to fixed (but not to DWtype!) and add it in.
!      Sometimes A comes out negative.  This is significant, since
!      A has more bits than a long int does.  */
!   if (a < 0)
!     v -= (UWtype) (- a);
!   else
!     v += (UWtype) a;
    return v;
  }
  #endif
  
  #if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
  DWtype
  __fixxfdi (XFtype a)
  {
!   if (a < 0)
!     return - __fixunsxfDI (-a);
!   return __fixunsxfDI (a);
  }
  #endif
  
--- 907,958 ----
  __fixunsxfDI (XFtype a)
  {
    XFtype b;
!   UDWtype v = 0;
  
!   if (a > 0)
!     {
!       /* Compute high word of result, as a flonum.  */
!       b = (a / HIGH_WORD_COEFF);
!       /* Convert that to fixed (but not to DWtype!),
! 	 and shift it into the high word.  */
!       v = (UWtype) b;
!       v <<= WORD_SIZE;
!       /* Remove high part from the XFtype, leaving the low part as flonum.  */
!       a -= (XFtype) v;
!       /* Convert that to fixed (but not to DWtype!) and add it in.
! 	 Sometimes A comes out negative.  This is significant, since
! 	 A has more bits than a long int does.  */
!       if (a < 0)
! 	v -= (UWtype) (- a);
!       else
! 	v += (UWtype) a;
!     }
    return v;
  }
  #endif
  
  #if defined(L_fixxfdi) && (LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 96)
+ #define DWORD_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
+ #define MAXDWtype ((DWtype) (((UDWtype) 1 << (DWORD_SIZE - 1)) - 1))
+ 
  DWtype
  __fixxfdi (XFtype a)
  {
!   DWtype tmp;
! 
!   if (a >= 0)
!     {
!       tmp = __fixunsxfDI (a);
!       if (FLOAT_FIX_BOUND_OVERFLOW && tmp < 0)
! 	tmp = MAXDWtype;
!       return tmp;
!     }
! 
!   tmp = __fixunsxfDI (-a);
!   tmp = -tmp;
!   if (FLOAT_FIX_BOUND_OVERFLOW && tmp > 0)
!     tmp = -MAXDWtype - 1;
!   return tmp;
  }
  #endif
  
*************** DWtype
*** 934,970 ****
  __fixunsdfDI (DFtype a)
  {
    DFtype b;
!   UDWtype v;
! 
!   if (a < 0)
!     return 0;
  
!   /* Compute high word of result, as a flonum.  */
!   b = (a / HIGH_WORD_COEFF);
!   /* Convert that to fixed (but not to DWtype!),
!      and shift it into the high word.  */
!   v = (UWtype) b;
!   v <<= WORD_SIZE;
!   /* Remove high part from the DFtype, leaving the low part as flonum.  */
!   a -= (DFtype)v;
!   /* Convert that to fixed (but not to DWtype!) and add it in.
!      Sometimes A comes out negative.  This is significant, since
!      A has more bits than a long int does.  */
!   if (a < 0)
!     v -= (UWtype) (- a);
!   else
!     v += (UWtype) a;
    return v;
  }
  #endif
  
  #ifdef L_fixdfdi
  DWtype
  __fixdfdi (DFtype a)
  {
!   if (a < 0)
!     return - __fixunsdfDI (-a);
!   return __fixunsdfDI (a);
  }
  #endif
  
--- 964,1015 ----
  __fixunsdfDI (DFtype a)
  {
    DFtype b;
!   UDWtype v = 0;
  
!   if (a > 0)
!     {
!       /* Compute high word of result, as a flonum.  */
!       b = (a / HIGH_WORD_COEFF);
!       /* Convert that to fixed (but not to DWtype!),
! 	 and shift it into the high word.  */
!       v = (UWtype) b;
!       v <<= WORD_SIZE;
!       /* Remove high part from the DFtype, leaving the low part as flonum.  */
!       a -= (DFtype) v;
!       /* Convert that to fixed (but not to DWtype!) and add it in.
! 	 Sometimes A comes out negative.  This is significant, since
! 	 A has more bits than a long int does.  */
!       if (a < 0)
! 	v -= (UWtype) (- a);
!       else
! 	v += (UWtype) a;
!     }
    return v;
  }
  #endif
  
  #ifdef L_fixdfdi
+ #define DWORD_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
+ #define MAXDWtype ((DWtype) (((UDWtype) 1 << (DWORD_SIZE - 1)) - 1))
+ 
  DWtype
  __fixdfdi (DFtype a)
  {
!   DWtype tmp;
! 
!   if (a >= 0)
!     {
!       tmp = __fixunsdfDI (a);
!       if (FLOAT_FIX_BOUND_OVERFLOW && tmp < 0)
! 	tmp = MAXDWtype;
!       return tmp;
!     }
! 
!   tmp = __fixunsdfDI (-a);
!   tmp = -tmp;
!   if (FLOAT_FIX_BOUND_OVERFLOW && tmp > 0)
!     tmp = -MAXDWtype - 1;
!   return tmp;
  }
  #endif
  
*************** __fixunssfDI (SFtype original_a)
*** 980,1016 ****
       that avoids converting to DFtype, and verify it really works right.  */
    DFtype a = original_a;
    DFtype b;
!   UDWtype v;
! 
!   if (a < 0)
!     return 0;
  
!   /* Compute high word of result, as a flonum.  */
!   b = (a / HIGH_WORD_COEFF);
!   /* Convert that to fixed (but not to DWtype!),
!      and shift it into the high word.  */
!   v = (UWtype) b;
!   v <<= WORD_SIZE;
!   /* Remove high part from the DFtype, leaving the low part as flonum.  */
!   a -= (DFtype) v;
!   /* Convert that to fixed (but not to DWtype!) and add it in.
!      Sometimes A comes out negative.  This is significant, since
!      A has more bits than a long int does.  */
!   if (a < 0)
!     v -= (UWtype) (- a);
!   else
!     v += (UWtype) a;
    return v;
  }
  #endif
  
  #ifdef L_fixsfdi
  DWtype
  __fixsfdi (SFtype a)
  {
!   if (a < 0)
!     return - __fixunssfDI (-a);
!   return __fixunssfDI (a);
  }
  #endif
  
--- 1025,1076 ----
       that avoids converting to DFtype, and verify it really works right.  */
    DFtype a = original_a;
    DFtype b;
!   UDWtype v = 0;
  
!   if (a > 0)
!     {
!       /* Compute high word of result, as a flonum.  */
!       b = (a / HIGH_WORD_COEFF);
!       /* Convert that to fixed (but not to DWtype!),
! 	 and shift it into the high word.  */
!       v = (UWtype) b;
!       v <<= WORD_SIZE;
!       /* Remove high part from the DFtype, leaving the low part as flonum.  */
!       a -= (DFtype) v;
!       /* Convert that to fixed (but not to DWtype!) and add it in.
! 	 Sometimes A comes out negative.  This is significant, since
! 	 A has more bits than a long int does.  */
!       if (a < 0)
! 	v -= (UWtype) (- a);
!       else
! 	v += (UWtype) a;
!     }
    return v;
  }
  #endif
  
  #ifdef L_fixsfdi
+ #define DWORD_SIZE (sizeof (DWtype) * BITS_PER_UNIT)
+ #define MAXDWtype ((DWtype) (((UDWtype) 1 << (DWORD_SIZE - 1)) - 1))
+ 
  DWtype
  __fixsfdi (SFtype a)
  {
!   DWtype tmp;
! 
!   if (a >= 0)
!     {
!       tmp = __fixunssfDI (a);
!       if (FLOAT_FIX_BOUND_OVERFLOW && tmp < 0)
! 	tmp = MAXDWtype;
!       return tmp;
!     }
! 
!   tmp = __fixunssfDI (-a);
!   tmp = -tmp;
!   if (FLOAT_FIX_BOUND_OVERFLOW && tmp > 0)
!     tmp = -MAXDWtype - 1;
!   return tmp;
  }
  #endif
  
*************** __floatdisf (DWtype u)
*** 1133,1141 ****
  UWtype
  __fixunsxfSI (XFtype a)
  {
!   if (a >= - (DFtype) Wtype_MIN)
!     return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
!   return (Wtype) a;
  }
  #endif
  
--- 1193,1208 ----
  UWtype
  __fixunsxfSI (XFtype a)
  {
!   UWtype v = 0;
! 
!   if (!FLOAT_FIX_BOUND_OVERFLOW || a > 0)
!     {
!       if (a >= - (XFtype) Wtype_MIN)
! 	v = (Wtype) (a + Wtype_MIN) - Wtype_MIN;
!       else
! 	v = (Wtype) a;
!     }
!   return v;
  }
  #endif
  
*************** __fixunsxfSI (XFtype a)
*** 1155,1163 ****
  UWtype
  __fixunsdfSI (DFtype a)
  {
!   if (a >= - (DFtype) Wtype_MIN)
!     return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
!   return (Wtype) a;
  }
  #endif
  
--- 1222,1237 ----
  UWtype
  __fixunsdfSI (DFtype a)
  {
!   UWtype v = 0;
! 
!   if (!FLOAT_FIX_BOUND_OVERFLOW || a > 0)
!     {
!       if (a >= - (DFtype) Wtype_MIN)
! 	v = (Wtype) (a + Wtype_MIN) - Wtype_MIN;
!       else
! 	v = (Wtype) a;
!     }
!   return v;
  }
  #endif
  
*************** __fixunsdfSI (DFtype a)
*** 1177,1185 ****
  UWtype
  __fixunssfSI (SFtype a)
  {
!   if (a >= - (SFtype) Wtype_MIN)
!     return (Wtype) (a + Wtype_MIN) - Wtype_MIN;
!   return (Wtype) a;
  }
  #endif
  
--- 1251,1266 ----
  UWtype
  __fixunssfSI (SFtype a)
  {
!   UWtype v = 0;
! 
!   if (!FLOAT_FIX_BOUND_OVERFLOW || a > 0)
!     {
!       if (a >= - (SFtype) Wtype_MIN)
! 	v = (Wtype) (a + Wtype_MIN) - Wtype_MIN;
!       else
! 	v = (Wtype) a;
!     }
!   return v;
  }
  #endif
  
Index: gcc/optabs.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.c,v
retrieving revision 1.150
diff -c -p -r1.150 optabs.c
*** gcc/optabs.c	24 Oct 2002 08:48:27 -0000	1.150
--- gcc/optabs.c	4 Nov 2002 22:59:02 -0000
*************** expand_fix (to, from, unsignedp)
*** 4750,4755 ****
--- 4750,4757 ----
  
  	if (icode != CODE_FOR_nothing)
  	  {
+ 	    rtx lab1 = NULL_RTX;
+ 
  	    to = protect_from_queue (to, 1);
  	    from = protect_from_queue (from, 0);
  
*************** expand_fix (to, from, unsignedp)
*** 4759,4771 ****
  	    if (must_trunc)
  	      from = ftruncify (from);
  
  	    if (imode != GET_MODE (to))
  	      target = gen_reg_rtx (imode);
  
  	    emit_unop_insn (icode, target, from,
  			    doing_unsigned ? UNSIGNED_FIX : FIX);
  	    if (target != to)
! 	      convert_move (to, target, unsignedp);
  	    return;
  	  }
        }
--- 4761,4827 ----
  	    if (must_trunc)
  	      from = ftruncify (from);
  
+ 	    if (FLOAT_FIX_NANS_TO_ZERO)
+ 	      {
+ 		lab1 = gen_label_rtx ();
+ 		emit_move_insn (to, const0_rtx);
+ 		do_pending_stack_adjust ();
+ 		emit_cmp_and_jump_insns (from, from, NE, NULL_RTX,
+ 					 fmode, 0, lab1);
+ 	      }
+ 
  	    if (imode != GET_MODE (to))
  	      target = gen_reg_rtx (imode);
  
  	    emit_unop_insn (icode, target, from,
  			    doing_unsigned ? UNSIGNED_FIX : FIX);
  	    if (target != to)
! 	      {
! 		convert_move (to, target, unsignedp);
! 
! 		if (FLOAT_FIX_BOUND_OVERFLOW)
! 		  {
! 		    rtx wide, lab2;
! 		    HOST_WIDE_INT lim;
! 
! 		    lab2 = gen_label_rtx ();
! 		    wide = gen_reg_rtx (imode);
! 		    convert_move (wide, to, unsignedp);
! 
! 		    if (!FLOAT_FIX_NANS_TO_ZERO)
! 		      do_pending_stack_adjust ();
! 		    emit_cmp_and_jump_insns (target, wide, EQ, NULL_RTX,
! 					     imode, unsignedp, lab2);
! 
! 		    lim = 0;
! 		    if (!unsignedp)
! 		      {
! 			int bitsize = GET_MODE_BITSIZE (GET_MODE (to));
! 			lim = (HOST_WIDE_INT) -1 << (bitsize - 1);
! 		      }
! 
! 		    emit_move_insn (to, GEN_INT (lim));
! 		    emit_cmp_and_jump_insns (target, CONST0_RTX (imode), LT,
! 					     NULL_RTX, imode, 0, lab2);
! 		    emit_move_insn (to, GEN_INT (~lim));
! 		    emit_label (lab2);
! 		  }
! 
! 		if (mov_optab->handlers[(int) GET_MODE (to)].insn_code
! 		    != CODE_FOR_nothing)
! 		  {
! 		    rtx insn, x;
! 
! 		    /* Make a place for a REG_NOTE and add it.  */
! 		    insn = emit_move_insn (to, to);
! 		    x = gen_rtx_fmt_e (unsignedp ? UNSIGNED_FIX : FIX,
! 				       GET_MODE (to), copy_rtx (from));
! 		    set_unique_reg_note (insn, REG_EQUAL, x);
! 		  }
! 	      }
! 
! 	    if (lab1 != NULL_RTX)
! 	      emit_label (lab1);
  	    return;
  	  }
        }
*************** expand_fix (to, from, unsignedp)
*** 4782,4791 ****
    if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
      for (fmode = GET_MODE (from); fmode != VOIDmode;
  	 fmode = GET_MODE_WIDER_MODE (fmode))
!       /* Make sure we won't lose significant bits doing this.  */
!       if (GET_MODE_BITSIZE (fmode) > GET_MODE_BITSIZE (GET_MODE (to))
! 	  && CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0,
! 					    &must_trunc))
  	{
  	  int bitsize;
  	  REAL_VALUE_TYPE offset;
--- 4838,4844 ----
    if (unsignedp && GET_MODE_BITSIZE (GET_MODE (to)) <= HOST_BITS_PER_WIDE_INT)
      for (fmode = GET_MODE (from); fmode != VOIDmode;
  	 fmode = GET_MODE_WIDER_MODE (fmode))
!       if (CODE_FOR_nothing != can_fix_p (GET_MODE (to), fmode, 0, &must_trunc))
  	{
  	  int bitsize;
  	  REAL_VALUE_TYPE offset;
*************** expand_fix (to, from, unsignedp)
*** 4814,4819 ****
--- 4867,4882 ----
  
  	  /* If not, do the signed "fix" and branch around fixup code.  */
  	  expand_fix (to, from, 0);
+ 
+ 	  if (FLOAT_FIX_BOUND_OVERFLOW)
+ 	    {
+ 	      /* Test for underflow.  */
+ 	      emit_cmp_and_jump_insns (from, CONST0_RTX (fmode), GT, NULL_RTX,
+ 				       GET_MODE (from), 0, lab2);
+ 
+ 	      emit_move_insn (to, CONST0_RTX (GET_MODE (to)));
+ 	    }
+ 
  	  emit_jump_insn (gen_jump (lab2));
  	  emit_barrier ();
  
Index: gcc/simplify-rtx.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/simplify-rtx.c,v
retrieving revision 1.126
diff -c -p -r1.126 simplify-rtx.c
*** gcc/simplify-rtx.c	4 Nov 2002 16:57:03 -0000	1.126
--- gcc/simplify-rtx.c	4 Nov 2002 22:59:06 -0000
*************** simplify_unary_operation (code, mode, op
*** 643,654 ****
  	   && width <= HOST_BITS_PER_WIDE_INT && width > 0)
      {
        HOST_WIDE_INT i;
        REAL_VALUE_TYPE d;
        REAL_VALUE_FROM_CONST_DOUBLE (d, trueop);
        switch (code)
  	{
! 	case FIX:		i = REAL_VALUE_FIX (d);		  break;
! 	case UNSIGNED_FIX:	i = REAL_VALUE_UNSIGNED_FIX (d);  break;
  	default:
  	  abort ();
  	}
--- 643,690 ----
  	   && width <= HOST_BITS_PER_WIDE_INT && width > 0)
      {
        HOST_WIDE_INT i;
+       int bitsize;
+       REAL_VALUE_TYPE lim;
        REAL_VALUE_TYPE d;
        REAL_VALUE_FROM_CONST_DOUBLE (d, trueop);
        switch (code)
  	{
! 	case FIX:
! 	  if (FLOAT_FIX_BOUND_OVERFLOW)
! 	    {
! 	      bitsize = GET_MODE_BITSIZE (mode);
! 	      if (bitsize < GET_MODE_BITSIZE (SImode))
! 		bitsize = GET_MODE_BITSIZE (SImode);
! 	      real_ldexp (&lim, &dconstm1, bitsize - 1);
! 
! 	      i = (HOST_WIDE_INT) -1 << (bitsize - 1);
! 	      if (REAL_VALUES_LESS (d, lim))
! 		break;
! 	      i = ~i;
! 	      REAL_VALUE_NEGATE (lim);
! 	      if (!REAL_VALUES_LESS (d, lim))
! 		break;
! 	    }
! 	  i = REAL_VALUE_FIX (d);
! 	  break;
! 
! 	case UNSIGNED_FIX:
! 	  if (FLOAT_FIX_BOUND_OVERFLOW)
! 	    {
! 	      i = 0;
! 	      if (REAL_VALUES_LESS (d, dconst0))
! 		break;
! 	      bitsize = GET_MODE_BITSIZE (mode);
! 	      if (bitsize < GET_MODE_BITSIZE (SImode))
! 		bitsize = GET_MODE_BITSIZE (SImode);
! 	      real_ldexp (&lim, &dconst1, bitsize);
! 	      i = ~i;
! 	      if (!REAL_VALUES_LESS (d, lim))
! 		break;
! 	    }
! 	  i = REAL_VALUE_UNSIGNED_FIX (d);
! 	  break;
! 
  	default:
  	  abort ();
  	}
Index: gcc/config/rs6000/rs6000.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.h,v
retrieving revision 1.234
diff -c -p -r1.234 rs6000.h
*** gcc/config/rs6000/rs6000.h	4 Nov 2002 16:57:09 -0000	1.234
--- gcc/config/rs6000/rs6000.h	4 Nov 2002 22:59:17 -0000
*************** extern int rs6000_default_long_calls;
*** 607,612 ****
--- 607,619 ----
  /* No data type wants to be aligned rounder than this.  */
  #define BIGGEST_ALIGNMENT 128
  
+ /* Ensure conversions of floating point numbers that overflow the target
+    integer type result in the max/min value rather than wrapping.  */
+ #define FLOAT_FIX_BOUND_OVERFLOW 1
+ 
+ /* When converting floating point to integer, convert NaNs to zero.  */
+ #define FLOAT_FIX_NANS_TO_ZERO 1
+ 
  /* A C expression to compute the alignment for a variables in the
     local store.  TYPE is the data type, and ALIGN is the alignment
     that the object would ordinarily have.  */


-- 
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]