aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vrp.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r--gcc/tree-vrp.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index b5654c5..bbdf9ce 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -5310,6 +5310,27 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
if (is_gimple_assign (def_stmt))
rhs_code = gimple_assign_rhs_code (def_stmt);
+ /* In the case of NAME != CST1 where NAME = A +- CST2 we can
+ assert that A != CST1 -+ CST2. */
+ if ((comp_code == EQ_EXPR || comp_code == NE_EXPR)
+ && (rhs_code == PLUS_EXPR || rhs_code == MINUS_EXPR))
+ {
+ tree op0 = gimple_assign_rhs1 (def_stmt);
+ tree op1 = gimple_assign_rhs2 (def_stmt);
+ if (TREE_CODE (op0) == SSA_NAME
+ && TREE_CODE (op1) == INTEGER_CST
+ && live_on_edge (e, op0)
+ && !has_single_use (op0))
+ {
+ enum tree_code reverse_op = (rhs_code == PLUS_EXPR
+ ? MINUS_EXPR : PLUS_EXPR);
+ op1 = int_const_binop (reverse_op, val, op1);
+ if (TREE_OVERFLOW (op1))
+ op1 = drop_tree_overflow (op1);
+ register_new_assert_for (op0, op0, comp_code, op1, NULL, e, bsi);
+ }
+ }
+
/* Add asserts for NAME cmp CST and NAME being defined
as NAME = (int) NAME2. */
if (!TYPE_UNSIGNED (TREE_TYPE (val))