aboutsummaryrefslogtreecommitdiff
path: root/gcc/tree-vrp.c
diff options
context:
space:
mode:
authorDavid Malcolm <dmalcolm@redhat.com>2017-12-14 17:15:39 +0000
committerDavid Malcolm <dmalcolm@gcc.gnu.org>2017-12-14 17:15:39 +0000
commit5505bb43b7b3277354563b69d1287efca21315cb (patch)
tree7d33437a2b214b3948aaf13e6a38a38a5cc1a739 /gcc/tree-vrp.c
parent9de2192154a3d5ec055b535aa143a927fcc2c2ee (diff)
downloadgcc-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.c76
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