Move simplification of statements using ranges into its own class.

Message ID 9987ee3d-d78b-b719-5a23-6450dd54f73f@redhat.com
State New
Headers show
Series
  • Move simplification of statements using ranges into its own class.
Related show

Commit Message

Christophe Lyon via Gcc-patches June 18, 2020, 11:24 a.m.
Howdy.

This moves all the simplification code from vr_values into a separate 
class (simplify_using_ranges).  In doing so, we get rid of a bunch of 
dependencies on the internals of vr_values.  The goal is to (a) remove 
unnecessary interdependendcies (b) be able to use this engine with any 
range infrastructure, as all it needs is a method to get the range for 
an SSA name (get_value_range).

I also removed as many dependencies on value_range_equiv as possible, 
preferring value_range.  A few value_range_equiv uses remain, but for 
cases where equivalences are actually used (folding conditionals, etc).

The plan is to use it like this:

   simplify_using_ranges simplifier (vr_values_thinggie);
   simplifier.simplify (gsi);

OK?

Aldy

Comments

Christophe Lyon via Gcc-patches June 25, 2020, 4:09 p.m. | #1
PING

On Thu, Jun 18, 2020, 13:24 Aldy Hernandez <aldyh@redhat.com> wrote:

> Howdy.

>

> This moves all the simplification code from vr_values into a separate

> class (simplify_using_ranges).  In doing so, we get rid of a bunch of

> dependencies on the internals of vr_values.  The goal is to (a) remove

> unnecessary interdependendcies (b) be able to use this engine with any

> range infrastructure, as all it needs is a method to get the range for

> an SSA name (get_value_range).

>

> I also removed as many dependencies on value_range_equiv as possible,

> preferring value_range.  A few value_range_equiv uses remain, but for

> cases where equivalences are actually used (folding conditionals, etc).

>

> The plan is to use it like this:

>

>    simplify_using_ranges simplifier (vr_values_thinggie);

>    simplifier.simplify (gsi);

>

> OK?

>

> Aldy

>

>
Christophe Lyon via Gcc-patches June 26, 2020, 9:19 p.m. | #2
On Thu, 2020-06-18 at 13:24 +0200, Aldy Hernandez wrote:
> Howdy.

> 

> This moves all the simplification code from vr_values into a separate 

> class (simplify_using_ranges).  In doing so, we get rid of a bunch of 

> dependencies on the internals of vr_values.  The goal is to (a) remove 

> unnecessary interdependendcies (b) be able to use this engine with any 

> range infrastructure, as all it needs is a method to get the range for 

> an SSA name (get_value_range).

> 

> I also removed as many dependencies on value_range_equiv as possible, 

> preferring value_range.  A few value_range_equiv uses remain, but for 

> cases where equivalences are actually used (folding conditionals, etc).

> 

> The plan is to use it like this:

> 

>    simplify_using_ranges simplifier (vr_values_thinggie);

>    simplifier.simplify (gsi);

> 

> OK?

OK
jeff
>

Patch

commit 753d495161942d7085c5955f47fefa7a4378562a
Author: Aldy Hernandez <aldyh@redhat.com>
Date:   Thu Jun 18 10:37:14 2020 +0200

    Move simplification of statements using ranges into its own class.
    
    This moves all the simplification code from vr_values into a separate
    class (simplify_using_ranges).  In doing so, we get rid of a bunch of
    dependencies on the internals of vr_values.  The goal is to (a) remove
    unnecessary interdependendcies (b) be able to use this engine with any
    range infrastructure, as all it needs is a method to get the range for
    an SSA name (get_value_range).
    
    I also removed as many dependencies on value_range_equiv as possible,
    preferring value_range.  A few value_range_equiv uses remain, but for
    cases where equivalences are actually used (folding conditionals, etc).
    
    gcc/ChangeLog:
    
            * gimple-ssa-evrp-analyze.h (vrp_visit_cond_stmt): Use
            simplify_using_ranges class.
            * gimple-ssa-evrp.c (class evrp_folder): New simplify_using_ranges
            field.  Adjust all methods to use new field.
            * tree-ssa-dom.c (simplify_stmt_for_jump_threading): Use
            simplify_using_ranges class.
            * tree-vrp.c (class vrp_folder): New simplify_using_ranges
            field.  Adjust all methods to use new field.
            (simplify_stmt_for_jump_threading): Use simplify_using_ranges class.
            (vrp_prop::vrp_finalize): New vrp_folder argument.
            (execute_vrp): Pass folder to vrp_finalize.  Use
            simplify_using_ranges class.
            Remove cleanup_edges_and_switches call.
            * vr-values.c (vr_values::op_with_boolean_value_range_p): Change
            value_range_equiv uses to value_range.
            (simplify_using_ranges::op_with_boolean_value_range_p): Use
            simplify_using_ranges class.
            (check_for_binary_op_overflow): Make static.
            (vr_values::extract_range_basic): Pass this to
            check_for_binary_op_overflow.
            (compare_range_with_value): Change value_range_equiv uses to
            value_range.
            (vr_values::vr_values): Initialize simplifier field.
            Remove uses of to_remove_edges and to_update_switch_stmts.
            (vr_values::~vr_values): Remove uses of to_remove_edges and
            to_update_switch_stmts.
            (vr_values::get_vr_for_comparison): Move to simplify_using_ranges
            class.
            (vr_values::compare_name_with_value): Same.
            (vr_values::compare_names): Same.
            (vr_values::vrp_evaluate_conditional_warnv_with_ops): Same.
            (vr_values::vrp_evaluate_conditional): Same.
            (vr_values::vrp_visit_cond_stmt): Same.
            (find_case_label_ranges): Change value_range_equiv uses to
            value_range.
            (vr_values::extract_range_from_stmt): Use simplify_using_ranges class.
            (vr_values::simplify_truth_ops_using_ranges): Move to
            simplify_using_ranges class.
            (vr_values::simplify_div_or_mod_using_ranges): Same.
            (vr_values::simplify_min_or_max_using_ranges): Same.
            (vr_values::simplify_abs_using_ranges): Same.
            (vr_values::simplify_bit_ops_using_ranges): Same.
            (test_for_singularity): Change value_range_equiv uses to
            value_range.
            (range_fits_type_p): Same.
            (vr_values::simplify_cond_using_ranges_1): Same.
            (vr_values::simplify_cond_using_ranges_2): Make extern.
            (vr_values::fold_cond): Move to simplify_using_ranges class.
            (vr_values::simplify_switch_using_ranges): Same.
            (vr_values::cleanup_edges_and_switches): Same.
            (vr_values::simplify_float_conversion_using_ranges): Same.
            (vr_values::simplify_internal_call_using_ranges): Same.
            (vr_values::two_valued_val_range_p): Same.
            (vr_values::simplify_stmt_using_ranges): Move to...
            (simplify_using_ranges::simplify): ...here.
            * vr-values.h (class vr_values): Move all the simplification of
            statements using ranges methods and code from here...
            (class simplify_using_ranges): ...to here.
            (simplify_cond_using_ranges_2): New extern prototype.

diff --git a/gcc/gimple-ssa-evrp-analyze.h b/gcc/gimple-ssa-evrp-analyze.h
index d16279f89b9..8abbbe3180d 100644
--- a/gcc/gimple-ssa-evrp-analyze.h
+++ b/gcc/gimple-ssa-evrp-analyze.h
@@ -50,7 +50,10 @@  class evrp_range_analyzer
 
   /* A bit of a wart.  This should ideally go away.  */
   void vrp_visit_cond_stmt (gcond *cond, edge *e)
-    { return vr_values->vrp_visit_cond_stmt (cond, e); }
+  {
+    simplify_using_ranges simpl (vr_values);
+    simpl.vrp_visit_cond_stmt (cond, e);
+  }
 
   /* Get the underlying vr_values class instance.  If TRANSFER is
      true, then we are transferring ownership.  Else we keep ownership.
diff --git a/gcc/gimple-ssa-evrp.c b/gcc/gimple-ssa-evrp.c
index af780fd0519..e8fde63aa34 100644
--- a/gcc/gimple-ssa-evrp.c
+++ b/gcc/gimple-ssa-evrp.c
@@ -46,14 +46,13 @@  class evrp_folder : public substitute_and_fold_engine
 {
 public:
   evrp_folder () : m_range_analyzer (/*update_global_ranges=*/true),
-    m_vr_values (m_range_analyzer.get_vr_values ())
+    m_vr_values (m_range_analyzer.get_vr_values ()),
+    simplifier (m_vr_values)
   {
   }
 
   ~evrp_folder ()
   {
-    m_vr_values->cleanup_edges_and_switches ();
-
     if (dump_file)
       {
 	fprintf (dump_file, "\nValue ranges after Early VRP:\n\n");
@@ -86,7 +85,7 @@  public:
 
   bool fold_stmt (gimple_stmt_iterator *gsi) OVERRIDE
   {
-    return m_vr_values->simplify_stmt_using_ranges (gsi);
+    return simplifier.simplify (gsi);
   }
 
   void post_fold_bb (basic_block bb) OVERRIDE
@@ -96,13 +95,15 @@  public:
 
   void post_new_stmt (gimple *stmt) OVERRIDE
   {
-    m_vr_values->set_defs_to_varying (stmt);
+    m_range_analyzer.get_vr_values ()->set_defs_to_varying (stmt);
   }
 
 private:
   DISABLE_COPY_AND_ASSIGN (evrp_folder);
   class evrp_range_analyzer m_range_analyzer;
   class vr_values *m_vr_values;
+
+  simplify_using_ranges simplifier;
 };
 
 /* Main entry point for the early vrp pass which is a simplified non-iterative
diff --git a/gcc/tree-ssa-dom.c b/gcc/tree-ssa-dom.c
index 864c984f636..69eaec345bf 100644
--- a/gcc/tree-ssa-dom.c
+++ b/gcc/tree-ssa-dom.c
@@ -887,12 +887,11 @@  simplify_stmt_for_jump_threading (gimple *stmt,
      copy in tree-vrp is scheduled for removal in gcc-9.  */
   if (gcond *cond_stmt = dyn_cast <gcond *> (stmt))
     {
-      cached_lhs
-	= x_vr_values->vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
-						 gimple_cond_lhs (cond_stmt),
-						 gimple_cond_rhs (cond_stmt),
-						 within_stmt);
-      return cached_lhs;
+      simplify_using_ranges simplifier (x_vr_values);
+      return simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
+						  gimple_cond_lhs (cond_stmt),
+						  gimple_cond_rhs (cond_stmt),
+						  within_stmt);
     }
 
   if (gswitch *switch_stmt = dyn_cast <gswitch *> (stmt))
diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c
index c39a6f5e374..7193ca4ad5e 100644
--- a/gcc/tree-vrp.c
+++ b/gcc/tree-vrp.c
@@ -3373,7 +3373,7 @@  public:
   struct function *fun;
 
   void vrp_initialize (struct function *);
-  void vrp_finalize (bool);
+  void vrp_finalize (class vrp_folder *, bool);
 
   class vr_values vr_values;
 
@@ -3938,23 +3938,28 @@  vrp_prop::visit_phi (gphi *phi)
 
 class vrp_folder : public substitute_and_fold_engine
 {
-public:
-  vrp_folder () : substitute_and_fold_engine (/* Fold all stmts.  */ true) {  }
+ public:
+  vrp_folder (vr_values *v)
+    : substitute_and_fold_engine (/* Fold all stmts.  */ true),
+      m_vr_values (v), simplifier (v)
+    {  }
   tree get_value (tree, gimple *stmt) FINAL OVERRIDE;
   bool fold_stmt (gimple_stmt_iterator *) FINAL OVERRIDE;
 
-  class vr_values *vr_values;
+  class vr_values *m_vr_values;
 
 private:
   bool fold_predicate_in (gimple_stmt_iterator *);
   /* Delegators.  */
   tree vrp_evaluate_conditional (tree_code code, tree op0,
 				 tree op1, gimple *stmt)
-    { return vr_values->vrp_evaluate_conditional (code, op0, op1, stmt); }
+    { return simplifier.vrp_evaluate_conditional (code, op0, op1, stmt); }
   bool simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
-    { return vr_values->simplify_stmt_using_ranges (gsi); }
+    { return simplifier.simplify (gsi); }
  tree op_with_constant_singleton_value_range (tree op)
-    { return vr_values->op_with_constant_singleton_value_range (op); }
+    { return m_vr_values->op_with_constant_singleton_value_range (op); }
+
+  simplify_using_ranges simplifier;
 };
 
 /* If the statement pointed by SI has a predicate whose value can be
@@ -4096,7 +4101,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 vr_values->vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
+      simplify_using_ranges simplifier (vr_values);
+      return simplifier.vrp_evaluate_conditional (gimple_cond_code (cond_stmt),
 						  op0, op1, within_stmt);
     }
 
@@ -4332,7 +4338,7 @@  identify_jump_threads (struct function *fun, class vr_values *vr_values)
 /* Traverse all the blocks folding conditionals with known ranges.  */
 
 void
-vrp_prop::vrp_finalize (bool warn_array_bounds_p)
+vrp_prop::vrp_finalize (vrp_folder *folder, bool warn_array_bounds_p)
 {
   size_t i;
 
@@ -4376,9 +4382,7 @@  vrp_prop::vrp_finalize (bool warn_array_bounds_p)
   if (warn_array_bounds && warn_array_bounds_p)
     set_all_edges_as_executable (fun);
 
-  class vrp_folder vrp_folder;
-  vrp_folder.vr_values = &vr_values;
-  vrp_folder.substitute_and_fold ();
+  folder->substitute_and_fold ();
 
   if (warn_array_bounds && warn_array_bounds_p)
     {
@@ -4453,7 +4457,10 @@  execute_vrp (struct function *fun, bool warn_array_bounds_p)
   class vrp_prop vrp_prop;
   vrp_prop.vrp_initialize (fun);
   vrp_prop.ssa_propagate ();
-  vrp_prop.vrp_finalize (warn_array_bounds_p);
+  /* Instantiate the folder here, so that edge cleanups happen at the
+     end of this function.  */
+  vrp_folder folder (&vrp_prop.vr_values);
+  vrp_prop.vrp_finalize (&folder, warn_array_bounds_p);
 
   /* We must identify jump threading opportunities before we release
      the datastructures built by VRP.  */
@@ -4471,7 +4478,8 @@  execute_vrp (struct function *fun, bool warn_array_bounds_p)
     {
       gimple *last = last_stmt (bb);
       if (last && gimple_code (last) == GIMPLE_COND)
-	vrp_prop.vr_values.simplify_cond_using_ranges_2 (as_a <gcond *> (last));
+	simplify_cond_using_ranges_2 (&vrp_prop.vr_values,
+				      as_a <gcond *> (last));
     }
 
   free_numbers_of_iterations_estimates (fun);
@@ -4496,7 +4504,6 @@  execute_vrp (struct function *fun, bool warn_array_bounds_p)
      processing by the pass manager.  */
   thread_through_all_blocks (false);
 
-  vrp_prop.vr_values.cleanup_edges_and_switches ();
   threadedge_finalize_values ();
 
   scev_finalize ();
diff --git a/gcc/vr-values.c b/gcc/vr-values.c
index e95df78870a..d0303599002 100644
--- a/gcc/vr-values.c
+++ b/gcc/vr-values.c
@@ -435,10 +435,8 @@  vr_values::op_with_constant_singleton_value_range (tree op)
 /* Return true if op is in a boolean [0, 1] value-range.  */
 
 bool
-vr_values::op_with_boolean_value_range_p (tree op)
+simplify_using_ranges::op_with_boolean_value_range_p (tree op)
 {
-  const value_range_equiv *vr;
-
   if (TYPE_PRECISION (TREE_TYPE (op)) == 1)
     return true;
 
@@ -449,7 +447,7 @@  vr_values::op_with_boolean_value_range_p (tree op)
   if (TREE_CODE (op) != SSA_NAME)
     return false;
 
-  vr = get_value_range (op);
+  const value_range *vr = get_value_range (op);
   return (vr->kind () == VR_RANGE
 	  && integer_zerop (vr->min ())
 	  && integer_onep (vr->max ()));
@@ -976,10 +974,9 @@  vr_values::extract_range_from_comparison (value_range_equiv *vr,
 					  tree type, tree op0, tree op1)
 {
   bool sop;
-  tree val;
-
-  val = vrp_evaluate_conditional_warnv_with_ops (code, op0, op1, false, &sop,
-  						 NULL);
+  tree val
+    = simplifier.vrp_evaluate_conditional_warnv_with_ops (code, op0, op1,
+							  false, &sop, NULL);
   if (val)
     {
       /* Since this expression was found on the RHS of an assignment,
@@ -1002,20 +999,21 @@  vr_values::extract_range_from_comparison (value_range_equiv *vr,
    always overflow.  Set *OVF to true if it is known to always
    overflow.  */
 
-bool
-vr_values::check_for_binary_op_overflow (enum tree_code subcode, tree type,
-					 tree op0, tree op1, bool *ovf)
+static bool
+check_for_binary_op_overflow (vr_values *store,
+			      enum tree_code subcode, tree type,
+			      tree op0, tree op1, bool *ovf)
 {
   value_range vr0, vr1;
   if (TREE_CODE (op0) == SSA_NAME)
-    vr0 = *get_value_range (op0);
+    vr0 = *store->get_value_range (op0);
   else if (TREE_CODE (op0) == INTEGER_CST)
     vr0.set (op0);
   else
     vr0.set_varying (TREE_TYPE (op0));
 
   if (TREE_CODE (op1) == SSA_NAME)
-    vr1 = *get_value_range (op1);
+    vr1 = *store->get_value_range (op1);
   else if (TREE_CODE (op1) == INTEGER_CST)
     vr1.set (op1);
   else
@@ -1395,7 +1393,7 @@  vr_values::extract_range_basic (value_range_equiv *vr, gimple *stmt)
 		  if (code == IMAGPART_EXPR)
 		    {
 		      bool ovf = false;
-		      if (check_for_binary_op_overflow (subcode, type,
+		      if (check_for_binary_op_overflow (this, subcode, type,
 							op0, op1, &ovf))
 			vr->set (build_int_cst (type, ovf));
 		      else if (TYPE_PRECISION (type) == 1
@@ -1636,7 +1634,7 @@  compare_ranges (enum tree_code comp, const value_range_equiv *vr0,
    assumed signed overflow is undefined.  */
 
 static tree
-compare_range_with_value (enum tree_code comp, const value_range_equiv *vr,
+compare_range_with_value (enum tree_code comp, const value_range *vr,
 			  tree val, bool *strict_overflow_p)
 {
   if (vr->varying_p () || vr->undefined_p ())
@@ -1946,15 +1944,14 @@  vr_values::dump_all_value_ranges (FILE *file)
 
 /* Initialize VRP lattice.  */
 
-vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges")
+vr_values::vr_values () : vrp_value_range_pool ("Tree VRP value ranges"),
+  simplifier (this)
 {
   values_propagated = false;
   num_vr_values = num_ssa_names * 2;
   vr_value = XCNEWVEC (value_range_equiv *, num_vr_values);
   vr_phi_edge_counts = XCNEWVEC (int, num_ssa_names);
   bitmap_obstack_initialize (&vrp_equiv_obstack);
-  to_remove_edges = vNULL;
-  to_update_switch_stmts = vNULL;
 }
 
 /* Free VRP lattice.  */
@@ -1971,12 +1968,6 @@  vr_values::~vr_values ()
      and not available.  */
   vr_value = NULL;
   vr_phi_edge_counts = NULL;
-
-  /* If there are entries left in TO_REMOVE_EDGES or TO_UPDATE_SWITCH_STMTS
-     then an EVRP client did not clean up properly.  Catch it now rather
-     than seeing something more obscure later.  */
-  gcc_assert (to_remove_edges.is_empty ()
-	      && to_update_switch_stmts.is_empty ());
 }
 
 
@@ -2094,7 +2085,7 @@  vr_values::vrp_visit_assignment_or_call (gimple *stmt, tree *output_p,
    is varying or undefined.  Uses TEM as storage for the alternate range.  */
 
 const value_range_equiv *
-vr_values::get_vr_for_comparison (int i, value_range_equiv *tem)
+simplify_using_ranges::get_vr_for_comparison (int i, value_range_equiv *tem)
 {
   /* Shallow-copy equiv bitmap.  */
   const value_range_equiv *vr = get_value_range (ssa_name (i));
@@ -2117,8 +2108,9 @@  vr_values::get_vr_for_comparison (int i, value_range_equiv *tem)
    *STRICT_OVERFLOW_P.  */
 
 tree
-vr_values::compare_name_with_value (enum tree_code comp, tree var, tree val,
-				    bool *strict_overflow_p, bool use_equiv_p)
+simplify_using_ranges::compare_name_with_value
+				(enum tree_code comp, tree var, tree val,
+				 bool *strict_overflow_p, bool use_equiv_p)
 {
   /* Get the set of equivalences for VAR.  */
   bitmap e = get_value_range (var)->equiv ();
@@ -2196,8 +2188,8 @@  vr_values::compare_name_with_value (enum tree_code comp, tree var, tree val,
 
 
 tree
-vr_values::compare_names (enum tree_code comp, tree n1, tree n2,
-			  bool *strict_overflow_p)
+simplify_using_ranges::compare_names (enum tree_code comp, tree n1, tree n2,
+				      bool *strict_overflow_p)
 {
   /* Compare the ranges of every name equivalent to N1 against the
      ranges of every name equivalent to N2.  */
@@ -2310,7 +2302,7 @@  vr_values::compare_names (enum tree_code comp, tree n1, tree n2,
    optimizers.  */
 
 tree
-vr_values::vrp_evaluate_conditional_warnv_with_ops_using_ranges
+simplify_using_ranges::vrp_evaluate_conditional_warnv_with_ops_using_ranges
     (enum tree_code code, tree op0, tree op1, bool * strict_overflow_p)
 {
   const value_range_equiv *vr0, *vr1;
@@ -2331,11 +2323,12 @@  vr_values::vrp_evaluate_conditional_warnv_with_ops_using_ranges
 /* Helper function for vrp_evaluate_conditional_warnv. */
 
 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)
+simplify_using_ranges::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)
@@ -2438,8 +2431,8 @@  vr_values::vrp_evaluate_conditional_warnv_with_ops (enum tree_code code,
    appropriate.  */
 
 tree
-vr_values::vrp_evaluate_conditional (tree_code code, tree op0,
-				     tree op1, gimple *stmt)
+simplify_using_ranges::vrp_evaluate_conditional (tree_code code, tree op0,
+						 tree op1, gimple *stmt)
 {
   bool sop;
   tree ret;
@@ -2531,7 +2524,7 @@  vr_values::vrp_evaluate_conditional (tree_code code, tree op0,
    *TAKEN_EDGE_P.  Otherwise, set *TAKEN_EDGE_P to NULL.  */
 
 void
-vr_values::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p)
+simplify_using_ranges::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p)
 {
   tree val;
 
@@ -2551,7 +2544,7 @@  vr_values::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p)
 	  fprintf (dump_file, "\t");
 	  print_generic_expr (dump_file, use);
 	  fprintf (dump_file, ": ");
-	  dump_value_range (dump_file, vr_value[SSA_NAME_VERSION (use)]);
+	  dump_value_range (dump_file, get_value_range (use));
 	}
 
       fprintf (dump_file, "\n");
@@ -2624,7 +2617,7 @@  vr_values::vrp_visit_cond_stmt (gcond *stmt, edge *taken_edge_p)
    Returns true if the default label is not needed.  */
 
 static bool
-find_case_label_ranges (gswitch *stmt, const value_range_equiv *vr,
+find_case_label_ranges (gswitch *stmt, const value_range *vr,
 			size_t *min_idx1, size_t *max_idx1,
 			size_t *min_idx2, size_t *max_idx2)
 {
@@ -2808,7 +2801,7 @@  vr_values::extract_range_from_stmt (gimple *stmt, edge *taken_edge_p,
   else if (is_gimple_assign (stmt) || is_gimple_call (stmt))
     vrp_visit_assignment_or_call (stmt, output_p, vr);
   else if (gimple_code (stmt) == GIMPLE_COND)
-    vrp_visit_cond_stmt (as_a <gcond *> (stmt), taken_edge_p);
+    simplifier.vrp_visit_cond_stmt (as_a <gcond *> (stmt), taken_edge_p);
   else if (gimple_code (stmt) == GIMPLE_SWITCH)
     vrp_visit_switch_stmt (as_a <gswitch *> (stmt), taken_edge_p);
 }
@@ -3029,8 +3022,9 @@  update_range:
 /* Simplify boolean operations if the source is known
    to be already a boolean.  */
 bool
-vr_values::simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi,
-					    gimple *stmt)
+simplify_using_ranges::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;
@@ -3106,8 +3100,9 @@  vr_values::simplify_truth_ops_using_ranges (gimple_stmt_iterator *gsi,
    modulo.  */
 
 bool
-vr_values::simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi,
-					     gimple *stmt)
+simplify_using_ranges::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;
@@ -3115,7 +3110,7 @@  vr_values::simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi,
   tree op1 = gimple_assign_rhs2 (stmt);
   tree op0min = NULL_TREE, op0max = NULL_TREE;
   tree op1min = op1;
-  const value_range_equiv *vr = NULL;
+  const value_range *vr = NULL;
 
   if (TREE_CODE (op0) == INTEGER_CST)
     {
@@ -3231,8 +3226,9 @@  vr_values::simplify_div_or_mod_using_ranges (gimple_stmt_iterator *gsi,
    disjoint.   Return true if we do simplify.  */
 
 bool
-vr_values::simplify_min_or_max_using_ranges (gimple_stmt_iterator *gsi,
-					     gimple *stmt)
+simplify_using_ranges::simplify_min_or_max_using_ranges
+				(gimple_stmt_iterator *gsi,
+				 gimple *stmt)
 {
   tree op0 = gimple_assign_rhs1 (stmt);
   tree op1 = gimple_assign_rhs2 (stmt);
@@ -3279,10 +3275,11 @@  vr_values::simplify_min_or_max_using_ranges (gimple_stmt_iterator *gsi,
    ABS_EXPR into a NEGATE_EXPR.  */
 
 bool
-vr_values::simplify_abs_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
+simplify_using_ranges::simplify_abs_using_ranges (gimple_stmt_iterator *gsi,
+						  gimple *stmt)
 {
   tree op = gimple_assign_rhs1 (stmt);
-  const value_range_equiv *vr = get_value_range (op);
+  const value_range *vr = get_value_range (op);
 
   if (vr)
     {
@@ -3359,8 +3356,9 @@  vr_set_zero_nonzero_bits (const tree expr_type,
    operation is redundant.  */
 
 bool
-vr_values::simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi,
-					  gimple *stmt)
+simplify_using_ranges::simplify_bit_ops_using_ranges
+				(gimple_stmt_iterator *gsi,
+				 gimple *stmt)
 {
   tree op0 = gimple_assign_rhs1 (stmt);
   tree op1 = gimple_assign_rhs2 (stmt);
@@ -3444,7 +3442,7 @@  vr_values::simplify_bit_ops_using_ranges (gimple_stmt_iterator *gsi,
 
 static tree
 test_for_singularity (enum tree_code cond_code, tree op0,
-		      tree op1, const value_range_equiv *vr)
+		      tree op1, const value_range *vr)
 {
   tree min = NULL;
   tree max = NULL;
@@ -3502,7 +3500,7 @@  test_for_singularity (enum tree_code cond_code, tree op0,
    by PRECISION and UNSIGNED_P.  */
 
 static bool
-range_fits_type_p (const value_range_equiv *vr,
+range_fits_type_p (const value_range *vr,
 		   unsigned dest_precision, signop dest_sgn)
 {
   tree src_type;
@@ -3554,7 +3552,7 @@  range_fits_type_p (const value_range_equiv *vr,
    conditional as such, and return TRUE.  */
 
 bool
-vr_values::fold_cond (gcond *cond)
+simplify_using_ranges::fold_cond (gcond *cond)
 {
   /* ?? vrp_folder::fold_predicate_in() is a superset of this.  At
      some point we should merge all variants of this code.  */
@@ -3579,7 +3577,7 @@  vr_values::fold_cond (gcond *cond)
    the original conditional.  */
 
 bool
-vr_values::simplify_cond_using_ranges_1 (gcond *stmt)
+simplify_using_ranges::simplify_cond_using_ranges_1 (gcond *stmt)
 {
   tree op0 = gimple_cond_lhs (stmt);
   tree op1 = gimple_cond_rhs (stmt);
@@ -3594,7 +3592,7 @@  vr_values::simplify_cond_using_ranges_1 (gcond *stmt)
       && INTEGRAL_TYPE_P (TREE_TYPE (op0))
       && is_gimple_min_invariant (op1))
     {
-      const value_range_equiv *vr = get_value_range (op0);
+      const value_range *vr = get_value_range (op0);
 
       /* If we have range information for OP0, then we might be
 	 able to simplify this conditional. */
@@ -3667,7 +3665,7 @@  vr_values::simplify_cond_using_ranges_1 (gcond *stmt)
    subsequent passes.  */
 
 void
-vr_values::simplify_cond_using_ranges_2 (gcond *stmt)
+simplify_cond_using_ranges_2 (vr_values *store, gcond *stmt)
 {
   tree op0 = gimple_cond_lhs (stmt);
   tree op1 = gimple_cond_rhs (stmt);
@@ -3697,7 +3695,7 @@  vr_values::simplify_cond_using_ranges_2 (gcond *stmt)
 	  && !SSA_NAME_OCCURS_IN_ABNORMAL_PHI (innerop)
 	  && desired_pro_or_demotion_p (TREE_TYPE (innerop), TREE_TYPE (op0)))
 	{
-	  const value_range_equiv *vr = get_value_range (innerop);
+	  const value_range *vr = store->get_value_range (innerop);
 
 	  if (range_int_cst_p (vr)
 	      && range_fits_type_p (vr,
@@ -3724,10 +3722,10 @@  vr_values::simplify_cond_using_ranges_2 (gcond *stmt)
    argument.  */
 
 bool
-vr_values::simplify_switch_using_ranges (gswitch *stmt)
+simplify_using_ranges::simplify_switch_using_ranges (gswitch *stmt)
 {
   tree op = gimple_switch_index (stmt);
-  const value_range_equiv *vr = NULL;
+  const value_range *vr = NULL;
   bool take_default;
   edge e;
   edge_iterator ei;
@@ -3905,7 +3903,7 @@  vr_values::simplify_switch_using_ranges (gswitch *stmt)
 }
 
 void
-vr_values::cleanup_edges_and_switches (void)
+simplify_using_ranges::cleanup_edges_and_switches (void)
 {
   int i;
   edge e;
@@ -4023,11 +4021,12 @@  simplify_conversion_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt)
 /* Simplify a conversion from integral SSA name to float in STMT.  */
 
 bool
-vr_values::simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
-						   gimple *stmt)
+simplify_using_ranges::simplify_float_conversion_using_ranges
+					(gimple_stmt_iterator *gsi,
+					 gimple *stmt)
 {
   tree rhs1 = gimple_assign_rhs1 (stmt);
-  const value_range_equiv *vr = get_value_range (rhs1);
+  const value_range *vr = get_value_range (rhs1);
   scalar_float_mode fltmode
     = SCALAR_FLOAT_TYPE_MODE (TREE_TYPE (gimple_assign_lhs (stmt)));
   scalar_int_mode mode;
@@ -4085,8 +4084,9 @@  vr_values::simplify_float_conversion_using_ranges (gimple_stmt_iterator *gsi,
 /* Simplify an internal fn call using ranges if possible.  */
 
 bool
-vr_values::simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi,
-						gimple *stmt)
+simplify_using_ranges::simplify_internal_call_using_ranges
+					(gimple_stmt_iterator *gsi,
+					 gimple *stmt)
 {
   enum tree_code subcode;
   bool is_ubsan = false;
@@ -4131,7 +4131,7 @@  vr_values::simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi,
     return false;
   else
     type = TREE_TYPE (TREE_TYPE (gimple_call_lhs (stmt)));
-  if (!check_for_binary_op_overflow (subcode, type, op0, op1, &ovf)
+  if (!check_for_binary_op_overflow (store, subcode, type, op0, op1, &ovf)
       || (is_ubsan && ovf))
     return false;
 
@@ -4188,9 +4188,9 @@  vr_values::simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi,
    two-values when it is true.  Return false otherwise.  */
 
 bool
-vr_values::two_valued_val_range_p (tree var, tree *a, tree *b)
+simplify_using_ranges::two_valued_val_range_p (tree var, tree *a, tree *b)
 {
-  const value_range_equiv *vr = get_value_range (var);
+  const value_range *vr = get_value_range (var);
   if (vr->varying_p ()
       || vr->undefined_p ()
       || TREE_CODE (vr->min ()) != INTEGER_CST
@@ -4220,10 +4220,22 @@  vr_values::two_valued_val_range_p (tree var, tree *a, tree *b)
   return false;
 }
 
+simplify_using_ranges::simplify_using_ranges (vr_values *store)
+  : store (store)
+{
+  to_remove_edges = vNULL;
+  to_update_switch_stmts = vNULL;
+}
+
+simplify_using_ranges::~simplify_using_ranges ()
+{
+  cleanup_edges_and_switches ();
+}
+
 /* Simplify STMT using ranges if possible.  */
 
 bool
-vr_values::simplify_stmt_using_ranges (gimple_stmt_iterator *gsi)
+simplify_using_ranges::simplify (gimple_stmt_iterator *gsi)
 {
   gimple *stmt = gsi_stmt (*gsi);
   if (is_gimple_assign (stmt))
diff --git a/gcc/vr-values.h b/gcc/vr-values.h
index ac25139762a..62a20218c6d 100644
--- a/gcc/vr-values.h
+++ b/gcc/vr-values.h
@@ -22,6 +22,65 @@  along with GCC; see the file COPYING3.  If not see
 
 #include "value-range-equiv.h"
 
+// Class to simplify a statement using range information.
+//
+// The constructor takes a full vr_values, but all it needs is
+// get_value_range() from it.  This class could be made to work with
+// any range repository.
+
+class simplify_using_ranges
+{
+public:
+  simplify_using_ranges (class vr_values *);
+  ~simplify_using_ranges ();
+  bool simplify (gimple_stmt_iterator *);
+
+  // ?? These should be cleaned, merged, and made private.
+  tree vrp_evaluate_conditional (tree_code, tree, tree, gimple *);
+  void vrp_visit_cond_stmt (gcond *, edge *);
+  tree vrp_evaluate_conditional_warnv_with_ops (enum tree_code,
+						tree, tree, bool,
+						bool *, bool *);
+
+private:
+  const value_range_equiv *get_value_range (const_tree op);
+  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 *);
+  bool fold_cond (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 two_valued_val_range_p (tree, tree *, tree *);
+  bool op_with_boolean_value_range_p (tree);
+  tree compare_name_with_value (enum tree_code, tree, tree, bool *, bool);
+  tree compare_names (enum tree_code, tree, tree, bool *);
+  const value_range_equiv *get_vr_for_comparison (int, value_range_equiv *);
+  tree vrp_evaluate_conditional_warnv_with_ops_using_ranges (enum tree_code,
+							     tree, tree,
+							     bool *);
+  void cleanup_edges_and_switches (void);
+
+  /* Vectors of edges that need removing and switch statements that
+     need updating.  It is expected that a pass using the simplification
+     routines will, at the end of the pass, clean up the edges and
+     switch statements.  The class dtor will try to detect cases
+     that do not follow that expectation.  */
+  struct switch_update {
+    gswitch *stmt;
+    tree vec;
+  };
+
+  vec<edge> to_remove_edges;
+  vec<switch_update> to_update_switch_stmts;
+  class vr_values *store;
+};
+
 /* The VR_VALUES class holds the current view of range information
    for all the SSA_NAMEs in the IL.
 
@@ -52,7 +111,6 @@  class vr_values
   tree op_with_constant_singleton_value_range (tree);
   void adjust_range_with_scev (value_range_equiv *, class loop *,
 			       gimple *, tree);
-  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,
@@ -62,11 +120,6 @@  class vr_values
   void extract_range_basic (value_range_equiv *, gimple *);
   void extract_range_from_stmt (gimple *, edge *, tree *, value_range_equiv *);
 
-  void vrp_visit_cond_stmt (gcond *, edge *);
-
-  void simplify_cond_using_ranges_2 (gcond *);
-  bool simplify_stmt_using_ranges (gimple_stmt_iterator *);
-
   /* Indicate that propagation through the lattice is complete.  */
   void set_lattice_propagation_complete (void) { values_propagated = true; }
 
@@ -76,24 +129,9 @@  class vr_values
   void free_value_range (value_range_equiv *vr)
     { vrp_value_range_pool.remove (vr); }
 
-  /* */
-  void cleanup_edges_and_switches (void);
-
  private:
   value_range_equiv *get_lattice_entry (const_tree);
   bool vrp_stmt_computes_nonzero (gimple *);
-  bool op_with_boolean_value_range_p (tree);
-  bool check_for_binary_op_overflow (enum tree_code, tree, tree, tree, bool *);
-  const value_range_equiv *get_vr_for_comparison (int, value_range_equiv *);
-  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 *);
   void extract_range_from_assignment (value_range_equiv *, gassign *);
   void extract_range_from_assert (value_range_equiv *, tree);
   void extract_range_from_ssa_name (value_range_equiv *, tree);
@@ -106,17 +144,6 @@  class vr_values
 				      tree, tree, tree);
   void vrp_visit_assignment_or_call (gimple*, tree *, value_range_equiv *);
   void vrp_visit_switch_stmt (gswitch *, 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 *);
-  bool fold_cond (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 *);
 
   /* Allocation pools for value_range objects.  */
   object_allocator<value_range_equiv> vrp_value_range_pool;
@@ -136,20 +163,18 @@  class vr_values
      number of executable edges we saw the last time we visited the
      node.  */
   int *vr_phi_edge_counts;
-
-  /* Vectors of edges that need removing and switch statements that
-     need updating.  It is expected that a pass using the simplification
-     routines will, at the end of the pass, clean up the edges and
-     switch statements.  The class dtor will try to detect cases
-     that do not follow that expectation.  */
-  struct switch_update {
-    gswitch *stmt;
-    tree vec;
-  };
-
-  vec<edge> to_remove_edges;
-  vec<switch_update> to_update_switch_stmts;
+  simplify_using_ranges simplifier;
 };
 
+inline const value_range_equiv *
+simplify_using_ranges::get_value_range (const_tree op)
+{
+  return store->get_value_range (op);
+}
+
 extern tree get_output_for_vrp (gimple *);
+
+// FIXME: Move this to tree-vrp.c.
+void simplify_cond_using_ranges_2 (class vr_values *, gcond *);
+
 #endif /* GCC_VR_VALUES_H */