Move array bounds checking out of vrp_prop and into its own class.

This commit is contained in:
Aldy Hernandez 2020-05-05 18:40:44 +02:00
parent add058cf93
commit 65d44272bd
2 changed files with 73 additions and 37 deletions

View File

@ -1,3 +1,15 @@
2020-05-17 Aldy Hernandez <aldyh@redhat.com>
* tree-vrp.c (class vrp_prop): Move check_all_array_refs,
check_array_ref, check_mem_ref, and search_for_addr_array
into new class...
(class array_bounds_checker): ...here.
(class check_array_bounds_dom_walker): Adjust to use
array_bounds_checker.
(check_all_array_refs): Move into array_bounds_checker and rename
to check.
(class vrp_folder): Make fold_predicate_in private.
2020-05-15 Jeff Law <law@redhat.com>
* config/h8300/h8300.md (SFI iterator): New iterator for

View File

@ -3521,7 +3521,7 @@ vrp_insert::insert_range_assertions (void)
class vrp_prop : public ssa_propagation_engine
{
public:
public:
enum ssa_prop_result visit_stmt (gimple *, edge *, tree *) FINAL OVERRIDE;
enum ssa_prop_result visit_phi (gphi *) FINAL OVERRIDE;
@ -3529,12 +3529,10 @@ class vrp_prop : public ssa_propagation_engine
void vrp_initialize (struct function *);
void vrp_finalize (bool);
void check_all_array_refs (void);
bool check_array_ref (location_t, tree, bool);
bool check_mem_ref (location_t, tree, bool);
void search_for_addr_array (tree, location_t);
class vr_values vr_values;
private:
/* Temporary delegator to minimize code churn. */
const value_range_equiv *get_value_range (const_tree op)
{ return vr_values.get_value_range (op); }
@ -3552,6 +3550,29 @@ class vrp_prop : public ssa_propagation_engine
void extract_range_from_phi_node (gphi *phi, value_range_equiv *vr)
{ vr_values.extract_range_from_phi_node (phi, vr); }
};
/* Array bounds checking pass. */
class array_bounds_checker
{
friend class check_array_bounds_dom_walker;
public:
array_bounds_checker (struct function *fun, class vr_values *v)
: fun (fun), ranges (v) { }
void check ();
private:
static tree check_array_bounds (tree *tp, int *walk_subtree, void *data);
bool check_array_ref (location_t, tree, bool ignore_off_by_one);
bool check_mem_ref (location_t, tree, bool ignore_off_by_one);
void check_addr_expr (location_t, tree);
const value_range_equiv *get_value_range (const_tree op)
{ return ranges->get_value_range (op); }
struct function *fun;
class vr_values *ranges;
};
/* Checks one ARRAY_REF in REF, located at LOCUS. Ignores flexible arrays
and "struct" hacks. If VRP can determine that the
array subscript is a constant, check if it is outside valid
@ -3561,8 +3582,8 @@ class vrp_prop : public ssa_propagation_engine
Returns true if a warning has been issued. */
bool
vrp_prop::check_array_ref (location_t location, tree ref,
bool ignore_off_by_one)
array_bounds_checker::check_array_ref (location_t location, tree ref,
bool ignore_off_by_one)
{
if (TREE_NO_WARNING (ref))
return false;
@ -3760,8 +3781,8 @@ vrp_prop::check_array_ref (location_t location, tree ref,
Returns true if a warning has been issued. */
bool
vrp_prop::check_mem_ref (location_t location, tree ref,
bool ignore_off_by_one)
array_bounds_checker::check_mem_ref (location_t location, tree ref,
bool ignore_off_by_one)
{
if (TREE_NO_WARNING (ref))
return false;
@ -4038,7 +4059,7 @@ vrp_prop::check_mem_ref (location_t location, tree ref,
address of an ARRAY_REF, and call check_array_ref on it. */
void
vrp_prop::search_for_addr_array (tree t, location_t location)
array_bounds_checker::check_addr_expr (location_t location, tree t)
{
/* Check each ARRAY_REF and MEM_REF in the reference chain. */
do
@ -4122,14 +4143,12 @@ vrp_prop::search_for_addr_array (tree t, location_t location)
}
}
/* walk_tree() callback that checks if *TP is
an ARRAY_REF inside an ADDR_EXPR (in which an array
subscript one outside the valid range is allowed). Call
check_array_ref for each ARRAY_REF found. The location is
passed in DATA. */
/* Callback for walk_tree to check a tree for out of bounds array
accesses. The array_bounds_checker class is passed in DATA. */
static tree
check_array_bounds (tree *tp, int *walk_subtree, void *data)
tree
array_bounds_checker::check_array_bounds (tree *tp, int *walk_subtree,
void *data)
{
tree t = *tp;
struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
@ -4143,14 +4162,16 @@ check_array_bounds (tree *tp, int *walk_subtree, void *data)
*walk_subtree = TRUE;
bool warned = false;
vrp_prop *vrp_prop = (class vrp_prop *)wi->info;
array_bounds_checker *checker = (array_bounds_checker *) wi->info;
if (TREE_CODE (t) == ARRAY_REF)
warned = vrp_prop->check_array_ref (location, t, false/*ignore_off_by_one*/);
warned = checker->check_array_ref (location, t,
false/*ignore_off_by_one*/);
else if (TREE_CODE (t) == MEM_REF)
warned = vrp_prop->check_mem_ref (location, t, false /*ignore_off_by_one*/);
warned = checker->check_mem_ref (location, t,
false /*ignore_off_by_one*/);
else if (TREE_CODE (t) == ADDR_EXPR)
{
vrp_prop->search_for_addr_array (t, location);
checker->check_addr_expr (location, t);
*walk_subtree = FALSE;
}
/* Propagate the no-warning bit to the outer expression. */
@ -4160,26 +4181,26 @@ check_array_bounds (tree *tp, int *walk_subtree, void *data)
return NULL_TREE;
}
/* 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. */
/* A dom_walker subclass for use by check_all_array_refs, to walk over
all statements of all reachable BBs and call check_array_bounds on
them. */
class check_array_bounds_dom_walker : public dom_walker
{
public:
check_array_bounds_dom_walker (vrp_prop *prop)
public:
check_array_bounds_dom_walker (array_bounds_checker *checker)
: dom_walker (CDI_DOMINATORS,
/* Discover non-executable edges, preserving EDGE_EXECUTABLE
flags, so that we can merge in information on
non-executable edges from vrp_folder . */
REACHABLE_BLOCKS_PRESERVING_FLAGS),
m_prop (prop) {}
checker (checker) { }
~check_array_bounds_dom_walker () {}
edge before_dom_children (basic_block) FINAL OVERRIDE;
private:
vrp_prop *m_prop;
private:
array_bounds_checker *checker;
};
/* Implementation of dom_walker::before_dom_children.
@ -4201,9 +4222,9 @@ check_array_bounds_dom_walker::before_dom_children (basic_block bb)
memset (&wi, 0, sizeof (wi));
wi.info = m_prop;
wi.info = checker;
walk_gimple_op (stmt, check_array_bounds, &wi);
walk_gimple_op (stmt, array_bounds_checker::check_array_bounds, &wi);
}
/* Determine if there's a unique successor edge, and if so, return
@ -4213,11 +4234,10 @@ check_array_bounds_dom_walker::before_dom_children (basic_block bb)
return find_taken_edge (bb, NULL_TREE);
}
/* Walk over all statements of all reachable BBs and call check_array_bounds
on them. */
/* Entry point into array bounds checking pass. */
void
vrp_prop::check_all_array_refs ()
array_bounds_checker::check ()
{
check_array_bounds_dom_walker w (this);
w.walk (ENTRY_BLOCK_PTR_FOR_FN (fun));
@ -4851,14 +4871,15 @@ vrp_prop::visit_phi (gphi *phi)
class vrp_folder : public substitute_and_fold_engine
{
public:
public:
vrp_folder () : substitute_and_fold_engine (/* Fold all stmts. */ true) { }
tree get_value (tree) FINAL OVERRIDE;
bool fold_stmt (gimple_stmt_iterator *) FINAL OVERRIDE;
bool fold_predicate_in (gimple_stmt_iterator *);
class vr_values *vr_values;
private:
bool fold_predicate_in (gimple_stmt_iterator *);
/* Delegators. */
tree vrp_evaluate_conditional (tree_code code, tree op0,
tree op1, gimple *stmt)
@ -5293,7 +5314,10 @@ vrp_prop::vrp_finalize (bool warn_array_bounds_p)
vrp_folder.substitute_and_fold ();
if (warn_array_bounds && warn_array_bounds_p)
check_all_array_refs ();
{
array_bounds_checker array_checker (fun, &vr_values);
array_checker.check ();
}
}
/* Main entry point to VRP (Value Range Propagation). This pass is