Move simplification of statements using ranges into its own class.
authorAldy Hernandez <aldyh@redhat.com>
Thu, 18 Jun 2020 08:37:14 +0000 (10:37 +0200)
committerAldy Hernandez <aldyh@redhat.com>
Sat, 27 Jun 2020 12:11:41 +0000 (14:11 +0200)
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.

gcc/gimple-ssa-evrp-analyze.h
gcc/gimple-ssa-evrp.c
gcc/tree-ssa-dom.c
gcc/tree-vrp.c
gcc/vr-values.c
gcc/vr-values.h

index d16279f..8abbbe3 100644 (file)
@@ -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.
index af780fd..e8fde63 100644 (file)
@@ -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
index 864c984..69eaec3 100644 (file)
@@ -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))
index c39a6f5..7193ca4 100644 (file)
@@ -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 ();
index e95df78..d030359 100644 (file)
@@ -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))
index ac25139..62a2021 100644 (file)
@@ -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 */