diff mbox series

[COMMITTED,3/4] Provide relation queries for a stmt.

Message ID 92f97ed8-6149-21c7-731e-0b618667f33c@redhat.com
State New
Headers show
Series [COMMITTED,1/4] - Make ssa_cache and ssa_lazy_cache virtual. | expand

Commit Message

Andrew MacLeod May 24, 2023, 9:19 p.m. UTC
This tweaks someof the fold_stmt routines and helpers.. in particular 
the ones which you provide a vector of ranges to to satisfy any ssa-names.

Previously, once the vector was depleted, any remaining values were 
picked up from the default get_global_range_query() query. It is useful 
to be able to speiocyf your own range_query to these routines, as most 
fo the other fold_stmt routines allow.

This patch changes it so the default doesnt change, but you can 
optionally specify your own range_query to the routines.

It also provides a new routine:

     relation_trio fold_relations (gimple *s, range_query *q)

Which instead of folding a stmt, will return a relation trio based on 
folding the stmt with the range_query.  The relation trio will let you 
know if the statement causes a relation between LHS-OP1,  LHS_OP2, or 
OP1_OP2...  so for something like
    a_3 = b_4 + 6
based on known ranges and types, we might get back (LHS  > OP1)

It just provides  a generic interface into what relations a statement 
may provide based on what a range_query returns for values and the stmt 
itself.

There is no performance impact.

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

Andrew
diff mbox series

Patch

From 933e14dc613269641ffe3613bf4792ac50590275 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Wed, 24 May 2023 09:17:32 -0400
Subject: [PATCH 3/4] Provide relation queries for a stmt.

Allow fur_list and fold_stmt to be provided a range_query rather than
always defaultsing to NULL (which becomes a global query).
Also provide a fold_relations () routine which can provide a range_trio
for an arbitrary statement using any range_query

	* gimple-range-fold.cc (fur_list::fur_list): Add range_query param
	to contructors.
	(fold_range): Add range_query parameter.
	(fur_relation::fur_relation): New.
	(fur_relation::trio): New.
	(fur_relation::register_relation): New.
	(fold_relations): New.
	* gimple-range-fold.h (fold_range): Adjust prototypes.
	(fold_relations): New.
---
 gcc/gimple-range-fold.cc | 128 +++++++++++++++++++++++++++++++++++----
 gcc/gimple-range-fold.h  |  11 +++-
 2 files changed, 124 insertions(+), 15 deletions(-)

diff --git a/gcc/gimple-range-fold.cc b/gcc/gimple-range-fold.cc
index 96cbd799488..4df065c8a6e 100644
--- a/gcc/gimple-range-fold.cc
+++ b/gcc/gimple-range-fold.cc
@@ -214,9 +214,9 @@  fur_depend::register_relation (edge e, relation_kind k, tree op1, tree op2)
 class fur_list : public fur_source
 {
 public:
-  fur_list (vrange &r1);
-  fur_list (vrange &r1, vrange &r2);
-  fur_list (unsigned num, vrange **list);
+  fur_list (vrange &r1, range_query *q = NULL);
+  fur_list (vrange &r1, vrange &r2, range_query *q = NULL);
+  fur_list (unsigned num, vrange **list, range_query *q = NULL);
   virtual bool get_operand (vrange &r, tree expr) override;
   virtual bool get_phi_operand (vrange &r, tree expr, edge e) override;
 private:
@@ -228,7 +228,7 @@  private:
 
 // One range supplied for unary operations.
 
-fur_list::fur_list (vrange &r1) : fur_source (NULL)
+fur_list::fur_list (vrange &r1, range_query *q) : fur_source (q)
 {
   m_list = m_local;
   m_index = 0;
@@ -238,7 +238,7 @@  fur_list::fur_list (vrange &r1) : fur_source (NULL)
 
 // Two ranges supplied for binary operations.
 
-fur_list::fur_list (vrange &r1, vrange &r2) : fur_source (NULL)
+fur_list::fur_list (vrange &r1, vrange &r2, range_query *q) : fur_source (q)
 {
   m_list = m_local;
   m_index = 0;
@@ -249,7 +249,8 @@  fur_list::fur_list (vrange &r1, vrange &r2) : fur_source (NULL)
 
 // Arbitrary number of ranges in a vector.
 
-fur_list::fur_list (unsigned num, vrange **list) : fur_source (NULL)
+fur_list::fur_list (unsigned num, vrange **list, range_query *q)
+  : fur_source (q)
 {
   m_list = list;
   m_index = 0;
@@ -278,20 +279,20 @@  fur_list::get_phi_operand (vrange &r, tree expr, edge e ATTRIBUTE_UNUSED)
 // Fold stmt S into range R using R1 as the first operand.
 
 bool
-fold_range (vrange &r, gimple *s, vrange &r1)
+fold_range (vrange &r, gimple *s, vrange &r1, range_query *q)
 {
   fold_using_range f;
-  fur_list src (r1);
+  fur_list src (r1, q);
   return f.fold_stmt (r, s, src);
 }
 
 // Fold stmt S into range R using R1  and R2 as the first two operands.
 
 bool
-fold_range (vrange &r, gimple *s, vrange &r1, vrange &r2)
+fold_range (vrange &r, gimple *s, vrange &r1, vrange &r2, range_query *q)
 {
   fold_using_range f;
-  fur_list src (r1, r2);
+  fur_list src (r1, r2, q);
   return f.fold_stmt (r, s, src);
 }
 
@@ -299,10 +300,11 @@  fold_range (vrange &r, gimple *s, vrange &r1, vrange &r2)
 // operands encountered.
 
 bool
-fold_range (vrange &r, gimple *s, unsigned num_elements, vrange **vector)
+fold_range (vrange &r, gimple *s, unsigned num_elements, vrange **vector,
+	    range_query *q)
 {
   fold_using_range f;
-  fur_list src (num_elements, vector);
+  fur_list src (num_elements, vector, q);
   return f.fold_stmt (r, s, src);
 }
 
@@ -326,6 +328,108 @@  fold_range (vrange &r, gimple *s, edge on_edge, range_query *q)
   return f.fold_stmt (r, s, src);
 }
 
+// Provide a fur_source which can be used to determine any relations on
+// a statement.  It manages the callback from fold_using_ranges to determine
+// a relation_trio for a statement.
+
+class fur_relation : public fur_stmt
+{
+public:
+  fur_relation (gimple *s, range_query *q = NULL);
+  virtual void register_relation (gimple *stmt, relation_kind k, tree op1,
+				  tree op2);
+  virtual void register_relation (edge e, relation_kind k, tree op1,
+				  tree op2);
+  relation_trio trio() const;
+private:
+  relation_kind def_op1, def_op2, op1_op2;
+};
+
+fur_relation::fur_relation (gimple *s, range_query *q) : fur_stmt (s, q)
+{
+  def_op1 = def_op2 = op1_op2 = VREL_VARYING;
+}
+
+// Construct a trio from what is known.
+
+relation_trio
+fur_relation::trio () const
+{
+  return relation_trio (def_op1, def_op2, op1_op2);
+}
+
+// Don't support edges, but avoid a compiler warning by providing the routine.
+
+void
+fur_relation::register_relation (edge, relation_kind, tree, tree)
+{
+}
+
+// Register relation K between OP1 and OP2 on STMT.
+
+void
+fur_relation::register_relation (gimple *stmt, relation_kind k, tree op1,
+				 tree op2)
+{
+  tree lhs = gimple_get_lhs (stmt);
+  tree a1 = NULL_TREE;
+  tree a2 = NULL_TREE;
+  switch (gimple_code (stmt))
+    {
+      case GIMPLE_COND:
+	a1 = gimple_cond_lhs (stmt);
+	a2 = gimple_cond_rhs (stmt);
+	break;
+      case GIMPLE_ASSIGN:
+	a1 = gimple_assign_rhs1 (stmt);
+	if (gimple_num_ops (stmt) >= 3)
+	  a2 = gimple_assign_rhs2 (stmt);
+	break;
+      default:
+	break;
+    }
+  // STMT is of the form LHS = A1 op A2, now map the relation to these
+  // operands, if possible.
+  if (op1 == lhs)
+    {
+      if (op2 == a1)
+	def_op1 = k;
+      else if (op2 == a2)
+	def_op2 = k;
+    }
+  else if (op2 == lhs)
+    {
+      if (op1 == a1)
+	def_op1 = relation_swap (k);
+      else if (op1 == a2)
+	def_op2 = relation_swap (k);
+    }
+  else
+    {
+      if (op1 == a1 && op2 == a2)
+	op1_op2 = k;
+      else if (op2 == a1 && op1 == a2)
+	op1_op2 = relation_swap (k);
+    }
+}
+
+// Return the relation trio for stmt S using query Q.
+
+relation_trio
+fold_relations (gimple *s, range_query *q)
+{
+  fold_using_range f;
+  fur_relation src (s, q);
+  tree lhs = gimple_range_ssa_p (gimple_get_lhs (s));
+  if (lhs)
+    {
+      Value_Range vr(TREE_TYPE (lhs));
+      if (f.fold_stmt (vr, s, src))
+	return src.trio ();
+    }
+  return TRIO_VARYING;
+}
+
 // -------------------------------------------------------------------------
 
 // Adjust the range for a pointer difference where the operands came
diff --git a/gcc/gimple-range-fold.h b/gcc/gimple-range-fold.h
index 68c6d7743e9..939b7a76f0e 100644
--- a/gcc/gimple-range-fold.h
+++ b/gcc/gimple-range-fold.h
@@ -37,9 +37,14 @@  bool fold_range (vrange &v, gimple *s, edge on_edge, range_query *q = NULL);
 
 // These routines the operands to be specified when manually folding.
 // Any excess queries will be drawn from the current range_query.
-bool fold_range (vrange &r, gimple *s, vrange &r1);
-bool fold_range (vrange &r, gimple *s, vrange &r1, vrange &r2);
-bool fold_range (vrange &r, gimple *s, unsigned num_elements, vrange **vector);
+bool fold_range (vrange &r, gimple *s, vrange &r1, range_query *q = NULL);
+bool fold_range (vrange &r, gimple *s, vrange &r1, vrange &r2,
+		 range_query *q = NULL);
+bool fold_range (vrange &r, gimple *s, unsigned num_elements, vrange **vector,
+		 range_query *q = NULL);
+
+// This routine will return a relation trio for stmt S.
+relation_trio fold_relations (gimple *s, range_query *q = NULL);
 
 // Return the type of range which statement S calculates.  If the type is
 // unsupported or no type can be determined, return NULL_TREE.
-- 
2.40.1