On Tue, Dec 8, 2015 at 7:15 AM, Jeff Law <l...@redhat.com> wrote:
>
> First in the series.  This merely refactors code from tree-ssa-sccvn.c into
> domwalk.c so that other walkers can use it as they see fit.
>
>
> There's an initialization function which sets all edges to executable.
>
> There's a test function to see if a block is reachable.
>
> There's a propagation function to propagate the unreachable property to
> edges.
>
> Finally a function to clear m_unreachable_dom.  I consider this a wart.
> Essentially that data member contains the highest unreachable block in the
> dominator tree.  Once we've finished processing that block's children, we
> need to clear the member.  Ideally clients wouldn't need to call this member
> function.
>
> Bikeshedding on the members names is encouraged.  And if someone has a
> clean, simple way to ensure that the m_unreachable_dom member gets cleared
> regardless of whether or not a client has its own after_dom_children
> callback, I'd love to hear it.

I wonder if it makes more sense to integrate this with the domwalker
itself.  Add
a constructor flag to it and do everything in itself.  By letting the
before_dom_children
return a taken edge (or NULL if unknown) it can drive the outgoing edge marking.
And the domwalk worker would simply not recurse to dom children for unreachable
blocks.

Richard.

> OK for trunk?
>
>
> Jeff
>
> commit 5e53fefae0373768b98d51d5746d43f36cecbe2a
> Author: Jeff Law <l...@redhat.com>
> Date:   Mon Dec 7 11:32:58 2015 -0700
>
>         * domwalk.h (dom_walker::init_edge_executable): New method.
>         (dom_walker::maybe_clear_unreachable_dom): Likewise.
>         (dom_walker::bb_reachable): Likewise.
>         (dom_walker::propagate_unreachable_to_edges): Likewise.
>         (dom_walker::m_unreachable_dom): New private data member.
>         * domwalk.c: Include dumpfile.h.
>         (dom_walker::init_edge_executable): New method.
>         (dom_walker::maybe_clear_unreachable_dom): Likewise.
>         (dom_walker::bb_reachable): Likewise.  Factored out of
>         tree-ssa-sccvn.c
>         (dom_walker::propagate_unreachable_to_edges): Likewise.
>         * tree-ssa-sccvn.c (sccvn_dom_walker::unreachable_dom): Remove
>         private data member.
>         (sccvn_dom_walker::after_dom_children): Use methods from dom_walker
>         class.
>         (sccvn_dom_walker::before_dom_children): Similarly.
>         (run_scc_vn): Likewise.
>
> diff --git a/gcc/domwalk.c b/gcc/domwalk.c
> index 167fc38..feb6478 100644
> --- a/gcc/domwalk.c
> +++ b/gcc/domwalk.c
> @@ -24,6 +24,7 @@ along with GCC; see the file COPYING3.  If not see
>  #include "backend.h"
>  #include "cfganal.h"
>  #include "domwalk.h"
> +#include "dumpfile.h"
>
>  /* This file implements a generic walker for dominator trees.
>
> @@ -142,6 +143,93 @@ cmp_bb_postorder (const void *a, const void *b)
>    return 1;
>  }
>
> +/* Mark all edges in the CFG as possibly being executable.  */
> +
> +void
> +dom_walker::init_edge_executable (struct function *fun)
> +{
> +  basic_block bb;
> +  FOR_ALL_BB_FN (bb, fun)
> +    {
> +      edge_iterator ei;
> +      edge e;
> +      FOR_EACH_EDGE (e, ei, bb->succs)
> +       e->flags |= EDGE_EXECUTABLE;
> +    }
> +}
> +
> +/* Return TRUE if BB is reachable, false otherwise.  */
> +
> +bool
> +dom_walker::bb_reachable (struct function *fun, basic_block bb)
> +{
> +  /* If any of the predecessor edges that do not come from blocks dominated
> +     by us are still marked as possibly executable consider this block
> +     reachable.  */
> +  bool reachable = false;
> +  if (!m_unreachable_dom)
> +    {
> +      reachable = bb == ENTRY_BLOCK_PTR_FOR_FN (fun);
> +      edge_iterator ei;
> +      edge e;
> +      FOR_EACH_EDGE (e, ei, bb->preds)
> +       if (!dominated_by_p (CDI_DOMINATORS, e->src, bb))
> +         reachable |= (e->flags & EDGE_EXECUTABLE);
> +    }
> +
> +  return reachable;
> +}
> +
> +/* BB has been determined to be unreachable.  Propagate that property
> +   to incoming and outgoing edges of BB as appropriate.  */
> +
> +void
> +dom_walker::propagate_unreachable_to_edges (basic_block bb,
> +                                           FILE *dump_file,
> +                                           int dump_flags)
> +{
> +  if (dump_file && (dump_flags & TDF_DETAILS))
> +    fprintf (dump_file, "Marking all outgoing edges of unreachable "
> +            "BB %d as not executable\n", bb->index);
> +
> +  edge_iterator ei;
> +  edge e;
> +  FOR_EACH_EDGE (e, ei, bb->succs)
> +    e->flags &= ~EDGE_EXECUTABLE;
> +
> +  FOR_EACH_EDGE (e, ei, bb->preds)
> +    {
> +      if (dominated_by_p (CDI_DOMINATORS, e->src, bb))
> +       {
> +         if (dump_file && (dump_flags & TDF_DETAILS))
> +           fprintf (dump_file, "Marking backedge from BB %d into "
> +                    "unreachable BB %d as not executable\n",
> +                    e->src->index, bb->index);
> +         e->flags &= ~EDGE_EXECUTABLE;
> +       }
> +    }
> +
> +  if (!m_unreachable_dom)
> +    m_unreachable_dom = bb;
> +}
> +
> +/* When we propagate the unreachable property to edges, we
> +   also arrange to track the highest block in the dominator
> +   walk which was unreachable.  We can use that to identify
> +   more unreachable blocks.
> +
> +   When we finish processing the dominator children for that
> +   highest unreachable block, we need to make sure to clear
> +   that recorded highest block unreachable block in the
> +   dominator tree.  */
> +
> +void
> +dom_walker::maybe_clear_unreachable_dom (basic_block bb)
> +{
> +  if (m_unreachable_dom == bb)
> +    m_unreachable_dom = NULL;
> +}
> +
>  /* Recursively walk the dominator tree.
>     BB is the basic block we are currently visiting.  */
>
> diff --git a/gcc/domwalk.h b/gcc/domwalk.h
> index 71a7c47..d6b37a2 100644
> --- a/gcc/domwalk.h
> +++ b/gcc/domwalk.h
> @@ -30,7 +30,8 @@ along with GCC; see the file COPYING3.  If not see
>  class dom_walker
>  {
>  public:
> -  dom_walker (cdi_direction direction) : m_dom_direction (direction) {}
> +  dom_walker (cdi_direction direction) : m_dom_direction (direction),
> +    m_unreachable_dom (NULL) {}
>
>    /* Walk the dominator tree.  */
>    void walk (basic_block);
> @@ -41,12 +42,41 @@ public:
>    /* Function to call after the recursive walk of the dominator children.
> */
>    virtual void after_dom_children (basic_block) {}
>
> +  /* The next several methods support discovering unreachable blocks
> +     and edges in the CFG during the dominator walk.  Using these routines
> +     is totally optional and only makes sense if your walker can change
> +     the state of a block/edge to unreachable/unexecutable and your walker
> +     can exploit that information to optimize better.  */
> +
> +  /* Set EDGE_EXECUTABLE for every edge in the CFG.  This must be done
> +     before walking begins.  */
> +  void init_edge_executable (struct function *);
> +
> +  /* Query whether or not the given block is reachable or not.
> +
> +     Typically used in the before_dom_children callback.  */
> +  bool bb_reachable (struct function *, basic_block);
> +
> +  /* Given an unreachable block, propagate that property to outgoing
> +     and possibly incoming edges for the block.  Typically called after
> +     determining a block is unreachable in the before_dom_children
> +     callback.  */
> +  void propagate_unreachable_to_edges (basic_block, FILE *, int);
> +
> +  /* This is a bit of a wart.  We need to conditionally clear a bit of
> +     state after we have process the dominator children.
> +
> +     I'd prefer to hide this detail within domwalk, but right now it
> +     bleeds out into the clients.  */
> +  void maybe_clear_unreachable_dom (basic_block);
> +
>  private:
>    /* This is the direction of the dominator tree we want to walk.  i.e.,
>       if it is set to CDI_DOMINATORS, then we walk the dominator tree,
>       if it is set to CDI_POST_DOMINATORS, then we walk the post
>       dominator tree.  */
>    const ENUM_BITFIELD (cdi_direction) m_dom_direction : 2;
> +  basic_block m_unreachable_dom;
>  };
>
>  #endif
> diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
> index 2014ee7..dbd61c9 100644
> --- a/gcc/tree-ssa-sccvn.c
> +++ b/gcc/tree-ssa-sccvn.c
> @@ -4207,8 +4207,7 @@ class sccvn_dom_walker : public dom_walker
>  {
>  public:
>    sccvn_dom_walker ()
> -    : dom_walker (CDI_DOMINATORS), fail (false), unreachable_dom (NULL),
> -      cond_stack (vNULL) {}
> +    : dom_walker (CDI_DOMINATORS), fail (false), cond_stack (vNULL) {}
>    ~sccvn_dom_walker ();
>
>    virtual void before_dom_children (basic_block);
> @@ -4220,7 +4219,6 @@ public:
>                      enum tree_code code, tree lhs, tree rhs, bool value);
>
>    bool fail;
> -  basic_block unreachable_dom;
>    vec<std::pair <basic_block, std::pair <vn_nary_op_t, vn_nary_op_t> > >
>      cond_stack;
>  };
> @@ -4301,8 +4299,7 @@ sccvn_dom_walker::record_conds (basic_block bb,
>  void
>  sccvn_dom_walker::after_dom_children (basic_block bb)
>  {
> -  if (unreachable_dom == bb)
> -    unreachable_dom = NULL;
> +  this->maybe_clear_unreachable_dom (bb);
>
>    while (!cond_stack.is_empty ()
>          && cond_stack.last ().first == bb)
> @@ -4327,45 +4324,11 @@ sccvn_dom_walker::before_dom_children (basic_block
> bb)
>    if (fail)
>      return;
>
> -  /* If any of the predecessor edges that do not come from blocks dominated
> -     by us are still marked as possibly executable consider this block
> -     reachable.  */
> -  bool reachable = false;
> -  if (!unreachable_dom)
> +  /* If BB is not reachable, then propagate that property to edges, but
> +     do not process this block any further.  */
> +  if (!this->bb_reachable (cfun, bb))
>      {
> -      reachable = bb == ENTRY_BLOCK_PTR_FOR_FN (cfun);
> -      FOR_EACH_EDGE (e, ei, bb->preds)
> -       if (!dominated_by_p (CDI_DOMINATORS, e->src, bb))
> -         reachable |= (e->flags & EDGE_EXECUTABLE);
> -    }
> -
> -  /* If the block is not reachable all outgoing edges are not
> -     executable.  Neither are incoming edges with src dominated by us.  */
> -  if (!reachable)
> -    {
> -      if (dump_file && (dump_flags & TDF_DETAILS))
> -       fprintf (dump_file, "Marking all outgoing edges of unreachable "
> -                "BB %d as not executable\n", bb->index);
> -
> -      FOR_EACH_EDGE (e, ei, bb->succs)
> -       e->flags &= ~EDGE_EXECUTABLE;
> -
> -      FOR_EACH_EDGE (e, ei, bb->preds)
> -       {
> -         if (dominated_by_p (CDI_DOMINATORS, e->src, bb))
> -           {
> -             if (dump_file && (dump_flags & TDF_DETAILS))
> -               fprintf (dump_file, "Marking backedge from BB %d into "
> -                        "unreachable BB %d as not executable\n",
> -                        e->src->index, bb->index);
> -             e->flags &= ~EDGE_EXECUTABLE;
> -           }
> -       }
> -
> -      /* Record the most dominating unreachable block.  */
> -      if (!unreachable_dom)
> -       unreachable_dom = bb;
> -
> +      this->propagate_unreachable_to_edges (bb, dump_file, dump_flags);
>        return;
>      }
>
> @@ -4519,7 +4482,6 @@ sccvn_dom_walker::before_dom_children (basic_block bb)
>  bool
>  run_scc_vn (vn_lookup_kind default_vn_walk_kind_)
>  {
> -  basic_block bb;
>    size_t i;
>
>    default_vn_walk_kind = default_vn_walk_kind_;
> @@ -4549,18 +4511,10 @@ run_scc_vn (vn_lookup_kind default_vn_walk_kind_)
>         }
>      }
>
> -  /* Mark all edges as possibly executable.  */
> -  FOR_ALL_BB_FN (bb, cfun)
> -    {
> -      edge_iterator ei;
> -      edge e;
> -      FOR_EACH_EDGE (e, ei, bb->succs)
> -       e->flags |= EDGE_EXECUTABLE;
> -    }
> -
>    /* Walk all blocks in dominator order, value-numbering stmts
>       SSA defs and decide whether outgoing edges are not executable.  */
>    sccvn_dom_walker walker;
> +  walker.init_edge_executable (cfun);
>    walker.walk (ENTRY_BLOCK_PTR_FOR_FN (cfun));
>    if (walker.fail)
>      {
>

Reply via email to