https://gcc.gnu.org/g:ae06482cb6fa4f68305192481e9efb3a8ef4a619

commit r17-5581-gae06482cb6fa4f68305192481e9efb3a8ef4a619
Author: Aldy Hernandez <[email protected]>
Date:   Fri Oct 9 10:54:53 2026 +0000

    sccvn: finish elimination in vn_driver::finalize [PR126904]
    
    vn_driver::finalize's job is to finish what the walk eliminated, so
    that FRE's upcoming jump threader can still use the value numbers in
    between.  Move eliminate_cleanup to finalize, so that in between the
    threader sees the IL as elimination left it, with value numbers that
    still describe it.
    
      vn_driver vn (fun, iterate_p, true);
      // The names and the CFG are still the ones the value numbers
      // describe.
      todo = vn.finalize ();
    
    When iterating, FRE now eliminates in the walk too, so the threader
    searches the IL as elimination leaves it.  Searching before eliminating
    would complicate the threader considerably: neither it nor the jump
    threading registry handles the IL changing under them between the
    search and applying the paths.
    
    No functional change.
    
            PR tree-optimization/126904
    
    gcc/ChangeLog:
    
            * tree-ssa-sccvn.h (vn_driver::todo): Remove.
            (class vn_driver): Add m_region_p and m_eliminator.
            * tree-ssa-sccvn.cc (do_rpo_vn_1): Take the walker that eliminates
            when iterating.  Leave eliminate_cleanup to the caller.
            (do_rpo_vn): Pass ELIMINATE through.  Return what finalize
            returns.
            (vn_driver::vn_driver): When iterating and eliminating, make a
            walker of its own for the elimination.
            (vn_driver::~vn_driver): Free it.
            (vn_driver::finalize): Call eliminate_cleanup on the walker that
            eliminated.  Remove the full elimination.
            (pass_fre::execute): Have the walk eliminate when iterating too.

Diff:
---
 gcc/tree-ssa-sccvn.cc | 48 +++++++++++++++++++++---------------------------
 gcc/tree-ssa-sccvn.h  |  7 +++++--
 2 files changed, 26 insertions(+), 29 deletions(-)

diff --git a/gcc/tree-ssa-sccvn.cc b/gcc/tree-ssa-sccvn.cc
index 1f8449abc6bd..3b195b60c08d 100644
--- a/gcc/tree-ssa-sccvn.cc
+++ b/gcc/tree-ssa-sccvn.cc
@@ -8860,13 +8860,16 @@ do_unwind (unwind_state *to, rpo_elim &avail)
    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.  AVAIL and
-   BB_TO_RPO belong to the caller, which can keep them past the walk.  */
+   is true then force PHI nodes in ENTRY->dest to VARYING.  AVAIL,
+   BB_TO_RPO and ELIMINATOR belong to the caller, which can keep them
+   past the walk.  Elimination stops short of eliminate_cleanup, which
+   is left 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, rpo_elim &avail, int *bb_to_rpo)
+            vn_lookup_kind kind, rpo_elim &avail, int *bb_to_rpo,
+            eliminate_dom_walker *eliminator)
 {
   unsigned todo = 0;
   default_vn_walk_kind = kind;
@@ -9268,10 +9271,9 @@ 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);
+         rpo_avail = eliminator;
+         eliminator->walk (ENTRY_BLOCK_PTR_FOR_FN (fn));
        }
-      else
-       todo |= avail.eliminate_cleanup (do_region);
     }
 
   vn_valueize = NULL;
@@ -9304,13 +9306,9 @@ do_rpo_vn (function *fn, edge entry, bitmap exit_bbs,
 {
   auto_timevar tv (TV_TREE_RPO_VN);
 
-  /* We don't support elimination in region-based iteration.  */
-  gcc_assert (!entry || !iterate || !eliminate);
-  /* When iterating, finalize does the elimination; otherwise the
-     constructor's walk does.  */
-  vn_driver vn (fn, entry, exit_bbs, iterate, eliminate && !iterate,
+  vn_driver vn (fn, entry, exit_bbs, iterate, eliminate,
                skip_entry_phis, kind);
-  return eliminate ? vn.finalize () : vn.todo ();
+  return vn.finalize ();
 }
 
 vn_driver::vn_driver (function *fn, bool iterate, bool eliminate,
@@ -9327,20 +9325,26 @@ vn_driver::vn_driver (function *fn, bool iterate, bool 
eliminate,
 vn_driver::vn_driver (function *fn, edge entry, bitmap exit_bbs,
                      bool iterate, bool eliminate, bool skip_entry_phis,
                      vn_lookup_kind kind)
-  : m_eliminate (eliminate)
+  : m_eliminate (eliminate), m_region_p (entry != NULL)
 {
   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));
+  /* When iterating, elimination is a walk of its own.  */
+  m_eliminator = (iterate && eliminate
+                 ? new eliminate_dom_walker (CDI_DOMINATORS, NULL) : m_avail);
   m_todo = do_rpo_vn_1 (fn, entry, exit_bbs, iterate, eliminate,
-                       skip_entry_phis, kind, *m_avail, m_bb_to_rpo);
+                       skip_entry_phis, kind, *m_avail, m_bb_to_rpo,
+                       m_eliminator);
 }
 
 vn_driver::~vn_driver ()
 {
   free_rpo_vn ();
   XDELETEVEC (m_bb_to_rpo);
+  if (m_eliminator != m_avail)
+    delete m_eliminator;
   delete m_avail;
 }
 
@@ -9351,7 +9355,7 @@ vn_driver::finalize (bitmap inserted_exprs)
 {
   /* If ELIMINATE was passed to the constructor, finish the elimination.  */
   if (m_eliminate)
-    return m_todo;
+    return m_todo | m_eliminator->eliminate_cleanup (m_region_p);
 
   /* PRE eliminates after its insertions, when the RPO map no longer
      describes the IL.  Return only its flags, as PRE always has, to avoid
@@ -9359,15 +9363,7 @@ vn_driver::finalize (bitmap inserted_exprs)
   if (inserted_exprs)
     return eliminate_with_rpo_vn (inserted_exprs);
 
-  /* Otherwise do full elimination.  */
-  rpo_avail = m_avail;
-  vn_bb_to_rpo = m_bb_to_rpo;
-  vn_valueize = rpo_vn_valueize;
-  unsigned todo = m_todo | eliminate_with_rpo_vn (NULL);
-  vn_valueize = NULL;
-  rpo_avail = NULL;
-  vn_bb_to_rpo = NULL;
-  return todo;
+  return m_todo;
 }
 
 
@@ -9423,9 +9419,7 @@ pass_fre::execute (function *fun)
     loop_optimizer_init (LOOPS_HAVE_SIMPLE_LATCHES);
 
   {
-    /* When iterating, finalize below does the elimination; otherwise the
-       constructor's walk does.  */
-    vn_driver vn (fun, iterate_p, !iterate_p);
+    vn_driver vn (fun, iterate_p, true);
     todo = vn.finalize ();
   }
 
diff --git a/gcc/tree-ssa-sccvn.h b/gcc/tree-ssa-sccvn.h
index cc0b36df27cc..9af7cf666c5b 100644
--- a/gcc/tree-ssa-sccvn.h
+++ b/gcc/tree-ssa-sccvn.h
@@ -320,8 +320,6 @@ public:
             bool eliminate, bool skip_entry_phis, vn_lookup_kind);
   ~vn_driver ();
   unsigned finalize (bitmap inserted_exprs = NULL);
-  /* The TODO flags of the walk, for a caller that does not eliminate.  */
-  unsigned todo () const { return m_todo; }
 
 private:
   DISABLE_COPY_AND_ASSIGN (vn_driver);
@@ -330,6 +328,11 @@ private:
   unsigned m_todo;
   /* Whether the walk eliminated.  */
   bool m_eliminate;
+  /* Whether the walk was of a region.  */
+  bool m_region_p;
+  /* The walker that eliminated, if the walk did: M_AVAIL unless the walk
+     iterated.  */
+  class eliminate_dom_walker *m_eliminator;
 };
 
 /* Valueize NAME if it is an SSA name, otherwise just return it.  This hook

Reply via email to