This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[committed[PATCH] Refactoring tree-vrp, step one introducing vr_values


And the big part of the patch.  Only changes were two conceptual chunks
were committed earlier, one member function name change and removal of
unnecessary vertical whitespace in a class definition.

Committing to the trunk.  Posting for archival purposes.

jeff
commit dcd9367d22b6f49fe4fca8d6a412c36ee43045ca
Author: Jeff Law <law@torsion.usersys.redhat.com>
Date:   Wed Nov 8 12:04:42 2017 -0500

            * vr-values.h: New file with vr_values class.
            * tree-vrp.c: Include vr-values.h
            (vrp_value_range_pool, vrp_equiv_obstack, num_vr_values): Move static
            data objects into the vr_values class.
            (vr_value, values_propagated, vr_phi_edge_counts): Likewise.
            (get_value_range): Make it a member function within vr_values class.
            (set_defs_to_varying, update_value_range, add_equivalence): Likewise.
            (vrp_stmt_computes_nonzero_p, op_with_boolean_value_range_p): Likewise.
            (op_with_constant_singleton_value_range): Likewise.
            (extract_range_for_var_from_comparison_expr): Likewise.
            (extract_range_from_assert, extract_range_from_ssa_name): Likewise.
            (extract_range_from_binary_expr): Likewise.
            (extract_range_from_unary_expr): Likewise.
            (extract_range_from_cond_expr, extrat_range_from_comparison): Likewise.
            (check_for_binary_op_overflow, extract_range_basic): Likewise.
            (extract_range_from_assignment, adjust_range_with_scev): Likewise.
            (dump_all_value_ranges, get_vr_for_comparison): Likewise.
            (compare_name_with_value, compare_names): Likewise.
            (vrp_evaluate_conditional_warnv_with_ops_using_ranges): Likewise.
            (vrp_evaluate_conditional_warnv_with_ops): Likewise.  Remove prototype.
            (vrp_evaluate_conditional, vrp_visit_cond_stmt): Likewise.
            (vrp_visit_switch_stmt, extract_range_from_stmt): Likewise.
            (extract_range_from_phi_node): Likewise.
            (simplify_truth_ops_using_ranges): Likewise.
            (simplify_div_or_mod_using_ranges): Likewise.
            (simplify_min_or_max_using_ranges, simplify_abs_using_ranges): Likewise.
            (simplify_bit_ops_using_ranges, simplify_cond_using_ranges_1): Likewise.
            (simplify_cond_using_ranges_2, simplify_switch_using_ranges): Likewise.
            (simplify_float_conversion_using_ranges): Likewise.
            (simplify_internal_call_using_ranges): Likewise.
            (two_valued_val_range_p, simplify_stmt_using_ranges): Likewise.
            (vrp_visit_assignment_or_call): Likewise.  Smuggle class instance
            poitner via x_vr_values for calls into gimple folder.
            (vrp_initialize_lattice): Make this the vr_values ctor.
            (vrp_free_lattice): Make this the vr_values dtor.
            (set_vr_value): New function.
            (class vrp_prop): Add vr_values data member.  Add various member
            functions as well as member functions that delegate to vr_values.
            (check_array_ref): Make a member function within vrp_prop class.
            (search_for_addr_array, vrp_initialize): Likewise.
            (vrp_finalize): Likewise.  Revamp to avoid direct access to
            vr_value, values_propagated, etc.
            (check_array_bounds): Extract vrp_prop class instance pointer from
            walk info structure.  Use it to call member functions.
            (check_all_array_refs): Make a member function within vrp_prop class.
            Smuggle class instance pointer via walk info structure.
            (x_vr_values): New local static.
            (vrp_valueize): Use x_vr_values to get class instance.
            (vr_valueize_1): Likewise.
            (class vrp_folder): Add vr_values data member.  Add various member
            functions as well as member functions that delegate to vr_values.
            (fold_predicate_in): Make a mber fucntion within vrp_folder class.
            (simplify_stmt_for_jump_threading): Extract smuggled vr_values
            class instance from vr_values.  Use it to call member functions.
            (vrp_dom_walker): Add vr_values data member.
            (vrp_dom_walker::after_dom_children): Smuggle vr_values class
            instance via x_vr_values.
            (identify_jump_threads): Accept vr_values as argument.  Store
            it into the walker structure.
            (evrp_dom_walker): Add vr_values class data member.  Add various
            delegators.
            (evrp_dom_walker::try_find_new_range): Use vr_values data
            member to access the memory allocator.
            (evrp_dom_walker::before_dom_children): Store vr_values class
            instance into the vrp_folder class.
            (evrp_dom_walker::push_value_range): Rework to avoid direct
            access to num_vr_values and vr_value.
            (evrp_dom_walker::pop_value_range): Likewise.
            (execute_early_vrp): Remove call to vrp_initialize_lattice.
            Use vr_values to get to dump_all_value_ranges member function.
            Remove call to vrp_free_lattice.  Call vrp_initialize, vrp_finalize,
            and simplify_cond_using_ranges_2 via vrp_prop class instance.
            Pass vr_values class instance down to identify_jump_threads.
            Remove call to vrp_free_lattice.
            (debug_all_value_ranges): Remove.

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9b93a852099..0c6f9489389 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,81 @@
 2017-11-09  Jeff Law  <law@redhat.com>
 
+	* vr-values.h: New file with vr_values class.
+	* tree-vrp.c: Include vr-values.h
+	(vrp_value_range_pool, vrp_equiv_obstack, num_vr_values): Move static
+	data objects into the vr_values class.
+	(vr_value, values_propagated, vr_phi_edge_counts): Likewise.
+	(get_value_range): Make it a member function within vr_values class.
+	(set_defs_to_varying, update_value_range, add_equivalence): Likewise.
+	(vrp_stmt_computes_nonzero_p, op_with_boolean_value_range_p): Likewise.
+	(op_with_constant_singleton_value_range): Likewise.
+	(extract_range_for_var_from_comparison_expr): Likewise.
+	(extract_range_from_assert, extract_range_from_ssa_name): Likewise.
+	(extract_range_from_binary_expr): Likewise.
+	(extract_range_from_unary_expr): Likewise.
+	(extract_range_from_cond_expr, extrat_range_from_comparison): Likewise.
+	(check_for_binary_op_overflow, extract_range_basic): Likewise.
+	(extract_range_from_assignment, adjust_range_with_scev): Likewise.
+	(dump_all_value_ranges, get_vr_for_comparison): Likewise.
+	(compare_name_with_value, compare_names): Likewise.
+	(vrp_evaluate_conditional_warnv_with_ops_using_ranges): Likewise.
+	(vrp_evaluate_conditional_warnv_with_ops): Likewise.  Remove prototype.
+	(vrp_evaluate_conditional, vrp_visit_cond_stmt): Likewise.
+	(vrp_visit_switch_stmt, extract_range_from_stmt): Likewise.
+	(extract_range_from_phi_node): Likewise.
+	(simplify_truth_ops_using_ranges): Likewise.
+	(simplify_div_or_mod_using_ranges): Likewise.
+	(simplify_min_or_max_using_ranges, simplify_abs_using_ranges): Likewise.
+	(simplify_bit_ops_using_ranges, simplify_cond_using_ranges_1): Likewise.
+	(simplify_cond_using_ranges_2, simplify_switch_using_ranges): Likewise.
+	(simplify_float_conversion_using_ranges): Likewise.
+	(simplify_internal_call_using_ranges): Likewise.
+	(two_valued_val_range_p, simplify_stmt_using_ranges): Likewise.
+	(vrp_visit_assignment_or_call): Likewise.  Smuggle class instance
+	poitner via x_vr_values for calls into gimple folder.
+	(vrp_initialize_lattice): Make this the vr_values ctor.
+	(vrp_free_lattice): Make this the vr_values dtor.
+	(set_vr_value): New function.
+	(class vrp_prop): Add vr_values data member.  Add various member
+	functions as well as member functions that delegate to vr_values.
+	(check_array_ref): Make a member function within vrp_prop class.
+	(search_for_addr_array, vrp_initialize): Likewise.
+	(vrp_finalize): Likewise.  Revamp to avoid direct access to
+	vr_value, values_propagated, etc.
+	(check_array_bounds): Extract vrp_prop class instance pointer from
+	walk info structure.  Use it to call member functions.
+	(check_all_array_refs): Make a member function within vrp_prop class.
+	Smuggle class instance pointer via walk info structure.
+	(x_vr_values): New local static.
+	(vrp_valueize): Use x_vr_values to get class instance.
+	(vr_valueize_1): Likewise.
+	(class vrp_folder): Add vr_values data member.  Add various member
+	functions as well as member functions that delegate to vr_values.
+	(fold_predicate_in): Make a mber fucntion within vrp_folder class.
+	(simplify_stmt_for_jump_threading): Extract smuggled vr_values
+	class instance from vr_values.  Use it to call member functions.
+	(vrp_dom_walker): Add vr_values data member.
+	(vrp_dom_walker::after_dom_children): Smuggle vr_values class
+	instance via x_vr_values.
+	(identify_jump_threads): Accept vr_values as argument.  Store
+	it into the walker structure.
+	(evrp_dom_walker): Add vr_values class data member.  Add various
+	delegators.
+	(evrp_dom_walker::try_find_new_range): Use vr_values data
+	member to access the memory allocator.
+	(evrp_dom_walker::before_dom_children): Store vr_values class
+	instance into the vrp_folder class.
+	(evrp_dom_walker::push_value_range): Rework to avoid direct
+	access to num_vr_values and vr_value.
+	(evrp_dom_walker::pop_value_range): Likewise.
+	(execute_early_vrp): Remove call to vrp_initialize_lattice.
+	Use vr_values to get to dump_all_value_ranges member function.
+	Remove call to vrp_free_lattice.  Call vrp_initialize, vrp_finalize,
+	and simplify_cond_using_ranges_2 via vrp_prop class instance.
+	Pass vr_values class instance down to identify_jump_threads.  
+	Remove call to vrp_free_lattice.
+	(debug_all_value_ranges): Remove.
+
 	* tree-vrp.c (vrp_prop): Move class to earlier point in the file.
 	(vrp_folder): Likewise.
 
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index fc9ad4adebe..7173ab22478 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -64,13 +64,10 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-cfgcleanup.h"
 #include "stringpool.h"
 #include "attribs.h"
+#include "vr-values.h"
 
 #define VR_INITIALIZER { VR_UNDEFINED, NULL_TREE, NULL_TREE, NULL }
 
-/* Allocation pools for tree-vrp allocations.  */
-static object_allocator<value_range> vrp_value_range_pool ("Tree VRP value ranges");
-static bitmap_obstack vrp_equiv_obstack;
-
 /* Set of SSA names found live during the RPO traversal of the function
    for still active basic-blocks.  */
 static sbitmap *live;
@@ -87,9 +84,6 @@ live_on_edge (edge e, tree name)
 /* Local functions.  */
 static int compare_values (tree val1, tree val2);
 static int compare_values_warnv (tree val1, tree val2, bool *);
-static tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code,
-						     tree, tree, bool, bool *,
-						     bool *);
 
 struct assert_info
 {
@@ -145,17 +139,6 @@ static bitmap need_assert_for;
    ASSERT_EXPRs for SSA name N_I should be inserted.  */
 static assert_locus **asserts_for;
 
-/* Value range array.  After propagation, VR_VALUE[I] holds the range
-   of values that SSA name N_I may take.  */
-static unsigned num_vr_values;
-static value_range **vr_value;
-static bool values_propagated;
-
-/* For a PHI node which sets SSA name N_I, VR_COUNTS[I] holds the
-   number of executable edges we saw the last time we visited the
-   node.  */
-static int *vr_phi_edge_counts;
-
 struct switch_update {
   gswitch *stmt;
   tree vec;
@@ -509,8 +492,8 @@ abs_extent_range (value_range *vr, tree min, tree max)
    If we have no values ranges recorded (ie, VRP is not running), then
    return NULL.  Otherwise create an empty range if none existed for VAR.  */
 
-static value_range *
-get_value_range (const_tree var)
+value_range *
+vr_values::get_value_range (const_tree var)
 {
   static const value_range vr_const_varying
     = { VR_VARYING, NULL_TREE, NULL_TREE, NULL };
@@ -582,8 +565,8 @@ get_value_range (const_tree var)
 
 /* Set value-ranges of all SSA names defined by STMT to varying.  */
 
-static void
-set_defs_to_varying (gimple *stmt)
+void
+vr_values::set_defs_to_varying (gimple *stmt)
 {
   ssa_op_iter i;
   tree def;
@@ -631,8 +614,8 @@ vrp_bitmap_equal_p (const_bitmap b1, const_bitmap b2)
    this function.  Do not call update_value_range when NEW_VR
    is the range object associated with another SSA name.  */
 
-static inline bool
-update_value_range (const_tree var, value_range *new_vr)
+bool
+vr_values::update_value_range (const_tree var, value_range *new_vr)
 {
   value_range *old_vr;
   bool is_new;
@@ -690,8 +673,8 @@ update_value_range (const_tree var, value_range *new_vr)
 /* Add VAR and VAR's equivalence set to EQUIV.  This is the central
    point where equivalence processing can be turned on/off.  */
 
-static void
-add_equivalence (bitmap *equiv, const_tree var)
+void
+vr_values::add_equivalence (bitmap *equiv, const_tree var)
 {
   unsigned ver = SSA_NAME_VERSION (var);
   value_range *vr = get_value_range (var);
@@ -933,8 +916,8 @@ gimple_stmt_nonzero_p (gimple *stmt)
 /* Like tree_expr_nonzero_p, but this function uses value ranges
    obtained so far.  */
 
-static bool
-vrp_stmt_computes_nonzero (gimple *stmt)
+bool
+vr_values::vrp_stmt_computes_nonzero (gimple *stmt)
 {
   if (gimple_stmt_nonzero_p (stmt))
     return true;
@@ -1260,8 +1243,8 @@ value_range_constant_singleton (value_range *vr)
    otherwise return NULL_TREE.  This returns OP itself if OP is a
    constant.  */
 
-static tree
-op_with_constant_singleton_value_range (tree op)
+tree
+vr_values::op_with_constant_singleton_value_range (tree op)
 {
   if (is_gimple_min_invariant (op))
     return op;
@@ -1274,8 +1257,8 @@ op_with_constant_singleton_value_range (tree op)
 
 /* Return true if op is in a boolean [0, 1] value-range.  */
 
-static bool
-op_with_boolean_value_range_p (tree op)
+bool
+vr_values::op_with_boolean_value_range_p (tree op)
 {
   value_range *vr;
 
@@ -1298,10 +1281,11 @@ op_with_boolean_value_range_p (tree op)
 /* Extract value range information for VAR when (OP COND_CODE LIMIT) is
    true and store it in *VR_P.  */
 
-static void
-extract_range_for_var_from_comparison_expr (tree var, enum tree_code cond_code,
-					    tree op, tree limit,
-					    value_range *vr_p)
+void
+vr_values::extract_range_for_var_from_comparison_expr (tree var,
+						       enum tree_code cond_code,
+						       tree op, tree limit,
+						       value_range *vr_p)
 {
   tree  min, max, type;
   value_range *limit_vr;
@@ -1545,8 +1529,8 @@ extract_range_for_var_from_comparison_expr (tree var, enum tree_code cond_code,
 /* Extract value range information from an ASSERT_EXPR EXPR and store
    it in *VR_P.  */
 
-static void
-extract_range_from_assert (value_range *vr_p, tree expr)
+void
+vr_values::extract_range_from_assert (value_range *vr_p, tree expr)
 {
   tree var = ASSERT_EXPR_VAR (expr);
   tree cond = ASSERT_EXPR_COND (expr);
@@ -1591,8 +1575,8 @@ extract_range_from_assert (value_range *vr_p, tree expr)
     Even if y_5 is deemed VARYING, we can determine that x_3 > y_5 is
     always false.  */
 
-static void
-extract_range_from_ssa_name (value_range *vr, tree var)
+void
+vr_values::extract_range_from_ssa_name (value_range *vr, tree var)
 {
   value_range *var_vr = get_value_range (var);
 
@@ -3027,10 +3011,10 @@ extract_range_from_binary_expr_1 (value_range *vr,
    the ranges of each of its operands with resulting type EXPR_TYPE.
    The resulting range is stored in *VR.  */
 
-static void
-extract_range_from_binary_expr (value_range *vr,
-				enum tree_code code,
-				tree expr_type, tree op0, tree op1)
+void
+vr_values::extract_range_from_binary_expr (value_range *vr,
+					   enum tree_code code,
+					   tree expr_type, tree op0, tree op1)
 {
   value_range vr0 = VR_INITIALIZER;
   value_range vr1 = VR_INITIALIZER;
@@ -3374,9 +3358,9 @@ extract_range_from_unary_expr (value_range *vr,
    the range of its operand with resulting type TYPE.
    The resulting range is stored in *VR.  */
 
-static void
-extract_range_from_unary_expr (value_range *vr, enum tree_code code,
-			       tree type, tree op0)
+void
+vr_values::extract_range_from_unary_expr (value_range *vr, enum tree_code code,
+					  tree type, tree op0)
 {
   value_range vr0 = VR_INITIALIZER;
 
@@ -3389,15 +3373,15 @@ extract_range_from_unary_expr (value_range *vr, enum tree_code code,
   else
     set_value_range_to_varying (&vr0);
 
-  extract_range_from_unary_expr (vr, code, type, &vr0, TREE_TYPE (op0));
+  ::extract_range_from_unary_expr (vr, code, type, &vr0, TREE_TYPE (op0));
 }
 
 
 /* Extract range information from a conditional expression STMT based on
    the ranges of each of its operands and the expression code.  */
 
-static void
-extract_range_from_cond_expr (value_range *vr, gassign *stmt)
+void
+vr_values::extract_range_from_cond_expr (value_range *vr, gassign *stmt)
 {
   tree op0, op1;
   value_range vr0 = VR_INITIALIZER;
@@ -3430,9 +3414,9 @@ extract_range_from_cond_expr (value_range *vr, gassign *stmt)
 /* Extract range information from a comparison expression EXPR based
    on the range of its operand and the expression code.  */
 
-static void
-extract_range_from_comparison (value_range *vr, enum tree_code code,
-			       tree type, tree op0, tree op1)
+void
+vr_values::extract_range_from_comparison (value_range *vr, enum tree_code code,
+					  tree type, tree op0, tree op1)
 {
   bool sop;
   tree val;
@@ -3461,9 +3445,9 @@ extract_range_from_comparison (value_range *vr, enum tree_code code,
    always overflow.  Set *OVF to true if it is known to always
    overflow.  */
 
-static bool
-check_for_binary_op_overflow (enum tree_code subcode, tree type,
-			      tree op0, tree op1, bool *ovf)
+bool
+vr_values::check_for_binary_op_overflow (enum tree_code subcode, tree type,
+					 tree op0, tree op1, bool *ovf)
 {
   value_range vr0 = VR_INITIALIZER;
   value_range vr1 = VR_INITIALIZER;
@@ -3566,8 +3550,8 @@ check_for_binary_op_overflow (enum tree_code subcode, tree type,
    primarily on generic routines in fold in conjunction with range data.
    Store the result in *VR */
 
-static void
-extract_range_basic (value_range *vr, gimple *stmt)
+void
+vr_values::extract_range_basic (value_range *vr, gimple *stmt)
 {
   bool sop;
   tree type = gimple_expr_type (stmt);
@@ -3917,8 +3901,8 @@ extract_range_basic (value_range *vr, gimple *stmt)
 /* Try to compute a useful range out of assignment STMT and store it
    in *VR.  */
 
-static void
-extract_range_from_assignment (value_range *vr, gassign *stmt)
+void
+vr_values::extract_range_from_assignment (value_range *vr, gassign *stmt)
 {
   enum tree_code code = gimple_assign_rhs_code (stmt);
 
@@ -3956,9 +3940,9 @@ extract_range_from_assignment (value_range *vr, gassign *stmt)
    would be profitable to adjust VR using scalar evolution information
    for VAR.  If so, update VR with the new limits.  */
 
-static void
-adjust_range_with_scev (value_range *vr, struct loop *loop,
-			gimple *stmt, tree var)
+void
+vr_values::adjust_range_with_scev (value_range *vr, struct loop *loop,
+				   gimple *stmt, tree var)
 {
   tree init, step, chrec, tmin, tmax, min, max, type, tem;
   enum ev_direction dir;
@@ -4402,7 +4386,6 @@ compare_range_with_value (enum tree_code comp, value_range *vr, tree val,
 void dump_value_range (FILE *, const value_range *);
 void debug_value_range (value_range *);
 void dump_all_value_ranges (FILE *);
-void debug_all_value_ranges (void);
 void dump_vr_equiv (FILE *, bitmap);
 void debug_vr_equiv (bitmap);
 
@@ -4476,7 +4459,7 @@ debug_value_range (value_range *vr)
 /* Dump value ranges of all SSA_NAMEs to FILE.  */
 
 void
-dump_all_value_ranges (FILE *file)
+vr_values::dump_all_value_ranges (FILE *file)
 {
   size_t i;
 
@@ -4494,16 +4477,6 @@ dump_all_value_ranges (FILE *file)
   fprintf (file, "\n");
 }
 
-
-/* Dump all value ranges to stderr.  */
-
-DEBUG_FUNCTION void
-debug_all_value_ranges (void)
-{
-  dump_all_value_ranges (stderr);
-}
-
-
 /* Given a COND_EXPR COND of the form 'V OP W', and an SSA name V,
    create a new SSA name N and return the assertion assignment
    'N = ASSERT_EXPR <V, V OP W>'.  */
@@ -6640,6 +6613,28 @@ class vrp_prop : public ssa_propagation_engine
  public:
   enum ssa_prop_result visit_stmt (gimple *, edge *, tree *) FINAL OVERRIDE;
   enum ssa_prop_result visit_phi (gphi *) FINAL OVERRIDE;
+
+  void vrp_initialize (void);
+  void vrp_finalize (bool);
+  void check_all_array_refs (void);
+  void check_array_ref (location_t, tree, bool);
+  void search_for_addr_array (tree, location_t);
+
+  class vr_values vr_values;
+  /* Temporary delegator to minimize code churn.  */
+  value_range *get_value_range (const_tree op)
+    { return vr_values.get_value_range (op); }
+  void set_defs_to_varying (gimple *stmt)
+    { return vr_values.set_defs_to_varying (stmt); }
+  void extract_range_from_stmt (gimple *stmt, edge *taken_edge_p,
+				tree *output_p, value_range *vr)
+    { vr_values.extract_range_from_stmt (stmt, taken_edge_p, output_p, vr); }
+  bool update_value_range (const_tree op, value_range *vr)
+    { return vr_values.update_value_range (op, vr); }
+  void extract_range_basic (value_range *vr, gimple *stmt)
+    { vr_values.extract_range_basic (vr, stmt); }
+  void extract_range_from_phi_node (gphi *phi, value_range *vr)
+    { vr_values.extract_range_from_phi_node (phi, vr); }
 };
 
 /* Checks one ARRAY_REF in REF, located at LOCUS. Ignores flexible arrays
@@ -6649,8 +6644,9 @@ class vrp_prop : public ssa_propagation_engine
    non-overlapping with valid range.
    IGNORE_OFF_BY_ONE is true if the ARRAY_REF is inside a ADDR_EXPR.  */
 
-static void
-check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
+void
+vrp_prop::check_array_ref (location_t location, tree ref,
+			   bool ignore_off_by_one)
 {
   value_range *vr = NULL;
   tree low_sub, up_sub;
@@ -6742,8 +6738,8 @@ check_array_ref (location_t location, tree ref, bool ignore_off_by_one)
 /* Searches if the expr T, located at LOCATION computes
    address of an ARRAY_REF, and call check_array_ref on it.  */
 
-static void
-search_for_addr_array (tree t, location_t location)
+void
+vrp_prop::search_for_addr_array (tree t, location_t location)
 {
   /* Check each ARRAY_REFs in the reference chain. */
   do
@@ -6828,12 +6824,13 @@ check_array_bounds (tree *tp, int *walk_subtree, void *data)
 
   *walk_subtree = TRUE;
 
+  vrp_prop *vrp_prop = (class vrp_prop *)wi->info;
   if (TREE_CODE (t) == ARRAY_REF)
-    check_array_ref (location, t, false /*ignore_off_by_one*/);
+    vrp_prop->check_array_ref (location, t, false /*ignore_off_by_one*/);
 
   else if (TREE_CODE (t) == ADDR_EXPR)
     {
-      search_for_addr_array (t, location);
+      vrp_prop->search_for_addr_array (t, location);
       *walk_subtree = FALSE;
     }
 
@@ -6843,8 +6840,8 @@ check_array_bounds (tree *tp, int *walk_subtree, void *data)
 /* Walk over all statements of all reachable BBs and call check_array_bounds
    on them.  */
 
-static void
-check_all_array_refs (void)
+void
+vrp_prop::check_all_array_refs ()
 {
   basic_block bb;
   gimple_stmt_iterator si;
@@ -6871,6 +6868,8 @@ check_all_array_refs (void)
 
 	  memset (&wi, 0, sizeof (wi));
 
+	  wi.info = this;
+
 	  walk_gimple_op (gsi_stmt (si),
 			  check_array_bounds,
 			  &wi);
@@ -7121,8 +7120,7 @@ stmt_interesting_for_vrp (gimple *stmt)
 
 /* Initialize VRP lattice.  */
 
-static void
-vrp_initialize_lattice ()
+vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges")
 {
   values_propagated = false;
   num_vr_values = num_ssa_names;
@@ -7133,8 +7131,8 @@ vrp_initialize_lattice ()
 
 /* Initialization required by ssa_propagate engine.  */
 
-static void
-vrp_initialize ()
+void
+vrp_prop::vrp_initialize ()
 {
   basic_block bb;
 
@@ -7175,6 +7173,9 @@ vrp_initialize ()
     }
 }
 
+/* A hack.  */
+static class vr_values *x_vr_values;
+
 /* Return the singleton value-range for NAME or NAME.  */
 
 static inline tree
@@ -7182,7 +7183,7 @@ vrp_valueize (tree name)
 {
   if (TREE_CODE (name) == SSA_NAME)
     {
-      value_range *vr = get_value_range (name);
+      value_range *vr = x_vr_values->get_value_range (name);
       if (vr->type == VR_RANGE
 	  && (TREE_CODE (vr->min) == SSA_NAME
 	      || is_gimple_min_invariant (vr->min))
@@ -7207,7 +7208,7 @@ vrp_valueize_1 (tree name)
       if (!gimple_nop_p (def_stmt)
 	  && prop_simulate_again_p (def_stmt))
 	return NULL_TREE;
-      value_range *vr = get_value_range (name);
+      value_range *vr = x_vr_values->get_value_range (name);
       if (range_int_cst_singleton_p (vr))
 	return vr->min;
     }
@@ -7217,8 +7218,9 @@ vrp_valueize_1 (tree name)
 /* Visit assignment STMT.  If it produces an interesting range, record
    the range in VR and set LHS to OUTPUT_P.  */
 
-static void
-vrp_visit_assignment_or_call (gimple *stmt, tree *output_p, value_range *vr)
+void
+vr_values::vrp_visit_assignment_or_call (gimple *stmt, tree *output_p,
+					 value_range *vr)
 {
   tree lhs;
   enum gimple_code code = gimple_code (stmt);
@@ -7237,8 +7239,10 @@ vrp_visit_assignment_or_call (gimple *stmt, tree *output_p, value_range *vr)
       *output_p = lhs;
 
       /* Try folding the statement to a constant first.  */
+      x_vr_values = this;
       tree tem = gimple_fold_stmt_to_constant_1 (stmt, vrp_valueize,
 						 vrp_valueize_1);
+      x_vr_values = NULL;
       if (tem)
 	{
 	  if (TREE_CODE (tem) == SSA_NAME
@@ -7266,8 +7270,8 @@ vrp_visit_assignment_or_call (gimple *stmt, tree *output_p, value_range *vr)
    or a symbolic range containing the SSA_NAME only if the value range
    is varying or undefined.  */
 
-static inline value_range
-get_vr_for_comparison (int i)
+value_range
+vr_values::get_vr_for_comparison (int i)
 {
   value_range vr = *get_value_range (ssa_name (i));
 
@@ -7289,9 +7293,9 @@ get_vr_for_comparison (int i)
    compare_range_with_value, including the setting of
    *STRICT_OVERFLOW_P.  */
 
-static tree
-compare_name_with_value (enum tree_code comp, tree var, tree val,
-			 bool *strict_overflow_p, bool use_equiv_p)
+tree
+vr_values::compare_name_with_value (enum tree_code comp, tree var, tree val,
+				    bool *strict_overflow_p, bool use_equiv_p)
 {
   bitmap_iterator bi;
   unsigned i;
@@ -7374,9 +7378,9 @@ compare_name_with_value (enum tree_code comp, tree var, tree val,
    whether we relied on undefined signed overflow in the comparison.  */
 
 
-static tree
-compare_names (enum tree_code comp, tree n1, tree n2,
-	       bool *strict_overflow_p)
+tree
+vr_values::compare_names (enum tree_code comp, tree n1, tree n2,
+			  bool *strict_overflow_p)
 {
   tree t, retval;
   bitmap e1, e2;
@@ -7489,10 +7493,9 @@ compare_names (enum tree_code comp, tree n1, tree n2,
 /* Helper function for vrp_evaluate_conditional_warnv & other
    optimizers.  */
 
-static tree
-vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code code,
-						      tree op0, tree op1,
-						      bool * strict_overflow_p)
+tree
+vr_values::vrp_evaluate_conditional_warnv_with_ops_using_ranges
+    (enum tree_code code, tree op0, tree op1, bool * strict_overflow_p)
 {
   value_range *vr0, *vr1;
 
@@ -7512,10 +7515,12 @@ vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code code,
 
 /* Helper function for vrp_evaluate_conditional_warnv. */
 
-static tree
-vrp_evaluate_conditional_warnv_with_ops (enum tree_code code, tree op0,
-					 tree op1, bool use_equiv_p,
-					 bool *strict_overflow_p, bool *only_ranges)
+tree
+vr_values::vrp_evaluate_conditional_warnv_with_ops (enum tree_code code,
+						    tree op0, tree op1,
+						    bool use_equiv_p,
+						    bool *strict_overflow_p,
+						    bool *only_ranges)
 {
   tree ret;
   if (only_ranges)
@@ -7584,8 +7589,9 @@ vrp_evaluate_conditional_warnv_with_ops (enum tree_code code, tree op0,
    based on undefined signed overflow, issue a warning if
    appropriate.  */
 
-static tree
-vrp_evaluate_conditional (tree_code code, tree op0, tree op1, gimple *stmt)
+tree
+vr_values::vrp_evaluate_conditional (tree_code code, tree op0,
+				     tree op1, gimple *stmt)
 {
   bool sop;
   tree ret;
@@ -7676,8 +7682,8 @@ vrp_evaluate_conditional (tree_code code, tree op0, tree op1, gimple *stmt)
    will be taken out of STMT's basic block, record it in
    *TAKEN_EDGE_P.  Otherwise, set *TAKEN_EDGE_P to NULL.  */
 
-static void
-vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p)
+void
+vr_values::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p)
 {
   tree val;
 
@@ -7960,8 +7966,8 @@ find_case_label_ranges (gswitch *stmt, value_range *vr, size_t *min_idx1,
    will be taken out of STMT's basic block, record it in
    *TAKEN_EDGE_P.  Otherwise, *TAKEN_EDGE_P set to NULL.  */
 
-static void
-vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p)
+void
+vr_values::vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p)
 {
   tree op, val;
   value_range *vr;
@@ -8052,9 +8058,9 @@ vrp_visit_switch_stmt (gswitch *stmt, edge *taken_edge_p)
    If STMT is a conditional branch and we can determine its truth
    value, the taken edge is recorded in *TAKEN_EDGE_P.  */
 
-static void
-extract_range_from_stmt (gimple *stmt, edge *taken_edge_p,
-			 tree *output_p, value_range *vr)
+void
+vr_values::extract_range_from_stmt (gimple *stmt, edge *taken_edge_p,
+				    tree *output_p, value_range *vr)
 {
 
   if (dump_file && (dump_flags & TDF_DETAILS))
@@ -8960,8 +8966,8 @@ vrp_meet (value_range *vr0, const value_range *vr1)
    edges.  If a valid value range can be derived from all the incoming
    value ranges, set a new range in VR_RESULT.  */
 
-static void
-extract_range_from_phi_node (gphi *phi, value_range *vr_result)
+void
+vr_values::extract_range_from_phi_node (gphi *phi, value_range *vr_result)
 {
   size_t i;
   tree lhs = PHI_RESULT (phi);
@@ -9205,8 +9211,9 @@ vrp_prop::visit_phi (gphi *phi)
 
 /* Simplify boolean operations if the source is known
    to be already a boolean.  */
-static bool
-simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
+bool
+vr_values::simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi,
+					    gimple *stmt)
 {
   enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
   tree lhs, op0, op1;
@@ -9281,8 +9288,9 @@ simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
    [-op1min + 1, op1min - 1] for signed and [0, op1min - 1] for unsigned
    modulo.  */
 
-static bool
-simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
+bool
+vr_values::simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi,
+					     gimple *stmt)
 {
   enum tree_code rhs_code = gimple_assign_rhs_code (stmt);
   tree val = NULL;
@@ -9405,8 +9413,9 @@ simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
 /* Simplify a min or max if the ranges of the two operands are
    disjoint.   Return true if we do simplify.  */
 
-static bool
-simplify_min_or_max_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
+bool
+vr_values::simplify_min_or_max_using_ranges (gimple_stmt_iterator *gsi,
+					     gimple *stmt)
 {
   tree op0 = gimple_assign_rhs1 (stmt);
   tree op1 = gimple_assign_rhs2 (stmt);
@@ -9452,8 +9461,8 @@ simplify_min_or_max_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
    ABS_EXPR.  If the operand is <= 0, then simplify the
    ABS_EXPR into a NEGATE_EXPR.  */
 
-static bool
-simplify_abs_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
+bool
+vr_values::simplify_abs_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
 {
   tree op = gimple_assign_rhs1 (stmt);
   value_range *vr = get_value_range (op);
@@ -9508,8 +9517,9 @@ simplify_abs_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
    set by | are already known to be one from VR, the bit
    operation is redundant.  */
 
-static bool
-simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
+bool
+vr_values::simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi,
+					  gimple *stmt)
 {
   tree op0 = gimple_assign_rhs1 (stmt);
   tree op1 = gimple_assign_rhs2 (stmt);
@@ -9705,8 +9715,8 @@ range_fits_type_p (value_range *vr, unsigned dest_precision, signop dest_sgn)
    test if the range information indicates only one value can satisfy
    the original conditional.  */
 
-static bool
-simplify_cond_using_ranges_1 (gcond *stmt)
+bool
+vr_values::simplify_cond_using_ranges_1 (gcond *stmt)
 {
   tree op0 = gimple_cond_lhs (stmt);
   tree op1 = gimple_cond_rhs (stmt);
@@ -9790,8 +9800,8 @@ simplify_cond_using_ranges_1 (gcond *stmt)
    of the type conversion.  Doing so makes the conversion dead which helps
    subsequent passes.  */
 
-static void
-simplify_cond_using_ranges_2 (gcond *stmt)
+void
+vr_values::simplify_cond_using_ranges_2 (gcond *stmt)
 {
   tree op0 = gimple_cond_lhs (stmt);
   tree op1 = gimple_cond_rhs (stmt);
@@ -9847,8 +9857,8 @@ simplify_cond_using_ranges_2 (gcond *stmt)
 /* Simplify a switch statement using the value range of the switch
    argument.  */
 
-static bool
-simplify_switch_using_ranges (gswitch *stmt)
+bool
+vr_values::simplify_switch_using_ranges (gswitch *stmt)
 {
   tree op = gimple_switch_index (stmt);
   value_range *vr = NULL;
@@ -10105,9 +10115,9 @@ simplify_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
 
 /* Simplify a conversion from integral SSA name to float in STMT.  */
 
-static bool
-simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
-					gimple *stmt)
+bool
+vr_values::simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
+						   gimple *stmt)
 {
   tree rhs1 = gimple_assign_rhs1 (stmt);
   value_range *vr = get_value_range (rhs1);
@@ -10169,8 +10179,9 @@ simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
 
 /* Simplify an internal fn call using ranges if possible.  */
 
-static bool
-simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
+bool
+vr_values::simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi,
+						gimple *stmt)
 {
   enum tree_code subcode;
   bool is_ubsan = false;
@@ -10271,8 +10282,8 @@ simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
 /* Return true if VAR is a two-valued variable.  Set a and b with the
    two-values when it is true.  Return false otherwise.  */
 
-static bool
-two_valued_val_range_p (tree var, tree *a, tree *b)
+bool
+vr_values::two_valued_val_range_p (tree var, tree *a, tree *b)
 {
   value_range *vr = get_value_range (var);
   if ((vr->type != VR_RANGE
@@ -10306,8 +10317,8 @@ two_valued_val_range_p (tree var, tree *a, tree *b)
 
 /* Simplify STMT using ranges if possible.  */
 
-static bool
-simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
+bool
+vr_values::simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
 {
   gimple *stmt = gsi_stmt (*gsi);
   if (is_gimple_assign (stmt))
@@ -10455,14 +10466,26 @@ class vrp_folder : public substitute_and_fold_engine
  public:
   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;
+
+  /* Delegators.  */
+  tree vrp_evaluate_conditional (tree_code code, tree op0,
+				 tree op1, gimple *stmt)
+    { return vr_values->vrp_evaluate_conditional (code, op0, op1, stmt); }
+  bool simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
+    { return vr_values->simplify_stmt_using_ranges (gsi); }
+ tree op_with_constant_singleton_value_range (tree op)
+    { return vr_values->op_with_constant_singleton_value_range (op); }
 };
 
 /* If the statement pointed by SI has a predicate whose value can be
    computed using the value range information computed by VRP, compute
    its value and return true.  Otherwise, return false.  */
 
-static bool
-fold_predicate_in (gimple_stmt_iterator *si)
+bool
+vrp_folder::fold_predicate_in (gimple_stmt_iterator *si)
 {
   bool assignment_p = false;
   tree val;
@@ -10584,6 +10607,7 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
   if (cached_lhs && is_gimple_min_invariant (cached_lhs))
     return cached_lhs;
 
+  vr_values *vr_values = x_vr_values;
   if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
     {
       tree op0 = gimple_cond_lhs (cond_stmt);
@@ -10592,8 +10616,8 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
       tree op1 = gimple_cond_rhs (cond_stmt);
       op1 = lhs_of_dominating_assert (op1, bb, stmt);
 
-      return vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
-				       op0, op1, within_stmt);
+      return vr_values->vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
+						  op0, op1, within_stmt);
     }
 
   /* We simplify a switch statement by trying to determine which case label
@@ -10607,7 +10631,7 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
 
       op = lhs_of_dominating_assert (op, bb, stmt);
 
-      value_range *vr = get_value_range (op);
+      value_range *vr = vr_values->get_value_range (op);
       if ((vr->type != VR_RANGE && vr->type != VR_ANTI_RANGE)
 	  || symbolic_range_p (vr))
 	return NULL_TREE;
@@ -10668,7 +10692,7 @@ simplify_stmt_for_jump_threading (gimple *stmt, gimple *within_stmt,
 	  && (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
 	      || POINTER_TYPE_P (TREE_TYPE (lhs))))
 	{
-	  extract_range_from_assignment (&new_vr, assign_stmt);
+	  vr_values->extract_range_from_assignment (&new_vr, assign_stmt);
 	  if (range_int_cst_singleton_p (&new_vr))
 	    return new_vr.min;
 	}
@@ -10691,11 +10715,14 @@ public:
   virtual edge before_dom_children (basic_block);
   virtual void after_dom_children (basic_block);
 
+  class vr_values *vr_values;
+
 private:
   class const_and_copies *m_const_and_copies;
   class avail_exprs_stack *m_avail_exprs_stack;
 
   gcond *m_dummy_cond;
+
 };
 
 /* Called before processing dominator children of BB.  We want to look
@@ -10748,9 +10775,11 @@ vrp_dom_walker::after_dom_children (basic_block bb)
 				      integer_zero_node, integer_zero_node,
 				      NULL, NULL);
 
+  x_vr_values = vr_values;
   thread_outgoing_edges (bb, m_dummy_cond, m_const_and_copies,
 			 m_avail_exprs_stack,
 			 simplify_stmt_for_jump_threading);
+  x_vr_values = NULL;
 
   m_avail_exprs_stack->pop_to_marker ();
   m_const_and_copies->pop_to_marker ();
@@ -10777,7 +10806,7 @@ vrp_dom_walker::after_dom_children (basic_block bb)
    for later realization.  */
 
 static void
-identify_jump_threads (void)
+identify_jump_threads (class vr_values *vr_values)
 {
   int i;
   edge e;
@@ -10809,6 +10838,7 @@ identify_jump_threads (void)
     = new class avail_exprs_stack (avail_exprs);
 
   vrp_dom_walker walker (CDI_DOMINATORS, equiv_stack, avail_exprs_stack);
+  walker.vr_values = vr_values;
   walker.walk (cfun->cfg->x_entry_block_ptr);
 
   /* Clear EDGE_IGNORE.  */
@@ -10825,8 +10855,7 @@ identify_jump_threads (void)
 
 /* Free VRP lattice.  */
 
-static void
-vrp_free_lattice ()
+vr_values::~vr_values ()
 {
   /* Free allocated memory.  */
   free (vr_value);
@@ -10842,48 +10871,49 @@ vrp_free_lattice ()
 
 /* Traverse all the blocks folding conditionals with known ranges.  */
 
-static void
-vrp_finalize (bool warn_array_bounds_p)
+void
+vrp_prop::vrp_finalize (bool warn_array_bounds_p)
 {
   size_t i;
 
-  values_propagated = true;
+  vr_values.values_propagated = true;
 
   if (dump_file)
     {
       fprintf (dump_file, "\nValue ranges after VRP:\n\n");
-      dump_all_value_ranges (dump_file);
+      vr_values.dump_all_value_ranges (dump_file);
       fprintf (dump_file, "\n");
     }
 
   /* Set value range to non pointer SSA_NAMEs.  */
-  for (i  = 0; i < num_vr_values; i++)
-    if (vr_value[i])
-      {
-	tree name = ssa_name (i);
+  for (i = 0; i < num_ssa_names; i++)
+    {
+      tree name = ssa_name (i);
+      if (!name)
+	continue;
 
-	if (!name
-	    || (vr_value[i]->type == VR_VARYING)
-	    || (vr_value[i]->type == VR_UNDEFINED)
-	    || (TREE_CODE (vr_value[i]->min) != INTEGER_CST)
-	    || (TREE_CODE (vr_value[i]->max) != INTEGER_CST))
-	  continue;
+      value_range *vr = get_value_range (name);
+      if (!name
+	  || (vr->type == VR_VARYING)
+	  || (vr->type == VR_UNDEFINED)
+	  || (TREE_CODE (vr->min) != INTEGER_CST)
+	  || (TREE_CODE (vr->max) != INTEGER_CST))
+	continue;
 
-	if (POINTER_TYPE_P (TREE_TYPE (name))
-	    && ((vr_value[i]->type == VR_RANGE
-		 && range_includes_zero_p (vr_value[i]->min,
-					   vr_value[i]->max) == 0)
-		|| (vr_value[i]->type == VR_ANTI_RANGE
-		    && range_includes_zero_p (vr_value[i]->min,
-					      vr_value[i]->max) == 1)))
-	  set_ptr_nonnull (name);
-	else if (!POINTER_TYPE_P (TREE_TYPE (name)))
-	  set_range_info (name, vr_value[i]->type,
-			  wi::to_wide (vr_value[i]->min),
-			  wi::to_wide (vr_value[i]->max));
-      }
+      if (POINTER_TYPE_P (TREE_TYPE (name))
+	  && ((vr->type == VR_RANGE
+	       && range_includes_zero_p (vr->min, vr->max) == 0)
+	      || (vr->type == VR_ANTI_RANGE
+		  && range_includes_zero_p (vr->min, vr->max) == 1)))
+	set_ptr_nonnull (name);
+      else if (!POINTER_TYPE_P (TREE_TYPE (name)))
+	set_range_info (name, vr->type,
+			wi::to_wide (vr->min),
+			wi::to_wide (vr->max));
+    }
 
   class vrp_folder vrp_folder;
+  vrp_folder.vr_values = &vr_values;
   vrp_folder.substitute_and_fold ();
 
   if (warn_array_bounds && warn_array_bounds_p)
@@ -10917,6 +10947,38 @@ public:
   bitmap need_eh_cleanup;
   auto_vec<gimple *> stmts_to_fixup;
   auto_vec<gimple *> stmts_to_remove;
+
+  class vr_values vr_values;
+
+  /* Temporary delegators.  */
+  value_range *get_value_range (const_tree op)
+    { return vr_values.get_value_range (op); }
+  bool update_value_range (const_tree op, value_range *vr)
+    { return vr_values.update_value_range (op, vr); }
+  void extract_range_from_phi_node (gphi *phi, value_range *vr)
+    { vr_values.extract_range_from_phi_node (phi, vr); }
+  void extract_range_for_var_from_comparison_expr (tree var,
+						   enum tree_code cond_code,
+						   tree op, tree limit,
+						   value_range *vr_p)
+    { vr_values.extract_range_for_var_from_comparison_expr (var, cond_code,
+							    op, limit, vr_p); }
+  void adjust_range_with_scev (value_range *vr, struct loop *loop,
+			       gimple *stmt, tree var)
+    { vr_values.adjust_range_with_scev (vr, loop, stmt, var); }
+  tree op_with_constant_singleton_value_range (tree op)
+    { return vr_values.op_with_constant_singleton_value_range (op); }
+  void extract_range_from_stmt (gimple *stmt, edge *taken_edge_p,
+				tree *output_p, value_range *vr)
+    { vr_values.extract_range_from_stmt (stmt, taken_edge_p, output_p, vr); }
+  void set_defs_to_varying (gimple *stmt)
+    { return vr_values.set_defs_to_varying (stmt); }
+  void set_vr_value (tree name, value_range *vr)
+    { vr_values.set_vr_value (name, vr); }
+  void simplify_cond_using_ranges_2 (gcond *stmt)
+    { vr_values.simplify_cond_using_ranges_2 (stmt); }
+  void vrp_visit_cond_stmt (gcond *cond, edge *e)
+    { vr_values.vrp_visit_cond_stmt (cond, e); }
 };
 
 /*  Find new range for NAME such that (OP CODE LIMIT) is true.  */
@@ -10939,7 +11001,7 @@ evrp_dom_walker::try_find_new_range (tree name,
 	  && 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 ();
+      value_range *new_vr = vr_values.vrp_value_range_pool.allocate ();
       *new_vr = vr;
       return new_vr;
     }
@@ -11208,6 +11270,7 @@ evrp_dom_walker::before_dom_children (basic_block bb)
 
       /* Try folding stmts with the VR discovered.  */
       class vrp_folder vrp_folder;
+      vrp_folder.vr_values = &vr_values;
       bool did_replace = vrp_folder.replace_uses_in (stmt);
       if (fold_stmt (&gsi, follow_single_use_edges)
 	  || did_replace)
@@ -11274,13 +11337,19 @@ evrp_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED)
   stack.pop ();
 }
 
+void
+vr_values::set_vr_value (tree var, value_range *vr)
+{
+  if (SSA_NAME_VERSION (var) >= num_vr_values)
+    return;
+  vr_value[SSA_NAME_VERSION (var)] = vr;
+}
+
 /* Push the Value Range of VAR to the stack and update it with new VR.  */
 
 void
 evrp_dom_walker::push_value_range (tree var, value_range *vr)
 {
-  if (SSA_NAME_VERSION (var) >= num_vr_values)
-    return;
   if (dump_file && (dump_flags & TDF_DETAILS))
     {
       fprintf (dump_file, "pushing new range for ");
@@ -11290,7 +11359,7 @@ evrp_dom_walker::push_value_range (tree var, value_range *vr)
       fprintf (dump_file, "\n");
     }
   stack.safe_push (std::make_pair (var, get_value_range (var)));
-  vr_value[SSA_NAME_VERSION (var)] = vr;
+  set_vr_value (var, vr);
 }
 
 /* Pop the Value Range from the vrp_stack and update VAR with it.  */
@@ -11308,7 +11377,7 @@ evrp_dom_walker::pop_value_range (tree var)
       dump_value_range (dump_file, vr);
       fprintf (dump_file, "\n");
     }
-  vr_value[SSA_NAME_VERSION (var)] = vr;
+  set_vr_value (var, vr);
   stack.pop ();
   return vr;
 }
@@ -11335,7 +11404,6 @@ execute_early_vrp ()
       FOR_EACH_EDGE (e, ei, bb->preds)
 	e->flags |= EDGE_EXECUTABLE;
     }
-  vrp_initialize_lattice ();
 
   /* Walk stmts in dominance order and propagate VRP.  */
   evrp_dom_walker walker;
@@ -11344,7 +11412,7 @@ execute_early_vrp ()
   if (dump_file)
     {
       fprintf (dump_file, "\nValue ranges after Early VRP:\n\n");
-      dump_all_value_ranges (dump_file);
+      walker.vr_values.dump_all_value_ranges (dump_file);
       fprintf (dump_file, "\n");
     }
 
@@ -11382,7 +11450,6 @@ execute_early_vrp ()
       fixup_noreturn_call (stmt);
     }
 
-  vrp_free_lattice ();
   scev_finalize ();
   loop_optimizer_finalize ();
   return 0;
@@ -11456,15 +11523,14 @@ execute_vrp (bool warn_array_bounds_p)
   /* For visiting PHI nodes we need EDGE_DFS_BACK computed.  */
   mark_dfs_back_edges ();
 
-  vrp_initialize_lattice ();
-  vrp_initialize ();
   class vrp_prop vrp_prop;
+  vrp_prop.vrp_initialize ();
   vrp_prop.ssa_propagate ();
-  vrp_finalize (warn_array_bounds_p);
+  vrp_prop.vrp_finalize (warn_array_bounds_p);
 
   /* We must identify jump threading opportunities before we release
      the datastructures built by VRP.  */
-  identify_jump_threads ();
+  identify_jump_threads (&vrp_prop.vr_values);
 
   /* A comparison of an SSA_NAME against a constant where the SSA_NAME
      was set by a type conversion can often be rewritten to use the
@@ -11478,11 +11544,9 @@ execute_vrp (bool warn_array_bounds_p)
     {
       gimple *last = last_stmt (bb);
       if (last && gimple_code (last) == GIMPLE_COND)
-	simplify_cond_using_ranges_2 (as_a <gcond *> (last));
+	vrp_prop.vr_values.simplify_cond_using_ranges_2 (as_a <gcond *> (last));
     }
 
-  vrp_free_lattice ();
-
   free_numbers_of_iterations_estimates (cfun);
 
   /* ASSERT_EXPRs must be removed before finalizing jump threads
diff --git a/gcc/vr-values.h b/gcc/vr-values.h
new file mode 100644
index 00000000000..3b38ab6e941
--- /dev/null
+++ b/gcc/vr-values.h
@@ -0,0 +1,119 @@
+/* Support routines for Value Range Propagation (VRP).
+   Copyright (C) 2016-2017 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_VR_VALUES_H
+#define GCC_VR_VALUES_H
+
+/* The VR_VALUES class holds the current view of range information
+   for all the SSA_NAMEs in the IL.
+
+   It can be used to hold context sensitive range information during
+   a dominator walk or it may be used to hold range information in the
+   standard VRP pass as ranges are propagated through the lattice to a
+   steady state.
+
+   This information is independent of the range information that gets
+   attached to SSA_NAMEs.  A pass such as VRP may choose to transfer
+   the global information it produces into global range information that
+   gets attached to an SSA_NAME.  It's unclear how useful that global
+   information will be in a world where we can compute context sensitive
+   range information fast or perform on-demand queries.  */
+class vr_values
+{
+ public:
+  vr_values (void);
+  ~vr_values (void);
+
+  /* Value range array.  After propagation, VR_VALUE[I] holds the range
+     of values that SSA name N_I may take.  */
+  unsigned int num_vr_values;
+  value_range **vr_value;
+  bool values_propagated;
+
+  /* For a PHI node which sets SSA name N_I, VR_COUNTS[I] holds the
+     number of executable edges we saw the last time we visited the
+     node.  */
+  int *vr_phi_edge_counts;
+
+  /* Allocation pools for tree-vrp allocations.  */
+  object_allocator<value_range> vrp_value_range_pool;
+  bitmap_obstack vrp_equiv_obstack;
+
+  value_range *get_value_range (const_tree);
+  void set_vr_value (tree, value_range *);
+
+  void set_defs_to_varying (gimple *);
+  bool update_value_range (const_tree, value_range *);
+  void add_equivalence (bitmap *, const_tree);
+  bool vrp_stmt_computes_nonzero (gimple *);
+  tree op_with_constant_singleton_value_range (tree);
+  bool op_with_boolean_value_range_p (tree);
+  bool check_for_binary_op_overflow (enum tree_code, tree, tree, tree, bool *);
+  void adjust_range_with_scev (value_range *, struct loop *, gimple *, tree);
+  value_range get_vr_for_comparison (int);
+  tree compare_name_with_value (enum tree_code, tree, tree, bool *, bool);
+  tree compare_names (enum tree_code, tree, tree, bool *);
+  bool two_valued_val_range_p (tree, tree *, tree *);
+
+  tree vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code,
+							     tree, tree,
+							     bool *);
+  tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code,
+						tree, tree, bool,
+						bool *, bool *);
+  tree vrp_evaluate_conditional (tree_code, tree, tree, gimple *);
+
+
+  void dump_all_value_ranges (FILE *);
+
+  void extract_range_for_var_from_comparison_expr (tree, enum tree_code,
+						   tree, tree, value_range *);
+  void extract_range_from_assert (value_range *, tree);
+  void extract_range_from_ssa_name (value_range *, tree);
+  void extract_range_from_binary_expr (value_range *, enum tree_code,
+				       tree, tree, tree);
+  void extract_range_from_unary_expr (value_range *, enum tree_code,
+				      tree, tree);
+  void extract_range_from_phi_node (gphi *, value_range *);
+  void extract_range_from_cond_expr (value_range *, gassign *);
+  void extract_range_basic (value_range *, gimple *);
+  void extract_range_from_assignment (value_range *, gassign *);
+  void extract_range_from_stmt (gimple *, edge *, tree *, value_range *);
+  void extract_range_from_comparison (value_range *, enum tree_code,
+				      tree, tree, tree);
+
+  void vrp_visit_assignment_or_call (gimple*, tree *, value_range *);
+  void vrp_visit_switch_stmt (gswitch *, edge *);
+  void vrp_visit_cond_stmt (gcond *, edge *);
+
+  bool simplify_truth_ops_using_ranges (gimple_stmt_iterator *, gimple *);
+  bool simplify_div_or_mod_using_ranges (gimple_stmt_iterator *, gimple *);
+  bool simplify_abs_using_ranges (gimple_stmt_iterator *, gimple *);
+  bool simplify_bit_ops_using_ranges (gimple_stmt_iterator *, gimple *);
+  bool simplify_min_or_max_using_ranges (gimple_stmt_iterator *, gimple *);
+  bool simplify_cond_using_ranges_1 (gcond *);
+  void simplify_cond_using_ranges_2 (gcond *);
+  bool simplify_switch_using_ranges (gswitch *);
+  bool simplify_float_conversion_using_ranges (gimple_stmt_iterator *,
+					       gimple *);
+  bool simplify_internal_call_using_ranges (gimple_stmt_iterator *, gimple *);
+  bool simplify_stmt_using_ranges (gimple_stmt_iterator *);
+};
+
+#endif /* GCC_VR_VALUES_H */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]