real.c (real_maxval): New function to return the largest finite value representable...
authorRoger Sayle <roger@eyesopen.com>
Fri, 23 May 2003 03:46:53 +0000 (03:46 +0000)
committerRoger Sayle <sayle@gcc.gnu.org>
Fri, 23 May 2003 03:46:53 +0000 (03:46 +0000)
* 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.

From-SVN: r67112

gcc/ChangeLog
gcc/fold-const.c
gcc/real.c
gcc/real.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/ieee/inf-2.c [new file with mode: 0644]

index 453fea8..fa4639e 100644 (file)
@@ -1,3 +1,11 @@
+2003-05-22  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).
+
 2003-05-22  Mike Stump  <mrs@apple.com>
 
        * config.gcc (*-*-darwin*): Remove use_collect2=no, as it is the
index eb65795..6a4e229 100644 (file)
@@ -4820,15 +4820,23 @@ fold_inf_compare (code, type, arg0, arg1)
      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.  */
-  if (REAL_VALUE_NEGATIVE (TREE_REAL_CST (arg1)))
+  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 (TYPE_MODE (TREE_TYPE (arg0))))
+      if (HONOR_SNANS (mode))
         return NULL_TREE;
       return omit_one_operand (type,
                               convert (type, integer_zero_node),
@@ -4836,7 +4844,7 @@ fold_inf_compare (code, type, arg0, arg1)
 
     case LE_EXPR:
       /* x <= +Inf is always true, if we don't case about NaNs.  */
-      if (! HONOR_NANS (TYPE_MODE (TREE_TYPE (arg0))))
+      if (! HONOR_NANS (mode))
        return omit_one_operand (type,
                                 convert (type, integer_one_node),
                                 arg0);
@@ -4850,10 +4858,28 @@ fold_inf_compare (code, type, arg0, arg1)
        }
       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)  */
+    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;
index 16cd02a..4a4b040 100644 (file)
@@ -2280,6 +2280,33 @@ real_nan (r, str, quiet, mode)
   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 1611392..15a5d93 100644 (file)
@@ -219,6 +219,9 @@ extern void real_inf                PARAMS ((REAL_VALUE_TYPE *));
 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 c3b456e..6774aea 100644 (file)
@@ -1,3 +1,7 @@
+2003-05-22  Roger Sayle  <roger@eyesopen.com>
+
+       * gcc.c-torture/execute/ieee/inf-2.c: New test case.
+
 2003-05-21  Janis Johnson  <janis187@us.ibm.com>
 
        * gcc.dg/compat/scalar-return-1_main.c: New file.
diff --git a/gcc/testsuite/gcc.c-torture/execute/ieee/inf-2.c b/gcc/testsuite/gcc.c-torture/execute/ieee/inf-2.c
new file mode 100644 (file)
index 0000000..40270c0
--- /dev/null
@@ -0,0 +1,79 @@
+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;
+}
+