OSDN Git Service

* fold-const.c (fold) [EQ_EXPR]: Place both integer and real
authorsayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 7 Jun 2002 23:42:53 +0000 (23:42 +0000)
committersayle <sayle@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 7 Jun 2002 23:42:53 +0000 (23:42 +0000)
constants last in comparisons.  Optimize (x+1.0)>0.0 into the
equivalent x > -1.0 when -ffast-math.

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

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

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

index db56e7f..afff77b 100644 (file)
@@ -1,3 +1,9 @@
+2002-06-07  Roger Sayle  <roger@eyesopen.com>
+
+       * fold-const.c (fold) [EQ_EXPR]:  Place both integer and real
+       constants last in comparisons.  Optimize (x+1.0)>0.0 into the
+       equivalent x > -1.0 when -ffast-math.
+
 2002-06-07  Jason Thorpe  <thorpej@wasabisystems.com>
 
        * config.gcc (mips*-*-netbsd*): Add mips/t-netbsd to ${tmake_file}.
index 6febe58..db41564 100644 (file)
@@ -5814,6 +5814,20 @@ fold (expr)
     case GT_EXPR:
     case LE_EXPR:
     case GE_EXPR:
+      /* If one arg is a real or integer constant, put it last.  */
+      if ((TREE_CODE (arg0) == INTEGER_CST
+          && TREE_CODE (arg1) != INTEGER_CST)
+         || (TREE_CODE (arg0) == REAL_CST
+             && TREE_CODE (arg0) != REAL_CST))
+       {
+         TREE_OPERAND (t, 0) = arg1;
+         TREE_OPERAND (t, 1) = arg0;
+         arg0 = TREE_OPERAND (t, 0);
+         arg1 = TREE_OPERAND (t, 1);
+         code = swap_tree_comparison (code);
+         TREE_SET_CODE (t, code);
+       }
+
       if (FLOAT_TYPE_P (TREE_TYPE (arg0)))
        {
          /* (-a) CMP (-b) -> b CMP a  */
@@ -5835,18 +5849,21 @@ fold (expr)
              && REAL_VALUE_MINUS_ZERO (TREE_REAL_CST (arg1)))
            return fold (build (code, type, arg0,
                                build_real (TREE_TYPE (arg1), dconst0)));
-       }
 
-      /* If one arg is a constant integer, put it last.  */
-      if (TREE_CODE (arg0) == INTEGER_CST
-         && TREE_CODE (arg1) != INTEGER_CST)
-       {
-         TREE_OPERAND (t, 0) = arg1;
-         TREE_OPERAND (t, 1) = arg0;
-         arg0 = TREE_OPERAND (t, 0);
-         arg1 = TREE_OPERAND (t, 1);
-         code = swap_tree_comparison (code);
-         TREE_SET_CODE (t, code);
+         /* If this is a comparison of a real constant with a PLUS_EXPR
+            or a MINUS_EXPR of a real constant, we can convert it into a
+            comparison with a revised real constant as long as no overflow
+            occurs when unsafe_math_optimizations are enabled.  */
+         if (flag_unsafe_math_optimizations
+             && TREE_CODE (arg1) == REAL_CST
+             && (TREE_CODE (arg0) == PLUS_EXPR
+                 || TREE_CODE (arg0) == MINUS_EXPR)
+             && TREE_CODE (TREE_OPERAND (arg0, 1)) == REAL_CST
+             && 0 != (tem = const_binop (TREE_CODE (arg0) == PLUS_EXPR
+                                         ? MINUS_EXPR : PLUS_EXPR,
+                                         arg1, TREE_OPERAND (arg0, 1), 0))
+             && ! TREE_CONSTANT_OVERFLOW (tem))
+           return fold (build (code, type, TREE_OPERAND (arg0, 0), tem));
        }
 
       /* Convert foo++ == CONST into ++foo == CONST + INCR.
index 576ef54..ea104cf 100644 (file)
@@ -1,3 +1,7 @@
+2002-06-07  Roger Sayle  <roger@eyesopen.com>
+
+       * gcc.dg/20020607-2.c: New test case.
+
 2002-06-07  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.c-torture/compile/20020604-1.c: New test.
diff --git a/gcc/testsuite/gcc.dg/20020607-2.c b/gcc/testsuite/gcc.dg/20020607-2.c
new file mode 100644 (file)
index 0000000..239aa9b
--- /dev/null
@@ -0,0 +1,74 @@
+/* Copyright (C) 2002 Free Software Foundation.
+
+   Test for correctness of floating point comparisons.
+
+   Written by Roger Sayle, 3rd June 2002.  */
+
+/* { dg-do run } */
+/* { dg-options "-O2 -ffast-math" } */
+
+extern void abort (void);
+
+int test1 (double x, int ok)
+{
+  if ((x - 1.0) > 0.0)
+    {
+      if (!ok) abort ();
+    }
+  else
+    if (ok) abort ();
+}
+
+int test1f (float x, int ok)
+{
+  if ((x - 1.0f) > 0.0f)
+    {
+      if (!ok) abort ();
+    }
+  else
+    if (ok) abort ();
+}
+
+int test2 (double x, int ok)
+{
+  if ((x + 1.0) < 0.0)
+    {
+      if (!ok) abort ();
+    }
+  else
+    if (ok) abort ();
+}
+
+int test2f (float x, int ok)
+{
+  if ((x + 1.0f) < 0.0f)
+    {
+      if (!ok) abort ();
+    }
+  else
+    if (ok) abort ();
+}
+
+
+int
+main ()
+{
+  test1 (-2.0, 0);
+  test1 ( 0.0, 0);
+  test1 ( 2.0, 1);
+
+  test1f (-2.0f, 0);
+  test1f ( 0.0f, 0);
+  test1f ( 2.0f, 1);
+
+  test2 (-2.0, 1);
+  test2 ( 0.0, 0);
+  test2 ( 2.0, 0);
+
+  test2f (-2.0f, 1);
+  test2f ( 0.0f, 0);
+  test2f ( 2.0f, 0);
+
+  return 0;
+}
+