Hello,

this patch removes in forward-propagation useless comparisons X != 0
and X != ~0 for boolean-typed X.  For one-bit precision typed X we
simplifiy X == 0 (and X != ~0) to ~X, and for X != 0 (and X == ~0) to
X.
For none one-bit precisione typed X, we simplify here X == 0 -> X ^ 1,
and for X != 0 -> X.  We can do this as even for Ada - which has only
boolean-type with none-one-bit precision - the truth-value is one.

Additionally this patch changes for function
forward_propagate_comparison the meaning of true-result.  As this
result wasn't used and it is benefitial to use this propagation also
in second loop in function ssa_forward_propagate_and_combine, it
returns true iff statement was altered.  Additionally this function
handles now the boolean-typed simplifications.

For the hunk in gimple.c for function canonicalize_cond_expr_cond:
This change seems to show no real effect, but IMHO it makes sense to
add here the check for cast from boolean-type to be consitant.

ChangeLog

2011-08-02  Kai Tietz  <kti...@redhat.com>

        * gimple.c (canonicalize_cond_expr_cond): Handle cast from boolean-type.
        * tree-ssa-forwprop.c (forward_propagate_comparison): Return
true iff statement was modified.
        Handle boolean-typed simplification for EQ_EXPR/NE_EXPR.
        (ssa_forward_propagate_and_combine): Call
forward_propagate_comparison for comparisons.

2011-08-02  Kai Tietz  <kti...@redhat.com>

        * gcc.dg/tree-ssa/forwprop-9.c: New testcase.


Bootstrapped and regression tested for all languages (including Ada
and Obj-C++) on host x86_64-pc-linux-gnu.  Ok for apply?

Regards,
Kai

Index: gcc/gcc/gimple.c
===================================================================
--- gcc.orig/gcc/gimple.c
+++ gcc/gcc/gimple.c
@@ -3160,7 +3160,9 @@ canonicalize_cond_expr_cond (tree t)
 {
   /* Strip conversions around boolean operations.  */
   if (CONVERT_EXPR_P (t)
-      && truth_value_p (TREE_CODE (TREE_OPERAND (t, 0))))
+      && (truth_value_p (TREE_CODE (TREE_OPERAND (t, 0)))
+          || TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0)))
+            == BOOLEAN_TYPE))
     t = TREE_OPERAND (t, 0);

   /* For !x use x == 0.  */
Index: gcc/gcc/tree-ssa-forwprop.c
===================================================================
--- gcc.orig/gcc/tree-ssa-forwprop.c
+++ gcc/gcc/tree-ssa-forwprop.c
@@ -1114,7 +1114,18 @@ forward_propagate_addr_expr (tree name,
      a_1 = (T')cond_1
      a_1 = !cond_1
      a_1 = cond_1 != 0
-   Returns true if stmt is now unused.  */
+     For boolean typed comparisons with type-precision of one
+     X == 0 -> ~X
+     X != ~0 -> ~X
+     X != 0 -> X
+     X == ~0 -> X
+     For boolean typed comparison with none one-bit type-precision
+     we can assume that truth-value is one, and false-value is zero.
+     X == 1 -> X
+     X != 1 -> X ^ 1
+     X == 0 -> X ^ 1
+     X != 0 -> X
+   Returns true if stmt is changed.  */

 static bool
 forward_propagate_comparison (gimple stmt)
@@ -1123,9 +1134,48 @@ forward_propagate_comparison (gimple stm
   gimple use_stmt;
   tree tmp = NULL_TREE;
   gimple_stmt_iterator gsi;
-  enum tree_code code;
+  enum tree_code code = gimple_assign_rhs_code (stmt);
   tree lhs;

+  /* Simplify X != 0 -> X and X == 0 -> ~X, if X is boolean-typed
+     and X has a compatible type to the comparison-expression.  */
+  if ((code == EQ_EXPR || code == NE_EXPR)
+      && TREE_CODE (TREE_TYPE (gimple_assign_rhs1 (stmt))) == BOOLEAN_TYPE
+      && TREE_CODE (gimple_assign_rhs2 (stmt)) == INTEGER_CST
+      /* A comparison is always boolean-typed, but there might be
+        differences in mode-size.  */
+      && useless_type_conversion_p (TREE_TYPE (name),
+                                   TREE_TYPE (gimple_assign_rhs1 (stmt))))
+    {
+      tree tmp2;
+
+      /* Normalize to reduce cases.  */
+      if (!integer_zerop (gimple_assign_rhs2 (stmt)))
+        code = (code == EQ_EXPR ? NE_EXPR : EQ_EXPR);
+      tmp = gimple_assign_rhs1 (stmt);
+      tmp2 = NULL_TREE;
+
+      /* Convert X == 0 -> ~X for 1-bit precision boolean-type.
+        Otherwise convert X == 0 -> X ^ 1.  */
+      if (code == EQ_EXPR)
+       {
+         if (TYPE_PRECISION (TREE_TYPE (tmp)) == 1)
+           code = BIT_NOT_EXPR;
+         else
+           {
+             code = BIT_XOR_EXPR;
+             tmp2 = build_one_cst (TREE_TYPE (tmp));
+           }
+       }
+      else
+       code = TREE_CODE (tmp);
+      gsi = gsi_for_stmt (stmt);
+      gimple_assign_set_rhs_with_ops (&gsi, code,
+                                     tmp, tmp2);
+      update_stmt (stmt);
+      return true;
+    }
+
   /* Don't propagate ssa names that occur in abnormal phis.  */
   if ((TREE_CODE (gimple_assign_rhs1 (stmt)) == SSA_NAME
        && SSA_NAME_OCCURS_IN_ABNORMAL_PHI (gimple_assign_rhs1 (stmt)))
@@ -1179,7 +1229,8 @@ forward_propagate_comparison (gimple stm
     }

   /* Remove defining statements.  */
-  return remove_prop_source_from_use (name);
+  remove_prop_source_from_use (name);
+  return true;
 }


@@ -2459,6 +2510,9 @@ ssa_forward_propagate_and_combine (void)
                        (!no_warning && changed,
                         stmt, WARN_STRICT_OVERFLOW_CONDITIONAL);
                    changed = did_something != 0;
+                   if (!changed)
+                     changed = forward_propagate_comparison (stmt);
+
                  }
                else if (code == BIT_AND_EXPR
                         || code == BIT_IOR_EXPR
Index: gcc/gcc/testsuite/gcc.dg/tree-ssa/forwprop-9.c
===================================================================
--- gcc.orig/gcc/testsuite/gcc.dg/tree-ssa/forwprop-9.c
+++ gcc/gcc/testsuite/gcc.dg/tree-ssa/forwprop-9.c
@@ -1,21 +1,14 @@
 /* { dg-do compile } */
-/* { dg-options "-O1 -fdump-tree-optimized -fdump-tree-fre1 -W -Wall
-fno-early-inlining" } */
+/* { dg-options "-O2 -fdump-tree-forwprop1" }  */

-int b;
-unsigned a;
-static inline int *g(void)
+_Bool
+foo (_Bool a, _Bool b, _Bool c
 {
-  a = 1;
-  return (int*)&a;
+  _Bool r1 = a == 0 & b != 0;
+  _Bool r2 = b != 0 & c == 0;
+  return (r1 == 0 & r2 == 0);
 }
-void f(void)
-{
-   b = *g();
-}
-
-/* We should have converted the assignments to two = 1.  FRE does this.  */

-/* { dg-final { scan-tree-dump-times " = 1" 2 "optimized"} } */
-/* { dg-final { scan-tree-dump-not " = a;" "fre1"} } */
-/* { dg-final { cleanup-tree-dump "fre1" } } */
-/* { dg-final { cleanup-tree-dump "optimized" } } */
+/* { dg-final { scan-tree-dump-times " == " 0 "forwprop1" } } */
+/* { dg-final { scan-tree-dump-times " != " 0 "forwprop1" } } */
+/* { dg-final { cleanup-tree-dump "forwprop1" } } */

Reply via email to