From 837ce8a2d75231b68f13da00d9be8d2fd404804e Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Fri, 17 May 2024 10:50:24 -0400
Subject: [PATCH 05/12] 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.
---
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(-)
@@ -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);
}
@@ -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;
@@ -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));
}
}
}
@@ -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:
@@ -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);
}
}
@@ -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);
}
}
@@ -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 ();
}
@@ -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);
--
2.41.0