diff mbox series

[COMMITTED,01/12] - Move all relation queries into relation_oracle.

Message ID ced168cc-9b12-4a58-9479-c950c871f2dd@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:52 p.m. UTC
A range-query currently provides a couple of relation query routines, 
plus it also provides direct access to an oracle.   This patch moves 
those queries into the oracle where they should be, and ands the ability 
to create and destroy the basic dominance oracle ranger uses.  This is 
the usual oracle most passes would want, and this provides full access 
to it if ranger has been enabled.  It also allows passes which do not 
use ranger to turn on an oracle and work with it.

Full documentation  for relations and the oracle can be found at:   
https://gcc.gnu.org/wiki/AndrewMacLeod/Relations

Moving the queries into the oracle removes the need to check for a NULL 
pointer on every query, and results in speeding up VRP by about 0.7%

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

Comments

Mikael Morin May 30, 2024, 1:36 p.m. UTC | #1
Hello...

Le 23/05/2024 à 22:52, Andrew MacLeod a écrit :
> A range-query currently provides a couple of relation query routines, 
> plus it also provides direct access to an oracle.   This patch moves 
> those queries into the oracle where they should be, and ands the ability 
> to create and destroy the basic dominance oracle ranger uses.  This is 
> the usual oracle most passes would want, and this provides full access 
> to it if ranger has been enabled.  It also allows passes which do not 
> use ranger to turn on an oracle and work with it.
> 
> Full documentation  for relations and the oracle can be found at: 
> https://gcc.gnu.org/wiki/AndrewMacLeod/Relations
> 
> Moving the queries into the oracle removes the need to check for a NULL 
> pointer on every query, and results in speeding up VRP by about 0.7%
> 
> Bootstrapped on x86_64-pc-linux-gnu with no regressions.  Pushed.
> 
> 
(...)

> diff --git a/gcc/value-query.cc b/gcc/value-query.cc
> index c2ab745a466..b275a43b679 100644
> --- a/gcc/value-query.cc
> +++ b/gcc/value-query.cc
> @@ -437,53 +439,3 @@ global_range_query::range_of_expr (vrange &r, tree expr, gimple *stmt)
>  
>    return true;
>  }
> -
> -// Return any known relation between SSA1 and SSA2 before stmt S is executed.
> -// If GET_RANGE is true, query the range of both operands first to ensure
> -// the definitions have been processed and any relations have be created.
> -
> -relation_kind
> -range_query::query_relation (gimple *s, tree ssa1, tree ssa2, bool get_range) > -{
> -  if (!m_oracle || TREE_CODE (ssa1) != SSA_NAME || TREE_CODE (ssa2) != SSA_NAME)
> -    return VREL_VARYING;
> -
> -  // Ensure ssa1 and ssa2 have both been evaluated.
> -  if (get_range)
> -    {
> -      Value_Range tmp1 (TREE_TYPE (ssa1));
> -      Value_Range tmp2 (TREE_TYPE (ssa2));
> -      range_of_expr (tmp1, ssa1, s);
> -      range_of_expr (tmp2, ssa2, s);
> -    }
> -  return m_oracle->query_relation (gimple_bb (s), ssa1, ssa2);
> -}
> -
> -// Return any known relation between SSA1 and SSA2 on edge E.
> -// If GET_RANGE is true, query the range of both operands first to ensure
> -// the definitions have been processed and any relations have be created.
> -
> -relation_kind
> -range_query::query_relation (edge e, tree ssa1, tree ssa2, bool get_range)
> -{
> -  basic_block bb;
> -  if (!m_oracle || TREE_CODE (ssa1) != SSA_NAME || TREE_CODE (ssa2) != SSA_NAME)
> -    return VREL_VARYING;
> -
> -  // Use destination block if it has a single predecessor, and this picks
> -  // up any relation on the edge.
> -  // Otherwise choose the src edge and the result is the same as on-exit.
> -  if (!single_pred_p (e->dest))
> -    bb = e->src;
> -  else
> -    bb = e->dest;
> -
> -  // Ensure ssa1 and ssa2 have both been evaluated.
> -  if (get_range)
> -    {
> -      Value_Range tmp (TREE_TYPE (ssa1));
> -      range_on_edge (tmp, e, ssa1);
> -      range_on_edge (tmp, e, ssa2);
> -    }
> -  return m_oracle->query_relation (bb, ssa1, ssa2);
> -}

(...)

> diff --git a/gcc/value-relation.cc b/gcc/value-relation.cc
> index 619ee5f0867..d1081b3b3f5 100644
> --- a/gcc/value-relation.cc
> +++ b/gcc/value-relation.cc
> @@ -288,6 +288,39 @@ relation_oracle::valid_equivs (bitmap b, const_bitmap equivs, basic_block bb)
>      }
>  }
>  
> +// Return any known relation between SSA1 and SSA2 before stmt S is executed.
> +// If GET_RANGE is true, query the range of both operands first to ensure
> +// the definitions have been processed and any relations have be created.

The method lost its argument GET_RANGE in the move from value-query.cc, 
so the documentation for GET_RANGE can be removed as well.

> +
> +relation_kind
> +relation_oracle::query_relation (gimple *s, tree ssa1, tree ssa2)
> +{
> +  if (TREE_CODE (ssa1) != SSA_NAME || TREE_CODE (ssa2) != SSA_NAME)
> +    return VREL_VARYING;
> +  return query_relation (gimple_bb (s), ssa1, ssa2);
> +}
> +
> +// Return any known relation between SSA1 and SSA2 on edge E.
> +// If GET_RANGE is true, query the range of both operands first to ensure
> +// the definitions have been processed and any relations have be created.

Same here.

> +
> +relation_kind
> +relation_oracle::query_relation (edge e, tree ssa1, tree ssa2)
> +{
> +  basic_block bb;
> +  if (TREE_CODE (ssa1) != SSA_NAME || TREE_CODE (ssa2) != SSA_NAME)
> +    return VREL_VARYING;
> +
> +  // Use destination block if it has a single predecessor, and this picks
> +  // up any relation on the edge.
> +  // Otherwise choose the src edge and the result is the same as on-exit.
> +  if (!single_pred_p (e->dest))
> +    bb = e->src;
> +  else
> +    bb = e->dest;
> +
> +  return query_relation (bb, ssa1, ssa2);
> +}
>  // -------------------------------------------------------------------------
>  
>  // The very first element in the m_equiv chain is actually just a summary
diff mbox series

Patch

From b0cbffd5655b9fc108691c6b15e8eaed4ab9746a Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Mon, 29 Apr 2024 13:32:00 -0400
Subject: [PATCH 01/12] Move all relation queries into relation_oracle.

Move relation queries from range_query object into the relation oracle.

	* gimple-range-cache.cc (ranger_cache::ranger_cache): Call
	create_relation_oracle.
	(ranger_cache::~ranger_cache): Call destroy_relation_oracle.
	* gimple-range-fold.cc (fur_stmt::get_phi_operand): Check for
	relation oracle bnefore calling query_relation.
	(fold_using_range::range_of_phi): Likewise.
	* gimple-range-path.cc (path_range_query::path_range_query): Set
	relation oracle pointer to NULL after deleting it.
	* value-query.cc (range_query::~range_query): Ensure any
	relation oracle is destroyed.
	(range_query::query_relation): relocate to relation_oracle object.
	* value-query.h (class range_query): Adjust method proototypes.
	(range_query::create_relation_oracle): New.
	(range_query::destroy_relation_oracle): New.
	* value-relation.cc (relation_oracle::query_relation): Relocate
	from range query class.
	* value-relation.h (Call relation_oracle): New prototypes.
---
 gcc/gimple-range-cache.cc |  9 +++----
 gcc/gimple-range-fold.cc  |  9 +++++--
 gcc/gimple-range-path.cc  |  1 +
 gcc/gimple-range.cc       |  1 +
 gcc/value-query.cc        | 52 ++-------------------------------------
 gcc/value-query.h         | 32 +++++++++++++++++++-----
 gcc/value-relation.cc     | 33 +++++++++++++++++++++++++
 gcc/value-relation.h      |  4 ++-
 8 files changed, 76 insertions(+), 65 deletions(-)

diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index bdd2832873a..cf17a6af9db 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -957,11 +957,9 @@  ranger_cache::ranger_cache (int not_executable_flag, bool use_imm_uses)
   m_workback.safe_grow_cleared (last_basic_block_for_fn (cfun));
   m_workback.truncate (0);
   m_temporal = new temporal_cache;
+
   // If DOM info is available, spawn an oracle as well.
-  if (dom_info_available_p (CDI_DOMINATORS))
-      m_oracle = new dom_oracle ();
-    else
-      m_oracle = NULL;
+  create_relation_oracle ();
 
   unsigned x, lim = last_basic_block_for_fn (cfun);
   // Calculate outgoing range info upfront.  This will fully populate the
@@ -979,8 +977,7 @@  ranger_cache::ranger_cache (int not_executable_flag, bool use_imm_uses)
 ranger_cache::~ranger_cache ()
 {
   delete m_update;
-  if (m_oracle)
-    delete m_oracle;
+  destroy_relation_oracle ();
   delete m_temporal;
   m_workback.release ();
 }
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index a9c8c4d03e6..41b6d350c40 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -178,7 +178,10 @@  fur_stmt::get_phi_operand (vrange &r, tree expr, edge e)
 relation_kind
 fur_stmt::query_relation (tree op1, tree op2)
 {
-  return m_query->query_relation (m_stmt, op1, op2);
+  relation_oracle *oracle = m_query->oracle ();
+  if (!oracle)
+    return VREL_VARYING;
+  return oracle->query_relation (m_stmt, op1, op2);
 }
 
 // Instantiate a stmt based fur_source with a GORI object.
@@ -860,6 +863,7 @@  fold_using_range::range_of_phi (vrange &r, gphi *phi, fur_source &src)
   tree single_arg = NULL_TREE;
   bool seen_arg = false;
 
+  relation_oracle *oracle = src.query()->oracle ();
   // Start with an empty range, unioning in each argument's range.
   r.set_undefined ();
   for (x = 0; x < gimple_phi_num_args (phi); x++)
@@ -880,7 +884,8 @@  fold_using_range::range_of_phi (vrange &r, gphi *phi, fur_source &src)
 	  // Likewise, if the incoming PHI argument is equivalent to this
 	  // PHI definition, it provides no new info.  Accumulate these ranges
 	  // in case all arguments are equivalences.
-	  if (src.query ()->query_relation (e, arg, phi_def, false) == VREL_EQ)
+	  if (oracle
+	      && oracle->query_relation (e, arg, phi_def) == VREL_EQ)
 	    equiv_range.union_(arg_range);
 	  else
 	    r.union_ (arg_range);
diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc
index f1a12f76144..ef3db10470e 100644
--- a/gcc/gimple-range-path.cc
+++ b/gcc/gimple-range-path.cc
@@ -60,6 +60,7 @@  path_range_query::path_range_query (gimple_ranger &ranger, bool resolve)
 path_range_query::~path_range_query ()
 {
   delete m_oracle;
+  m_oracle = NULL;
 }
 
 // Return TRUE if NAME is an exit dependency for the path.
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
index e75e2e17dc3..22e8add5de1 100644
--- a/gcc/gimple-range.cc
+++ b/gcc/gimple-range.cc
@@ -67,6 +67,7 @@  gimple_ranger::gimple_ranger (bool use_imm_uses) :
 
 gimple_ranger::~gimple_ranger ()
 {
+  m_oracle = NULL;
   m_stmt_list.release ();
 }
 
diff --git a/gcc/value-query.cc b/gcc/value-query.cc
index c2ab745a466..b275a43b679 100644
--- a/gcc/value-query.cc
+++ b/gcc/value-query.cc
@@ -185,6 +185,8 @@  range_query::range_query ()
 
 range_query::~range_query ()
 {
+  if (m_oracle)
+    destroy_relation_oracle ();
 }
 
 // This routine will invoke the equivalent of range_of_expr on
@@ -437,53 +439,3 @@  global_range_query::range_of_expr (vrange &r, tree expr, gimple *stmt)
 
   return true;
 }
-
-// Return any known relation between SSA1 and SSA2 before stmt S is executed.
-// If GET_RANGE is true, query the range of both operands first to ensure
-// the definitions have been processed and any relations have be created.
-
-relation_kind
-range_query::query_relation (gimple *s, tree ssa1, tree ssa2, bool get_range)
-{
-  if (!m_oracle || TREE_CODE (ssa1) != SSA_NAME || TREE_CODE (ssa2) != SSA_NAME)
-    return VREL_VARYING;
-
-  // Ensure ssa1 and ssa2 have both been evaluated.
-  if (get_range)
-    {
-      Value_Range tmp1 (TREE_TYPE (ssa1));
-      Value_Range tmp2 (TREE_TYPE (ssa2));
-      range_of_expr (tmp1, ssa1, s);
-      range_of_expr (tmp2, ssa2, s);
-    }
-  return m_oracle->query_relation (gimple_bb (s), ssa1, ssa2);
-}
-
-// Return any known relation between SSA1 and SSA2 on edge E.
-// If GET_RANGE is true, query the range of both operands first to ensure
-// the definitions have been processed and any relations have be created.
-
-relation_kind
-range_query::query_relation (edge e, tree ssa1, tree ssa2, bool get_range)
-{
-  basic_block bb;
-  if (!m_oracle || TREE_CODE (ssa1) != SSA_NAME || TREE_CODE (ssa2) != SSA_NAME)
-    return VREL_VARYING;
-
-  // Use destination block if it has a single predecessor, and this picks
-  // up any relation on the edge.
-  // Otherwise choose the src edge and the result is the same as on-exit.
-  if (!single_pred_p (e->dest))
-    bb = e->src;
-  else
-    bb = e->dest;
-
-  // Ensure ssa1 and ssa2 have both been evaluated.
-  if (get_range)
-    {
-      Value_Range tmp (TREE_TYPE (ssa1));
-      range_on_edge (tmp, e, ssa1);
-      range_on_edge (tmp, e, ssa2);
-    }
-  return m_oracle->query_relation (bb, ssa1, ssa2);
-}
diff --git a/gcc/value-query.h b/gcc/value-query.h
index 4d2a7bce485..9df89905ace 100644
--- a/gcc/value-query.h
+++ b/gcc/value-query.h
@@ -75,16 +75,12 @@  public:
   virtual bool range_on_entry (vrange &r, basic_block bb, tree expr);
   virtual bool range_on_exit (vrange &r, basic_block bb, tree expr);
 
-  // Query if there is any relation between SSA1 and SSA2.
-  relation_kind query_relation (gimple *s, tree ssa1, tree ssa2,
-				bool get_range = true);
-  relation_kind query_relation (edge e, tree ssa1, tree ssa2,
-				bool get_range = true);
-  // If present, Access relation oracle for more advanced uses.
   inline relation_oracle *oracle () const  { return m_oracle; }
 
   virtual void dump (FILE *);
 
+  void create_relation_oracle ();
+  void destroy_relation_oracle ();
 protected:
   bool get_tree_range (vrange &v, tree expr, gimple *stmt,
 		       basic_block bbentry = NULL, basic_block bbexit = NULL);
@@ -123,4 +119,28 @@  get_range_query (const struct function *fun)
 extern void gimple_range_global (vrange &v, tree name,
 				 struct function *f = cfun);
 
+// Create dominance based range oracle for the current query if dom info is
+// available.
+
+inline void
+range_query::create_relation_oracle ()
+{
+  if (!dom_info_available_p (CDI_DOMINATORS))
+    return;
+  gcc_checking_assert (m_oracle == NULL);
+  m_oracle = new dom_oracle ();
+}
+
+// Destroy any relation oracle that was created.
+
+inline void
+range_query::destroy_relation_oracle ()
+{
+  if (m_oracle != NULL)
+    {
+      delete m_oracle;
+      m_oracle = NULL;
+    }
+}
+
 #endif // GCC_QUERY_H
diff --git a/gcc/value-relation.cc b/gcc/value-relation.cc
index 619ee5f0867..d1081b3b3f5 100644
--- a/gcc/value-relation.cc
+++ b/gcc/value-relation.cc
@@ -288,6 +288,39 @@  relation_oracle::valid_equivs (bitmap b, const_bitmap equivs, basic_block bb)
     }
 }
 
+// Return any known relation between SSA1 and SSA2 before stmt S is executed.
+// If GET_RANGE is true, query the range of both operands first to ensure
+// the definitions have been processed and any relations have be created.
+
+relation_kind
+relation_oracle::query_relation (gimple *s, tree ssa1, tree ssa2)
+{
+  if (TREE_CODE (ssa1) != SSA_NAME || TREE_CODE (ssa2) != SSA_NAME)
+    return VREL_VARYING;
+  return query_relation (gimple_bb (s), ssa1, ssa2);
+}
+
+// Return any known relation between SSA1 and SSA2 on edge E.
+// If GET_RANGE is true, query the range of both operands first to ensure
+// the definitions have been processed and any relations have be created.
+
+relation_kind
+relation_oracle::query_relation (edge e, tree ssa1, tree ssa2)
+{
+  basic_block bb;
+  if (TREE_CODE (ssa1) != SSA_NAME || TREE_CODE (ssa2) != SSA_NAME)
+    return VREL_VARYING;
+
+  // Use destination block if it has a single predecessor, and this picks
+  // up any relation on the edge.
+  // Otherwise choose the src edge and the result is the same as on-exit.
+  if (!single_pred_p (e->dest))
+    bb = e->src;
+  else
+    bb = e->dest;
+
+  return query_relation (bb, ssa1, ssa2);
+}
 // -------------------------------------------------------------------------
 
 // The very first element in the m_equiv chain is actually just a summary
diff --git a/gcc/value-relation.h b/gcc/value-relation.h
index 61d2497743c..5adf736cf41 100644
--- a/gcc/value-relation.h
+++ b/gcc/value-relation.h
@@ -105,8 +105,10 @@  public:
 
   // register a relation between 2 ssa names in a basic block.
   virtual void register_relation (basic_block, relation_kind, tree, tree) = 0;
-  // Query for a relation between two ssa names in a basic block.
+  // Query if there is any relation between SSA1 and SSA2.
   virtual relation_kind query_relation (basic_block, tree, tree) = 0;
+  relation_kind query_relation (gimple *s, tree ssa1, tree ssa2);
+  relation_kind query_relation (edge e, tree ssa1, tree ssa2);
 
   relation_kind validate_relation (relation_kind, tree, tree);
   relation_kind validate_relation (relation_kind, vrange &, vrange &);
-- 
2.41.0