From 4280df0abc2d692924ab45dd95c6ef0dc61703ea Mon Sep 17 00:00:00 2001 From: Richard Biener Date: Wed, 2 Nov 2016 08:11:48 +0000 Subject: [PATCH] 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 * 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 --- gcc/ChangeLog | 9 ++ gcc/testsuite/ChangeLog | 8 ++ gcc/testsuite/gcc.dg/tree-ssa/pr20702.c | 2 +- gcc/testsuite/gcc.dg/tree-ssa/pr21086.c | 2 +- gcc/testsuite/gcc.dg/tree-ssa/pr58480.c | 2 +- gcc/testsuite/gcc.dg/tree-ssa/vrp08.c | 2 +- gcc/testsuite/gcc.dg/tree-ssa/vrp111.c | 13 +++ gcc/tree-vrp.c | 122 +++++++++++++++++++----- 8 files changed, 132 insertions(+), 28 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/vrp111.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 54465213392..163f5f68ffb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2016-11-02 Richard Biener + + * 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 * emit-rtl.c (prev_nonnote_insn_bb): Change argument type to diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 42b667d4279..20ef692bb19 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,11 @@ +2016-11-02 Richard Biener + + * 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 * gfortran.dg/pr70937.f90: require-effective-target lto. diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr20702.c b/gcc/testsuite/gcc.dg/tree-ssa/pr20702.c index cc7370cad4e..c896857748c 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr20702.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr20702.c @@ -4,7 +4,7 @@ immediate successors of the basic block. */ /* { 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); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21086.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21086.c index e8b62c2ca1f..950371ba55d 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr21086.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21086.c @@ -1,5 +1,5 @@ /* { 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 foo (int *p) diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr58480.c b/gcc/testsuite/gcc.dg/tree-ssa/pr58480.c index 7df8f8affbd..42898e72d4e 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr58480.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr58480.c @@ -1,5 +1,5 @@ /* { 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* f1 (void *a, void *b) __attribute__((nonnull)); diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp08.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp08.c index 023b4eb3b94..c2da30b4b68 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/vrp08.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp08.c @@ -1,5 +1,5 @@ /* { 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. */ int diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp111.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp111.c new file mode 100644 index 00000000000..2511c1964bb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp111.c @@ -0,0 +1,13 @@ +/* { 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" } } */ diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index fcdb3417bb3..68fe2acb997 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -10650,18 +10650,17 @@ public: } virtual edge before_dom_children (basic_block); virtual void after_dom_children (basic_block); - void push_value_range (const_tree var, value_range *vr); - value_range *pop_value_range (const_tree var); + void push_value_range (tree var, value_range *vr); + value_range *pop_value_range (tree var); value_range *try_find_new_range (tree op, tree_code code, tree limit); /* Cond_stack holds the old VR. */ - auto_vec > stack; + auto_vec > stack; bitmap need_eh_cleanup; auto_vec stmts_to_fixup; auto_vec stmts_to_remove; }; - /* Find new range for OP such that (OP CODE LIMIT) is true. */ value_range * @@ -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. */ 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 (); *new_vr = vr; return new_vr; @@ -10696,7 +10699,10 @@ evrp_dom_walker::before_dom_children (basic_block bb) edge_iterator ei; 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; FOR_EACH_EDGE (e, ei, bb->preds) @@ -10723,6 +10729,11 @@ evrp_dom_walker::before_dom_children (basic_block bb) && (INTEGRAL_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 here. */ tree op1 = gimple_cond_rhs (stmt); @@ -10778,6 +10789,11 @@ evrp_dom_walker::before_dom_children (basic_block bb) continue; value_range vr_result = VR_INITIALIZER; 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 && interesting) extract_range_from_phi_node (phi, &vr_result); @@ -10814,6 +10830,12 @@ evrp_dom_walker::before_dom_children (basic_block bb) bool was_noreturn = (is_gimple_call (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 (stmt)) { vrp_visit_cond_stmt (cond, &taken_edge); @@ -10825,6 +10847,7 @@ evrp_dom_walker::before_dom_children (basic_block bb) gimple_cond_make_false (cond); else gcc_unreachable (); + update_stmt (stmt); } } else if (stmt_interesting_for_vrp (stmt)) @@ -10873,6 +10896,55 @@ evrp_dom_walker::before_dom_children (basic_block bb) else 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. */ bool did_replace = 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) gcc_checking_assert (!stack.is_empty ()); while (stack.last ().first != NULL_TREE) 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. */ 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); - gcc_checking_assert (vr_value); - stack.safe_push (std::make_pair (var, vr_value[ver])); - - if (ver < num_vr_values) - vr_value[ver] = vr; + fprintf (dump_file, "pushing new range for "); + print_generic_expr (dump_file, var, 0); + fprintf (dump_file, ": "); + dump_value_range (dump_file, vr); + fprintf (dump_file, "\n"); } - else - stack.safe_push (std::make_pair (var, vr)); + stack.safe_push (std::make_pair (var, get_value_range (var))); + vr_value[SSA_NAME_VERSION (var)] = vr; } /* Pop the Value Range from the vrp_stack and update VAR with it. */ 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; - if (vr != NULL) + gcc_checking_assert (var == stack.last ().first); + if (dump_file && (dump_flags & TDF_DETAILS)) { - unsigned ver = SSA_NAME_VERSION (var); - gcc_checking_assert (var == stack.last ().first); - gcc_checking_assert (vr_value); - - if (ver < num_vr_values) - vr_value[ver] = vr; + fprintf (dump_file, "popping range for "); + print_generic_expr (dump_file, var, 0); + fprintf (dump_file, ", restoring "); + dump_value_range (dump_file, vr); + fprintf (dump_file, "\n"); } + vr_value[SSA_NAME_VERSION (var)] = vr; stack.pop (); return vr; } -- 2.30.2