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
