Commit 119092c1 by Richard Biener Committed by Richard Biener

tree-vrp.c (assert_info): New struct.

2017-04-28  Richard Biener  <rguenther@suse.de>

	* tree-vrp.c (assert_info): New struct.
	(add_assert_info): New helper.
	(register_edge_assert_for_2): Refactor to add asserts to a vector
	of assert_info.
	(register_edge_assert_for_1): Likewise.
	(register_edge_assert_for): Likewise.
	(finish_register_edge_assert_for): New helper actually registering
	asserts where live on edge.
	(find_conditional_asserts): Adjust.
	(find_switch_asserts): Likewise.
	(evrp_dom_walker::try_find_new_range): Generalize.
	(evrp_dom_walker::before_dom_children): Use register_edge_assert_for.

	* gcc.dg/tree-ssa/evrp7.c: New testcase.
	* gcc.dg/tree-ssa/evrp8.c: Likewise.
	* gcc.dg/tree-ssa/evrp9.c: Likewise.
	* gcc.dg/tree-ssa/vrp35.c: Disable EVRP.
	* gcc.dg/tree-ssa/vrp36.c: Likewise.
	* gcc.dg/tree-ssa/pr49039.c: Likewise.

From-SVN: r247362
parent e223180e
2017-04-28 Richard Biener <rguenther@suse.de>
* tree-vrp.c (assert_info): New struct.
(add_assert_info): New helper.
(register_edge_assert_for_2): Refactor to add asserts to a vector
of assert_info.
(register_edge_assert_for_1): Likewise.
(register_edge_assert_for): Likewise.
(finish_register_edge_assert_for): New helper actually registering
asserts where live on edge.
(find_conditional_asserts): Adjust.
(find_switch_asserts): Likewise.
(evrp_dom_walker::try_find_new_range): Generalize.
(evrp_dom_walker::before_dom_children): Use register_edge_assert_for.
2017-04-27 Marek Polacek <polacek@redhat.com> 2017-04-27 Marek Polacek <polacek@redhat.com>
PR sanitizer/80349 PR sanitizer/80349
......
2017-04-28 Richard Biener <rguenther@suse.de>
* gcc.dg/tree-ssa/evrp7.c: New testcase.
* gcc.dg/tree-ssa/evrp8.c: Likewise.
* gcc.dg/tree-ssa/evrp9.c: Likewise.
* gcc.dg/tree-ssa/vrp35.c: Disable EVRP.
* gcc.dg/tree-ssa/vrp36.c: Likewise.
* gcc.dg/tree-ssa/pr49039.c: Likewise.
2017-04-27 Marek Polacek <polacek@redhat.com> 2017-04-27 Marek Polacek <polacek@redhat.com>
PR sanitizer/80349 PR sanitizer/80349
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-evrp-details" } */
int test1(int i, int k)
{
if (i > 0 && i <= 5 && k >= 10 && k < 42)
{
int j = i + 1 + k;
return j == 10;
}
return 1;
}
/* { dg-final { scan-tree-dump "Removing dead stmt \[^\r\n\]* = j_.* == 10" "evrp" } } */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-evrp-details" } */
int foo(int i)
{
if (i < 0 || i >= 5)
return i == 1;
return 1;
}
/* { dg-final { scan-tree-dump "Removing dead stmt \[^\r\n\]* = i_.* == 1" "evrp" } } */
/* PR tree-optimization/49039 */
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-evrp" } */
extern void bar (void);
void
foo (unsigned int x, unsigned int y)
{
unsigned int minv, maxv;
if (x >= 3 && x <= 6)
return;
if (y >= 5 && y <= 8)
return;
minv = x < y ? x : y;
maxv = x > y ? x : y;
if (minv == 5)
bar ();
if (minv == 6)
bar ();
if (maxv == 5)
bar ();
if (maxv == 6)
bar ();
}
/* { dg-final { scan-tree-dump-not "== 5" "evrp" } } */
/* { dg-final { scan-tree-dump-not "== 6" "evrp" } } */
/* PR tree-optimization/49039 */ /* PR tree-optimization/49039 */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-vrp1" } */ /* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-vrp1" } */
extern void bar (void); extern void bar (void);
......
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-vrp1-details" } */ /* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-vrp1-details" } */
int test1(int i, int k) int test1(int i, int k)
{ {
......
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-vrp1-details" } */ /* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-vrp1-details" } */
int foo(int i) int foo(int i)
{ {
......
...@@ -89,6 +89,21 @@ static tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code, ...@@ -89,6 +89,21 @@ static tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code,
tree, tree, bool, bool *, tree, tree, bool, bool *,
bool *); bool *);
struct assert_info
{
/* Predicate code for the ASSERT_EXPR. Must be COMPARISON_CLASS_P. */
enum tree_code comp_code;
/* Name to register the assert for. */
tree name;
/* Value being compared against. */
tree val;
/* Expression to compare. */
tree expr;
};
/* Location information for ASSERT_EXPRs. Each instance of this /* Location information for ASSERT_EXPRs. Each instance of this
structure describes an ASSERT_EXPR for an SSA name. Since a single structure describes an ASSERT_EXPR for an SSA name. Since a single
SSA name may have more than one assertion associated with it, these SSA name may have more than one assertion associated with it, these
...@@ -5029,6 +5044,19 @@ debug_all_asserts (void) ...@@ -5029,6 +5044,19 @@ debug_all_asserts (void)
dump_all_asserts (stderr); dump_all_asserts (stderr);
} }
/* Push the assert info for NAME, EXPR, COMP_CODE and VAL to ASSERTS. */
static void
add_assert_info (vec<assert_info> &asserts,
tree name, tree expr, enum tree_code comp_code, tree val)
{
assert_info info;
info.comp_code = comp_code;
info.name = name;
info.val = val;
info.expr = expr;
asserts.safe_push (info);
}
/* If NAME doesn't have an ASSERT_EXPR registered for asserting /* If NAME doesn't have an ASSERT_EXPR registered for asserting
'EXPR COMP_CODE VAL' at a location that dominates block BB or 'EXPR COMP_CODE VAL' at a location that dominates block BB or
...@@ -5357,9 +5385,10 @@ overflow_comparison_p (tree_code code, tree name, tree val, ...@@ -5357,9 +5385,10 @@ overflow_comparison_p (tree_code code, tree name, tree val,
Invert the condition COND if INVERT is true. */ Invert the condition COND if INVERT is true. */
static void static void
register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, register_edge_assert_for_2 (tree name, edge e,
enum tree_code cond_code, enum tree_code cond_code,
tree cond_op0, tree cond_op1, bool invert) tree cond_op0, tree cond_op1, bool invert,
vec<assert_info> &asserts)
{ {
tree val; tree val;
enum tree_code comp_code; enum tree_code comp_code;
...@@ -5370,20 +5399,15 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -5370,20 +5399,15 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
invert, &comp_code, &val)) invert, &comp_code, &val))
return; return;
/* Only register an ASSERT_EXPR if NAME was found in the sub-graph /* Queue the assert. */
reachable from E. */ tree x;
if (live_on_edge (e, name)) if (overflow_comparison_p (comp_code, name, val, false, &x))
{ {
tree x; enum tree_code new_code = ((comp_code == GT_EXPR || comp_code == GE_EXPR)
if (overflow_comparison_p (comp_code, name, val, false, &x)) ? GT_EXPR : LE_EXPR);
{ add_assert_info (asserts, name, name, new_code, x);
enum tree_code new_code
= ((comp_code == GT_EXPR || comp_code == GE_EXPR)
? GT_EXPR : LE_EXPR);
register_new_assert_for (name, name, new_code, x, NULL, e, bsi);
}
register_new_assert_for (name, name, comp_code, val, NULL, e, bsi);
} }
add_assert_info (asserts, name, name, comp_code, val);
/* In the case of NAME <= CST and NAME being defined as /* In the case of NAME <= CST and NAME being defined as
NAME = (unsigned) NAME2 + CST2 we can assert NAME2 >= -CST2 NAME = (unsigned) NAME2 + CST2 we can assert NAME2 >= -CST2
...@@ -5423,8 +5447,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -5423,8 +5447,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
&& TREE_CODE (name3) == SSA_NAME && TREE_CODE (name3) == SSA_NAME
&& (cst2 == NULL_TREE && (cst2 == NULL_TREE
|| TREE_CODE (cst2) == INTEGER_CST) || TREE_CODE (cst2) == INTEGER_CST)
&& INTEGRAL_TYPE_P (TREE_TYPE (name3)) && INTEGRAL_TYPE_P (TREE_TYPE (name3)))
&& live_on_edge (e, name3))
{ {
tree tmp; tree tmp;
...@@ -5442,15 +5465,14 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -5442,15 +5465,14 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
fprintf (dump_file, "\n"); fprintf (dump_file, "\n");
} }
register_new_assert_for (name3, tmp, comp_code, val, NULL, e, bsi); add_assert_info (asserts, name3, tmp, comp_code, val);
} }
/* If name2 is used later, create an ASSERT_EXPR for it. */ /* If name2 is used later, create an ASSERT_EXPR for it. */
if (name2 != NULL_TREE if (name2 != NULL_TREE
&& TREE_CODE (name2) == SSA_NAME && TREE_CODE (name2) == SSA_NAME
&& TREE_CODE (cst2) == INTEGER_CST && TREE_CODE (cst2) == INTEGER_CST
&& INTEGRAL_TYPE_P (TREE_TYPE (name2)) && INTEGRAL_TYPE_P (TREE_TYPE (name2)))
&& live_on_edge (e, name2))
{ {
tree tmp; tree tmp;
...@@ -5470,7 +5492,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -5470,7 +5492,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
fprintf (dump_file, "\n"); fprintf (dump_file, "\n");
} }
register_new_assert_for (name2, tmp, comp_code, val, NULL, e, bsi); add_assert_info (asserts, name2, tmp, comp_code, val);
} }
} }
...@@ -5496,8 +5518,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -5496,8 +5518,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
continue; continue;
tree name2 = gimple_assign_lhs (use_stmt); tree name2 = gimple_assign_lhs (use_stmt);
if (TREE_CODE (name2) != SSA_NAME if (TREE_CODE (name2) != SSA_NAME)
|| !live_on_edge (e, name2))
continue; continue;
enum tree_code code = gimple_assign_rhs_code (use_stmt); enum tree_code code = gimple_assign_rhs_code (use_stmt);
...@@ -5525,8 +5546,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -5525,8 +5546,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
if (TREE_OVERFLOW_P (cst)) if (TREE_OVERFLOW_P (cst))
cst = drop_tree_overflow (cst); cst = drop_tree_overflow (cst);
register_new_assert_for (name2, name2, comp_code, cst, add_assert_info (asserts, name2, name2, comp_code, cst);
NULL, e, bsi);
} }
} }
...@@ -5552,15 +5572,14 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -5552,15 +5572,14 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
tree op0 = gimple_assign_rhs1 (def_stmt); tree op0 = gimple_assign_rhs1 (def_stmt);
tree op1 = gimple_assign_rhs2 (def_stmt); tree op1 = gimple_assign_rhs2 (def_stmt);
if (TREE_CODE (op0) == SSA_NAME if (TREE_CODE (op0) == SSA_NAME
&& TREE_CODE (op1) == INTEGER_CST && TREE_CODE (op1) == INTEGER_CST)
&& live_on_edge (e, op0))
{ {
enum tree_code reverse_op = (rhs_code == PLUS_EXPR enum tree_code reverse_op = (rhs_code == PLUS_EXPR
? MINUS_EXPR : PLUS_EXPR); ? MINUS_EXPR : PLUS_EXPR);
op1 = int_const_binop (reverse_op, val, op1); op1 = int_const_binop (reverse_op, val, op1);
if (TREE_OVERFLOW (op1)) if (TREE_OVERFLOW (op1))
op1 = drop_tree_overflow (op1); op1 = drop_tree_overflow (op1);
register_new_assert_for (op0, op0, comp_code, op1, NULL, e, bsi); add_assert_info (asserts, op0, op0, comp_code, op1);
} }
} }
...@@ -5578,8 +5597,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -5578,8 +5597,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
&& prec == TYPE_PRECISION (TREE_TYPE (name2)) && prec == TYPE_PRECISION (TREE_TYPE (name2))
&& (comp_code == LE_EXPR || comp_code == GT_EXPR && (comp_code == LE_EXPR || comp_code == GT_EXPR
|| !tree_int_cst_equal (val, || !tree_int_cst_equal (val,
TYPE_MIN_VALUE (TREE_TYPE (val)))) TYPE_MIN_VALUE (TREE_TYPE (val)))))
&& live_on_edge (e, name2))
{ {
tree tmp, cst; tree tmp, cst;
enum tree_code new_comp_code = comp_code; enum tree_code new_comp_code = comp_code;
...@@ -5606,8 +5624,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -5606,8 +5624,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
fprintf (dump_file, "\n"); fprintf (dump_file, "\n");
} }
register_new_assert_for (name2, tmp, new_comp_code, cst, NULL, add_assert_info (asserts, name2, tmp, new_comp_code, cst);
e, bsi);
} }
} }
...@@ -5623,8 +5640,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -5623,8 +5640,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
&& tree_fits_uhwi_p (cst2) && tree_fits_uhwi_p (cst2)
&& INTEGRAL_TYPE_P (TREE_TYPE (name2)) && INTEGRAL_TYPE_P (TREE_TYPE (name2))
&& IN_RANGE (tree_to_uhwi (cst2), 1, prec - 1) && IN_RANGE (tree_to_uhwi (cst2), 1, prec - 1)
&& prec == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (val))) && prec == GET_MODE_PRECISION (TYPE_MODE (TREE_TYPE (val))))
&& live_on_edge (e, name2))
{ {
mask = wi::mask (tree_to_uhwi (cst2), false, prec); mask = wi::mask (tree_to_uhwi (cst2), false, prec);
val2 = fold_binary (LSHIFT_EXPR, TREE_TYPE (val), val, cst2); val2 = fold_binary (LSHIFT_EXPR, TREE_TYPE (val), val, cst2);
...@@ -5682,8 +5698,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -5682,8 +5698,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
fprintf (dump_file, "\n"); fprintf (dump_file, "\n");
} }
register_new_assert_for (name2, tmp, new_comp_code, new_val, add_assert_info (asserts, name2, tmp, new_comp_code, new_val);
NULL, e, bsi);
} }
} }
...@@ -5728,12 +5743,10 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -5728,12 +5743,10 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
if (!CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt2)) if (!CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (def_stmt2))
|| !INTEGRAL_TYPE_P (TREE_TYPE (names[1])) || !INTEGRAL_TYPE_P (TREE_TYPE (names[1]))
|| (TYPE_PRECISION (TREE_TYPE (name2)) || (TYPE_PRECISION (TREE_TYPE (name2))
!= TYPE_PRECISION (TREE_TYPE (names[1]))) != TYPE_PRECISION (TREE_TYPE (names[1]))))
|| !live_on_edge (e, names[1]))
names[1] = NULL_TREE; names[1] = NULL_TREE;
} }
if (live_on_edge (e, name2)) names[0] = name2;
names[0] = name2;
} }
} }
if (names[0] || names[1]) if (names[0] || names[1])
...@@ -5924,8 +5937,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -5924,8 +5937,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
fprintf (dump_file, "\n"); fprintf (dump_file, "\n");
} }
register_new_assert_for (names[i], tmp, LE_EXPR, add_assert_info (asserts, names[i], tmp, LE_EXPR, new_val);
new_val, NULL, e, bsi);
} }
} }
} }
...@@ -5941,7 +5953,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi, ...@@ -5941,7 +5953,7 @@ register_edge_assert_for_2 (tree name, edge e, gimple_stmt_iterator bsi,
static void static void
register_edge_assert_for_1 (tree op, enum tree_code code, register_edge_assert_for_1 (tree op, enum tree_code code,
edge e, gimple_stmt_iterator bsi) edge e, vec<assert_info> &asserts)
{ {
gimple *op_def; gimple *op_def;
tree val; tree val;
...@@ -5951,13 +5963,9 @@ register_edge_assert_for_1 (tree op, enum tree_code code, ...@@ -5951,13 +5963,9 @@ register_edge_assert_for_1 (tree op, enum tree_code code,
if (TREE_CODE (op) != SSA_NAME) if (TREE_CODE (op) != SSA_NAME)
return; return;
/* We know that OP will have a zero or nonzero value. If OP is used /* We know that OP will have a zero or nonzero value. */
more than once go ahead and register an assert for OP. */ val = build_int_cst (TREE_TYPE (op), 0);
if (live_on_edge (e, op)) add_assert_info (asserts, op, op, code, val);
{
val = build_int_cst (TREE_TYPE (op), 0);
register_new_assert_for (op, op, code, val, NULL, e, bsi);
}
/* Now look at how OP is set. If it's set from a comparison, /* Now look at how OP is set. If it's set from a comparison,
a truth operation or some bit operations, then we may be able a truth operation or some bit operations, then we may be able
...@@ -5975,9 +5983,9 @@ register_edge_assert_for_1 (tree op, enum tree_code code, ...@@ -5975,9 +5983,9 @@ register_edge_assert_for_1 (tree op, enum tree_code code,
tree op1 = gimple_assign_rhs2 (op_def); tree op1 = gimple_assign_rhs2 (op_def);
if (TREE_CODE (op0) == SSA_NAME) if (TREE_CODE (op0) == SSA_NAME)
register_edge_assert_for_2 (op0, e, bsi, rhs_code, op0, op1, invert); register_edge_assert_for_2 (op0, e, rhs_code, op0, op1, invert, asserts);
if (TREE_CODE (op1) == SSA_NAME) if (TREE_CODE (op1) == SSA_NAME)
register_edge_assert_for_2 (op1, e, bsi, rhs_code, op0, op1, invert); register_edge_assert_for_2 (op1, e, rhs_code, op0, op1, invert, asserts);
} }
else if ((code == NE_EXPR else if ((code == NE_EXPR
&& gimple_assign_rhs_code (op_def) == BIT_AND_EXPR) && gimple_assign_rhs_code (op_def) == BIT_AND_EXPR)
...@@ -5989,22 +5997,22 @@ register_edge_assert_for_1 (tree op, enum tree_code code, ...@@ -5989,22 +5997,22 @@ register_edge_assert_for_1 (tree op, enum tree_code code,
tree op1 = gimple_assign_rhs2 (op_def); tree op1 = gimple_assign_rhs2 (op_def);
if (TREE_CODE (op0) == SSA_NAME if (TREE_CODE (op0) == SSA_NAME
&& has_single_use (op0)) && has_single_use (op0))
register_edge_assert_for_1 (op0, code, e, bsi); register_edge_assert_for_1 (op0, code, e, asserts);
if (TREE_CODE (op1) == SSA_NAME if (TREE_CODE (op1) == SSA_NAME
&& has_single_use (op1)) && has_single_use (op1))
register_edge_assert_for_1 (op1, code, e, bsi); register_edge_assert_for_1 (op1, code, e, asserts);
} }
else if (gimple_assign_rhs_code (op_def) == BIT_NOT_EXPR else if (gimple_assign_rhs_code (op_def) == BIT_NOT_EXPR
&& TYPE_PRECISION (TREE_TYPE (gimple_assign_lhs (op_def))) == 1) && TYPE_PRECISION (TREE_TYPE (gimple_assign_lhs (op_def))) == 1)
{ {
/* Recurse, flipping CODE. */ /* Recurse, flipping CODE. */
code = invert_tree_comparison (code, false); code = invert_tree_comparison (code, false);
register_edge_assert_for_1 (gimple_assign_rhs1 (op_def), code, e, bsi); register_edge_assert_for_1 (gimple_assign_rhs1 (op_def), code, e, asserts);
} }
else if (gimple_assign_rhs_code (op_def) == SSA_NAME) else if (gimple_assign_rhs_code (op_def) == SSA_NAME)
{ {
/* Recurse through the copy. */ /* Recurse through the copy. */
register_edge_assert_for_1 (gimple_assign_rhs1 (op_def), code, e, bsi); register_edge_assert_for_1 (gimple_assign_rhs1 (op_def), code, e, asserts);
} }
else if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (op_def))) else if (CONVERT_EXPR_CODE_P (gimple_assign_rhs_code (op_def)))
{ {
...@@ -6014,7 +6022,7 @@ register_edge_assert_for_1 (tree op, enum tree_code code, ...@@ -6014,7 +6022,7 @@ register_edge_assert_for_1 (tree op, enum tree_code code,
if (INTEGRAL_TYPE_P (TREE_TYPE (rhs)) if (INTEGRAL_TYPE_P (TREE_TYPE (rhs))
&& (TYPE_PRECISION (TREE_TYPE (rhs)) && (TYPE_PRECISION (TREE_TYPE (rhs))
<= TYPE_PRECISION (TREE_TYPE (op)))) <= TYPE_PRECISION (TREE_TYPE (op))))
register_edge_assert_for_1 (rhs, code, e, bsi); register_edge_assert_for_1 (rhs, code, e, asserts);
} }
} }
...@@ -6023,9 +6031,9 @@ register_edge_assert_for_1 (tree op, enum tree_code code, ...@@ -6023,9 +6031,9 @@ register_edge_assert_for_1 (tree op, enum tree_code code,
SI. */ SI. */
static void static void
register_edge_assert_for (tree name, edge e, gimple_stmt_iterator si, register_edge_assert_for (tree name, edge e,
enum tree_code cond_code, tree cond_op0, enum tree_code cond_code, tree cond_op0,
tree cond_op1) tree cond_op1, vec<assert_info> &asserts)
{ {
tree val; tree val;
enum tree_code comp_code; enum tree_code comp_code;
...@@ -6043,8 +6051,8 @@ register_edge_assert_for (tree name, edge e, gimple_stmt_iterator si, ...@@ -6043,8 +6051,8 @@ register_edge_assert_for (tree name, edge e, gimple_stmt_iterator si,
return; return;
/* Register ASSERT_EXPRs for name. */ /* Register ASSERT_EXPRs for name. */
register_edge_assert_for_2 (name, e, si, cond_code, cond_op0, register_edge_assert_for_2 (name, e, cond_code, cond_op0,
cond_op1, is_else_edge); cond_op1, is_else_edge, asserts);
/* If COND is effectively an equality test of an SSA_NAME against /* If COND is effectively an equality test of an SSA_NAME against
...@@ -6064,8 +6072,8 @@ register_edge_assert_for (tree name, edge e, gimple_stmt_iterator si, ...@@ -6064,8 +6072,8 @@ register_edge_assert_for (tree name, edge e, gimple_stmt_iterator si,
{ {
tree op0 = gimple_assign_rhs1 (def_stmt); tree op0 = gimple_assign_rhs1 (def_stmt);
tree op1 = gimple_assign_rhs2 (def_stmt); tree op1 = gimple_assign_rhs2 (def_stmt);
register_edge_assert_for_1 (op0, NE_EXPR, e, si); register_edge_assert_for_1 (op0, NE_EXPR, e, asserts);
register_edge_assert_for_1 (op1, NE_EXPR, e, si); register_edge_assert_for_1 (op1, NE_EXPR, e, asserts);
} }
} }
...@@ -6086,12 +6094,28 @@ register_edge_assert_for (tree name, edge e, gimple_stmt_iterator si, ...@@ -6086,12 +6094,28 @@ register_edge_assert_for (tree name, edge e, gimple_stmt_iterator si,
{ {
tree op0 = gimple_assign_rhs1 (def_stmt); tree op0 = gimple_assign_rhs1 (def_stmt);
tree op1 = gimple_assign_rhs2 (def_stmt); tree op1 = gimple_assign_rhs2 (def_stmt);
register_edge_assert_for_1 (op0, EQ_EXPR, e, si); register_edge_assert_for_1 (op0, EQ_EXPR, e, asserts);
register_edge_assert_for_1 (op1, EQ_EXPR, e, si); register_edge_assert_for_1 (op1, EQ_EXPR, e, asserts);
} }
} }
} }
/* Finish found ASSERTS for E and register them at GSI. */
static void
finish_register_edge_assert_for (edge e, gimple_stmt_iterator gsi,
vec<assert_info> &asserts)
{
for (unsigned i = 0; i < asserts.length (); ++i)
/* Only register an ASSERT_EXPR if NAME was found in the sub-graph
reachable from E. */
if (live_on_edge (e, asserts[i].name))
register_new_assert_for (asserts[i].name, asserts[i].expr,
asserts[i].comp_code, asserts[i].val,
NULL, e, gsi);
}
/* Determine whether the outgoing edges of BB should receive an /* Determine whether the outgoing edges of BB should receive an
ASSERT_EXPR for each of the operands of BB's LAST statement. ASSERT_EXPR for each of the operands of BB's LAST statement.
...@@ -6123,11 +6147,13 @@ find_conditional_asserts (basic_block bb, gcond *last) ...@@ -6123,11 +6147,13 @@ find_conditional_asserts (basic_block bb, gcond *last)
/* Register the necessary assertions for each operand in the /* Register the necessary assertions for each operand in the
conditional predicate. */ conditional predicate. */
auto_vec<assert_info, 8> asserts;
FOR_EACH_SSA_TREE_OPERAND (op, last, iter, SSA_OP_USE) FOR_EACH_SSA_TREE_OPERAND (op, last, iter, SSA_OP_USE)
register_edge_assert_for (op, e, bsi, register_edge_assert_for (op, e,
gimple_cond_code (last), gimple_cond_code (last),
gimple_cond_lhs (last), gimple_cond_lhs (last),
gimple_cond_rhs (last)); gimple_cond_rhs (last), asserts);
finish_register_edge_assert_for (e, bsi, asserts);
} }
} }
...@@ -6239,12 +6265,16 @@ find_switch_asserts (basic_block bb, gswitch *last) ...@@ -6239,12 +6265,16 @@ find_switch_asserts (basic_block bb, gswitch *last)
/* Register the necessary assertions for the operand in the /* Register the necessary assertions for the operand in the
SWITCH_EXPR. */ SWITCH_EXPR. */
register_edge_assert_for (op, e, bsi, auto_vec<assert_info, 8> asserts;
register_edge_assert_for (op, e,
max ? GE_EXPR : EQ_EXPR, max ? GE_EXPR : EQ_EXPR,
op, fold_convert (TREE_TYPE (op), min)); op, fold_convert (TREE_TYPE (op), min),
asserts);
if (max) if (max)
register_edge_assert_for (op, e, bsi, LE_EXPR, op, register_edge_assert_for (op, e, LE_EXPR, op,
fold_convert (TREE_TYPE (op), max)); fold_convert (TREE_TYPE (op), max),
asserts);
finish_register_edge_assert_for (e, bsi, asserts);
} }
XDELETEVEC (ci); XDELETEVEC (ci);
...@@ -6293,8 +6323,11 @@ find_switch_asserts (basic_block bb, gswitch *last) ...@@ -6293,8 +6323,11 @@ find_switch_asserts (basic_block bb, gswitch *last)
if (max == NULL_TREE) if (max == NULL_TREE)
{ {
/* Register the assertion OP != MIN. */ /* Register the assertion OP != MIN. */
auto_vec<assert_info, 8> asserts;
min = fold_convert (TREE_TYPE (op), min); min = fold_convert (TREE_TYPE (op), min);
register_edge_assert_for (op, default_edge, bsi, NE_EXPR, op, min); register_edge_assert_for (op, default_edge, NE_EXPR, op, min,
asserts);
finish_register_edge_assert_for (default_edge, bsi, asserts);
} }
else else
{ {
...@@ -11160,7 +11193,7 @@ public: ...@@ -11160,7 +11193,7 @@ public:
virtual void after_dom_children (basic_block); virtual void after_dom_children (basic_block);
void push_value_range (tree var, value_range *vr); void push_value_range (tree var, value_range *vr);
value_range *pop_value_range (tree var); value_range *pop_value_range (tree var);
value_range *try_find_new_range (tree op, tree_code code, tree limit); value_range *try_find_new_range (tree, tree op, tree_code code, tree limit);
/* Cond_stack holds the old VR. */ /* Cond_stack holds the old VR. */
auto_vec<std::pair <tree, value_range*> > stack; auto_vec<std::pair <tree, value_range*> > stack;
...@@ -11169,19 +11202,18 @@ public: ...@@ -11169,19 +11202,18 @@ public:
auto_vec<gimple *> stmts_to_remove; auto_vec<gimple *> stmts_to_remove;
}; };
/* Find new range for OP such that (OP CODE LIMIT) is true. */ /* Find new range for NAME such that (OP CODE LIMIT) is true. */
value_range * value_range *
evrp_dom_walker::try_find_new_range (tree op, tree_code code, tree limit) evrp_dom_walker::try_find_new_range (tree name,
tree op, tree_code code, tree limit)
{ {
value_range vr = VR_INITIALIZER; value_range vr = VR_INITIALIZER;
value_range *old_vr = get_value_range (op); value_range *old_vr = get_value_range (name);
/* Discover VR when condition is true. */ /* Discover VR when condition is true. */
extract_range_for_var_from_comparison_expr (op, code, op, extract_range_for_var_from_comparison_expr (name, code, op,
limit, &vr); limit, &vr);
if (old_vr->type == VR_RANGE || old_vr->type == VR_ANTI_RANGE)
vrp_intersect_ranges (&vr, old_vr);
/* If we found any usable VR, set the VR to ssa_name and create a /* If we found any usable VR, set the VR to ssa_name and create a
PUSH old value in the stack with the old VR. */ PUSH old value in the stack with the old VR. */
if (vr.type == VR_RANGE || vr.type == VR_ANTI_RANGE) if (vr.type == VR_RANGE || vr.type == VR_ANTI_RANGE)
...@@ -11245,36 +11277,29 @@ evrp_dom_walker::before_dom_children (basic_block bb) ...@@ -11245,36 +11277,29 @@ evrp_dom_walker::before_dom_children (basic_block bb)
/* Entering a new scope. Try to see if we can find a VR /* Entering a new scope. Try to see if we can find a VR
here. */ here. */
tree op1 = gimple_cond_rhs (stmt); tree op1 = gimple_cond_rhs (stmt);
tree_code code = gimple_cond_code (stmt);
if (TREE_OVERFLOW_P (op1)) if (TREE_OVERFLOW_P (op1))
op1 = drop_tree_overflow (op1); op1 = drop_tree_overflow (op1);
tree_code code = gimple_cond_code (stmt);
/* If condition is false, invert the cond. */ auto_vec<assert_info, 8> asserts;
if (pred_e->flags & EDGE_FALSE_VALUE) register_edge_assert_for (op0, pred_e, code, op0, op1, asserts);
code = invert_tree_comparison (gimple_cond_code (stmt), if (TREE_CODE (op1) == SSA_NAME)
HONOR_NANS (op0)); register_edge_assert_for (op1, pred_e, code, op0, op1, asserts);
/* Add VR when (OP0 CODE OP1) condition is true. */
value_range *op0_range = try_find_new_range (op0, code, op1); auto_vec<std::pair<tree, value_range *>, 8> vrs;
for (unsigned i = 0; i < asserts.length (); ++i)
/* Register ranges for y in x < y where
y might have ranges that are useful. */
tree limit;
tree_code new_code;
if (TREE_CODE (op1) == SSA_NAME
&& extract_code_and_val_from_cond_with_ops (op1, code,
op0, op1,
false,
&new_code, &limit))
{ {
/* Add VR when (OP1 NEW_CODE LIMIT) condition is true. */ value_range *vr = try_find_new_range (asserts[i].name,
value_range *op1_range = try_find_new_range (op1, new_code, limit); asserts[i].expr,
if (op1_range) asserts[i].comp_code,
push_value_range (op1, op1_range); asserts[i].val);
if (vr)
vrs.safe_push (std::make_pair (asserts[i].name, vr));
} }
/* Push updated ranges only after finding all of them to avoid
if (op0_range) ordering issues that can lead to worse ranges. */
push_value_range (op0, op0_range); for (unsigned i = 0; i < vrs.length (); ++i)
push_value_range (vrs[i].first, vrs[i].second);
} }
} }
...@@ -11462,13 +11487,13 @@ evrp_dom_walker::before_dom_children (basic_block bb) ...@@ -11462,13 +11487,13 @@ evrp_dom_walker::before_dom_children (basic_block bb)
/* Add VR when (T COMP_CODE value) condition is /* Add VR when (T COMP_CODE value) condition is
true. */ true. */
value_range *op_range value_range *op_range
= try_find_new_range (t, comp_code, value); = try_find_new_range (t, t, comp_code, value);
if (op_range) if (op_range)
push_value_range (t, op_range); push_value_range (t, op_range);
} }
} }
/* Add VR when (OP COMP_CODE value) condition is true. */ /* Add VR when (OP COMP_CODE value) condition is true. */
value_range *op_range = try_find_new_range (op, value_range *op_range = try_find_new_range (op, op,
comp_code, value); comp_code, value);
if (op_range) if (op_range)
push_value_range (op, op_range); push_value_range (op, op_range);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment