summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew MacLeod <amacleod@redhat.com>2025-11-14 16:06:42 -0500
committerAndrew MacLeod <amacleod@redhat.com>2025-11-16 17:20:41 -0500
commit337ebeccfdaaea5549324e749ad503ac6008d860 (patch)
tree93a43227ef6c5aa93eaf0de12a6a280c0440f2bf
parent71f41d9b3ac80f428de61486f2cec9604c4d729e (diff)
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.
-rw-r--r--gcc/gimple-range-fold.cc28
-rw-r--r--gcc/gimple-range-phi.cc101
-rw-r--r--gcc/gimple-range-phi.h17
-rw-r--r--gcc/testsuite/gcc.dg/pr102983.c2
-rw-r--r--gcc/tree-vrp.cc3
5 files changed, 55 insertions, 96 deletions
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index d4481770d76..63e114e4d04 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 d9b583fe4fb..45895209600 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 ea5750520c2..34001f738da 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 ded748af08a..1b0e5c7587d 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 cad1a24ab33..b173ed26386 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 ();