https://gcc.gnu.org/g:07441e41f5eb4d385e8ee7cfb50b5d71520bff74
commit r15-801-g07441e41f5eb4d385e8ee7cfb50b5d71520bff74 Author: Andrew MacLeod <amacl...@redhat.com> Date: Fri May 17 10:50:24 2024 -0400 Move infer_manager to a range_query oracle. Turn the infer_manager class into an always available oracle accessible via a range_query object. Also assocaite each inferrred range with it's originating stmt. * gimple-range-cache.cc (ranger_cache::ranger_cache): Create an infer oracle instead of a local member. (ranger_cache::~ranger_cache): Destroy the oracle. (ranger_cache::edge_range): Use oracle. (ranger_cache::fill_block_cache): Likewise. (ranger_cache::range_from_dom): Likewise. (ranger_cache::apply_inferred_ranges): Likewise. * gimple-range-cache.h (ranger_cache::m_exit): Delete. * gimple-range-infer.cc (infer_oracle): New static object; (class infer_oracle): New. (non_null_wrapper::non_null_wrapper): New. (non_null_wrapper::add_nonzero): New. (non_null_wrapper::add_range): New. (non_null_loadstore): Use nonnull_wrapper. (gimple_infer_range::gimple_infer_range): New alternate constructor. (exit_range::stmt): New. (infer_range_manager::has_range_p): Combine seperate methods. (infer_range_manager::maybe_adjust_range): Adjust has_range_p call. (infer_range_manager::add_ranges): New. (infer_range_manager::add_range): Take stmt rather than BB. (infer_range_manager::add_nonzero): Adjust from BB to stmt. * gimple-range-infer.h (class gimple_infer_range): Adjust methods. (infer_range_oracle): New. (class infer_range_manager): Inherit from infer_range_oracle. Adjust methods. * gimple-range-path.cc (path_range_query::range_defined_in_block): Use oracle. (path_range_query::adjust_for_non_null_uses): Likewise. * gimple-range.cc (gimple_ranger::range_on_edge): Likewise (gimple_ranger::register_transitive_inferred_ranges): Likewise. * value-query.cc (default_infer_oracle): New. (range_query::create_infer_oracle): New. (range_query::destroy_infer_oracle): New. (range_query::share_query): Copy infer pointer. (range_query::range_query): Initialize infer pointer. (range_query::~range_query): destroy infer object. * value-query.h (range_query::infer_oracle): New. (range_query::create_infer_oracle): New prototype. (range_query::destroy_infer_oracle): New prototype. (range_query::m_infer): New. Diff: --- gcc/gimple-range-cache.cc | 24 ++++++------- gcc/gimple-range-cache.h | 1 - gcc/gimple-range-infer.cc | 90 +++++++++++++++++++++++++++++++++-------------- gcc/gimple-range-infer.h | 31 +++++++++++----- gcc/gimple-range-path.cc | 4 +-- gcc/gimple-range.cc | 14 ++++---- gcc/value-query.cc | 20 +++++++++++ gcc/value-query.h | 5 +++ 8 files changed, 131 insertions(+), 58 deletions(-) diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc index 55277ea8af1..34dc9c4a3ec 100644 --- a/gcc/gimple-range-cache.cc +++ b/gcc/gimple-range-cache.cc @@ -950,8 +950,7 @@ update_list::pop () // -------------------------------------------------------------------------- ranger_cache::ranger_cache (int not_executable_flag, bool use_imm_uses) - : m_gori (not_executable_flag), - m_exit (use_imm_uses) + : m_gori (not_executable_flag) { m_workback.create (0); m_workback.safe_grow_cleared (last_basic_block_for_fn (cfun)); @@ -960,6 +959,7 @@ ranger_cache::ranger_cache (int not_executable_flag, bool use_imm_uses) // If DOM info is available, spawn an oracle as well. create_relation_oracle (); + create_infer_oracle (use_imm_uses); unsigned x, lim = last_basic_block_for_fn (cfun); // Calculate outgoing range info upfront. This will fully populate the @@ -977,6 +977,7 @@ ranger_cache::ranger_cache (int not_executable_flag, bool use_imm_uses) ranger_cache::~ranger_cache () { delete m_update; + destroy_infer_oracle (); destroy_relation_oracle (); delete m_temporal; m_workback.release (); @@ -1175,7 +1176,7 @@ ranger_cache::edge_range (vrange &r, edge e, tree name, enum rfd_mode mode) exit_range (r, name, e->src, mode); // If this is not an abnormal edge, check for inferred ranges on exit. if ((e->flags & (EDGE_EH | EDGE_ABNORMAL)) == 0) - m_exit.maybe_adjust_range (r, name, e->src); + infer_oracle ().maybe_adjust_range (r, name, e->src); Value_Range er (TREE_TYPE (name)); if (m_gori.outgoing_edge_range_p (er, e, name, *this)) r.intersect (er); @@ -1544,7 +1545,7 @@ ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb) // Regardless of whether we have visited pred or not, if the // pred has inferred ranges, revisit this block. // Don't search the DOM tree. - if (m_exit.has_range_p (name, pred)) + if (infer_oracle ().has_range_p (pred, name)) { if (DEBUG_RANGE_CACHE) fprintf (dump_file, "Inferred range: update "); @@ -1667,7 +1668,7 @@ ranger_cache::range_from_dom (vrange &r, tree name, basic_block start_bb, for ( ; bb; prev_bb = bb, bb = get_immediate_dominator (CDI_DOMINATORS, bb)) { // Accumulate any block exit inferred ranges. - m_exit.maybe_adjust_range (infer, name, bb); + infer_oracle ().maybe_adjust_range (infer, name, bb); // This block has an outgoing range. if (m_gori.has_edge_range_p (name, bb)) @@ -1742,7 +1743,7 @@ ranger_cache::range_from_dom (vrange &r, tree name, basic_block start_bb, r.intersect (er); // If this is a normal edge, apply any inferred ranges. if ((e->flags & (EDGE_EH | EDGE_ABNORMAL)) == 0) - m_exit.maybe_adjust_range (r, name, bb); + infer_oracle ().maybe_adjust_range (r, name, bb); if (DEBUG_RANGE_CACHE) { @@ -1811,11 +1812,8 @@ ranger_cache::apply_inferred_ranges (gimple *s) update = false; } - for (unsigned x = 0; x < infer.num (); x++) - { - tree name = infer.name (x); - m_exit.add_range (name, bb, infer.range (x)); - if (update) - register_inferred_value (infer.range (x), name, bb); - } + infer_oracle ().add_ranges (s, infer); + if (update) + for (unsigned x = 0; x < infer.num (); x++) + register_inferred_value (infer.range (x), infer.name (x), bb); } diff --git a/gcc/gimple-range-cache.h b/gcc/gimple-range-cache.h index bdf07cd007c..e3ab89de02e 100644 --- a/gcc/gimple-range-cache.h +++ b/gcc/gimple-range-cache.h @@ -115,7 +115,6 @@ public: void register_inferred_value (const vrange &r, tree name, basic_block bb); void apply_inferred_ranges (gimple *s); gori_compute m_gori; - infer_range_manager m_exit; void dump_bb (FILE *f, basic_block bb); virtual void dump (FILE *f) override; diff --git a/gcc/gimple-range-infer.cc b/gcc/gimple-range-infer.cc index d5e1aa14275..757a2013c58 100644 --- a/gcc/gimple-range-infer.cc +++ b/gcc/gimple-range-infer.cc @@ -37,6 +37,25 @@ along with GCC; see the file COPYING3. If not see #include "cfganal.h" #include "tree-dfa.h" +// Create the global oracle. + +infer_range_oracle infer_oracle; + +// This class is merely an accessor which is granted internals to +// gimple_infer_range such that non_null_loadstore as a static callback can +// call the protected add_nonzero (). +// Static functions ccannot be friends, so we do it through a class wrapper. + +class non_null_wrapper +{ +public: + inline non_null_wrapper (gimple_infer_range *infer) : m_infer (infer) { } + inline void add_nonzero (tree name) { m_infer->add_nonzero (name); } + inline void add_range (tree t, vrange &r) { m_infer->add_range (t, r); } +private: + gimple_infer_range *m_infer; +}; + // Adapted from infer_nonnull_range_by_dereference and check_loadstore // to process nonnull ssa_name OP in S. DATA contains a pointer to a // stmt range inference instance. @@ -50,8 +69,8 @@ non_null_loadstore (gimple *, tree op, tree, void *data) addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (op)); if (!targetm.addr_space.zero_address_valid (as)) { - tree ssa = TREE_OPERAND (op, 0); - ((gimple_infer_range *)data)->add_nonzero (ssa); + non_null_wrapper wrapper ((gimple_infer_range *)data); + wrapper.add_nonzero (TREE_OPERAND (op, 0)); } } return false; @@ -173,6 +192,14 @@ gimple_infer_range::gimple_infer_range (gimple *s) } +// Create an single inferred range for NAMe using range R. + +gimple_infer_range::gimple_infer_range (tree name, vrange &r) +{ + num_args = 0; + add_range (name, r); +} + // ------------------------------------------------------------------------- // This class is an element in the list of inferred ranges. @@ -181,10 +208,12 @@ class exit_range { public: tree name; + gimple *stmt; vrange_storage *range; exit_range *next; }; + // If there is an element which matches SSA, return a pointer to the element. // Otherwise return NULL. @@ -253,33 +282,26 @@ infer_range_manager::get_nonzero (tree name) return *(m_nonzero[v]); } -// Return TRUE if there are any range inferences in block BB. - -bool -infer_range_manager::has_range_p (basic_block bb) -{ - if (bb->index >= (int)m_on_exit.length ()) - return false; - bitmap b = m_on_exit[bb->index].m_names; - return b && !bitmap_empty_p (b); -} - -// Return TRUE if NAME has a range inference in block BB. +// Return TRUE if NAME has a range inference in block BB. If NAME is NULL, +// return TRUE if there are any name sin BB. bool -infer_range_manager::has_range_p (tree name, basic_block bb) +infer_range_manager::has_range_p (basic_block bb, tree name) { // Check if this is an immediate use search model. - if (m_seen && !bitmap_bit_p (m_seen, SSA_NAME_VERSION (name))) + if (name && m_seen && !bitmap_bit_p (m_seen, SSA_NAME_VERSION (name))) register_all_uses (name); if (bb->index >= (int)m_on_exit.length ()) return false; - if (!m_on_exit[bb->index].m_names) - return false; - if (!bitmap_bit_p (m_on_exit[bb->index].m_names, SSA_NAME_VERSION (name))) + + bitmap b = m_on_exit[bb->index].m_names; + if (!b) return false; - return true; + + if (name) + return bitmap_bit_p (m_on_exit[bb->index].m_names, SSA_NAME_VERSION (name)); + return !bitmap_empty_p (b); } // Return TRUE if NAME has a range inference in block BB, and adjust range R @@ -288,7 +310,7 @@ infer_range_manager::has_range_p (tree name, basic_block bb) bool infer_range_manager::maybe_adjust_range (vrange &r, tree name, basic_block bb) { - if (!has_range_p (name, bb)) + if (!has_range_p (bb, name)) return false; exit_range *ptr = m_on_exit[bb->index].find_ptr (name); gcc_checking_assert (ptr); @@ -299,11 +321,23 @@ infer_range_manager::maybe_adjust_range (vrange &r, tree name, basic_block bb) return r.intersect (tmp); } -// Add range R as an inferred range for NAME in block BB. +// Add all inferred ranges in INFER at stmt S. + +void +infer_range_manager::add_ranges (gimple *s, gimple_infer_range &infer) +{ + for (unsigned x = 0; x < infer.num (); x++) + add_range (infer.name (x), s, infer.range (x)); +} + +// Add range R as an inferred range for NAME on stmt S. void -infer_range_manager::add_range (tree name, basic_block bb, const vrange &r) +infer_range_manager::add_range (tree name, gimple *s, const vrange &r) { + basic_block bb = gimple_bb (s); + if (!bb) + return; if (bb->index >= (int)m_on_exit.length ()) m_on_exit.safe_grow_cleared (last_basic_block_for_fn (cfun) + 1); @@ -334,6 +368,7 @@ infer_range_manager::add_range (tree name, basic_block bb, const vrange &r) ptr->range->set_vrange (cur); else ptr->range = m_range_allocator->clone (cur); + ptr->stmt = s; return; } @@ -342,16 +377,17 @@ infer_range_manager::add_range (tree name, basic_block bb, const vrange &r) ptr = (exit_range *)obstack_alloc (&m_list_obstack, sizeof (exit_range)); ptr->range = m_range_allocator->clone (r); ptr->name = name; + ptr->stmt = s; ptr->next = m_on_exit[bb->index].head; m_on_exit[bb->index].head = ptr; } -// Add a non-zero inferred range for NAME in block BB. +// Add a non-zero inferred range for NAME at stmt S. void -infer_range_manager::add_nonzero (tree name, basic_block bb) +infer_range_manager::add_nonzero (tree name, gimple *s) { - add_range (name, bb, get_nonzero (name)); + add_range (name, s, get_nonzero (name)); } // Follow immediate use chains and find all inferred ranges for NAME. @@ -378,7 +414,7 @@ infer_range_manager::register_all_uses (tree name) for (unsigned x = 0; x < infer.num (); x++) { if (name == infer.name (x)) - add_range (name, gimple_bb (s), infer.range (x)); + add_range (name, s, infer.range (x)); } } } diff --git a/gcc/gimple-range-infer.h b/gcc/gimple-range-infer.h index 384d8b2765e..fd5b2ad8dde 100644 --- a/gcc/gimple-range-infer.h +++ b/gcc/gimple-range-infer.h @@ -32,20 +32,35 @@ class gimple_infer_range { public: gimple_infer_range (gimple *s); + gimple_infer_range (tree name, vrange &r); inline unsigned num () const { return num_args; } inline tree name (unsigned index) const { gcc_checking_assert (index < num_args); return m_names[index]; } inline const vrange& range (unsigned index) const { gcc_checking_assert (index < num_args); return m_ranges[index]; } +private: void add_range (tree name, vrange &range); void add_nonzero (tree name); -private: void check_assume_func (gcall *call); unsigned num_args; static const int size_limit = 10; tree m_names[size_limit]; Value_Range m_ranges[size_limit]; inline void bump_index () { if (num_args < size_limit - 1) num_args++; } + friend class non_null_wrapper; +}; + +// This is the basic infer oracle API. Default functionaility does nothing. + +class infer_range_oracle +{ +public: + infer_range_oracle () { } + virtual ~infer_range_oracle () { } + virtual void add_ranges (gimple *, gimple_infer_range &) { } + virtual bool has_range_p (basic_block, tree = NULL_TREE) { return false; } + virtual bool maybe_adjust_range (vrange &, tree, basic_block) + { return false; } }; // This class manages a list of inferred ranges for each basic block. @@ -54,17 +69,17 @@ private: // followed the first time a name is referenced and block populated if // there are any inferred ranges. -class infer_range_manager +class infer_range_manager : public infer_range_oracle { public: infer_range_manager (bool do_search); - ~infer_range_manager (); - void add_range (tree name, basic_block bb, const vrange &r); - void add_nonzero (tree name, basic_block bb); - bool has_range_p (tree name, basic_block bb); - bool has_range_p (basic_block bb); - bool maybe_adjust_range (vrange &r, tree name, basic_block bb); + virtual ~infer_range_manager (); + virtual void add_ranges (gimple *s, gimple_infer_range &ir); + virtual bool has_range_p (basic_block bb, tree name = NULL_TREE); + virtual bool maybe_adjust_range (vrange &r, tree name, basic_block bb); private: + void add_range (tree name, gimple *s, const vrange &r); + void add_nonzero (tree name, gimple *s); class exit_range_head { public: diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc index e35bec0e50d..b35ab43524b 100644 --- a/gcc/gimple-range-path.cc +++ b/gcc/gimple-range-path.cc @@ -303,7 +303,7 @@ path_range_query::range_defined_in_block (vrange &r, tree name, basic_block bb) } if (bb && POINTER_TYPE_P (TREE_TYPE (name))) - m_ranger.m_cache.m_exit.maybe_adjust_range (r, name, bb); + m_ranger.infer_oracle ().maybe_adjust_range (r, name, bb); if (DEBUG_SOLVER && (bb || !r.varying_p ())) { @@ -463,7 +463,7 @@ path_range_query::adjust_for_non_null_uses (basic_block bb) else r.set_varying (TREE_TYPE (name)); - if (m_ranger.m_cache.m_exit.maybe_adjust_range (r, name, bb)) + if (m_ranger.infer_oracle ().maybe_adjust_range (r, name, bb)) m_cache.set_range (name, r); } } diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc index 4326976fc2a..efc84dc3b44 100644 --- a/gcc/gimple-range.cc +++ b/gcc/gimple-range.cc @@ -253,7 +253,7 @@ gimple_ranger::range_on_edge (vrange &r, edge e, tree name) range_on_exit (r, e->src, name); // If this is not an abnormal edge, check for a non-null exit . if ((e->flags & (EDGE_EH | EDGE_ABNORMAL)) == 0) - m_cache.m_exit.maybe_adjust_range (r, name, e->src); + infer_oracle ().maybe_adjust_range (r, name, e->src); gcc_checking_assert (r.undefined_p () || range_compatible_p (r.type(), TREE_TYPE (name))); @@ -516,8 +516,7 @@ void gimple_ranger::register_transitive_inferred_ranges (basic_block bb) { // Return if there are no inferred ranges in BB. - infer_range_manager &infer = m_cache.m_exit; - if (!infer.has_range_p (bb)) + if (!infer_oracle ().has_range_p (bb)) return; if (dump_file && (dump_flags & TDF_DETAILS)) @@ -530,7 +529,7 @@ gimple_ranger::register_transitive_inferred_ranges (basic_block bb) gimple *s = gsi_stmt (si); tree lhs = gimple_get_lhs (s); // If the LHS already has an inferred effect, leave it be. - if (!gimple_range_ssa_p (lhs) || infer.has_range_p (lhs, bb)) + if (!gimple_range_ssa_p (lhs) || infer_oracle ().has_range_p (bb, lhs)) continue; // Pick up global value. Value_Range g (TREE_TYPE (lhs)); @@ -543,13 +542,14 @@ gimple_ranger::register_transitive_inferred_ranges (basic_block bb) r.set_undefined (); tree name1 = gori ().depend1 (lhs); tree name2 = gori ().depend2 (lhs); - if ((name1 && infer.has_range_p (name1, bb)) - || (name2 && infer.has_range_p (name2, bb))) + if ((name1 && infer_oracle ().has_range_p (bb, name1)) + || (name2 && infer_oracle ().has_range_p (bb, name2))) { // Check if folding S produces a different result. if (fold_range (r, s, this) && g != r) { - infer.add_range (lhs, bb, r); + gimple_infer_range ir (lhs, r); + infer_oracle ().add_ranges (s, ir); m_cache.register_inferred_value (r, lhs, bb); } } diff --git a/gcc/value-query.cc b/gcc/value-query.cc index adcc59cadbf..41b581b20be 100644 --- a/gcc/value-query.cc +++ b/gcc/value-query.cc @@ -181,6 +181,23 @@ range_query::dump (FILE *) // Default oracle for all range queries. This contains no storage and thus // can be used anywhere. relation_oracle default_relation_oracle; +infer_range_oracle default_infer_oracle; + +void +range_query::create_infer_oracle (bool do_search) +{ + gcc_checking_assert (m_infer == &default_infer_oracle); + m_infer = new infer_range_manager (do_search); + gcc_checking_assert (m_infer); +} + +void +range_query::destroy_infer_oracle () +{ + if (m_infer && m_infer != &default_infer_oracle) + delete m_infer; + m_infer = &default_infer_oracle; +} // Create dominance based range oracle for the current query if dom info is // available. @@ -215,12 +232,14 @@ void range_query::share_query (range_query &q) { m_relation = q.m_relation; + m_infer = q.m_infer; m_shared_copy_p = true; } range_query::range_query () { m_relation = &default_relation_oracle; + m_infer = &default_infer_oracle; m_shared_copy_p = false; } @@ -229,6 +248,7 @@ range_query::~range_query () // Do not destroy anything if this is a shared copy. if (m_shared_copy_p) return; + destroy_infer_oracle (); destroy_relation_oracle (); } diff --git a/gcc/value-query.h b/gcc/value-query.h index a5735902af0..2f65d95bc9b 100644 --- a/gcc/value-query.h +++ b/gcc/value-query.h @@ -79,6 +79,10 @@ public: void create_relation_oracle (); void destroy_relation_oracle (); + inline class infer_range_oracle &infer_oracle () const { return *m_infer; } + void create_infer_oracle (bool do_search = TRUE); + void destroy_infer_oracle (); + virtual void dump (FILE *); protected: @@ -88,6 +92,7 @@ protected: basic_block bbentry, basic_block bbexit); bool get_arith_expr_range (vrange &r, tree expr, gimple *stmt); relation_oracle *m_relation; + infer_range_oracle *m_infer; // When multiple related range queries wish to share oracles. // This is an internal interface void share_query (range_query &q);