diff mbox series

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

Message ID 0adcf9b6-a37b-cef1-2850-e3bd8700c3ab@redhat.com
State New
Headers show
Series [committed] Move array bounds checking out of vrp_prop and into its own class. | expand

Commit Message

Aldy Hernandez May 17, 2020, 9:12 a.m. UTC
Howdy.

There's really no reason why the array bounds code should live in 
tree-vrp, when all it really needs is a get_value_range() call back. 
Particularly painful is that it partially lives inside the vrp_prop class.

This patch moves the array bounds code into its own class, while taking 
in a vr_values in the constructor which is ONLY used to get at 
get_value_range().

It is my ultimate desire to move this class into its own file (as a 
follow-up), minimizing distraction in tree-vrp.c.  It can take a 
vr_values (or similar object), and can be made to work with any ranger 
(evrp, vrp, or ranger).

Approved by Jeff, and committed to mainline.

Aldy
diff mbox series

Patch

commit 65d44272bd988f695a9b5fa7e1b88c266c3089cb
Author: Aldy Hernandez <aldyh@redhat.com>
Date:   Tue May 5 18:40:44 2020 +0200

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

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 4f48d443235..64681dd97fe 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index 1001c7f41d8..6e3510856a5 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -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