diff mbox series

[COMMITTED,02/12] - Move to an always available relation oracle.

Message ID d028fb01-82eb-440e-8a9e-318d29a21e26@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
This patch provides a basic oracle which doesn't do anything, but will 
still respond when queried.  This allows passes to avoid the NULL check 
for an oracle pointer before they do anything, and results in a slight 
speedup in VRP, and a slightly more significant 0.3% speedup in jump 
threading..

It also unifies the register and query names to nor specify what is 
already apparent in the parameters.

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

Patch

From 2f80eb1feb3f92c7e9e57d4726ec52ca7d27ce92 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Tue, 30 Apr 2024 09:35:23 -0400
Subject: [PATCH 02/12] Move to an always available relation oracle.

This eliminates the need to check if the relation oracle pointer is NULL
before every call by providing a default oracle which does nothing.
REmove unused routines, and Unify register_relation method names.

	* gimple-range-cache.cc (ranger_cache::dump_bb): Remove check for
	NULL oracle pointer.
	(ranger_cache::fill_block_cache): Likewise.
	* gimple-range-fold.cc (fur_stmt::get_phi_operand): Likewise.
	(fur_depend::fur_depend): Likewise.
	(fur_depend::register_relation): Likewise, use qury_relation.
	(fold_using_range::range_of_phi): Likewise.
	(fold_using_range::relation_fold_and_or): Likewise.
	* gimple-range-fold.h (fur_source::m_oracle): Delete.  Oracle
	can be accessed dirctly via m_query now.
	* gimple-range-path.cc (path_range_query::path_range_query):
	Adjust for oracle reference pointer.
	(path_range_query::compute_ranges): Likewise.
	(jt_fur_source::jt_fur_source): Adjust for no m_oracle member.
	(jt_fur_source::register_relation): Do not check for NULL
	pointer.
	(jt_fur_source::query_relation): Likewise.
	* gimple-range.cc (gimple_ranger::gimple_ranger):  Adjust for
	reference pointer.
	* value_query.cc (default_relation_oracle): New.
	(range_query::create_relation_oracle): Relocate from header.
	Ensure not being added to global query.
	(range_query::destroy_relation_oracle): Relocate from header.
	(range_query::range_query): Initailize to default oracle.
	(ange_query::~range_query): Call destroy_relation_oracle.
	* value-query.h (class range_query): Adjust prototypes.
	(range_query::create_relation_oracle): Move to source file.
	(range_query::destroy_relation_oracle): Move to source file.
	* value-relation.cc (relation_oracle::validate_relation): Delete.
	(relation_oracle::register_stmt): Rename to register_relation.
	(relation_oracle::register_edge): Likewise.
	* value-relation.h (register_stmt): Rename to register_relation and
	provide default function in base class.
	(register_edge): Likewise.
	(relation_oracle::query_relation): Provide default in base class.
	(relation_oracle::dump): Likewise.
	(relation_oracle::equiv_set): Likewise.
	(default_relation_oracle): New extenal reference.
	(partial_equiv_set, add_partial_equiv): Move to protected.
	* value-relation.h (relation_oracle::validate_relation): Delete.
---
 gcc/gimple-range-cache.cc | 98 +++++++++++++++++++--------------------
 gcc/gimple-range-fold.cc  | 22 +++------
 gcc/gimple-range-fold.h   |  2 -
 gcc/gimple-range-path.cc  | 22 +++------
 gcc/gimple-range.cc       |  5 +-
 gcc/value-query.cc        | 38 +++++++++++++--
 gcc/value-query.h         | 31 ++-----------
 gcc/value-relation.cc     | 66 ++------------------------
 gcc/value-relation.h      | 32 ++++++-------
 9 files changed, 119 insertions(+), 197 deletions(-)

diff --git a/gcc/gimple-range-cache.cc b/gcc/gimple-range-cache.cc
index cf17a6af9db..020069fd635 100644
--- a/gcc/gimple-range-cache.cc
+++ b/gcc/gimple-range-cache.cc
@@ -1001,8 +1001,7 @@  ranger_cache::dump_bb (FILE *f, basic_block bb)
 {
   m_gori.gori_map::dump (f, bb, false);
   m_on_entry.dump (f, bb);
-  if (m_oracle)
-    m_oracle->dump (f, bb);
+  m_oracle->dump (f, bb);
 }
 
 // Get the global range for NAME, and return in R.  Return false if the
@@ -1437,62 +1436,59 @@  ranger_cache::fill_block_cache (tree name, basic_block bb, basic_block def_bb)
       // See if any equivalences can refine it.
       // PR 109462, like 108139 below, a one way equivalence introduced
       // by a PHI node can also be through the definition side.  Disallow it.
-      if (m_oracle)
+      tree equiv_name;
+      relation_kind rel;
+      int prec = TYPE_PRECISION (type);
+      FOR_EACH_PARTIAL_AND_FULL_EQUIV (m_oracle, bb, name, equiv_name, rel)
 	{
-	  tree equiv_name;
-	  relation_kind rel;
-	  int prec = TYPE_PRECISION (type);
-	  FOR_EACH_PARTIAL_AND_FULL_EQUIV (m_oracle, bb, name, equiv_name, rel)
-	    {
-	      basic_block equiv_bb = gimple_bb (SSA_NAME_DEF_STMT (equiv_name));
+	  basic_block equiv_bb = gimple_bb (SSA_NAME_DEF_STMT (equiv_name));
 
-	      // Ignore partial equivs that are smaller than this object.
-	      if (rel != VREL_EQ && prec > pe_to_bits (rel))
-		continue;
+	  // Ignore partial equivs that are smaller than this object.
+	  if (rel != VREL_EQ && prec > pe_to_bits (rel))
+	    continue;
 
-	      // Check if the equiv has any ranges calculated.
-	      if (!m_gori.has_edge_range_p (equiv_name))
-		continue;
+	  // Check if the equiv has any ranges calculated.
+	  if (!m_gori.has_edge_range_p (equiv_name))
+	    continue;
 
-	      // Check if the equiv definition dominates this block
-	      if (equiv_bb == bb ||
-		  (equiv_bb && !dominated_by_p (CDI_DOMINATORS, bb, equiv_bb)))
-		continue;
+	  // Check if the equiv definition dominates this block
+	  if (equiv_bb == bb ||
+	      (equiv_bb && !dominated_by_p (CDI_DOMINATORS, bb, equiv_bb)))
+	    continue;
 
-	      if (DEBUG_RANGE_CACHE)
-		{
-		  if (rel == VREL_EQ)
-		    fprintf (dump_file, "Checking Equivalence (");
-		  else
-		    fprintf (dump_file, "Checking Partial equiv (");
-		  print_relation (dump_file, rel);
-		  fprintf (dump_file, ") ");
-		  print_generic_expr (dump_file, equiv_name, TDF_SLIM);
-		  fprintf (dump_file, "\n");
-		}
-	      Value_Range equiv_range (TREE_TYPE (equiv_name));
-	      if (range_from_dom (equiv_range, equiv_name, bb, RFD_READ_ONLY))
-		{
-		  if (rel != VREL_EQ)
-		    range_cast (equiv_range, type);
-		  else
-		    adjust_equivalence_range (equiv_range);
+	  if (DEBUG_RANGE_CACHE)
+	    {
+	      if (rel == VREL_EQ)
+		fprintf (dump_file, "Checking Equivalence (");
+	      else
+		fprintf (dump_file, "Checking Partial equiv (");
+	      print_relation (dump_file, rel);
+	      fprintf (dump_file, ") ");
+	      print_generic_expr (dump_file, equiv_name, TDF_SLIM);
+	      fprintf (dump_file, "\n");
+	    }
+	  Value_Range equiv_range (TREE_TYPE (equiv_name));
+	  if (range_from_dom (equiv_range, equiv_name, bb, RFD_READ_ONLY))
+	    {
+	      if (rel != VREL_EQ)
+		range_cast (equiv_range, type);
+	      else
+		adjust_equivalence_range (equiv_range);
 
-		  if (block_result.intersect (equiv_range))
+	      if (block_result.intersect (equiv_range))
+		{
+		  if (DEBUG_RANGE_CACHE)
 		    {
-		      if (DEBUG_RANGE_CACHE)
-			{
-			  if (rel == VREL_EQ)
-			    fprintf (dump_file, "Equivalence update! :  ");
-			  else
-			    fprintf (dump_file, "Partial equiv update! :  ");
-			  print_generic_expr (dump_file, equiv_name, TDF_SLIM);
-			  fprintf (dump_file, " has range  :  ");
-			  equiv_range.dump (dump_file);
-			  fprintf (dump_file, " refining range to :");
-			  block_result.dump (dump_file);
-			  fprintf (dump_file, "\n");
-			}
+		      if (rel == VREL_EQ)
+			fprintf (dump_file, "Equivalence update! :  ");
+		      else
+			fprintf (dump_file, "Partial equiv update! :  ");
+		      print_generic_expr (dump_file, equiv_name, TDF_SLIM);
+		      fprintf (dump_file, " has range  :  ");
+		      equiv_range.dump (dump_file);
+		      fprintf (dump_file, " refining range to :");
+		      block_result.dump (dump_file);
+		      fprintf (dump_file, "\n");
 		    }
 		}
 	    }
diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 41b6d350c40..eeffdce0b97 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -178,10 +178,7 @@  fur_stmt::get_phi_operand (vrange &r, tree expr, edge e)
 relation_kind
 fur_stmt::query_relation (tree op1, tree op2)
 {
-  relation_oracle *oracle = m_query->oracle ();
-  if (!oracle)
-    return VREL_VARYING;
-  return oracle->query_relation (m_stmt, op1, op2);
+  return m_query->oracle ().query_relation (m_stmt, op1, op2);
 }
 
 // Instantiate a stmt based fur_source with a GORI object.
@@ -192,10 +189,6 @@  fur_depend::fur_depend (gimple *s, gori_compute *gori, range_query *q)
 {
   gcc_checking_assert (gori);
   m_gori = gori;
-  // Set relations if there is an oracle in the range_query.
-  // This will enable registering of relationships as they are discovered.
-  m_oracle = q->oracle ();
-
 }
 
 // Register a relation on a stmt if there is an oracle.
@@ -203,8 +196,7 @@  fur_depend::fur_depend (gimple *s, gori_compute *gori, range_query *q)
 void
 fur_depend::register_relation (gimple *s, relation_kind k, tree op1, tree op2)
 {
-  if (m_oracle)
-    m_oracle->register_stmt (s, k, op1, op2);
+  m_query->oracle ().register_relation (s, k, op1, op2);
 }
 
 // Register a relation on an edge if there is an oracle.
@@ -212,8 +204,7 @@  fur_depend::register_relation (gimple *s, relation_kind k, tree op1, tree op2)
 void
 fur_depend::register_relation (edge e, relation_kind k, tree op1, tree op2)
 {
-  if (m_oracle)
-    m_oracle->register_edge (e, k, op1, op2);
+  m_query->oracle ().register_relation (e, k, op1, op2);
 }
 
 // This version of fur_source will pick a range up from a list of ranges
@@ -863,7 +854,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 ();
+  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++)
@@ -884,8 +875,7 @@  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 (oracle
-	      && oracle->query_relation (e, arg, phi_def) == VREL_EQ)
+	  if (oracle->query_relation (e, arg, phi_def) == VREL_EQ)
 	    equiv_range.union_(arg_range);
 	  else
 	    r.union_ (arg_range);
@@ -1135,7 +1125,7 @@  fold_using_range::relation_fold_and_or (irange& lhs_range, gimple *s,
 					vrange &op2)
 {
   // No queries or already folded.
-  if (!src.gori () || !src.query ()->oracle () || lhs_range.singleton_p ())
+  if (!src.gori () || lhs_range.singleton_p ())
     return;
 
   // Only care about AND and OR expressions.
diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
index c7c599bfc93..1925fb899e3 100644
--- a/gcc/gimple-range-fold.h
+++ b/gcc/gimple-range-fold.h
@@ -138,8 +138,6 @@  public:
 				  tree op2) override;
   virtual void register_relation (edge e, relation_kind k, tree op1,
 				  tree op2) override;
-protected:
-  relation_oracle *m_oracle;
 };
 
 // This class uses ranges to fold a gimple statement producing a range for
diff --git a/gcc/gimple-range-path.cc b/gcc/gimple-range-path.cc
index ef3db10470e..cf7e0409098 100644
--- a/gcc/gimple-range-path.cc
+++ b/gcc/gimple-range-path.cc
@@ -44,7 +44,7 @@  path_range_query::path_range_query (gimple_ranger &ranger,
     m_ranger (ranger),
     m_resolve (resolve)
 {
-  m_oracle = new path_oracle (m_ranger.oracle ());
+  m_oracle = new path_oracle (&(m_ranger.oracle ()));
 
   reset_path (path, dependencies);
 }
@@ -54,7 +54,7 @@  path_range_query::path_range_query (gimple_ranger &ranger, bool resolve)
     m_ranger (ranger),
     m_resolve (resolve)
 {
-  m_oracle = new path_oracle (m_ranger.oracle ());
+  m_oracle = new path_oracle (&(m_ranger.oracle ()));
 }
 
 path_range_query::~path_range_query ()
@@ -563,7 +563,7 @@  path_range_query::compute_ranges (const bitmap_head *dependencies)
   if (m_resolve)
     {
       path_oracle *p = get_path_oracle ();
-      p->reset_path (m_ranger.oracle ());
+      p->reset_path (&(m_ranger.oracle ()));
     }
 
   if (DEBUG_SOLVER)
@@ -629,11 +629,6 @@  jt_fur_source::jt_fur_source (gimple *s,
   gcc_checking_assert (!path.is_empty ());
 
   m_entry = path[path.length () - 1];
-
-  if (dom_info_available_p (CDI_DOMINATORS))
-    m_oracle = query->oracle ();
-  else
-    m_oracle = NULL;
 }
 
 // Ignore statement and register relation on entry to path.
@@ -641,8 +636,7 @@  jt_fur_source::jt_fur_source (gimple *s,
 void
 jt_fur_source::register_relation (gimple *, relation_kind k, tree op1, tree op2)
 {
-  if (m_oracle)
-    m_oracle->register_relation (m_entry, k, op1, op2);
+  m_query->oracle ().register_relation (m_entry, k, op1, op2);
 }
 
 // Ignore edge and register relation on entry to path.
@@ -650,20 +644,16 @@  jt_fur_source::register_relation (gimple *, relation_kind k, tree op1, tree op2)
 void
 jt_fur_source::register_relation (edge, relation_kind k, tree op1, tree op2)
 {
-  if (m_oracle)
-    m_oracle->register_relation (m_entry, k, op1, op2);
+  m_query->oracle ().register_relation (m_entry, k, op1, op2);
 }
 
 relation_kind
 jt_fur_source::query_relation (tree op1, tree op2)
 {
-  if (!m_oracle)
-    return VREL_VARYING;
-
   if (TREE_CODE (op1) != SSA_NAME || TREE_CODE (op2) != SSA_NAME)
     return VREL_VARYING;
 
-  return m_oracle->query_relation (m_entry, op1, op2);
+  return m_query->oracle().query_relation (m_entry, op1, op2);
 }
 
 // Return the range of STMT at the end of the path being analyzed.
diff --git a/gcc/gimple-range.cc b/gcc/gimple-range.cc
index 22e8add5de1..24ffd63c89b 100644
--- a/gcc/gimple-range.cc
+++ b/gcc/gimple-range.cc
@@ -43,8 +43,8 @@  gimple_ranger::gimple_ranger (bool use_imm_uses) :
 	tracer (""),
 	current_bb (NULL)
 {
-  // If the cache has a relation oracle, use it.
-  m_oracle = m_cache.oracle ();
+  // Share the oracle from the cache.
+  m_oracle = &m_cache.oracle ();
   if (dump_file && (param_ranger_debug & RANGER_DEBUG_TRACE))
     tracer.enable_trace ();
   m_stmt_list.create (0);
@@ -67,6 +67,7 @@  gimple_ranger::gimple_ranger (bool use_imm_uses) :
 
 gimple_ranger::~gimple_ranger ()
 {
+  // Restore the original oracle.
   m_oracle = NULL;
   m_stmt_list.release ();
 }
diff --git a/gcc/value-query.cc b/gcc/value-query.cc
index b275a43b679..03ce574bcb5 100644
--- a/gcc/value-query.cc
+++ b/gcc/value-query.cc
@@ -178,15 +178,47 @@  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;
+
+// Create dominance based range oracle for the current query if dom info is
+// available.
+
+void
+range_query::create_relation_oracle ()
+{
+  gcc_checking_assert (this != &global_ranges);
+  gcc_checking_assert (m_oracle == &default_relation_oracle);
+
+  if (!dom_info_available_p (CDI_DOMINATORS))
+    return;
+  m_oracle = new dom_oracle ();
+  gcc_checking_assert (m_oracle);
+}
+
+// Destroy any relation oracle that was created.
+
+void
+range_query::destroy_relation_oracle ()
+{
+  // m_oracle can be NULL if a derived range_query class took care of
+  // disposing its own oracle.
+  if (m_oracle && m_oracle != &default_relation_oracle)
+    {
+      delete m_oracle;
+      m_oracle = &default_relation_oracle;
+    }
+}
+
 range_query::range_query ()
 {
-  m_oracle = NULL;
+  m_oracle = &default_relation_oracle;
 }
 
 range_query::~range_query ()
 {
-  if (m_oracle)
-    destroy_relation_oracle ();
+  destroy_relation_oracle ();
 }
 
 // This routine will invoke the equivalent of range_of_expr on
diff --git a/gcc/value-query.h b/gcc/value-query.h
index 9df89905ace..ed355bedfa8 100644
--- a/gcc/value-query.h
+++ b/gcc/value-query.h
@@ -75,12 +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);
 
-  inline relation_oracle *oracle () const  { return m_oracle; }
+  inline class relation_oracle &oracle () const  { return *m_oracle; }
+  void create_relation_oracle ();
+  void destroy_relation_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);
@@ -118,29 +118,4 @@  get_range_query (const struct function *fun)
 // Query the global range of NAME in function F.  Default to cfun.
 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 d1081b3b3f5..fac15613945 100644
--- a/gcc/value-relation.cc
+++ b/gcc/value-relation.cc
@@ -208,66 +208,6 @@  static const tree_code relation_to_code [VREL_LAST] = {
   ERROR_MARK, ERROR_MARK, LT_EXPR, LE_EXPR, GT_EXPR, GE_EXPR, EQ_EXPR,
   NE_EXPR };
 
-// This routine validates that a relation can be applied to a specific set of
-// ranges.  In particular, floating point x == x may not be true if the NaN bit
-// is set in the range.  Symbolically the oracle will determine x == x,
-// but specific range instances may override this.
-// To verify, attempt to fold the relation using the supplied ranges.
-// One would expect [1,1] to be returned, anything else means there is something
-// in the range preventing the relation from applying.
-// If there is no mechanism to verify, assume the relation is acceptable.
-
-relation_kind
-relation_oracle::validate_relation (relation_kind rel, vrange &op1, vrange &op2)
-{
-  // If there is no mapping to a tree code, leave the relation as is.
-  tree_code code = relation_to_code [rel];
-  if (code == ERROR_MARK)
-    return rel;
-
-  // Undefined ranges cannot be checked either.
-  if (op1.undefined_p () || op2.undefined_p ())
-    return rel;
-
-  tree t1 = op1.type ();
-  tree t2 = op2.type ();
-
-  // If the range types are not compatible, no relation can exist.
-  if (!range_compatible_p (t1, t2))
-    return VREL_VARYING;
-
-  // If there is no handler, leave the relation as is.
-  range_op_handler handler (code);
-  if (!handler)
-    return rel;
-
-  // If the relation cannot be folded for any reason, leave as is.
-  Value_Range result (boolean_type_node);
-  if (!handler.fold_range (result, boolean_type_node, op1, op2,
-			   relation_trio::op1_op2 (rel)))
-    return rel;
-
-  // The expression op1 REL op2 using REL should fold to [1,1].
-  // Any other result means the relation is not verified to be true.
-  if (result.varying_p () || result.zero_p ())
-    return VREL_VARYING;
-
-  return rel;
-}
-
-// If no range is available, create a varying range for each SSA name and
-// verify.
-
-relation_kind
-relation_oracle::validate_relation (relation_kind rel, tree ssa1, tree ssa2)
-{
-  Value_Range op1, op2;
-  op1.set_varying (TREE_TYPE (ssa1));
-  op2.set_varying (TREE_TYPE (ssa2));
-
-  return validate_relation (rel, op1, op2);
-}
-
 // Given an equivalence set EQUIV, set all the bits in B that are still valid
 // members of EQUIV in basic block BB.
 
@@ -1058,8 +998,8 @@  dom_oracle::~dom_oracle ()
 // Register relation K between ssa_name OP1 and OP2 on STMT.
 
 void
-relation_oracle::register_stmt (gimple *stmt, relation_kind k, tree op1,
-				tree op2)
+relation_oracle::register_relation (gimple *stmt, relation_kind k, tree op1,
+				    tree op2)
 {
   gcc_checking_assert (TREE_CODE (op1) == SSA_NAME);
   gcc_checking_assert (TREE_CODE (op2) == SSA_NAME);
@@ -1106,7 +1046,7 @@  relation_oracle::register_stmt (gimple *stmt, relation_kind k, tree op1,
 // Register relation K between ssa_name OP1 and OP2 on edge E.
 
 void
-relation_oracle::register_edge (edge e, relation_kind k, tree op1, tree op2)
+relation_oracle::register_relation (edge e, relation_kind k, tree op1, tree op2)
 {
   gcc_checking_assert (TREE_CODE (op1) == SSA_NAME);
   gcc_checking_assert (TREE_CODE (op2) == SSA_NAME);
diff --git a/gcc/value-relation.h b/gcc/value-relation.h
index 5adf736cf41..528f00aecbb 100644
--- a/gcc/value-relation.h
+++ b/gcc/value-relation.h
@@ -98,37 +98,37 @@  class relation_oracle
 {
 public:
   virtual ~relation_oracle () { }
-  // register a relation between 2 ssa names at a stmt.
-  void register_stmt (gimple *, relation_kind, tree, tree);
-  // register a relation between 2 ssa names on an edge.
-  void register_edge (edge, relation_kind, tree, tree);
 
-  // register a relation between 2 ssa names in a basic block.
-  virtual void register_relation (basic_block, relation_kind, tree, tree) = 0;
+  // register a relation between 2 ssa names.
+  void register_relation (gimple *, relation_kind, tree, tree);
+  void register_relation (edge, relation_kind, tree, tree);
+  virtual void register_relation (basic_block, relation_kind, tree, tree) { }
+
   // 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);
+  virtual relation_kind query_relation (basic_block, tree, tree)
+    { return VREL_VARYING; }
 
-  relation_kind validate_relation (relation_kind, tree, tree);
-  relation_kind validate_relation (relation_kind, vrange &, vrange &);
-
-  virtual void dump (FILE *, basic_block) const = 0;
-  virtual void dump (FILE *) const = 0;
+  virtual void dump (FILE *, basic_block) const { }
+  virtual void dump (FILE *) const  { }
   void debug () const;
 protected:
   friend class equiv_relation_iterator;
   // Return equivalency set for an SSA name in a basic block.
-  virtual const_bitmap equiv_set (tree, basic_block) = 0;
+  virtual const_bitmap equiv_set (tree, basic_block) { return NULL; }
   // Return partial equivalency record for an SSA name.
   virtual const class pe_slice *partial_equiv_set (tree) { return NULL; }
   void valid_equivs (bitmap b, const_bitmap equivs, basic_block bb);
   // Query for a relation between two equivalency sets in a basic block.
   virtual relation_kind query_relation (basic_block, const_bitmap,
-					const_bitmap) = 0;
+					const_bitmap) { return VREL_VARYING; }
   friend class path_oracle;
 };
 
+// Instance with no storage used for default queries with no active oracle.
+extern relation_oracle default_relation_oracle;
+
 // This class represents an equivalency set, and contains a link to the next
 // one in the list to be searched.
 
@@ -162,11 +162,9 @@  public:
   ~equiv_oracle ();
 
   const_bitmap equiv_set (tree ssa, basic_block bb) final override;
-  const pe_slice *partial_equiv_set (tree name) final override;
   void register_relation (basic_block bb, relation_kind k, tree ssa1,
 			  tree ssa2) override;
 
-  void add_partial_equiv (relation_kind, tree, tree);
   relation_kind partial_equiv (tree ssa1, tree ssa2, tree *base = NULL) const;
   relation_kind query_relation (basic_block, tree, tree) override;
   relation_kind query_relation (basic_block, const_bitmap, const_bitmap)
@@ -175,6 +173,8 @@  public:
   void dump (FILE *f) const override;
 
 protected:
+  void add_partial_equiv (relation_kind, tree, tree);
+  const pe_slice *partial_equiv_set (tree name) final override;
   inline bool has_equiv_p (unsigned v) { return bitmap_bit_p (m_equiv_set, v); }
   bitmap_obstack m_bitmaps;
   struct obstack m_chain_obstack;
-- 
2.41.0