}
}
- // 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 ()
#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.
// 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.
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);
// 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
{
// 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);
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;
// 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.
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.
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