On Thu, 8 Oct 2026, Aldy Hernandez wrote:

> RPO VN is driven through a couple free functions that we can abstract
> out to a class to make things a bit tidier, and to make it easier to
> call the back threader from within FRE to get value numbering for
> free.
> 
> Make it an object that we can later sub-class into a path aware VN
> object.
> 
> OK for trunk?

Hmm.  I think .walk () should be part of constructing (it's a bad
name anyway), that makes it obvious it's a single-shot thing.

Overall it feels a bit of a half-way transition, merely covering
parts of the API, so I don't think it's much of an improvement.

As it is more like a "VN driver" class, maybe naming it accordingly
and _not_ move functions into it as member functions, just encapsulate
the toplevel flow, construct (with value-number), (optional) eliminate,
destruction.

So I think this patch goes too far and too little.

Not knowing how you'd use it exactly doesn't help making a constructive
suggestion, of course ;)

Richard.

> gcc/ChangeLog:
> 
>       * tree-ssa-sccvn.h (class vn): New.
>       (run_rpo_vn, eliminate_with_rpo_vn, free_rpo_vn): Remove.
>       * tree-ssa-sccvn.cc (class eliminate_dom_walker): Make the
>       destructor virtual.
>       (eliminate_with_rpo_vn): Rename to ...
>       (vn::eliminate): ... this.
>       (run_rpo_vn): Rename to ...
>       (vn::enumerate_values): ... this, without the walk.
>       (free_rpo_vn): Make static.
>       (vn::vn): New, for the whole function and for a region, which
>       says whether to skip its entry PHIs.
>       (vn::~vn): New.
>       (do_rpo_vn_1): Rename to ...
>       (vn::walk): ... this, on the object's region and walker.
>       (do_rpo_vn, pass_fre::execute): Use a vn.
>       * tree-ssa-pre.cc (pass_pre::execute): Same.
> ---
>  gcc/tree-ssa-pre.cc   |  8 ++---
>  gcc/tree-ssa-sccvn.cc | 76 ++++++++++++++++++++++++++++---------------
>  gcc/tree-ssa-sccvn.h  | 27 ++++++++++++---
>  3 files changed, 77 insertions(+), 34 deletions(-)
> 
> diff --git a/gcc/tree-ssa-pre.cc b/gcc/tree-ssa-pre.cc
> index f1bd8950983..8527eae1f9c 100644
> --- a/gcc/tree-ssa-pre.cc
> +++ b/gcc/tree-ssa-pre.cc
> @@ -4693,7 +4693,9 @@ pass_pre::execute (function *fun)
>    scev_initialize ();
>    calculate_dominance_info (CDI_DOMINATORS);
>  
> -  run_rpo_vn (VN_WALK);
> +  vn vn (fun);
> +  vn.walk (true, false, VN_WALK);
> +  vn.enumerate_values ();
>  
>    init_pre ();
>  
> @@ -4727,7 +4729,7 @@ pass_pre::execute (function *fun)
>    statistics_counter_event (fun, "HOIST inserted", pre_stats.hoist_insert);
>    statistics_counter_event (fun, "New PHIs", pre_stats.phis);
>  
> -  todo |= eliminate_with_rpo_vn (inserted_exprs);
> +  todo |= vn.eliminate (inserted_exprs);
>  
>    vn_valueize = NULL;
>  
> @@ -4761,8 +4763,6 @@ pass_pre::execute (function *fun)
>       - mark TODO_cleanup_cfg when necessary.  */
>    todo |= tail_merge_optimize (need_crit_edge_split);
>  
> -  free_rpo_vn ();
> -
>    /* Tail merging invalidates the virtual SSA web, together with
>       cfg-cleanup opportunities exposed by PRE this will wreck the
>       SSA updating machinery.  So make sure to run update-ssa
> diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
> index 7ff14cec119..fc4725972c5 100644
> --- a/gcc/tree-ssa-sccvn.cc
> +++ b/gcc/tree-ssa-sccvn.cc
> @@ -2693,7 +2693,7 @@ class eliminate_dom_walker : public dom_walker
>  {
>  public:
>    eliminate_dom_walker (cdi_direction, bitmap);
> -  ~eliminate_dom_walker ();
> +  virtual ~eliminate_dom_walker ();
>  
>    edge before_dom_children (basic_block) final override;
>    void after_dom_children (basic_block) final override;
> @@ -8055,7 +8055,7 @@ eliminate_dom_walker::eliminate_cleanup (bool region_p)
>  /* Eliminate fully redundant computations.  */
>  
>  unsigned
> -eliminate_with_rpo_vn (bitmap inserted_exprs)
> +vn::eliminate (bitmap inserted_exprs)
>  {
>    eliminate_dom_walker walker (CDI_DOMINATORS, inserted_exprs);
>  
> @@ -8067,16 +8067,11 @@ eliminate_with_rpo_vn (bitmap inserted_exprs)
>    return walker.eliminate_cleanup ();
>  }
>  
> -static unsigned
> -do_rpo_vn_1 (function *fn, edge entry, bitmap exit_bbs,
> -          bool iterate, bool eliminate, bool skip_entry_phis,
> -          vn_lookup_kind kind);
> +/* Give every value a value id, for PRE.  */
>  
>  void
> -run_rpo_vn (vn_lookup_kind kind)
> +vn::enumerate_values ()
>  {
> -  do_rpo_vn_1 (cfun, NULL, NULL, true, false, false, kind);
> -
>    /* ???  Prune requirement of these.  */
>    constant_to_value_id = new hash_table<vn_constant_hasher> (23);
>  
> @@ -8127,7 +8122,7 @@ run_rpo_vn (vn_lookup_kind kind)
>  
>  /* Free VN associated data structures.  */
>  
> -void
> +static void
>  free_rpo_vn (void)
>  {
>    free_vn_table (valid_info);
> @@ -8880,19 +8875,49 @@ do_unwind (unwind_state *to, rpo_elim &avail)
>      }
>  }
>  
> +vn::vn (function *fn)
> +  : vn (fn, NULL, NULL, false)
> +{
> +}
> +
> +/* A value numbering of the region ENTRY leads into, which exits to EXIT_BBS,
> +   or all of FN if ENTRY is NULL.  If SKIP_ENTRY_PHIS is set, force PHI nodes
> +   in ENTRY->dest to VARYING.  */
> +
> +vn::vn (function *fn, edge entry, bitmap exit_bbs, bool skip_entry_phis)
> +  : m_fn (fn), m_entry (entry), m_exit_bbs (exit_bbs),
> +    m_skip_entry_phis (skip_entry_phis), m_walked (false)
> +{
> +  basic_block entry_bb
> +    = entry ? entry->dest : single_succ (ENTRY_BLOCK_PTR_FOR_FN (fn));
> +  m_avail = new rpo_elim (entry_bb);
> +  m_bb_to_rpo = XNEWVEC (int, last_basic_block_for_fn (fn));
> +}
> +
> +vn::~vn ()
> +{
> +  if (m_walked)
> +    free_rpo_vn ();
> +  XDELETEVEC (m_bb_to_rpo);
> +  delete m_avail;
> +}
> +
>  /* Do VN on a SEME region specified by ENTRY and EXIT_BBS in FN.
>     If ITERATE is true then treat backedges optimistically as not
>     executed and iterate.  If ELIMINATE is true then perform
> -   elimination, otherwise leave that to the caller.  If SKIP_ENTRY_PHIS
> -   is true then force PHI nodes in ENTRY->dest to VARYING.  */
> +   elimination, otherwise leave that to the caller.  */
>  
> -static unsigned
> -do_rpo_vn_1 (function *fn, edge entry, bitmap exit_bbs,
> -          bool iterate, bool eliminate, bool skip_entry_phis,
> -          vn_lookup_kind kind)
> +unsigned
> +vn::walk (bool iterate, bool eliminate, vn_lookup_kind kind)
>  {
> +  function *fn = m_fn;
> +  edge entry = m_entry;
> +  bitmap exit_bbs = m_exit_bbs;
> +  bool skip_entry_phis = m_skip_entry_phis;
>    unsigned todo = 0;
>    default_vn_walk_kind = kind;
> +  gcc_checking_assert (!m_walked);
> +  m_walked = true;
>  
>    /* We currently do not support region-based iteration when
>       elimination is requested.  */
> @@ -8935,14 +8960,14 @@ do_rpo_vn_1 (function *fn, edge entry, bitmap 
> exit_bbs,
>            "the entry block, skipping its PHIs.\n");
>    skip_entry_phis |= e != NULL;
>  
> -  int *bb_to_rpo = XNEWVEC (int, last_basic_block_for_fn (fn));
> +  int *bb_to_rpo = m_bb_to_rpo;
>    for (int i = 0; i < n; ++i)
>      bb_to_rpo[rpo[i]] = i;
>    vn_bb_to_rpo = bb_to_rpo;
>  
>    unwind_state *rpo_state = XNEWVEC (unwind_state, n);
>  
> -  rpo_elim avail (entry->dest);
> +  rpo_elim &avail = *m_avail;
>    rpo_avail = &avail;
>  
>    /* Verify we have no extra entries into the region.  */
> @@ -9281,7 +9306,7 @@ do_rpo_vn_1 (function *fn, edge entry, bitmap exit_bbs,
>         /* Note we can't use avail.walk here because that gets confused
>            by the existing availability and it will be less efficient
>            as well.  */
> -       todo |= eliminate_with_rpo_vn (NULL);
> +       todo |= this->eliminate (NULL);
>       }
>        else
>       todo |= avail.eliminate_cleanup (do_region);
> @@ -9291,7 +9316,6 @@ do_rpo_vn_1 (function *fn, edge entry, bitmap exit_bbs,
>    rpo_avail = NULL;
>    vn_bb_to_rpo = NULL;
>  
> -  XDELETEVEC (bb_to_rpo);
>    XDELETEVEC (rpo);
>    XDELETEVEC (rpo_state);
>  
> @@ -9314,10 +9338,8 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
>          vn_lookup_kind kind)
>  {
>    auto_timevar tv (TV_TREE_RPO_VN);
> -  unsigned todo = do_rpo_vn_1 (fn, entry, exit_bbs, iterate, eliminate,
> -                            skip_entry_phis, kind);
> -  free_rpo_vn ();
> -  return todo;
> +  vn vn (fn, entry, exit_bbs, skip_entry_phis);
> +  return vn.walk (iterate, eliminate, kind);
>  }
>  
>  
> @@ -9371,8 +9393,10 @@ pass_fre::execute (function *fun)
>    if (iterate_p)
>      loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
>  
> -  todo = do_rpo_vn_1 (fun, NULL, NULL, iterate_p, true, false, 
> VN_WALKREWRITE);
> -  free_rpo_vn ();
> +  {
> +    vn vn (fun);
> +    todo = vn.walk (iterate_p, true);
> +  }
>  
>    if (iterate_p)
>      loop_optimizer_finalize ();
> diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h
> index 78729fbec64..92a4c657c1f 100644
> --- a/gcc/tree-ssa-sccvn.h
> +++ b/gcc/tree-ssa-sccvn.h
> @@ -309,10 +309,29 @@ unsigned do_rpo_vn (function *, edge, bitmap,
>                   /* skip_entry_phis */ bool = false,
>                   vn_lookup_kind = VN_WALKREWRITE);
>  
> -/* Private interface for PRE.  */
> -void run_rpo_vn (vn_lookup_kind);
> -unsigned eliminate_with_rpo_vn (bitmap);
> -void free_rpo_vn (void);
> +/* An RPO value numbering of a function.  */
> +
> +class vn
> +{
> +public:
> +  vn (function *);
> +  vn (function *, edge entry, bitmap exit_bbs, bool skip_entry_phis);
> +  virtual ~vn ();
> +  unsigned walk (bool iterate, bool eliminate,
> +              vn_lookup_kind = VN_WALKREWRITE);
> +  void enumerate_values ();
> +  unsigned eliminate (bitmap inserted_exprs);
> +
> +private:
> +  DISABLE_COPY_AND_ASSIGN (vn);
> +  function *m_fn;
> +  edge m_entry;
> +  bitmap m_exit_bbs;
> +  bool m_skip_entry_phis;
> +  class rpo_elim *m_avail;
> +  int *m_bb_to_rpo;
> +  bool m_walked;
> +};
>  
>  /* Valueize NAME if it is an SSA name, otherwise just return it.  This hook
>     is initialized by run_scc_vn.  */
> 

-- 
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Stefan Gaiser, Jochen Jaser, Abhinav Puri; (HRB 36809, AG Nuernberg)

Reply via email to