Hello,

this patch adds the ability to gimple-fold to operate for truth and/or
operations
on folded binary-and/or optimized truth trees - as done by fold-const.  As fold
converts trivial operations like (A && B) to (A & B) != 0, in most cases further
folding of truth and/or trees wasn't done.
folding will be again detected.

ChangeLog gcc/

2011-04-27  Kai Tietz

        * gimple-fold.c (is_bit_ior_and): New helper function.
        (fold_equal_and_or): New helper function for truth &&
        and || logic folding with treating binary optimization.
        (maybe_fold_and_comparisons): Folding for and.
        (maybe_fold_or_comparisons): Folding for or.

ChangeLog gcc/testsuite/

2011-04-27  Kai Tietz

        * gcc.dg/binop-tand1.c: New.
        * gcc.dg/binop-tand2.c: New.
        * gcc.dg/binop-tor1.c: New.
        * gcc.dg/binop-tor2.c: New.

Tested for x86_64-pc-linux-gnu and x86_64-w64-mingw32. Ok for apply?

Regards,
Kai
Index: gcc/gcc/gimple-fold.c
===================================================================
--- gcc.orig/gcc/gimple-fold.c  2011-04-26 13:25:59.000000000 +0200
+++ gcc/gcc/gimple-fold.c       2011-04-27 20:08:50.276783700 +0200
@@ -2300,6 +2300,85 @@ and_comparisons_1 (enum tree_code code1,
   return NULL_TREE;
 }
 
+/* Checks if the binary logic can be expand for truth logic specified by the
+   IS_AND flag.  We assume that C is EQ_EXPR or NE_EXPR.  If we see a binary
+   or the variable IS_IOR is set to true, otherwise it is set to zero.  */
+
+static bool
+is_bit_ior_and (tree op, enum tree_code c, bool *is_ior, bool is_and)
+{
+  enum tree_code code;
+  gimple s;
+
+  gcc_assert (c == EQ_EXPR || c == NE_EXPR);
+
+  if (TREE_CODE (op) != SSA_NAME
+      || !is_gimple_assign ((s = SSA_NAME_DEF_STMT (op))))
+    return false;
+  code = gimple_assign_rhs_code (s);
+  if (code != BIT_IOR_EXPR && code != BIT_AND_EXPR)
+    return false;
+  if (is_and)
+    {
+      if ((code == BIT_IOR_EXPR && c == NE_EXPR)
+          || (code != BIT_IOR_EXPR && c == EQ_EXPR))
+        return false;
+    }
+  else
+    {
+      if ((code == BIT_IOR_EXPR && c != NE_EXPR)
+          || (code != BIT_IOR_EXPR && c != EQ_EXPR))
+        return false;
+    }
+  *is_ior = (code == BIT_IOR_EXPR);
+  return true;
+}
+
+/* Try to unfold truth and/or logic by watching into binary and/or optimized
+   truth logic.  */
+static tree
+fold_equal_and_or (tree l, bool l_true, int l_and, tree r, bool r_true, int 
is_and)
+{
+  gimple s;
+  if (operand_equal_p (l, r, 0))
+    {
+      if (l_true == r_true)
+        return l;
+      return (is_and ? boolean_false_node : boolean_true_node);
+    }
+  if (TREE_CODE (l) == SSA_NAME && is_gimple_assign ((s = SSA_NAME_DEF_STMT 
(l)))
+      && gimple_assign_rhs_code (s) == (l_and ? BIT_AND_EXPR : BIT_IOR_EXPR))
+    {
+      tree l1, l2, t1, t2;
+      gimple_stmt_iterator gsi;
+      l1 = gimple_assign_rhs1 (s);
+      l2 = gimple_assign_rhs1 (s);
+      t1 = fold_equal_and_or (l1, l_true, l_and, r, r_true, is_and);
+      if (t1 && ((is_and && integer_zerop (t1)) || (!is_and && integer_onep 
(t1))))
+        return t1;
+      if (t1 && ((is_and && integer_zerop (t1)) || (!is_and && integer_zerop 
(t1))))
+        return l2;
+
+      t2 = fold_equal_and_or (l2, l_true, l_and, r, r_true, is_and);
+      if (!t1 && !t2)
+        return NULL_TREE;
+      if (t2 && ((is_and && integer_zerop (t2)) || (!is_and && integer_onep 
(t2))))
+        return t2;
+      if (t2 && ((is_and && integer_zerop (t2)) || (!is_and && integer_zerop 
(t2))))
+        return l1;
+      if (t1)
+        t2 = l2;
+      else if (t2)
+        t1 = l1;
+      t1 = fold_build2 ((l_and ? BIT_AND_EXPR : BIT_IOR_EXPR), TREE_TYPE 
(gimple_assign_lhs (s)),
+        t1, t2);
+      gsi = gsi_for_stmt (s);
+      gimple_assign_set_rhs_from_tree (&gsi, t1);
+      return gimple_assign_lhs (s);
+    }
+  return NULL;
+}
+
 /* Try to simplify the AND of two comparisons, specified by
    (OP1A CODE1 OP1B) and (OP2B CODE2 OP2B), respectively.
    If this can be simplified to a single expression (without requiring
@@ -2311,11 +2390,43 @@ tree
 maybe_fold_and_comparisons (enum tree_code code1, tree op1a, tree op1b,
                            enum tree_code code2, tree op2a, tree op2b)
 {
-  tree t = and_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b);
+  tree t;
+  bool is_ior;
+
+  t = and_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b);
   if (t)
     return t;
-  else
-    return and_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b);
+  t = and_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b);
+  if (t)
+    return t;
+
+  if ((code1 != NE_EXPR && code1 != EQ_EXPR)
+      || (code2 != NE_EXPR && code2 != EQ_EXPR)
+      || !integer_zerop (op1b) || !integer_zerop (op2b))
+    return NULL_TREE;
+
+  if (is_bit_ior_and (op1a, code1, &is_ior, true))
+    {
+      t = fold_equal_and_or (op1a, (code1 == NE_EXPR), !is_ior, op2a, (code2 
== NE_EXPR), 1);
+      if (t)
+       {
+         if (integer_zerop (t) || integer_onep (t))
+           return t;
+         return fold_build2 (code1, boolean_type_node, t, op1b);
+       }
+    }
+  if (is_bit_ior_and (op2a, code2, &is_ior, true))
+    {
+      t = fold_equal_and_or (op2a, (code2 == NE_EXPR), !is_ior, op1a, (code1 
== NE_EXPR), 1);
+      if (t)
+       {
+         if (integer_zerop (t) || integer_onep (t))
+           return t;
+         return fold_build2 (code2, boolean_type_node, t, op2b);
+       }
+    }
+
+  return NULL;
 }
 
 /* Helper function for or_comparisons_1:  try to simplify the OR of the
@@ -2761,11 +2872,43 @@ tree
 maybe_fold_or_comparisons (enum tree_code code1, tree op1a, tree op1b,
                           enum tree_code code2, tree op2a, tree op2b)
 {
-  tree t = or_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b);
+  tree t;
+  bool is_ior;
+
+  t = or_comparisons_1 (code1, op1a, op1b, code2, op2a, op2b);
   if (t)
     return t;
-  else
-    return or_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b);
+  t = or_comparisons_1 (code2, op2a, op2b, code1, op1a, op1b);
+  if (t)
+    return t;
+
+  if ((code1 != NE_EXPR && code1 != EQ_EXPR)
+      || (code2 != NE_EXPR && code2 != EQ_EXPR)
+      || !integer_zerop (op1b) || !integer_zerop (op2b))
+    return NULL_TREE;
+
+  if (is_bit_ior_and (op1a, code1, &is_ior, false))
+    {
+      t = fold_equal_and_or (op1a, (code1 == NE_EXPR), !is_ior, op2a, (code2 
== NE_EXPR), 0);
+      if (t)
+       {
+         if (integer_zerop (t) || integer_onep (t))
+           return t;
+         return fold_build2 (code1, boolean_type_node, t, op1b);
+       }
+    }
+  if (is_bit_ior_and (op2a, code2, &is_ior, false))
+    {
+      t = fold_equal_and_or (op2a, (code2 == NE_EXPR), !is_ior, op1a, (code1 
== NE_EXPR), 0);
+      if (t)
+       {
+         if (integer_zerop (t) || integer_onep (t))
+           return t;
+         return fold_build2 (code2, boolean_type_node, t, op2b);
+       }
+    }
+
+  return NULL;
 }
 
 
@@ -2806,7 +2949,7 @@ gimple_fold_stmt_to_constant_1 (gimple s
              else if (TREE_CODE (rhs) == ADDR_EXPR
                       && !is_gimple_min_invariant (rhs))
                {
-                 HOST_WIDE_INT offset;
+                 HOST_WIDE_INT offset = 0;
                  tree base;
                  base = get_addr_base_and_unit_offset_1 (TREE_OPERAND (rhs, 0),
                                                          &offset,
Index: gcc/gcc/testsuite/gcc.dg/binop-tand1.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ gcc/gcc/testsuite/gcc.dg/binop-tand1.c      2011-04-27 21:31:19.276726900 
+0200
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int
+foo (int a, int b, int c)
+{
+  return ((!a && !b) && c && b && c && a);
+}
+
+/* We expect to see "<bb N>"; confirm that, so that we know to count
+   it in the real test.  */
+/* { dg-final { scan-tree-dump-times "<bb\[^>\]*>" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
Index: gcc/gcc/testsuite/gcc.dg/binop-tand2.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ gcc/gcc/testsuite/gcc.dg/binop-tand2.c      2011-04-27 21:30:24.705797300 
+0200
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int
+foo (int a, int b, int c)
+{
+  return ((a && b) && (a & b) != 0 && c);
+}
+
+/* We expect to see "<bb N>"; confirm that, so that we know to count
+   it in the real test.  */
+/* { dg-final { scan-tree-dump-times "<bb\[^>\]*>" 5 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "&" 1 "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
Index: gcc/gcc/testsuite/gcc.dg/binop-tor1.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ gcc/gcc/testsuite/gcc.dg/binop-tor1.c       2011-04-27 21:37:35.889550600 
+0200
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int
+foo (int a, int b, int c)
+{
+  return ((a || b) || c || !b || c || !a);
+}
+
+/* We expect to see "<bb N>"; confirm that, so that we know to count
+   it in the real test.  */
+/* { dg-final { scan-tree-dump-times "<bb\[^>\]*>" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 1" 1 "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
Index: gcc/gcc/testsuite/gcc.dg/binop-tor2.c
===================================================================
--- /dev/null   1970-01-01 00:00:00.000000000 +0000
+++ gcc/gcc/testsuite/gcc.dg/binop-tor2.c       2011-04-27 21:41:04.270511700 
+0200
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+int
+foo (int a, int b, int c)
+{
+  return ((a || b) || c || (a & b) == 0 || c);
+}
+
+/* We expect to see "<bb N>"; confirm that, so that we know to count
+   it in the real test.  */
+/* { dg-final { scan-tree-dump-times "<bb\[^>\]*>" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "return 1" 1 "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */

Reply via email to