summaryrefslogtreecommitdiff
path: root/gcc/tree-vrp.c
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2010-07-12 22:11:27 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2010-07-12 22:11:27 +0000
commit273e780e59817ad6ee61abfb851d35e11c044c13 (patch)
tree2ea05cb45ffae6bb753a132c2144022300e03f44 /gcc/tree-vrp.c
parent0c5c4d5992e57440e4542c72b95bd1f02176193d (diff)
downloadgcc-273e780e59817ad6ee61abfb851d35e11c044c13.tar.gz
* tree-vrp.c (simplify_bit_ops_using_ranges): New function.
(simplify_stmt_using_ranges): Use it. * gcc.dg/tree-ssa/vrp53.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@162115 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r--gcc/tree-vrp.c92
1 files changed, 92 insertions, 0 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index c8555110a59..afe69a3b8a1 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -6913,6 +6913,89 @@ simplify_abs_using_ranges (gimple stmt)
return false;
}
+/* Optimize away redundant BIT_AND_EXPR and BIT_IOR_EXPR.
+ If all the bits that are being cleared by & are already
+ known to be zero from VR, or all the bits that are being
+ set by | are already known to be one from VR, the bit
+ operation is redundant. */
+
+static bool
+simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
+{
+ tree op0 = gimple_assign_rhs1 (stmt);
+ tree op1 = gimple_assign_rhs2 (stmt);
+ tree op = NULL_TREE;
+ value_range_t vr0 = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
+ value_range_t vr1 = { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL };
+ double_int may_be_nonzero0, may_be_nonzero1;
+ double_int must_be_nonzero0, must_be_nonzero1;
+ double_int mask;
+
+ if (TREE_CODE (op0) == SSA_NAME)
+ vr0 = *(get_value_range (op0));
+ else if (is_gimple_min_invariant (op0))
+ set_value_range_to_value (&vr0, op0, NULL);
+ else
+ return false;
+
+ if (TREE_CODE (op1) == SSA_NAME)
+ vr1 = *(get_value_range (op1));
+ else if (is_gimple_min_invariant (op1))
+ set_value_range_to_value (&vr1, op1, NULL);
+ else
+ return false;
+
+ if (!zero_nonzero_bits_from_vr (&vr0, &may_be_nonzero0, &must_be_nonzero0))
+ return false;
+ if (!zero_nonzero_bits_from_vr (&vr1, &may_be_nonzero1, &must_be_nonzero1))
+ return false;
+
+ switch (gimple_assign_rhs_code (stmt))
+ {
+ case BIT_AND_EXPR:
+ mask = double_int_and (may_be_nonzero0,
+ double_int_not (must_be_nonzero1));
+ if (double_int_zero_p (mask))
+ {
+ op = op0;
+ break;
+ }
+ mask = double_int_and (may_be_nonzero1,
+ double_int_not (must_be_nonzero0));
+ if (double_int_zero_p (mask))
+ {
+ op = op1;
+ break;
+ }
+ break;
+ case BIT_IOR_EXPR:
+ mask = double_int_and (may_be_nonzero0,
+ double_int_not (must_be_nonzero1));
+ if (double_int_zero_p (mask))
+ {
+ op = op1;
+ break;
+ }
+ mask = double_int_and (may_be_nonzero1,
+ double_int_not (must_be_nonzero0));
+ if (double_int_zero_p (mask))
+ {
+ op = op0;
+ break;
+ }
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ if (op == NULL_TREE)
+ return false;
+
+ gimple_assign_set_rhs_with_ops (gsi, TREE_CODE (op), op, NULL);
+ update_stmt (gsi_stmt (*gsi));
+ return true;
+}
+
/* We are comparing trees OP0 and OP1 using COND_CODE. OP0 has
a known value range VR.
@@ -7198,6 +7281,15 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
return simplify_abs_using_ranges (stmt);
break;
+ case BIT_AND_EXPR:
+ case BIT_IOR_EXPR:
+ /* Optimize away BIT_AND_EXPR and BIT_IOR_EXPR
+ if all the bits being cleared are already cleared or
+ all the bits being set are already set. */
+ if (INTEGRAL_TYPE_P (TREE_TYPE (gimple_assign_rhs1 (stmt))))
+ return simplify_bit_ops_using_ranges (gsi, stmt);
+ break;
+
default:
break;
}