OSDN Git Service

* fold-const.c (fold) <UNORDERED_EXPR, ORDERED_EXPR, UNLT_EXPR,
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 19 Jun 2004 00:17:33 +0000 (00:17 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 19 Jun 2004 00:17:33 +0000 (00:17 +0000)
UNLE_EXPR, UNGT_EXPR, UNGE_EXPR, UNEQ_EXPR, LTGT_EXPR>: Add
constant folding for unordered comparison tree nodes.  If both
operands are real constants, call fold_relational_const.  If either
operand is a NaN, evaluate the other for side-effects and return a
constant.  Optimize (double)float1 CMP (double)float2 into the
equivalent float1 CMP float2.
(nondestructive_fold_binary_to_constant) <UNORDERED_EXPR,
ORDERED_EXPR, UNLT_EXPR, UNLE_EXPR, UNGT_EXPR, UNGE_EXPR, UNEQ_EXPR,
LTGT_EXPR>: Call fold_relational_const for constant operands.
(fold_relational_const): Add support for unordered comparison tree
nodes.  Don't constant fold "ordered" floating point comparisons
against NaN if when flag_trapping_math is set.

* gcc.dg/unordered-2.c: New test case.
* gcc.dg/unordered-3.c: New test case.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@83379 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/fold-const.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/unordered-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/unordered-3.c [new file with mode: 0644]

index 069c48e..7694596 100644 (file)
@@ -1,3 +1,19 @@
+2004-06-18  Roger Sayle  <roger@eyesopen.com>
+
+       * fold-const.c (fold) <UNORDERED_EXPR, ORDERED_EXPR, UNLT_EXPR,
+       UNLE_EXPR, UNGT_EXPR, UNGE_EXPR, UNEQ_EXPR, LTGT_EXPR>: Add
+       constant folding for unordered comparison tree nodes.  If both
+       operands are real constants, call fold_relational_const.  If either
+       operand is a NaN, evaluate the other for side-effects and return a
+       constant.  Optimize (double)float1 CMP (double)float2 into the
+       equivalent float1 CMP float2.
+       (nondestructive_fold_binary_to_constant) <UNORDERED_EXPR,
+       ORDERED_EXPR, UNLT_EXPR, UNLE_EXPR, UNGT_EXPR, UNGE_EXPR, UNEQ_EXPR,
+       LTGT_EXPR>: Call fold_relational_const for constant operands.
+       (fold_relational_const): Add support for unordered comparison tree
+       nodes.  Don't constant fold "ordered" floating point comparisons
+       against NaN if when flag_trapping_math is set.
+
 2004-06-19  Jakub Jelinek  <jakub@redhat.com>
 
        * fold-const.c (build_range_check): If !in_p and recursive call
index 00fd134..5266b00 100644 (file)
@@ -8252,6 +8252,59 @@ fold (tree expr)
       t1 = fold_relational_const (code, type, arg0, arg1);
       return (t1 == NULL_TREE ? t : t1);
 
+    case UNORDERED_EXPR:
+    case ORDERED_EXPR:
+    case UNLT_EXPR:
+    case UNLE_EXPR:
+    case UNGT_EXPR:
+    case UNGE_EXPR:
+    case UNEQ_EXPR:
+    case LTGT_EXPR:
+      if (TREE_CODE (arg0) == REAL_CST && TREE_CODE (arg1) == REAL_CST)
+       {
+         t1 = fold_relational_const (code, type, arg0, arg1);
+         if (t1 != NULL_TREE)
+           return t1;
+       }
+
+      /* If the first operand is NaN, the result is constant.  */
+      if (TREE_CODE (arg0) == REAL_CST
+         && REAL_VALUE_ISNAN (TREE_REAL_CST (arg0))
+         && (code != LTGT_EXPR || ! flag_trapping_math))
+       {
+         t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
+              ? integer_zero_node
+              : integer_one_node;
+         return omit_one_operand (type, t1, arg1);
+       }
+
+      /* If the second operand is NaN, the result is constant.  */
+      if (TREE_CODE (arg1) == REAL_CST
+         && REAL_VALUE_ISNAN (TREE_REAL_CST (arg1))
+         && (code != LTGT_EXPR || ! flag_trapping_math))
+       {
+         t1 = (code == ORDERED_EXPR || code == LTGT_EXPR)
+              ? integer_zero_node
+              : integer_one_node;
+         return omit_one_operand (type, t1, arg0);
+       }
+
+      /* Fold (double)float1 CMP (double)float2 into float1 CMP float2.  */
+      {
+       tree targ0 = strip_float_extensions (arg0);
+       tree targ1 = strip_float_extensions (arg1);
+       tree newtype = TREE_TYPE (targ0);
+
+       if (TYPE_PRECISION (TREE_TYPE (targ1)) > TYPE_PRECISION (newtype))
+         newtype = TREE_TYPE (targ1);
+
+       if (TYPE_PRECISION (newtype) < TYPE_PRECISION (TREE_TYPE (arg0)))
+         return fold (build2 (code, type, fold_convert (newtype, targ0),
+                              fold_convert (newtype, targ1)));
+      }
+
+      return t;
+
     case COND_EXPR:
       /* Pedantic ANSI C says that a conditional expression is never an lvalue,
         so all simple results must be passed through pedantic_non_lvalue.  */
@@ -9770,6 +9823,16 @@ nondestructive_fold_binary_to_constant (enum tree_code code, tree type,
       if (tem)
        return tem;
 
+      /* Fall through.  */
+
+    case ORDERED_EXPR:
+    case UNORDERED_EXPR:
+    case UNLT_EXPR:
+    case UNLE_EXPR:
+    case UNGT_EXPR:
+    case UNGE_EXPR:
+    case UNEQ_EXPR:
+    case LTGT_EXPR:
       if (!wins)
        return NULL_TREE;
 
@@ -10075,7 +10138,82 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
   int result, invert;
 
   /* From here on, the only cases we handle are when the result is
-     known to be a constant.
+     known to be a constant.  */
+
+  if (TREE_CODE (op0) == REAL_CST && TREE_CODE (op1) == REAL_CST)
+    {
+      /* Handle the cases where either operand is a NaN.  */
+      if (REAL_VALUE_ISNAN (TREE_REAL_CST (op0))
+          || REAL_VALUE_ISNAN (TREE_REAL_CST (op1)))
+       {
+         switch (code)
+           {
+           case EQ_EXPR:
+           case ORDERED_EXPR:
+             result = 0;
+             break;
+
+           case NE_EXPR:
+           case UNORDERED_EXPR:
+           case UNLT_EXPR:
+           case UNLE_EXPR:
+           case UNGT_EXPR:
+           case UNGE_EXPR:
+           case UNEQ_EXPR:
+              result = 1;
+             break;
+
+           case LT_EXPR:
+           case LE_EXPR:
+           case GT_EXPR:
+           case GE_EXPR:
+           case LTGT_EXPR:
+             if (flag_trapping_math)
+               return NULL_TREE;
+             result = 0;
+             break;
+
+           default:
+             abort ();
+           }
+
+         return constant_boolean_node (result, type);
+       }
+
+      /* From here on we're sure there are no NaNs.  */
+      switch (code)
+       {
+       case ORDERED_EXPR:
+         return constant_boolean_node (true, type);
+
+       case UNORDERED_EXPR:
+         return constant_boolean_node (false, type);
+
+       case UNLT_EXPR:
+         code = LT_EXPR;
+         break;
+       case UNLE_EXPR:
+         code = LE_EXPR;
+         break;
+       case UNGT_EXPR:
+         code = GT_EXPR;
+         break;
+       case UNGE_EXPR:
+         code = GE_EXPR;
+         break;
+       case UNEQ_EXPR:
+         code = EQ_EXPR;
+         break;
+       case LTGT_EXPR:
+         code = NE_EXPR;
+         break;
+
+       default:
+         break;
+       }
+    }
+
+  /* From here on we only handle LT, LE, GT, GE, EQ and NE.
 
      To compute GT, swap the arguments and do LT.
      To compute GE, do LT and invert the result.
@@ -10093,7 +10231,7 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
     }
 
   /* Note that it is safe to invert for real values here because we
-     will check below in the one case that it matters.  */
+     have already handled the one case that it matters.  */
 
   invert = 0;
   if (code == NE_EXPR || code == GE_EXPR)
@@ -10121,18 +10259,7 @@ fold_relational_const (enum tree_code code, tree type, tree op0, tree op1)
   /* Two real constants can be compared explicitly.  */
   else if (TREE_CODE (op0) == REAL_CST && TREE_CODE (op1) == REAL_CST)
     {
-      /* If either operand is a NaN, the result is false with two
-        exceptions: First, an NE_EXPR is true on NaNs, but that case
-        is already handled correctly since we will be inverting the
-        result for NE_EXPR.  Second, if we had inverted a LE_EXPR
-        or a GE_EXPR into a LT_EXPR, we must return true so that it
-        will be inverted into false.  */
-
-      if (REAL_VALUE_ISNAN (TREE_REAL_CST (op0))
-          || REAL_VALUE_ISNAN (TREE_REAL_CST (op1)))
-       result = invert && code == LT_EXPR;
-
-      else if (code == EQ_EXPR)
+      if (code == EQ_EXPR)
        result = REAL_VALUES_EQUAL (TREE_REAL_CST (op0),
                                    TREE_REAL_CST (op1));
       else
index 856b789..362d4f9 100644 (file)
@@ -1,3 +1,8 @@
+2004-06-18  Roger Sayle  <roger@eyesopen.com>
+
+       * gcc.dg/unordered-2.c: New test case.
+       * gcc.dg/unordered-3.c: New test case.
+
 2004-06-19  David Billinghurst (David.Billinghurst@riotinto.com)
 
        PR other/16043
diff --git a/gcc/testsuite/gcc.dg/unordered-2.c b/gcc/testsuite/gcc.dg/unordered-2.c
new file mode 100644 (file)
index 0000000..0696d37
--- /dev/null
@@ -0,0 +1,51 @@
+/* { dg-do link } */
+
+void link_error ();
+
+int main()
+{
+  if (__builtin_isgreater(1.0,2.0) != 0)
+    link_error ();
+  if (__builtin_isgreater(3.0,3.0) != 0)
+    link_error ();
+  if (__builtin_isgreater(5.0,4.0) == 0)
+    link_error ();
+
+  if (__builtin_isgreaterequal(1.0,2.0) != 0)
+    link_error ();
+  if (__builtin_isgreaterequal(3.0,3.0) == 0)
+    link_error ();
+  if (__builtin_isgreaterequal(5.0,4.0) == 0)
+    link_error ();
+
+  if (__builtin_isless(1.0,2.0) == 0)
+    link_error ();
+  if (__builtin_isless(3.0,3.0) != 0)
+    link_error ();
+  if (__builtin_isless(5.0,4.0) != 0)
+    link_error ();
+
+  if (__builtin_islessequal(1.0,2.0) == 0)
+    link_error ();
+  if (__builtin_islessequal(3.0,3.0) == 0)
+    link_error ();
+  if (__builtin_islessequal(5.0,4.0) != 0)
+    link_error ();
+
+  if (__builtin_islessgreater(1.0,2.0) == 0)
+    link_error ();
+  if (__builtin_islessgreater(3.0,3.0) != 0)
+    link_error ();
+  if (__builtin_islessgreater(5.0,4.0) == 0)
+    link_error ();
+
+  if (__builtin_isunordered(1.0,2.0) != 0)
+    link_error ();
+  if (__builtin_isunordered(3.0,3.0) != 0)
+    link_error ();
+  if (__builtin_isunordered(5.0,4.0) != 0)
+    link_error ();
+
+  return 0;
+}
+
diff --git a/gcc/testsuite/gcc.dg/unordered-3.c b/gcc/testsuite/gcc.dg/unordered-3.c
new file mode 100644 (file)
index 0000000..4a11a6d
--- /dev/null
@@ -0,0 +1,79 @@
+/* { dg-do link } */
+
+void link_error ();
+
+void test1()
+{
+  if (__builtin_isgreater(1.0,__builtin_nan("")) != 0)
+    link_error ();
+  if (__builtin_isgreater(__builtin_nan(""),1.0) != 0)
+    link_error ();
+
+  if (__builtin_isgreaterequal(1.0,__builtin_nan("")) != 0)
+    link_error ();
+  if (__builtin_isgreaterequal(__builtin_nan(""),1.0) != 0)
+    link_error ();
+
+  if (__builtin_isless(1.0,__builtin_nan("")) != 0)
+    link_error ();
+  if (__builtin_isless(__builtin_nan(""),1.0) != 0)
+    link_error ();
+
+  if (__builtin_islessequal(1.0,__builtin_nan("")) != 0)
+    link_error ();
+  if (__builtin_islessequal(__builtin_nan(""),1.0) != 0)
+    link_error ();
+
+  if (__builtin_islessgreater(1.0,__builtin_nan("")) != 0)
+    link_error ();
+  if (__builtin_islessgreater(__builtin_nan(""),1.0) != 0)
+    link_error ();
+
+  if (__builtin_isunordered(1.0,__builtin_nan("")) == 0)
+    link_error ();
+  if (__builtin_isunordered(__builtin_nan(""),1.0) == 0)
+    link_error ();
+}
+
+
+void test2(double x)
+{
+  if (__builtin_isgreater(x,__builtin_nan("")) != 0)
+    link_error ();
+  if (__builtin_isgreater(__builtin_nan(""),x) != 0)
+    link_error ();
+
+  if (__builtin_isgreaterequal(x,__builtin_nan("")) != 0)
+    link_error ();
+  if (__builtin_isgreaterequal(__builtin_nan(""),x) != 0)
+    link_error ();
+
+  if (__builtin_isless(x,__builtin_nan("")) != 0)
+    link_error ();
+  if (__builtin_isless(__builtin_nan(""),x) != 0)
+    link_error ();
+
+  if (__builtin_islessequal(x,__builtin_nan("")) != 0)
+    link_error ();
+  if (__builtin_islessequal(__builtin_nan(""),x) != 0)
+    link_error ();
+
+  if (__builtin_islessgreater(x,__builtin_nan("")) != 0)
+    link_error ();
+  if (__builtin_islessgreater(__builtin_nan(""),x) != 0)
+    link_error ();
+
+  if (__builtin_isunordered(x,__builtin_nan("")) == 0)
+    link_error ();
+  if (__builtin_isunordered(__builtin_nan(""),x) == 0)
+    link_error ();
+}
+
+
+int main()
+{
+  test1 ();
+  test2 (1.0);
+  return 0;
+}
+