===================================================================
@@ -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-vrp1 -fdump-tree-dom1" } */
-/* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-dom1 -march=i586" {
target { i?86-*-* && ilp32 } } } */
+/* { dg-options "-O2 -fdump-tree-vrp1" } */
+/* { dg-options "-O2 -fdump-tree-vrp1 -march=i586" { target {
i?86-*-* && ilp32 } } } */
int h(int x, int y)
{
@@ -37,12 +37,10 @@ int f(int x)
/* { 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 "vrp1" } } */
-/* { dg-final { cleanup-tree-dump "dom1" } } */
===================================================================
@@ -6968,15 +6968,63 @@ simplify_abs_using_ranges (gimple stmt)
static bool
simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple stmt)
{
+ gimple def0, def1;
tree op0 = gimple_assign_rhs1 (stmt);
tree op1 = gimple_assign_rhs2 (stmt);
- tree op = NULL_TREE;
+ tree op = NULL_TREE, nop0 = NULL_TREE, nop1 = 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;
+ def0 = TREE_CODE (op0) == SSA_NAME ? SSA_NAME_DEF_STMT (op0) : NULL;
+ def1 = TREE_CODE (op1) == SSA_NAME ? SSA_NAME_DEF_STMT (op1) : NULL;
+ if (def0 && is_gimple_assign (def0))
+ nop0 = gimple_assign_rhs1 (def0);
+ if (def1 && is_gimple_assign (def1))
+ nop1 = gimple_assign_rhs1 (def1);
+
+ /* Simplify ((type) X) op ((type) Y) -> (type) (X op Y), if X and Y have
+ compatible integral types. */
+ if (nop0 != NULL_TREE && nop1 != NULL_TREE
+ && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def0))
+ && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def1))
+ && INTEGRAL_TYPE_P (TREE_TYPE (nop0))
+ && types_compatible_p (TREE_TYPE (nop0), TREE_TYPE (nop1)))
+ {
+ gimple newop;
+ tree tem = create_tmp_reg (TREE_TYPE (nop0), NULL);
+ newop = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt),
+ tem, nop0, nop1);
+ tem = make_ssa_name (tem, newop);
+ gimple_assign_set_lhs (newop, tem);
+ gsi_insert_before (gsi, newop, GSI_SAME_STMT);
+ update_stmt (newop);
+ gimple_assign_set_rhs_with_ops (gsi, NOP_EXPR, tem, NULL_TREE);
+ return true;
+ }
+ /* Simplify ((type) X) op CST -> (type) (X op (type-X) CST), if X has
+ an integral types. Additiona CST has to fit into type of X. */
+ else if (nop0 != NULL_TREE && TREE_CODE (op1) == INTEGER_CST
+ && CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def0))
+ && INTEGRAL_TYPE_P (TREE_TYPE (nop0))
+ && int_fits_type_p (op1, TREE_TYPE (nop0)))
+ {
+ gimple newop;
+ tree tem = create_tmp_reg (TREE_TYPE (nop0), NULL);
+
+ nop1 = fold_convert (TREE_TYPE (nop0), op1);
+ newop = gimple_build_assign_with_ops (gimple_assign_rhs_code (stmt),
+ tem, nop0, nop1);
+ tem = make_ssa_name (tem, newop);
+ gimple_assign_set_lhs (newop, tem);
+ gsi_insert_before (gsi, newop, GSI_SAME_STMT);
+ update_stmt (newop);
+ gimple_assign_set_rhs_with_ops (gsi, NOP_EXPR, tem, NULL_TREE);
+ return true;
+ }
+
if (TREE_CODE (op0) == SSA_NAME)
vr0 = *(get_value_range (op0));
else if (is_gimple_min_invariant (op0))