Commit 4280df0a by Richard Biener Committed by Richard Biener

tree-vrp.c (evrp_dom_walker::before_dom_children): Call infer_value_range on…

tree-vrp.c (evrp_dom_walker::before_dom_children): Call infer_value_range on stmt ops and update value-ranges.

2016-11-02  Richard Biener  <rguenther@suse.de>

	* tree-vrp.c (evrp_dom_walker::before_dom_children): Call
	infer_value_range on stmt ops and update value-ranges.
	Dump visited stmts and blocks.
	(evrp_dom_walker::push_value_range): Dump changes.
	(evrp_dom_walker::pop_value_range): Likewise.
	(evrp_dom_walker::try_find_new_range): Avoid noop changes.

	* gcc.dg/tree-ssa/vrp111.c: New testcase.
	* gcc.dg/tree-ssa/pr20702.c: Disable EVRP.
	* gcc.dg/tree-ssa/pr21086.c: Likewise.
	* gcc.dg/tree-ssa/pr58480.c: Likewise.
	* gcc.dg/tree-ssa/vrp08.c: Likewise.

From-SVN: r241774
parent 9815687d
2016-11-02 Richard Biener <rguenther@suse.de>
* tree-vrp.c (evrp_dom_walker::before_dom_children): Call
infer_value_range on stmt ops and update value-ranges.
Dump visited stmts and blocks.
(evrp_dom_walker::push_value_range): Dump changes.
(evrp_dom_walker::pop_value_range): Likewise.
(evrp_dom_walker::try_find_new_range): Avoid noop changes.
2016-11-01 Trevor Saunders <tbsaunde+gcc@tbsaunde.org> 2016-11-01 Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
* emit-rtl.c (prev_nonnote_insn_bb): Change argument type to * emit-rtl.c (prev_nonnote_insn_bb): Change argument type to
2016-11-02 Richard Biener <rguenther@suse.de>
* gcc.dg/tree-ssa/vrp111.c: New testcase.
* gcc.dg/tree-ssa/pr20702.c: Disable EVRP.
* gcc.dg/tree-ssa/pr21086.c: Likewise.
* gcc.dg/tree-ssa/pr58480.c: Likewise.
* gcc.dg/tree-ssa/vrp08.c: Likewise.
2016-11-01 David Edelsohn <dje.gcc@gmail.com> 2016-11-01 David Edelsohn <dje.gcc@gmail.com>
* gfortran.dg/pr70937.f90: require-effective-target lto. * gfortran.dg/pr70937.f90: require-effective-target lto.
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
immediate successors of the basic block. */ immediate successors of the basic block. */
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp1-details -fdelete-null-pointer-checks" } */ /* { dg-options "-O2 -fno-tree-dominator-opts -fdisable-tree-evrp -fdump-tree-vrp1-details -fdelete-null-pointer-checks" } */
extern void bar (int); extern void bar (int);
......
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-dce2 -fdelete-null-pointer-checks" } */ /* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-vrp1 -fdump-tree-dce2 -fdelete-null-pointer-checks" } */
int int
foo (int *p) foo (int *p)
......
/* { dg-do compile { target { ! keeps_null_pointer_checks } } } */ /* { dg-do compile { target { ! keeps_null_pointer_checks } } } */
/* { dg-options "-O2 -fdump-tree-vrp1 -fdelete-null-pointer-checks" } */ /* { dg-options "-O2 -fdisable-tree-evrp -fdump-tree-vrp1 -fdelete-null-pointer-checks" } */
extern void eliminate (void); extern void eliminate (void);
extern void* f1 (void *a, void *b) __attribute__((nonnull)); extern void* f1 (void *a, void *b) __attribute__((nonnull));
......
/* { dg-do compile } */ /* { dg-do compile } */
/* { dg-options "-O2 -fno-tree-fre -fdump-tree-vrp1-details -fdelete-null-pointer-checks" } */ /* { dg-options "-O2 -fno-tree-fre -fdisable-tree-evrp -fdump-tree-vrp1-details -fdelete-null-pointer-checks" } */
/* Compile with -fno-tree-fre -O2 to prevent CSEing *p. */ /* Compile with -fno-tree-fre -O2 to prevent CSEing *p. */
int int
......
/* { dg-do compile } */
/* { dg-options "-O2 -fdump-tree-evrp" } */
void foo (void *p) __attribute__((nonnull(1)));
void bar (void *p)
{
foo (p);
if (!p)
__builtin_abort ();
}
/* { dg-final { scan-tree-dump-not "abort" "evrp" } } */
...@@ -10650,18 +10650,17 @@ public: ...@@ -10650,18 +10650,17 @@ public:
} }
virtual edge before_dom_children (basic_block); virtual edge before_dom_children (basic_block);
virtual void after_dom_children (basic_block); virtual void after_dom_children (basic_block);
void push_value_range (const_tree var, value_range *vr); void push_value_range (tree var, value_range *vr);
value_range *pop_value_range (const_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 op, tree_code code, tree limit);
/* Cond_stack holds the old VR. */ /* Cond_stack holds the old VR. */
auto_vec<std::pair <const_tree, value_range*> > stack; auto_vec<std::pair <tree, value_range*> > stack;
bitmap need_eh_cleanup; bitmap need_eh_cleanup;
auto_vec<gimple *> stmts_to_fixup; auto_vec<gimple *> stmts_to_fixup;
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 OP such that (OP CODE LIMIT) is true. */
value_range * value_range *
...@@ -10679,6 +10678,10 @@ evrp_dom_walker::try_find_new_range (tree op, tree_code code, tree limit) ...@@ -10679,6 +10678,10 @@ evrp_dom_walker::try_find_new_range (tree op, tree_code code, tree limit)
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)
{ {
if (old_vr->type == vr.type
&& vrp_operand_equal_p (old_vr->min, vr.min)
&& vrp_operand_equal_p (old_vr->max, vr.max))
return NULL;
value_range *new_vr = vrp_value_range_pool.allocate (); value_range *new_vr = vrp_value_range_pool.allocate ();
*new_vr = vr; *new_vr = vr;
return new_vr; return new_vr;
...@@ -10696,7 +10699,10 @@ evrp_dom_walker::before_dom_children (basic_block bb) ...@@ -10696,7 +10699,10 @@ evrp_dom_walker::before_dom_children (basic_block bb)
edge_iterator ei; edge_iterator ei;
edge e; edge e;
push_value_range (NULL_TREE, NULL); if (dump_file && (dump_flags & TDF_DETAILS))
fprintf (dump_file, "Visiting BB%d\n", bb->index);
stack.safe_push (std::make_pair (NULL_TREE, (value_range *)NULL));
edge pred_e = NULL; edge pred_e = NULL;
FOR_EACH_EDGE (e, ei, bb->preds) FOR_EACH_EDGE (e, ei, bb->preds)
...@@ -10723,6 +10729,11 @@ evrp_dom_walker::before_dom_children (basic_block bb) ...@@ -10723,6 +10729,11 @@ evrp_dom_walker::before_dom_children (basic_block bb)
&& (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt))) && (INTEGRAL_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))
|| POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt))))) || POINTER_TYPE_P (TREE_TYPE (gimple_cond_lhs (stmt)))))
{ {
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Visiting controlling predicate ");
print_gimple_stmt (dump_file, stmt, 0, 0);
}
/* 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);
...@@ -10778,6 +10789,11 @@ evrp_dom_walker::before_dom_children (basic_block bb) ...@@ -10778,6 +10789,11 @@ evrp_dom_walker::before_dom_children (basic_block bb)
continue; continue;
value_range vr_result = VR_INITIALIZER; value_range vr_result = VR_INITIALIZER;
bool interesting = stmt_interesting_for_vrp (phi); bool interesting = stmt_interesting_for_vrp (phi);
if (interesting && dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Visiting PHI node ");
print_gimple_stmt (dump_file, phi, 0, 0);
}
if (!has_unvisited_preds if (!has_unvisited_preds
&& interesting) && interesting)
extract_range_from_phi_node (phi, &vr_result); extract_range_from_phi_node (phi, &vr_result);
...@@ -10814,6 +10830,12 @@ evrp_dom_walker::before_dom_children (basic_block bb) ...@@ -10814,6 +10830,12 @@ evrp_dom_walker::before_dom_children (basic_block bb)
bool was_noreturn = (is_gimple_call (stmt) bool was_noreturn = (is_gimple_call (stmt)
&& gimple_call_noreturn_p (stmt)); && gimple_call_noreturn_p (stmt));
if (dump_file && (dump_flags & TDF_DETAILS))
{
fprintf (dump_file, "Visiting stmt ");
print_gimple_stmt (dump_file, stmt, 0, 0);
}
if (gcond *cond = dyn_cast <gcond *> (stmt)) if (gcond *cond = dyn_cast <gcond *> (stmt))
{ {
vrp_visit_cond_stmt (cond, &taken_edge); vrp_visit_cond_stmt (cond, &taken_edge);
...@@ -10825,6 +10847,7 @@ evrp_dom_walker::before_dom_children (basic_block bb) ...@@ -10825,6 +10847,7 @@ evrp_dom_walker::before_dom_children (basic_block bb)
gimple_cond_make_false (cond); gimple_cond_make_false (cond);
else else
gcc_unreachable (); gcc_unreachable ();
update_stmt (stmt);
} }
} }
else if (stmt_interesting_for_vrp (stmt)) else if (stmt_interesting_for_vrp (stmt))
...@@ -10873,6 +10896,55 @@ evrp_dom_walker::before_dom_children (basic_block bb) ...@@ -10873,6 +10896,55 @@ evrp_dom_walker::before_dom_children (basic_block bb)
else else
set_defs_to_varying (stmt); set_defs_to_varying (stmt);
/* See if we can derive a range for any of STMT's operands. */
tree op;
ssa_op_iter i;
FOR_EACH_SSA_TREE_OPERAND (op, stmt, i, SSA_OP_USE)
{
tree value;
enum tree_code comp_code;
/* If OP is used in such a way that we can infer a value
range for it, and we don't find a previous assertion for
it, create a new assertion location node for OP. */
if (infer_value_range (stmt, op, &comp_code, &value))
{
/* If we are able to infer a nonzero value range for OP,
then walk backwards through the use-def chain to see if OP
was set via a typecast.
If so, then we can also infer a nonzero value range
for the operand of the NOP_EXPR. */
if (comp_code == NE_EXPR && integer_zerop (value))
{
tree t = op;
gimple *def_stmt = SSA_NAME_DEF_STMT (t);
while (is_gimple_assign (def_stmt)
&& CONVERT_EXPR_CODE_P
(gimple_assign_rhs_code (def_stmt))
&& TREE_CODE
(gimple_assign_rhs1 (def_stmt)) == SSA_NAME
&& POINTER_TYPE_P
(TREE_TYPE (gimple_assign_rhs1 (def_stmt))))
{
t = gimple_assign_rhs1 (def_stmt);
def_stmt = SSA_NAME_DEF_STMT (t);
/* Add VR when (T COMP_CODE value) condition is
true. */
value_range *op_range
= try_find_new_range (t, comp_code, value);
if (op_range)
push_value_range (t, op_range);
}
}
/* Add VR when (OP COMP_CODE value) condition is true. */
value_range *op_range = try_find_new_range (op,
comp_code, value);
if (op_range)
push_value_range (op, op_range);
}
}
/* Try folding stmts with the VR discovered. */ /* Try folding stmts with the VR discovered. */
bool did_replace bool did_replace
= replace_uses_in (stmt, op_with_constant_singleton_value_range); = replace_uses_in (stmt, op_with_constant_singleton_value_range);
...@@ -10938,42 +11010,44 @@ evrp_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED) ...@@ -10938,42 +11010,44 @@ evrp_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED)
gcc_checking_assert (!stack.is_empty ()); gcc_checking_assert (!stack.is_empty ());
while (stack.last ().first != NULL_TREE) while (stack.last ().first != NULL_TREE)
pop_value_range (stack.last ().first); pop_value_range (stack.last ().first);
pop_value_range (stack.last ().first); stack.pop ();
} }
/* Push the Value Range of VAR to the stack and update it with new VR. */ /* Push the Value Range of VAR to the stack and update it with new VR. */
void void
evrp_dom_walker::push_value_range (const_tree var, value_range *vr) evrp_dom_walker::push_value_range (tree var, value_range *vr)
{ {
if (vr != NULL) if (SSA_NAME_VERSION (var) >= num_vr_values)
return;
if (dump_file && (dump_flags & TDF_DETAILS))
{ {
unsigned ver = SSA_NAME_VERSION (var); fprintf (dump_file, "pushing new range for ");
gcc_checking_assert (vr_value); print_generic_expr (dump_file, var, 0);
stack.safe_push (std::make_pair (var, vr_value[ver])); fprintf (dump_file, ": ");
dump_value_range (dump_file, vr);
if (ver < num_vr_values) fprintf (dump_file, "\n");
vr_value[ver] = vr;
} }
else stack.safe_push (std::make_pair (var, get_value_range (var)));
stack.safe_push (std::make_pair (var, vr)); vr_value[SSA_NAME_VERSION (var)] = vr;
} }
/* Pop the Value Range from the vrp_stack and update VAR with it. */ /* Pop the Value Range from the vrp_stack and update VAR with it. */
value_range * value_range *
evrp_dom_walker::pop_value_range (const_tree var) evrp_dom_walker::pop_value_range (tree var)
{ {
value_range *vr = stack.last ().second; value_range *vr = stack.last ().second;
if (vr != NULL) gcc_checking_assert (var == stack.last ().first);
if (dump_file && (dump_flags & TDF_DETAILS))
{ {
unsigned ver = SSA_NAME_VERSION (var); fprintf (dump_file, "popping range for ");
gcc_checking_assert (var == stack.last ().first); print_generic_expr (dump_file, var, 0);
gcc_checking_assert (vr_value); fprintf (dump_file, ", restoring ");
dump_value_range (dump_file, vr);
if (ver < num_vr_values) fprintf (dump_file, "\n");
vr_value[ver] = vr;
} }
vr_value[SSA_NAME_VERSION (var)] = vr;
stack.pop (); stack.pop ();
return vr; return vr;
} }
......
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