diff mbox series

[COMMITTED,05/12] - Move infer_manager to a range_query oracle.

Message ID 2293adc5-4dcd-45a6-a173-ca610f1e5e77@redhat.com
State New
Headers show
Series [COMMITTED,01/12] - Move all relation queries into relation_oracle. | expand

Commit Message

Andrew MacLeod May 23, 2024, 8:53 p.m. UTC
Turn the infer_manager class into an always available oracle accessible 
via a range_query object.   This will make it easier to share and query 
inferred range info between objects and also makes the information 
easily accessible to any pass that is interested. This again removes the 
need to check for a non-null object, and again makes for a slight 
performance improvement.

Documentation on the inferred range manager can be found at : 
https://gcc.gnu.org/wiki/AndrewMacLeod/InferredRanges

It also associates each inferred range with it's originating stmt which 
was missing before (we only knew what block it came from). Future 
functionality will make use of the more specific information.

Bootstrapped on x86_64-pc-linux-gnu with no regressions.  Pushed.
diff mbox series

Patch

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(-)

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);
-- 
2.41.0