aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/tree-ssa/forwprop-17.c12
-rw-r--r--gcc/tree-ssa-forwprop.c48
4 files changed, 69 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6f40fa1..e62b04e 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2012-04-23 Andrew Pinski <apinski@cavium.com>
+
+ * tree-ssa-forwprop.c (simplify_bitwise_binary): Simplify (A & B) OP0
+ (C & B) to (A OP0) & B.
+
2012-04-23 Martin Jambor <mjambor@suse.cz>
* expr.c (expand_expr_real_1): Remove setting parent's alias set for
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 426d8fc..36fdbb5 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2012-04-23 Andrew Pinski <apinski@cavium.com>
+
+ * gcc.dg/tree-ssa/forwprop-17.c: New testcase.
+
2012-04-23 Bill Schmidt <wschmidt@linux.ibm.com>
PR regression/53076
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-17.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-17.c
new file mode 100644
index 0000000..a85d0eb
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-17.c
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-optimized" } */
+
+int foo (int xx, int xy)
+{
+ xx &=1;
+ xy &=1;
+ return xx ^ xy;
+}
+
+/* { dg-final { scan-tree-dump-times " & 1" 1 "optimized" } } */
+/* { dg-final { cleanup-tree-dump "optimized" } } */
diff --git a/gcc/tree-ssa-forwprop.c b/gcc/tree-ssa-forwprop.c
index 965f441..349272d 100644
--- a/gcc/tree-ssa-forwprop.c
+++ b/gcc/tree-ssa-forwprop.c
@@ -1886,6 +1886,54 @@ simplify_bitwise_binary (gimple_stmt_iterator *gsi)
return true;
}
+
+ /* Simplify (A & B) OP0 (C & B) to (A OP0 C) & B. */
+ if (def1_code == def2_code
+ && def1_code == BIT_AND_EXPR
+ && operand_equal_for_phi_arg_p (gimple_assign_rhs2 (def1),
+ gimple_assign_rhs2 (def2)))
+ {
+ tree b = gimple_assign_rhs2 (def1);
+ tree a = def1_arg1;
+ tree c = def2_arg1;
+ tree inner = fold_build2 (code, TREE_TYPE (arg2), a, c);
+ /* If A OP0 C (this usually means C is the same as A) is 0
+ then fold it down correctly. */
+ if (integer_zerop (inner))
+ {
+ gimple_assign_set_rhs_from_tree (gsi, inner);
+ update_stmt (stmt);
+ return true;
+ }
+ /* If A OP0 C (this usually means C is the same as A) is a ssa_name
+ then fold it down correctly. */
+ else if (TREE_CODE (inner) == SSA_NAME)
+ {
+ tree outer = fold_build2 (def1_code, TREE_TYPE (inner),
+ inner, b);
+ gimple_assign_set_rhs_from_tree (gsi, outer);
+ update_stmt (stmt);
+ return true;
+ }
+ else
+ {
+ gimple newop;
+ tree tem;
+ tem = create_tmp_reg (TREE_TYPE (arg2), NULL);
+ newop = gimple_build_assign_with_ops (code, tem, a, c);
+ tem = make_ssa_name (tem, newop);
+ gimple_assign_set_lhs (newop, tem);
+ gimple_set_location (newop, gimple_location (stmt));
+ /* Make sure to re-process the new stmt as it's walking upwards. */
+ gsi_insert_before (gsi, newop, GSI_NEW_STMT);
+ gimple_assign_set_rhs1 (stmt, tem);
+ gimple_assign_set_rhs2 (stmt, b);
+ gimple_assign_set_rhs_code (stmt, def1_code);
+ update_stmt (stmt);
+ return true;
+ }
+ }
+
/* (a | CST1) & CST2 -> (a & CST2) | (CST1 & CST2). */
if (code == BIT_AND_EXPR
&& def1_code == BIT_IOR_EXPR