===================================================================
@@ -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,
===================================================================
@@ -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" } } */
===================================================================
@@ -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" } } */
===================================================================
@@ -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" } } */
===================================================================
@@ -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" } } */