Hello,

this patch fixes regression of bug report PR middle-end/49806, which was caused 
due unhandled type-cast patterns reasoned by boolification of compares and 
type-cast preserving from/to boolean types.


ChangeLog

2011-07-29  Kai Tietz  <kti...@redhat.com>

        PR middle-end/49806
        * tree-vrp.c (has_operand_boolean_range): Helper function.
        (simplify_truth_ops_using_ranges): Factored out code pattern
        into new has_operand_boolean_range function and use it.
        (simplify_converted_bool_expr_using_ranges): New function.
        (simplify_stmt_using_ranges): Add new simplification function
        call.

        * gcc.dg/tree-ssa/vrp47.c: Remove dom-dump and adjusted
        scan test for vrp result.

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

Regards,
Kai

Index: gcc-head/gcc/tree-vrp.c
===================================================================
--- gcc-head.orig/gcc/tree-vrp.c
+++ gcc-head/gcc/tree-vrp.c
@@ -6747,15 +6747,46 @@ varying:
   return SSA_PROP_VARYING;
 }
 
+/* Returns true, if operand OP has either a one-bit type precision,
+   or if value-range of OP is between zero and one.  Otherwise false
+   is returned.  The destination of PSOP will be set to true, if a sign-
+   overflow on range-check occures.  PSOP might be NULL.  */
+static bool
+has_operand_boolean_range (tree op, bool *psop)
+{
+  tree val = NULL;
+  value_range_t *vr;
+  bool sop = false;
+
+  if (TYPE_PRECISION (TREE_TYPE (op)) == 1)
+    {
+      if (psop)
+        *psop = false;
+      return true;
+    }
+  if (TREE_CODE (op) != SSA_NAME)
+    return false;
+  vr = get_value_range (op);
+
+  val = compare_range_with_value (GE_EXPR, vr, integer_zero_node, &sop);
+  if (!val || !integer_onep (val))
+    return false;
+
+  val = compare_range_with_value (LE_EXPR, vr, integer_one_node, &sop);
+  if (!val || !integer_onep (val))
+    return false;
+  if (psop)
+    *psop = sop;
+  return true;
+}
+
 /* Simplify boolean operations if the source is known
    to be already a boolean.  */
 static bool
 simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
 {
   enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
-  tree val = NULL;
   tree op0, op1;
-  value_range_t *vr;
   bool sop = false;
   bool need_conversion;
 
@@ -6763,20 +6794,8 @@ simplify_truth_ops_using_ranges (gimple_
   gcc_assert (rhs_code == EQ_EXPR || rhs_code == NE_EXPR);
 
   op0 = gimple_assign_rhs1 (stmt);
-  if (TYPE_PRECISION (TREE_TYPE (op0)) != 1)
-    {
-      if (TREE_CODE (op0) != SSA_NAME)
-       return false;
-      vr = get_value_range (op0);
-
-      val = compare_range_with_value (GE_EXPR, vr, integer_zero_node, &sop);
-      if (!val || !integer_onep (val))
-        return false;
-
-      val = compare_range_with_value (LE_EXPR, vr, integer_one_node, &sop);
-      if (!val || !integer_onep (val))
-        return false;
-    }
+  if (!has_operand_boolean_range (op0, &sop))
+    return false;
 
   op1 = gimple_assign_rhs2 (stmt);
 
@@ -6802,17 +6821,8 @@ simplify_truth_ops_using_ranges (gimple_
       if (rhs_code == EQ_EXPR)
        return false;
 
-      if (TYPE_PRECISION (TREE_TYPE (op1)) != 1)
-       {
-         vr = get_value_range (op1);
-         val = compare_range_with_value (GE_EXPR, vr, integer_zero_node, &sop);
-         if (!val || !integer_onep (val))
-           return false;
-
-         val = compare_range_with_value (LE_EXPR, vr, integer_one_node, &sop);
-         if (!val || !integer_onep (val))
-           return false;
-       }
+      if (!has_operand_boolean_range (op1, &sop))
+        return false;
     }
 
   if (sop && issue_strict_overflow_warning (WARN_STRICT_OVERFLOW_MISC))
@@ -7320,6 +7330,126 @@ simplify_switch_using_ranges (gimple stm
   return false;
 }
 
+/* Simplify an integeral boolean-typed casted expression for the
+   following cases:
+   1) (type) ~ (bool) op1 -> op1 ^ 1
+   2) (type) ((bool)op1[0..1] & (bool)op2[0..1]) -> op1 & op2
+   3) (type) ((bool)op1[0..1] | (bool)op2[0..1]) -> op1 | op2
+   4) (type) ((bool)op1[0..1] ^ (bool)op2[0..1]) -> op2 ^ op2
+   5) (type) (val[0..1] == 0) -> val ^ 1
+   6) (type) (val[0..1] != 0) -> val
+
+   Assuming op1 and op2 hav\EDng type TYPE.  */
+
+static bool
+simplify_converted_bool_expr_using_ranges (gimple_stmt_iterator *gsi, gimple 
stmt)
+{
+  tree finaltype, expr, op1, op2 = NULL_TREE;
+  gimple def;
+  enum tree_code expr_code;
+
+  finaltype = TREE_TYPE (gimple_assign_lhs (stmt));
+  if (!INTEGRAL_TYPE_P (finaltype))
+    return false;
+  expr = gimple_assign_rhs1 (stmt);
+
+  /* Check that cast is from a boolean-typed expression.  */
+  if (TREE_CODE (TREE_TYPE (expr)) != BOOLEAN_TYPE)
+    return false;
+  /* Check for assignment.  */
+  def = SSA_NAME_DEF_STMT (expr);
+  if (!is_gimple_assign (def))
+    return false;
+
+  expr_code = gimple_assign_rhs_code (def);
+
+  op1 = gimple_assign_rhs1 (def);
+
+  switch (expr_code)
+    {
+    /* (TYPE) ~ (bool) X -> X ^ 1, if X has compatible type to final type
+       and truth-valued range.  */
+    case BIT_NOT_EXPR:
+      /* Bitwise not is only a logical-not for 1-bit precisioned
+         types.  */
+      if (TYPE_PRECISION (TREE_TYPE (expr)) != 1)
+        return false;
+
+      /* Check that we have a type-conversion as operand of bitwise-not.  */
+      def = SSA_NAME_DEF_STMT (op1);
+      if (!is_gimple_assign (def)
+          || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def)))
+       return false;
+      op1 = gimple_assign_rhs1 (def);
+      /* Has X compatible type to final type and truth-valued range?  */
+      if (!useless_type_conversion_p (finaltype, TREE_TYPE (op1))
+          || !has_operand_boolean_range (op1, NULL))
+       return false;
+      expr_code = BIT_XOR_EXPR;
+      op2 = fold_convert (finaltype, integer_one_node);
+      break;
+
+    /* (TYPE) ((bool) X op (bool) Y) -> X op Y, if X and Y have compatible type
+       TYPE and having truth-valued ranges.  */
+    case BIT_AND_EXPR:
+    case BIT_IOR_EXPR:
+    case BIT_XOR_EXPR:
+      op2 = gimple_assign_rhs2 (def);
+
+      def = SSA_NAME_DEF_STMT (op1);
+      if (!is_gimple_assign (def)
+          || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def)))
+       return false;
+      op1 = gimple_assign_rhs1 (def);
+      /* Has X compatible type to final type and truth-valued range?  */
+      if (!useless_type_conversion_p (finaltype, TREE_TYPE (op1))
+         || !has_operand_boolean_range (op1, NULL))
+        return false;
+
+      def = SSA_NAME_DEF_STMT (op2);
+      if (!is_gimple_assign (def)
+          || !CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def)))
+       return false;
+      op2 = gimple_assign_rhs1 (def);
+      /* Has Y compatible type to final type and truth-valued range?  */
+      if (!useless_type_conversion_p (finaltype, TREE_TYPE (op2))
+          || !has_operand_boolean_range (op2, NULL))
+        return false;
+      break;
+
+    /* If X has compatible type to final type and has truth-valued range,
+       tranform:
+       (TYPE) (X == 0) -> X ^ 1
+       (TYPE) (X != 0) -> X  */
+    case EQ_EXPR:
+    case NE_EXPR:
+      /* Is the comparison's second operand zero?  */
+      op2 = gimple_assign_rhs2 (def);
+      if (!INTEGRAL_TYPE_P (TREE_TYPE (op1))
+          || !integer_zerop (op2))
+        return false;
+      /* Is the type of comparison's first argument compatible to final type
+         and has it truth-valued range?  */
+      if (!useless_type_conversion_p (finaltype, TREE_TYPE (op1))
+         || !has_operand_boolean_range (op1, NULL))
+        return false;
+
+      op2 = NULL_TREE;
+      /* X == 0 -> X ^ 1.  */
+      if (expr_code == EQ_EXPR)
+       op2 = fold_convert (finaltype, integer_one_node);
+      expr_code = (!op2 ? SSA_NAME : BIT_XOR_EXPR);
+      break;
+
+    default:
+      return false;
+    }
+
+  gimple_assign_set_rhs_with_ops (gsi, expr_code, op1, op2);
+  update_stmt (gsi_stmt (*gsi));
+  return true;
+}
+
 /* Simplify an integral conversion from an SSA name in STMT.  */
 
 static bool
@@ -7546,7 +7676,11 @@ simplify_stmt_using_ranges (gimple_stmt_
        CASE_CONVERT:
          if (TREE_CODE (rhs1) == SSA_NAME
              && INTEGRAL_TYPE_P (TREE_TYPE (rhs1)))
-           return simplify_conversion_using_ranges (stmt);
+           {
+              if (simplify_conversion_using_ranges (stmt)
+                  || simplify_converted_bool_expr_using_ranges (gsi, stmt))
+                return true;
+           }
          break;
 
        case FLOAT_EXPR:
Index: gcc-head/gcc/testsuite/gcc.dg/tree-ssa/vrp47.c
===================================================================
--- gcc-head.orig/gcc/testsuite/gcc.dg/tree-ssa/vrp47.c
+++ gcc-head/gcc/testsuite/gcc.dg/tree-ssa/vrp47.c
@@ -4,8 +4,8 @@
    jumps when evaluating an && condition.  VRP is not able to optimize
    this.  */
 /* { dg-do compile { target { ! "mips*-*-* s390*-*-*  avr-*-* mn10300-*-*" } } 
} */
-/* { dg-options "-O2 -fdump-tree-vrp -fdump-tree-dom" } */
-/* { dg-options "-O2 -fdump-tree-vrp -fdump-tree-dom -march=i586" { target { 
i?86-*-* && ilp32 } } } */
+/* { dg-options "-O2 -fdump-tree-vrp" } */
+/* { dg-options "-O2 -fdump-tree-vrp -march=i586" { target { i?86-*-* && ilp32 
} } } */
 
 int h(int x, int y)
 {
@@ -36,13 +36,10 @@ int f(int x)
    0 or 1.  */
 /* { dg-final { scan-tree-dump-times "\[xy\]\[^ \]* !=" 0 "vrp1" } } */
 
-/* This one needs more copy propagation that only happens in dom1.  */
-/* { dg-final { scan-tree-dump-times "x\[^ \]* & y" 1 "dom1" } } */
-/* { dg-final { scan-tree-dump-times "x\[^ \]* & y" 1 "vrp1" { xfail *-*-* } } 
} */
+/* { dg-final { scan-tree-dump-times "x\[^ \]* & y" 1 "vrp1" } } */
 
 /* These two are fully simplified by VRP.  */
 /* { dg-final { scan-tree-dump-times "x\[^ \]* \[|\] y" 1 "vrp1" } } */
 /* { dg-final { scan-tree-dump-times "x\[^ \]* \\^ 1" 1 "vrp1" } } */
 
 /* { dg-final { cleanup-tree-dump "vrp\[0-9\]" } } */
-/* { dg-final { cleanup-tree-dump "dom\[0-9\]" } } */

Reply via email to