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]

[PATCH] Avoid FP comparisons against Infinity


This patch implements a suggestion of Richard Henderson's to avoid
FP comparisons against IEEE +Inf and -Inf, instead using DBL_MAX.
http://gcc.gnu.org/ml/gcc-patches/2003-03/msg01735.html

Apparently, comparing against an infinity on both the MIPS and
alpha platforms requires a emulation trap, whilst the equivalent
comparison against the maximum representable finite number, such
as DBL_MAX or FLT_MAX doesn't.  Hence this speeds up MIPS and
alpha and shouldn't adversely affect any other platform.

Could someone double check the real_maxval implementation?  This
appears to work correctly for IEEE representations, and I believe
that its fine for other FP formats, but its always good to have a
second opinion.


The following patch has been tested on i686-pc-linux-gnu with a
complete "make bootstrap", all languages except treelang (including
ada), and regression tested with a top-level "make -k check" with
no new failures.

Ok for mainline?


2003-05-18  Roger Sayle  <roger@eyesopen.com>

	* real.c (real_maxval): New function to return the largest finite
	value representable in a given mode (i.e. FLT_MAX and DBL_MAX).
	* real.h (real_maxval): Prototype here.
	* fold-const.c (fold_inf_compare): Transform comparisons against
	+-Infinity into comparisons against DBL_MAX (or equivalent).

	* gcc.c-torture/execute/ieee/inf-2.c: New test case.


Index: real.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/real.c,v
retrieving revision 1.118
diff -c -3 -p -r1.118 real.c
*** real.c	6 May 2003 03:14:09 -0000	1.118
--- real.c	18 May 2003 01:51:49 -0000
*************** real_nan (r, str, quiet, mode)
*** 2280,2285 ****
--- 2280,2312 ----
    return true;
  }

+ /* Fills R with the largest finite value representable in mode MODE.
+    If SIGN is non-zero, R is set to the most negative finite value.  */
+
+ void
+ real_maxval (r, sign, mode)
+      REAL_VALUE_TYPE *r;
+      int sign;
+      enum machine_mode mode;
+ {
+   const struct real_format *fmt;
+   int np2;
+
+   fmt = real_format_for_mode[mode - QFmode];
+   if (fmt == NULL)
+     abort ();
+
+   r->class = rvc_normal;
+   r->sign = sign;
+   r->signalling = 0;
+   r->canonical = 0;
+   r->exp = fmt->emax * fmt->log2_b;
+
+   np2 = SIGNIFICAND_BITS - fmt->p * fmt->log2_b;
+   memset (r->sig, -1, SIGSZ * sizeof (unsigned long));
+   clear_significand_below (r, np2);
+ }
+
  /* Fills R with 2**N.  */

  void
Index: real.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/real.h,v
retrieving revision 1.65
diff -c -3 -p -r1.65 real.h
*** real.h	6 May 2003 03:14:09 -0000	1.65
--- real.h	18 May 2003 01:51:49 -0000
*************** extern void real_inf		PARAMS ((REAL_VALU
*** 219,224 ****
--- 219,227 ----
  extern bool real_nan		PARAMS ((REAL_VALUE_TYPE *, const char *,
  					 int, enum machine_mode));

+ extern void real_maxval		PARAMS ((REAL_VALUE_TYPE *, int,
+ 					 enum machine_mode));
+
  extern void real_2expN		PARAMS ((REAL_VALUE_TYPE *, int));

  extern unsigned int real_hash	PARAMS ((const REAL_VALUE_TYPE *));
Index: fold-const.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/fold-const.c,v
retrieving revision 1.251
diff -c -3 -p -r1.251 fold-const.c
*** fold-const.c	22 Apr 2003 15:01:16 -0000	1.251
--- fold-const.c	18 May 2003 01:51:59 -0000
*************** fold_inf_compare (code, type, arg0, arg1
*** 4820,4834 ****
       enum tree_code code;
       tree type, arg0, arg1;
  {
    /* For negative infinity swap the sense of the comparison.  */
!   if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1)))
      code = swap_tree_comparison (code);

    switch (code)
      {
      case GT_EXPR:
        /* x > +Inf is always false, if with ignore sNANs.  */
!       if (HONOR_SNANS (TYPE_MODE (TREE_TYPE (arg0))))
          return NULL_TREE;
        return omit_one_operand (type,
  			       convert (type, integer_zero_node),
--- 4820,4842 ----
       enum tree_code code;
       tree type, arg0, arg1;
  {
+   enum machine_mode mode;
+   REAL_VALUE_TYPE max;
+   tree temp;
+   bool neg;
+
+   mode = TYPE_MODE (TREE_TYPE (arg0));
+
    /* For negative infinity swap the sense of the comparison.  */
!   neg = REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1));
!   if (neg)
      code = swap_tree_comparison (code);

    switch (code)
      {
      case GT_EXPR:
        /* x > +Inf is always false, if with ignore sNANs.  */
!       if (HONOR_SNANS (mode))
          return NULL_TREE;
        return omit_one_operand (type,
  			       convert (type, integer_zero_node),
*************** fold_inf_compare (code, type, arg0, arg1
*** 4836,4842 ****

      case LE_EXPR:
        /* x <= +Inf is always true, if we don't case about NaNs.  */
!       if (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
  	return omit_one_operand (type,
  				 convert (type, integer_one_node),
  				 arg0);
--- 4844,4850 ----

      case LE_EXPR:
        /* x <= +Inf is always true, if we don't case about NaNs.  */
!       if (! HONOR_NANS (mode))
  	return omit_one_operand (type,
  				 convert (type, integer_one_node),
  				 arg0);
*************** fold_inf_compare (code, type, arg0, arg1
*** 4850,4859 ****
  	}
        break;

!     case EQ_EXPR:  /* ??? x == +Inf is x > DBL_MAX  */
!     case GE_EXPR:  /* ??? x >= +Inf is x > DBL_MAX  */
!     case LT_EXPR:  /* ??? x < +Inf is x <= DBL_MAX  */
!     case NE_EXPR:  /* ??? x != +Inf is !(x > DBL_MAX)  */

      default:
        break;
--- 4858,4885 ----
  	}
        break;

!     case EQ_EXPR:
!     case GE_EXPR:
!       /* x == +Inf and x >= +Inf are always equal to x > DBL_MAX.  */
!       real_maxval (&max, neg, mode);
!       return fold (build (neg ? LT_EXPR : GT_EXPR, type,
! 			  arg0, build_real (TREE_TYPE (arg0), max)));
!
!     case LT_EXPR:
!       /* x < +Inf is always equal to x <= DBL_MAX.  */
!       real_maxval (&max, neg, mode);
!       return fold (build (neg ? GE_EXPR : LE_EXPR, type,
! 			  arg0, build_real (TREE_TYPE (arg0), max)));
!
!     case NE_EXPR:
!       /* x != +Inf is always equal to !(x > DBL_MAX).  */
!       real_maxval (&max, neg, mode);
!       if (! HONOR_NANS (mode))
! 	return fold (build (neg ? GE_EXPR : LE_EXPR, type,
! 			    arg0, build_real (TREE_TYPE (arg0), max)));
!       temp = fold (build (neg ? LT_EXPR : GT_EXPR, type,
! 			  arg0, build_real (TREE_TYPE (arg0), max)));
!       return fold (build1 (TRUTH_NOT_EXPR, type, temp));

      default:
        break;


extern void abort (void);

void test(double f, double i)
{
  if (f == __builtin_inf())
    abort ();
  if (f == -__builtin_inf())
    abort ();
  if (i == -__builtin_inf())
    abort ();
  if (i != __builtin_inf())
    abort ();

  if (f >= __builtin_inf())
    abort ();
  if (f > __builtin_inf())
    abort ();
  if (i > __builtin_inf())
    abort ();
  if (f <= -__builtin_inf())
    abort ();
  if (f < -__builtin_inf())
    abort ();
}

void testf(float f, float i)
{
  if (f == __builtin_inff())
    abort ();
  if (f == -__builtin_inff())
    abort ();
  if (i == -__builtin_inff())
    abort ();
  if (i != __builtin_inff())
    abort ();

  if (f >= __builtin_inff())
    abort ();
  if (f > __builtin_inff())
    abort ();
  if (i > __builtin_inff())
    abort ();
  if (f <= -__builtin_inff())
    abort ();
  if (f < -__builtin_inff())
    abort ();
}

void testl(long double f, long double i)
{
  if (f == __builtin_infl())
    abort ();
  if (f == -__builtin_infl())
    abort ();
  if (i == -__builtin_infl())
    abort ();
  if (i != __builtin_infl())
    abort ();

  if (f >= __builtin_infl())
    abort ();
  if (f > __builtin_infl())
    abort ();
  if (i > __builtin_infl())
    abort ();
  if (f <= -__builtin_infl())
    abort ();
  if (f < -__builtin_infl())
    abort ();
}

int main()
{
  test (34.0, __builtin_inf());
  testf (34.0f, __builtin_inff());
  testf (34.0l, __builtin_infl());
  return 0;
}


Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


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