On Fri, Nov 17, 2017 at 8:41 AM, Jeff Law <l...@redhat.com> wrote:
> This patch introduces the evrp_range_analyzer class.  This is the class
> we're going to be able to embed into existing dominator walkers to
> provide them with context sensitive range analysis.
>
> The bulk of the class is extracted from the evrp_dom_walker class.  A
> few minor notes.
>
> Setup of the reachable/executable state for blocks/edges moves into the
> evrp_range_analyzer class's constructor from execute_early_vrp.  It
> seems to bit better in the analyzer class as it sets state the analyzer
> uses internally.
>
> The analyzer has a enter/leave methods to call as well as a
> per-statement method to call.  I went back and forth several times on
> whether or not to have a per-statement method call or hide the
> per-statement stuff behind the enter method.  I could be easily
> convinced to return to the latter as it has a simpler interface for the
> clients.
>
> I suspect evrp_range_analyzer::get_value_range which is currently
> private and delegates to the embedded vr_values class to likely become a
> public member that continues to delegate to the embedded vr_values.
> Essentially it's the query interface for embedded range analysis.
> There's a couple other cleanups that need to happen with the goal that
> the vr_values data member can become private.
>
> Bootstrapped and regression tested on x86_64.  OK for the trunk?

Ok.

Thanks,
Richard.

> jeff
>
>
>
>         * gimple-ssa-evrp.c (class evrp_range_analyzer): New class extracted
>         from evrp_dom_walker class.  Various methods moved into new class.
>         (evrp_range_analyzer::evrp_range_analyzer): Constructor for new class.
>         (evrp_range_analyzer::enter): New method.
>         (evrp_range_analyzer::leave): New method.
>         (evrp_dom_walker): Remove delegators no longer needed by this class.
>         Replace vr_values data member with evrp_range_analyzer
>
> commit 45facb8e6d15937db1135310dd9ff85f85c17d81
> Author: Jeff Law <l...@torsion.usersys.redhat.com>
> Date:   Fri Nov 17 02:05:27 2017 -0500
>
>     Introduce range_analyzer class
>
> diff --git a/gcc/gimple-ssa-evrp.c b/gcc/gimple-ssa-evrp.c
> index 7b92beb..bb56696 100644
> --- a/gcc/gimple-ssa-evrp.c
> +++ b/gcc/gimple-ssa-evrp.c
> @@ -55,6 +55,72 @@ evrp_folder::get_value (tree op)
>    return vr_values->op_with_constant_singleton_value_range (op);
>  }
>
> +class evrp_range_analyzer
> +{
> + public:
> +  evrp_range_analyzer (void);
> +  ~evrp_range_analyzer (void) { stack.release (); }
> +
> +  void enter (basic_block);
> +  void leave (basic_block);
> +  void record_ranges_from_stmt (gimple *);
> +
> +  class vr_values vr_values;
> +
> + private:
> +  void push_value_range (tree var, value_range *vr);
> +  value_range *pop_value_range (tree var);
> +  value_range *try_find_new_range (tree, tree op, tree_code code, tree 
> limit);
> +  void record_ranges_from_incoming_edge (basic_block);
> +  void record_ranges_from_phis (basic_block);
> +
> +  /* We do not allow copying this object or initializing one from another.  
> */
> +  evrp_range_analyzer (const evrp_range_analyzer &);
> +  evrp_range_analyzer& operator= (const evrp_range_analyzer &);
> +
> +  /* Cond_stack holds the old VR.  */
> +  auto_vec<std::pair <tree, value_range*> > stack;
> +
> +  /* 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 adjust_range_with_scev (value_range *vr, struct loop *loop,
> +                               gimple *stmt, tree var)
> +    { vr_values.adjust_range_with_scev (vr, loop, stmt, var); }
> +  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 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); 
> }
> +};
> +
> +evrp_range_analyzer::evrp_range_analyzer () : stack (10)
> +{
> +  edge e;
> +  edge_iterator ei;
> +  basic_block bb;
> +
> +  FOR_EACH_BB_FN (bb, cfun)
> +    {
> +      bb->flags &= ~BB_VISITED;
> +      FOR_EACH_EDGE (e, ei, bb->preds)
> +       e->flags |= EDGE_EXECUTABLE;
> +    }
> +}
> +
> +
>  /* evrp_dom_walker visits the basic blocks in the dominance order and set
>     the Value Ranges (VR) for SSA_NAMEs in the scope.  Use this VR to
>     discover more VRs.  */
> @@ -62,8 +130,7 @@ evrp_folder::get_value (tree op)
>  class evrp_dom_walker : public dom_walker
>  {
>  public:
> -  evrp_dom_walker ()
> -    : dom_walker (CDI_DOMINATORS), stack (10)
> +  evrp_dom_walker () : dom_walker (CDI_DOMINATORS)
>      {
>        need_eh_cleanup = BITMAP_ALLOC (NULL);
>      }
> @@ -76,21 +143,11 @@ public:
>    void cleanup (void);
>
>   private:
> -  void push_value_range (tree var, value_range *vr);
> -  value_range *pop_value_range (tree var);
> -  value_range *try_find_new_range (tree, tree op, tree_code code, tree 
> limit);
> -
> -  void record_ranges_from_incoming_edge (basic_block);
> -  void record_ranges_from_phis (basic_block);
> -  void record_ranges_from_stmt (gimple *);
> -
> -  /* Cond_stack holds the old VR.  */
> -  auto_vec<std::pair <tree, value_range*> > stack;
>    bitmap need_eh_cleanup;
>    auto_vec<gimple *> stmts_to_fixup;
>    auto_vec<gimple *> stmts_to_remove;
>
> -  class vr_values vr_values;
> +  class evrp_range_analyzer evrp_range_analyzer;
>
>    /* We do not allow copying this object or initializing one from another.  
> */
>    evrp_dom_walker (const evrp_dom_walker &);
> @@ -98,40 +155,25 @@ public:
>
>    /* 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); }
> +    { return evrp_range_analyzer.vr_values.get_value_range (op); }
>    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); }
> +    { return 
> evrp_range_analyzer.vr_values.op_with_constant_singleton_value_range (op); }
>    void vrp_visit_cond_stmt (gcond *cond, edge *e)
> -    { vr_values.vrp_visit_cond_stmt (cond, e); }
> +    { evrp_range_analyzer.vr_values.vrp_visit_cond_stmt (cond, e); }
>  };
>
> -/*  Find new range for NAME such that (OP CODE LIMIT) is true.  */
> +void
> +evrp_range_analyzer::enter (basic_block bb)
> +{
> +  stack.safe_push (std::make_pair (NULL_TREE, (value_range *)NULL));
> +  record_ranges_from_incoming_edge (bb);
> +  record_ranges_from_phis (bb);
> +}
>
> +/* Find new range for NAME such that (OP CODE LIMIT) is true.  */
>  value_range *
> -evrp_dom_walker::try_find_new_range (tree name,
> -                                    tree op, tree_code code, tree limit)
> +evrp_range_analyzer::try_find_new_range (tree name,
> +                                   tree op, tree_code code, tree limit)
>  {
>    value_range vr = VR_INITIALIZER;
>    value_range *old_vr = get_value_range (name);
> @@ -158,10 +200,8 @@ evrp_dom_walker::try_find_new_range (tree name,
>     then derive ranges implied by traversing that edge.  */
>
>  void
> -evrp_dom_walker::record_ranges_from_incoming_edge (basic_block bb)
> +evrp_range_analyzer::record_ranges_from_incoming_edge (basic_block bb)
>  {
> -/* See if there is any new scope is entered with new VR and set that VR to
> -   ssa_name before visiting the statements in the scope.  */
>    edge pred_e = single_pred_edge_ignoring_loop_edges (bb, false);
>    if (pred_e)
>      {
> @@ -210,10 +250,8 @@ evrp_dom_walker::record_ranges_from_incoming_edge 
> (basic_block bb)
>      }
>  }
>
> -/* Record ranges from any PHI nodes at the start of basic block BB.  */
> -
>  void
> -evrp_dom_walker::record_ranges_from_phis (basic_block bb)
> +evrp_range_analyzer::record_ranges_from_phis (basic_block bb)
>  {
>    /* Visit PHI stmts and discover any new VRs possible.  */
>    bool has_unvisited_preds = false;
> @@ -234,15 +272,10 @@ evrp_dom_walker::record_ranges_from_phis (basic_block 
> bb)
>        tree lhs = PHI_RESULT (phi);
>        if (virtual_operand_p (lhs))
>         continue;
> +
>        value_range vr_result = VR_INITIALIZER;
>        bool interesting = stmt_interesting_for_vrp (phi);
> -      if (interesting && dump_file && (dump_flags & TDF_DETAILS))
> -       {
> -         fprintf (dump_file, "Visiting PHI node ");
> -         print_gimple_stmt (dump_file, phi, 0);
> -       }
> -      if (!has_unvisited_preds
> -         && interesting)
> +      if (!has_unvisited_preds && interesting)
>         extract_range_from_phi_node (phi, &vr_result);
>        else
>         {
> @@ -255,7 +288,7 @@ evrp_dom_walker::record_ranges_from_phis (basic_block bb)
>           if (interesting
>               && (l = loop_containing_stmt (phi))
>               && l->header == gimple_bb (phi))
> -           adjust_range_with_scev (&vr_result, l, phi, lhs);
> +         adjust_range_with_scev (&vr_result, l, phi, lhs);
>         }
>        update_value_range (lhs, &vr_result);
>
> @@ -284,7 +317,7 @@ evrp_dom_walker::record_ranges_from_phis (basic_block bb)
>  /* Record any ranges created by statement STMT.  */
>
>  void
> -evrp_dom_walker::record_ranges_from_stmt (gimple *stmt)
> +evrp_range_analyzer::record_ranges_from_stmt (gimple *stmt)
>  {
>    tree output = NULL_TREE;
>
> @@ -303,8 +336,8 @@ evrp_dom_walker::record_ranges_from_stmt (gimple *stmt)
>           if (INTEGRAL_TYPE_P (TREE_TYPE (output)))
>             {
>               if ((vr.type == VR_RANGE || vr.type == VR_ANTI_RANGE)
> -                  && (TREE_CODE (vr.min) == INTEGER_CST)
> -                  && (TREE_CODE (vr.max) == INTEGER_CST))
> +                 && (TREE_CODE (vr.min) == INTEGER_CST)
> +                 && (TREE_CODE (vr.max) == INTEGER_CST))
>                 set_range_info (output, vr.type,
>                                 wi::to_wide (vr.min),
>                                 wi::to_wide (vr.max));
> @@ -375,9 +408,7 @@ evrp_dom_walker::before_dom_children (basic_block bb)
>    if (dump_file && (dump_flags & TDF_DETAILS))
>      fprintf (dump_file, "Visiting BB%d\n", bb->index);
>
> -  stack.safe_push (std::make_pair (NULL_TREE, (value_range *)NULL));
> -  record_ranges_from_incoming_edge (bb);
> -  record_ranges_from_phis (bb);
> +  evrp_range_analyzer.enter (bb);
>
>    for (gphi_iterator gpi = gsi_start_phis (bb);
>         !gsi_end_p (gpi); gsi_next (&gpi))
> @@ -414,7 +445,8 @@ evrp_dom_walker::before_dom_children (basic_block bb)
>           print_gimple_stmt (dump_file, stmt, 0);
>         }
>
> -      record_ranges_from_stmt (stmt);
> +      evrp_range_analyzer.record_ranges_from_stmt (stmt);
> +
>        if (gcond *cond = dyn_cast <gcond *> (stmt))
>         {
>           vrp_visit_cond_stmt (cond, &taken_edge);
> @@ -435,10 +467,10 @@ evrp_dom_walker::before_dom_children (basic_block bb)
>           output = get_output_for_vrp (stmt);
>           if (output)
>             {
> +             tree val;
>               vr = *get_value_range (output);
>
>               /* Mark stmts whose output we fully propagate for removal.  */
> -             tree val;
>               if ((vr.type == VR_RANGE || vr.type == VR_ANTI_RANGE)
>                   && (val = op_with_constant_singleton_value_range (output))
>                   && may_propagate_copy (output, val)
> @@ -453,7 +485,7 @@ evrp_dom_walker::before_dom_children (basic_block bb)
>
>        /* Try folding stmts with the VR discovered.  */
>        class evrp_folder evrp_folder;
> -      evrp_folder.vr_values = &vr_values;
> +      evrp_folder.vr_values = &evrp_range_analyzer.vr_values;
>        bool did_replace = evrp_folder.replace_uses_in (stmt);
>        if (fold_stmt (&gsi, follow_single_use_edges)
>           || did_replace)
> @@ -511,10 +543,16 @@ evrp_dom_walker::before_dom_children (basic_block bb)
>    return taken_edge;
>  }
>
> +void
> +evrp_dom_walker::after_dom_children (basic_block bb)
> +{
> +  evrp_range_analyzer.leave (bb);
> +}
> +
>  /* Restore/pop VRs valid only for BB when we leave BB.  */
>
>  void
> -evrp_dom_walker::after_dom_children (basic_block bb ATTRIBUTE_UNUSED)
> +evrp_range_analyzer::leave (basic_block bb ATTRIBUTE_UNUSED)
>  {
>    gcc_checking_assert (!stack.is_empty ());
>    while (stack.last ().first != NULL_TREE)
> @@ -525,7 +563,7 @@ evrp_dom_walker::after_dom_children (basic_block bb 
> ATTRIBUTE_UNUSED)
>  /* 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)
> +evrp_range_analyzer::push_value_range (tree var, value_range *vr)
>  {
>    if (dump_file && (dump_flags & TDF_DETAILS))
>      {
> @@ -542,7 +580,7 @@ evrp_dom_walker::push_value_range (tree var, value_range 
> *vr)
>  /* Pop the Value Range from the vrp_stack and update VAR with it.  */
>
>  value_range *
> -evrp_dom_walker::pop_value_range (tree var)
> +evrp_range_analyzer::pop_value_range (tree var)
>  {
>    value_range *vr = stack.last ().second;
>    gcc_checking_assert (var == stack.last ().first);
> @@ -567,7 +605,7 @@ evrp_dom_walker::cleanup (void)
>    if (dump_file)
>      {
>        fprintf (dump_file, "\nValue ranges after Early VRP:\n\n");
> -      vr_values.dump_all_value_ranges (dump_file);
> +      evrp_range_analyzer.vr_values.dump_all_value_ranges (dump_file);
>        fprintf (dump_file, "\n");
>      }
>
> @@ -613,10 +651,6 @@ evrp_dom_walker::cleanup (void)
>  static unsigned int
>  execute_early_vrp ()
>  {
> -  edge e;
> -  edge_iterator ei;
> -  basic_block bb;
> -
>    /* Ideally this setup code would move into the ctor for the dominator
>       walk.  However, this setup can change the number of blocks which
>       invalidates the internal arrays that are set up by the dominator
> @@ -625,12 +659,6 @@ execute_early_vrp ()
>    rewrite_into_loop_closed_ssa (NULL, TODO_update_ssa);
>    scev_initialize ();
>    calculate_dominance_info (CDI_DOMINATORS);
> -  FOR_EACH_BB_FN (bb, cfun)
> -    {
> -      bb->flags &= ~BB_VISITED;
> -      FOR_EACH_EDGE (e, ei, bb->preds)
> -       e->flags |= EDGE_EXECUTABLE;
> -    }
>
>    /* Walk stmts in dominance order and propagate VRP.  */
>    evrp_dom_walker walker;
>

Reply via email to