OSDN Git Service

PR tree-optimization/46909
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 14 Dec 2010 14:09:59 +0000 (14:09 +0000)
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 14 Dec 2010 14:09:59 +0000 (14:09 +0000)
* gimple-fold.c (and_var_with_comparison_1): Save partial
result even in the is_and case, if both partial results
are the same, return it.
(or_var_with_comparison_1): Use is_or predicate instead of
innercode == TRUTH_OR_EXPR test.  Save partial result
even in the is_or case, if both partial results are the
same, return it.  In the !is_or case when both partial
results are the same, return the partial result instead
of boolean_true_node.

* gcc.c-torture/execute/pr46909-1.c: New test.
* gcc.c-torture/execute/pr46909-2.c: New test.
* gcc.dg/pr46909.c: New test.

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

gcc/ChangeLog
gcc/gimple-fold.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/pr46909-1.c [new file with mode: 0644]
gcc/testsuite/gcc.c-torture/execute/pr46909-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr46909.c [new file with mode: 0644]

index c99b931..b4efa6f 100644 (file)
@@ -1,3 +1,16 @@
+2010-12-14  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/46909
+       * gimple-fold.c (and_var_with_comparison_1): Save partial
+       result even in the is_and case, if both partial results
+       are the same, return it.
+       (or_var_with_comparison_1): Use is_or predicate instead of
+       innercode == TRUTH_OR_EXPR test.  Save partial result
+       even in the is_or case, if both partial results are the
+       same, return it.  In the !is_or case when both partial
+       results are the same, return the partial result instead
+       of boolean_true_node.
+
 2010-12-14  Jan Hubicka  <jh@suse.cz>
 
        PR middle-end/46667
index ba51ee8..bf5e804 100644 (file)
@@ -2008,14 +2008,11 @@ and_var_with_comparison_1 (gimple stmt,
          /* Handle the OR case, where we are redistributing:
             (inner1 OR inner2) AND (op2a code2 op2b)
             => (t OR (inner2 AND (op2a code2 op2b)))  */
-         else
-           {
-             if (integer_onep (t))
-               return boolean_true_node;
-             else
-               /* Save partial result for later.  */
-               partial = t;
-           }
+         else if (integer_onep (t))
+           return boolean_true_node;
+
+         /* Save partial result for later.  */
+         partial = t;
        }
       
       /* Compute the second partial result, (inner2 AND (op2a code op2b)) */
@@ -2036,6 +2033,10 @@ and_var_with_comparison_1 (gimple stmt,
                return inner1;
              else if (integer_zerop (t))
                return boolean_false_node;
+             /* If both are the same, we can apply the identity
+                (x AND x) == x.  */
+             else if (partial && same_bool_result_p (t, partial))
+               return t;
            }
 
          /* Handle the OR case. where we are redistributing:
@@ -2445,7 +2446,7 @@ or_var_with_comparison_1 (gimple stmt,
             => (t OR inner2)
             If the partial result t is a constant, we win.  Otherwise
             continue on to try reassociating with the other inner test.  */
-         if (innercode == TRUTH_OR_EXPR)
+         if (is_or)
            {
              if (integer_onep (t))
                return boolean_true_node;
@@ -2456,14 +2457,11 @@ or_var_with_comparison_1 (gimple stmt,
          /* Handle the AND case, where we are redistributing:
             (inner1 AND inner2) OR (op2a code2 op2b)
             => (t AND (inner2 OR (op2a code op2b)))  */
-         else
-           {
-             if (integer_zerop (t))
-               return boolean_false_node;
-             else
-               /* Save partial result for later.  */
-               partial = t;
-           }
+         else if (integer_zerop (t))
+           return boolean_false_node;
+
+         /* Save partial result for later.  */
+         partial = t;
        }
       
       /* Compute the second partial result, (inner2 OR (op2a code op2b)) */
@@ -2477,13 +2475,18 @@ or_var_with_comparison_1 (gimple stmt,
        {
          /* Handle the OR case, where we are reassociating:
             (inner1 OR inner2) OR (op2a code2 op2b)
-            => (inner1 OR t)  */
-         if (innercode == TRUTH_OR_EXPR)
+            => (inner1 OR t)
+            => (t OR partial)  */
+         if (is_or)
            {
              if (integer_zerop (t))
                return inner1;
              else if (integer_onep (t))
                return boolean_true_node;
+             /* If both are the same, we can apply the identity
+                (x OR x) == x.  */
+             else if (partial && same_bool_result_p (t, partial))
+               return t;
            }
          
          /* Handle the AND case, where we are redistributing:
@@ -2500,13 +2503,13 @@ or_var_with_comparison_1 (gimple stmt,
                     operand to the redistributed AND expression.  The
                     interesting case is when at least one is true.
                     Or, if both are the same, we can apply the identity
-                    (x AND x) == true.  */
+                    (x AND x) == x.  */
                  if (integer_onep (partial))
                    return t;
                  else if (integer_onep (t))
                    return partial;
                  else if (same_bool_result_p (t, partial))
-                   return boolean_true_node;
+                   return t;
                }
            }
        }
index 33be340..0d20e51 100644 (file)
@@ -1,3 +1,10 @@
+2010-12-14  Jakub Jelinek  <jakub@redhat.com>
+
+       PR tree-optimization/46909
+       * gcc.c-torture/execute/pr46909-1.c: New test.
+       * gcc.c-torture/execute/pr46909-2.c: New test.
+       * gcc.dg/pr46909.c: New test.
+
 2010-12-14  Alexander Monakov  <amonakov@ispras.ru>
 
        PR rtl-optimization/46875
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr46909-1.c b/gcc/testsuite/gcc.c-torture/execute/pr46909-1.c
new file mode 100644 (file)
index 0000000..c6c92fc
--- /dev/null
@@ -0,0 +1,22 @@
+/* PR tree-optimization/46909 */
+
+extern void abort ();
+
+int
+__attribute__ ((__noinline__))
+foo (unsigned int x)
+{
+  if (! (x == 4 || x == 6) || (x == 2 || x == 6))
+    return 1;
+  return -1;
+}
+
+int
+main ()
+{
+  int i;
+  for (i = -10; i < 10; i++)
+    if (foo (i) != 1 - 2 * (i == 4))
+      abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/execute/pr46909-2.c b/gcc/testsuite/gcc.c-torture/execute/pr46909-2.c
new file mode 100644 (file)
index 0000000..33da218
--- /dev/null
@@ -0,0 +1,22 @@
+/* PR tree-optimization/46909 */
+
+extern void abort (void);
+
+int
+__attribute__((noinline))
+foo (int x)
+{
+  if ((x != 0 && x != 13) || x == 5 || x == 20)
+    return 1;
+  return -1;
+}
+
+int
+main (void)
+{
+  int i;
+  for (i = -10; i < 30; i++)
+    if (foo (i) != 1 - 2 * (i == 0) - 2 * (i == 13))
+      abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/pr46909.c b/gcc/testsuite/gcc.dg/pr46909.c
new file mode 100644 (file)
index 0000000..affedab
--- /dev/null
@@ -0,0 +1,17 @@
+/* PR tree-optimization/46909 */
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-ifcombine" } */
+
+extern void abort ();
+
+int
+__attribute__ ((__noinline__))
+foo (unsigned int x)
+{
+  if (! (x == 4 || x == 6) || (x == 2 || x == 6))
+    return 1;
+  return -1;
+}
+
+/* { dg-final { scan-tree-dump "optimizing two comparisons to x_\[0-9\]+\\(D\\) != 4" "ifcombine" } } */
+/* { dg-final { cleanup-tree-dump "ifcombine" } } */