https://gcc.gnu.org/g:337ebeccfdaaea5549324e749ad503ac6008d860
commit r16-5323-g337ebeccfdaaea5549324e749ad503ac6008d860 Author: Andrew MacLeod <[email protected]> Date: Fri Nov 14 16:06:42 2025 -0500 Turn PHI analyzer to a simple pre-pass Rather than having a dynamic analyzer around that is handcuffed by only global values, invoke it as a prepass in VRP and put all values it finds in the query's global cache via update_range_info. gcc/ * gimple-range-fold.cc (fold_using_range::range_of_phi): Remove the PHI analysis query. * gimple-range-phi.cc (phi_analysis_object): Delete. (phi_analysis_initialize): Delete. (phi_analysis_finalize): Delete. (phi_analysis_available_p): Delete. (phi_analysis): Invoke a phi analyzer. (phi_analyzer::phi_analyzer): Preprocess all phi nodes and set global values for them in a query. (phi_analyzer::process_phi): Use query, and export any inital values found to the query. * gimple-range-phi.h (m_global): Delete. (phi_analysis_initialize): Delete. (phi_analysis_finalize): Delete. (phi_analysis_available_p): Delete. (phi_analysis): Change prototype. * tree-vrp.cc (execute_ranger_vrp): Call phi_analysis. gcc/testsuite/ * gcc.dg/pr102983.c: Adjust final check. Diff: --- gcc/gimple-range-fold.cc | 28 ++--------- gcc/gimple-range-phi.cc | 101 ++++++++++++++++++---------------------- gcc/gimple-range-phi.h | 17 ++----- gcc/testsuite/gcc.dg/pr102983.c | 2 +- gcc/tree-vrp.cc | 3 +- 5 files changed, 55 insertions(+), 96 deletions(-) diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc index d4481770d76e..63e114e4d044 100644 --- a/gcc/gimple-range-fold.cc +++ b/gcc/gimple-range-fold.cc @@ -1008,31 +1008,9 @@ fold_using_range::range_of_phi (vrange &r, gphi *phi, fur_source &src) } } - // If PHI analysis is available, see if there is an iniital range. - if (phi_analysis_available_p () - && irange::supports_p (TREE_TYPE (phi_def))) - { - phi_group *g = (phi_analysis())[phi_def]; - if (g && !(g->range ().varying_p ())) - { - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, "PHI GROUP query for "); - print_generic_expr (dump_file, phi_def, TDF_SLIM); - fprintf (dump_file, " found : "); - g->range ().dump (dump_file); - fprintf (dump_file, " and adjusted original range from :"); - r.dump (dump_file); - } - r.intersect (g->range ()); - if (dump_file && (dump_flags & TDF_DETAILS)) - { - fprintf (dump_file, " to :"); - r.dump (dump_file); - fprintf (dump_file, "\n"); - } - } - } + // Incorporate any global value. If a PHI analysis phase was run, there may + // be a restricted global range already. Query the range with no context + // to get a global range. // If SCEV is available, query if this PHI has any known values. if (scev_initialized_p () diff --git a/gcc/gimple-range-phi.cc b/gcc/gimple-range-phi.cc index d9b583fe4fbe..45895209600c 100644 --- a/gcc/gimple-range-phi.cc +++ b/gcc/gimple-range-phi.cc @@ -37,41 +37,14 @@ along with GCC; see the file COPYING3. If not see #include "gimple-walk.h" #include "cfganal.h" -// There can be only one running at a time. -static phi_analyzer *phi_analysis_object = NULL; - -// Initialize a PHI analyzer with range query Q. +// Invoke a phi analyzer. It will process all the current PHI groups +// and export any ranges found to set_range_info. +// When finished, it will simply dispose of itself. void -phi_analysis_initialize (range_query &q) -{ - gcc_checking_assert (!phi_analysis_object); - phi_analysis_object = new phi_analyzer (q); -} - -// Terminate the current PHI analyzer. if F is non-null, dump the tables - -void -phi_analysis_finalize () -{ - gcc_checking_assert (phi_analysis_object); - delete phi_analysis_object; - phi_analysis_object = NULL; -} - -// Return TRUE is there is a PHI analyzer operating. -bool -phi_analysis_available_p () -{ - return phi_analysis_object != NULL; -} - -// Return the phi analyzer object. - -phi_analyzer &phi_analysis () +phi_analysis (range_query &q) { - gcc_checking_assert (phi_analysis_object); - return *phi_analysis_object; + phi_analyzer analyze (q); } // Initialize a phi_group from another group G. @@ -254,16 +227,35 @@ phi_group::dump (FILE *f) // Construct a phi analyzer which uses range_query G to pick up values. -phi_analyzer::phi_analyzer (range_query &g) : m_global (g), m_phi_groups (vNULL) +phi_analyzer::phi_analyzer (range_query &query) : m_phi_groups (vNULL) { m_work.create (0); m_work.safe_grow (20); m_tab.create (0); -// m_tab.safe_grow_cleared (num_ssa_names + 100); + m_tab.safe_grow_cleared (num_ssa_names + 10); + bitmap_obstack_initialize (&m_bitmaps); m_simple = BITMAP_ALLOC (&m_bitmaps); m_current = BITMAP_ALLOC (&m_bitmaps); + + basic_block bb; + gphi_iterator gphi; + + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "PHI ANALYZER : processing PHIS.\n"); + + // Process each PHI node to see if it belongs in a group with others. + // Then calculate an initial value for the group. + FOR_EACH_BB_FN (bb, cfun) + { + for (gphi = gsi_start_nonvirtual_phis (bb); + !gsi_end_p (gphi); + gsi_next_nonvirtual_phi (&gphi)) + process_phi (gphi.phi (), query); + } + if (dump_file && (dump_flags & TDF_DETAILS)) + fprintf (dump_file, "PHI ANALYZER : Finished processing PHIS.\n"); } // Destruct a PHI analyzer. @@ -308,35 +300,33 @@ phi_analyzer::operator[] (tree name) return NULL; unsigned v = SSA_NAME_VERSION (name); - // Already been processed and not part of a group. - if (bitmap_bit_p (m_simple, v)) + if (v >= m_tab.length ()) return NULL; - - if (v >= m_tab.length () || !m_tab[v]) - { - process_phi (as_a<gphi *> (SSA_NAME_DEF_STMT (name))); - if (bitmap_bit_p (m_simple, v)) - return NULL; - // If m_simple bit isn't set, and process_phi didn't allocated the table - // no group was created, so return NULL. - if (v >= m_tab.length ()) - return NULL; - } return m_tab[v]; } -// Process phi node PHI to see if it is part of a group. +// Process phi node PHI to see if it is part of a group. Use QUERY +// to deteremine ranges. void -phi_analyzer::process_phi (gphi *phi) +phi_analyzer::process_phi (gphi *phi, range_query &query) { - gcc_checking_assert (!group (gimple_phi_result (phi))); + tree def = gimple_phi_result (phi); + unsigned v = SSA_NAME_VERSION (def); + + gcc_checking_assert (v < m_tab.length ()); + // If this is already on a group, or identified as a simple phi, or + // not an irange, do not process it. + if (m_tab[v] || bitmap_bit_p (m_simple, v) + || !irange::supports_p (TREE_TYPE (def))) + return; + bool cycle_p = true; // Start with the LHS of the PHI in the worklist. unsigned x; m_work.truncate (0); - m_work.safe_push (gimple_phi_result (phi)); + m_work.safe_push (def); unsigned phi_count = 1; bitmap_clear (m_current); @@ -447,7 +437,7 @@ phi_analyzer::process_phi (gphi *phi) // If there is an symbolic initializer as well, include it here. if (valid && init_idx != -1) { - if (m_global.range_on_edge (init_sym, m_ext_edge[init_idx], + if (query.range_on_edge (init_sym, m_ext_edge[init_idx], m_external[init_idx])) init_range.union_ (init_sym); else @@ -457,7 +447,7 @@ phi_analyzer::process_phi (gphi *phi) { // Try to create a group based on m_current. If a result comes back // with a range that isn't varying, create the group. - phi_group cyc (m_current, init_range, mod, &m_global); + phi_group cyc (m_current, init_range, mod, &query); if (!cyc.range ().varying_p ()) { g = new phi_group (cyc); @@ -490,9 +480,6 @@ phi_analyzer::process_phi (gphi *phi) return; } - if (num_ssa_names >= m_tab.length ()) - m_tab.safe_grow_cleared (num_ssa_names + 100); - // Now set all entries in the group to this record. unsigned i; bitmap_iterator bi; @@ -501,6 +488,8 @@ phi_analyzer::process_phi (gphi *phi) // Can't be in more than one group. gcc_checking_assert (m_tab[i] == NULL); m_tab[i] = g; + // Set the new range in the range query. + query.update_range_info (ssa_name (i), g->range ()); } // Allocate a new bitmap for the next time as the original one is now part // of the new phi group. diff --git a/gcc/gimple-range-phi.h b/gcc/gimple-range-phi.h index ea5750520c24..34001f738da7 100644 --- a/gcc/gimple-range-phi.h +++ b/gcc/gimple-range-phi.h @@ -81,8 +81,7 @@ public: void dump (FILE *f); protected: phi_group *group (tree name) const; - void process_phi (gphi *phi); - range_query &m_global; + void process_phi (gphi *phi, range_query &query); vec<tree> m_work; bitmap m_simple; // Processed, not part of a group. @@ -92,16 +91,10 @@ protected: bitmap_obstack m_bitmaps; }; -// These are the APIs to start and stop a phi analyzerin a SCEV like manner. -// There can only be one operating at any given time. -// When initialized, a range-query if provided to do lookups of values for -// PHIs and to evaluate modifier and initial value statements. -// To avoid problems, this should be some form of constant query, like -// global_range_query or better yet a const_query from a functioning ranger. +// Invoke a phi analyzer. It will process all the current PHI nodes and try +// to form groups with initial values. Then export any ranges found +// to set_range_info. When finished, it will simply dispose of itself. -bool phi_analysis_available_p (); -phi_analyzer &phi_analysis (); -void phi_analysis_initialize (range_query &); -void phi_analysis_finalize (); +void phi_analysis (range_query &q); #endif // GCC_SSA_RANGE_PHI_H diff --git a/gcc/testsuite/gcc.dg/pr102983.c b/gcc/testsuite/gcc.dg/pr102983.c index ded748af08a3..1b0e5c7587d5 100644 --- a/gcc/testsuite/gcc.dg/pr102983.c +++ b/gcc/testsuite/gcc.dg/pr102983.c @@ -18,4 +18,4 @@ int main() { } } -/* { dg-final { scan-tree-dump-times "Global Exported: c_.*1, 1" 1 "evrp" } } */ +/* { dg-final { scan-tree-dump-not "if \\(c_" "evrp" } } */ diff --git a/gcc/tree-vrp.cc b/gcc/tree-vrp.cc index cad1a24ab339..b173ed263866 100644 --- a/gcc/tree-vrp.cc +++ b/gcc/tree-vrp.cc @@ -1094,8 +1094,8 @@ execute_ranger_vrp (struct function *fun, bool final_p) set_all_edges_as_executable (fun); gimple_ranger *ranger = enable_ranger (fun, false); + phi_analysis (*ranger); rvrp_folder folder (ranger, final_p); - phi_analysis_initialize (ranger->const_query ()); folder.substitute_and_fold (); // Ensure the cache in SCEV has been cleared before processing // globals to be removed. @@ -1149,7 +1149,6 @@ execute_ranger_vrp (struct function *fun, bool final_p) } } - phi_analysis_finalize (); disable_ranger (fun); scev_finalize (); loop_optimizer_finalize ();
