diff options
author | David Malcolm <dmalcolm@redhat.com> | 2017-12-14 17:15:39 +0000 |
---|---|---|
committer | David Malcolm <dmalcolm@gcc.gnu.org> | 2017-12-14 17:15:39 +0000 |
commit | 5505bb43b7b3277354563b69d1287efca21315cb (patch) | |
tree | 7d33437a2b214b3948aaf13e6a38a38a5cc1a739 /gcc/tree-vrp.c | |
parent | 9de2192154a3d5ec055b535aa143a927fcc2c2ee (diff) | |
download | gcc-5505bb43b7b3277354563b69d1287efca21315cb.zip gcc-5505bb43b7b3277354563b69d1287efca21315cb.tar.gz gcc-5505bb43b7b3277354563b69d1287efca21315cb.tar.bz2 |
vrp_prop: Use dom_walker for -Warray-bounds (PR tree-optimization/83312)
gcc/ChangeLog:
PR tree-optimization/83312
* domwalk.h (dom_walker::dom_walker): Fix typo in comment.
* tree-cfg.c (find_taken_edge): Update to handle NULL_TREE for
"val" param, and to cope with arbitrary basic blocks.
(find_taken_edge_cond_expr): Add "cond_stmt" param and use it to
handle NULL_TREE for "val", dropping "bb" param.
(find_taken_edge_switch_expr): Make "switch_stmt" param const and
drop "bb" param. Handle NULL_TREE for "val".
(find_case_label_for_value): Make "switch_stmt" param const.
* tree-vrp.c (class check_array_bounds_dom_walker): New subclass
of dom_walker.
(vrp_prop::check_all_array_refs): Reimplement as...
(check_array_bounds_dom_walker::before_dom_children): ...this new
vfunc. Replace linear search through BB block list, excluding
those with non-executable in-edges via dominator walk.
gcc/testsuite/ChangeLog:
PR tree-optimization/83312
* gcc.dg/pr83312.c: New test case.
From-SVN: r255649
Diffstat (limited to 'gcc/tree-vrp.c')
-rw-r--r-- | gcc/tree-vrp.c | 76 |
1 files changed, 47 insertions, 29 deletions
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 7df6f24..8fa8616 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -5000,44 +5000,62 @@ check_array_bounds (tree *tp, int *walk_subtree, void *data) return NULL_TREE; } -/* Walk over all statements of all reachable BBs and call check_array_bounds - on them. */ +/* A dom_walker subclass for use by vrp_prop::check_all_array_refs, + to walk over all statements of all reachable BBs and call + check_array_bounds on them. */ -void -vrp_prop::check_all_array_refs () +class check_array_bounds_dom_walker : public dom_walker { - basic_block bb; - gimple_stmt_iterator si; + public: + check_array_bounds_dom_walker (vrp_prop *prop) + : dom_walker (CDI_DOMINATORS, true), m_prop (prop) {} + ~check_array_bounds_dom_walker () {} - FOR_EACH_BB_FN (bb, cfun) - { - edge_iterator ei; - edge e; - bool executable = false; + edge before_dom_children (basic_block) FINAL OVERRIDE; - /* Skip blocks that were found to be unreachable. */ - FOR_EACH_EDGE (e, ei, bb->preds) - executable |= !!(e->flags & EDGE_EXECUTABLE); - if (!executable) - continue; + private: + vrp_prop *m_prop; +}; - for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si)) - { - gimple *stmt = gsi_stmt (si); - struct walk_stmt_info wi; - if (!gimple_has_location (stmt) - || is_gimple_debug (stmt)) - continue; +/* Implementation of dom_walker::before_dom_children. - memset (&wi, 0, sizeof (wi)); + Walk over all statements of BB and call check_array_bounds on them, + and determine if there's a unique successor edge. */ - wi.info = this; +edge +check_array_bounds_dom_walker::before_dom_children (basic_block bb) +{ + gimple_stmt_iterator si; + for (si = gsi_start_bb (bb); !gsi_end_p (si); gsi_next (&si)) + { + gimple *stmt = gsi_stmt (si); + struct walk_stmt_info wi; + if (!gimple_has_location (stmt) + || is_gimple_debug (stmt)) + continue; - walk_gimple_op (gsi_stmt (si), - check_array_bounds, - &wi); - } + memset (&wi, 0, sizeof (wi)); + + wi.info = m_prop; + + walk_gimple_op (stmt, check_array_bounds, &wi); } + + /* Determine if there's a unique successor edge, and if so, return + that back to dom_walker, ensuring that we don't visit blocks that + became unreachable during the VRP propagation + (PR tree-optimization/83312). */ + return find_taken_edge (bb, NULL_TREE); +} + +/* Walk over all statements of all reachable BBs and call check_array_bounds + on them. */ + +void +vrp_prop::check_all_array_refs () +{ + check_array_bounds_dom_walker w (this); + w.walk (ENTRY_BLOCK_PTR_FOR_FN (cfun)); } /* Return true if all imm uses of VAR are either in STMT, or |