[1/3] Properly set GORI relation trios.

Message ID 79c78a5a-f2ec-7a1e-c3d6-d7091a2b4540@redhat.com
State Accepted
Headers
Series [1/3] Properly set GORI relation trios. |

Checks

Context Check Description
snail/gcc-patch-check success Github commit url

Commit Message

Andrew MacLeod Jan. 28, 2023, 1:04 a.m. UTC
  We added the concept of a relation trio this release.  Basically its a 
group of relations for a range-op statement indicating the relation 
between LHS & OP1, LHS & OP2, and OP1 & OP2.

This is primarily used in GORI so we can use relations during range 
calculation on outgoing edges, although It is also use during folding. 
We currently use them in just a couple of places so it was not really 
fleshed out completely.

The next couple of PRs require relations in range-ops, and in working 
with them, I found I had not been complete when I implemented 
relation_trio... just did enough to get it to work.

This patch properly sets each of the fields in relation trio, and then 
queries the proper field in the couple of places that currently use it.  
This patch invokes no new behaviour, just sets up the information 
correctly so future queries can get the right info.  It consolidates the 
relation trio setting code into one place (more utilization of the 
primary value_relation class) and is just basic goodness.

It also allows the next 2 PRs to be fixed with minimal changes.

Bootstraps on x86_64-pc-linux-gnu with no regressions. OK for trunk?

Andrew
  

Patch

From 5b552dde4d597444d867308fb94b9b49fac42927 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacleod@redhat.com>
Date: Wed, 25 Jan 2023 16:26:39 -0500
Subject: [PATCH 1/4] Properly set GORI relation trios.

When relation trios were added to GORI, there was only one use.  As they are
utilized more by range-ops, it is apparent that the implelemtation was
not complete.  This patch fleshes it out completely so that every GORI
operation has a complete relation trio.

	* gimple-range-gori.cc (gori_compute::compute_operand_range): Do
	not abort calculations if there is a valid relation available.
	(gori_compute::refine_using_relation): Pass correct relation trio.
	(gori_compute::compute_operand1_range): Create trio and use it.
	(gori_compute::compute_operand2_range): Ditto.
	* range-op.cc (operator_plus::op1_range): Use correct trio member.
	(operator_minus::op1_range): Use correct trio member.
	* value-relation.cc (value_relation::create_trio): New.
	* value-relation.h (value_relation::create_trio): New prototype.
---
 gcc/gimple-range-gori.cc | 70 ++++++++++++++--------------------------
 gcc/range-op.cc          |  4 +--
 gcc/value-relation.cc    | 34 +++++++++++++++++++
 gcc/value-relation.h     |  1 +
 4 files changed, 62 insertions(+), 47 deletions(-)

diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index 930e2a0f0ab..3dc4576ff13 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -632,6 +632,9 @@  gori_compute::compute_operand_range (vrange &r, gimple *stmt,
   if (op1 && op2)
     {
       relation_kind k = handler.op1_op2_relation (lhs);
+      // If there is no relation, and op1 == op2, create a relation.
+      if (!vrel_ptr && k == VREL_VARYING && op1 == op2)
+	k = VREL_EQ;
       if (k != VREL_VARYING)
        {
 	 vrel.set_relation (k, op1, op2);
@@ -952,7 +955,9 @@  gori_compute::refine_using_relation (tree op1, vrange &op1_range,
 {
   gcc_checking_assert (TREE_CODE (op1) == SSA_NAME);
   gcc_checking_assert (TREE_CODE (op2) == SSA_NAME);
-  gcc_checking_assert (k != VREL_VARYING && k != VREL_UNDEFINED);
+
+  if (k == VREL_VARYING || k == VREL_EQ || k == VREL_UNDEFINED)
+    return false;
 
   bool change = false;
   bool op1_def_p = in_chain_p (op2, op1);
@@ -991,7 +996,7 @@  gori_compute::refine_using_relation (tree op1, vrange &op1_range,
       Value_Range new_result (type);
       if (!op_handler.op1_range (new_result, type,
 				 op1_def_p ? op1_range : op2_range,
-				 other_op, relation_trio::lhs_op2 (k)))
+				 other_op, relation_trio::lhs_op1 (k)))
 	return false;
       if (op1_def_p)
 	{
@@ -1023,7 +1028,7 @@  gori_compute::refine_using_relation (tree op1, vrange &op1_range,
       Value_Range new_result (type);
       if (!op_handler.op2_range (new_result, type,
 				 op1_def_p ? op1_range : op2_range,
-				 other_op, relation_trio::lhs_op1 (k)))
+				 other_op, relation_trio::lhs_op2 (k)))
 	return false;
       if (op1_def_p)
 	{
@@ -1062,6 +1067,10 @@  gori_compute::compute_operand1_range (vrange &r,
   tree op2 = handler.operand2 ();
   tree lhs_name = gimple_get_lhs (stmt);
 
+  relation_trio trio;
+  if (rel)
+    trio = rel->create_trio (lhs_name, op1, op2);
+
   Value_Range op1_range (TREE_TYPE (op1));
   Value_Range tmp (TREE_TYPE (op1));
   Value_Range op2_range (op2 ? TREE_TYPE (op2) : TREE_TYPE (op1));
@@ -1073,27 +1082,11 @@  gori_compute::compute_operand1_range (vrange &r,
   if (op2)
     {
       src.get_operand (op2_range, op2);
-      relation_kind k = VREL_VARYING;
-      relation_kind op_op = (op1 == op2) ? VREL_EQ : VREL_VARYING;
-      if (rel)
-	{
-	 if (lhs_name == rel->op1 () && op1 == rel->op2 ())
-	   k = rel->kind ();
-	 else if (lhs_name == rel->op2 () && op1 == rel->op1 ())
-	   k = relation_swap (rel->kind ());
-	 else if (op1 == rel->op1 () && op2 == rel->op2 ())
-	   {
-	     op_op = rel->kind ();
-	     refine_using_relation (op1, op1_range, op2, op2_range, src, op_op);
-	   }
-	 else if (op1 == rel->op2 () && op2 == rel->op1 ())
-	   {
-	     op_op = relation_swap (rel->kind ());
-	     refine_using_relation (op1, op1_range, op2, op2_range, src, op_op);
-	   }
-       }
-      if (!handler.calc_op1 (tmp, lhs, op2_range, relation_trio (VREL_VARYING,
-								 k, op_op)))
+      relation_kind op_op = trio.op1_op2 ();
+      if (op_op != VREL_VARYING)
+	refine_using_relation (op1, op1_range, op2, op2_range, src, op_op);
+
+      if (!handler.calc_op1 (tmp, lhs, op2_range, trio))
 	return false;
     }
   else
@@ -1101,7 +1094,7 @@  gori_compute::compute_operand1_range (vrange &r,
       // We pass op1_range to the unary operation.  Nomally it's a
       // hidden range_for_type parameter, but sometimes having the
       // actual range can result in better information.
-      if (!handler.calc_op1 (tmp, lhs, op1_range, TRIO_VARYING))
+      if (!handler.calc_op1 (tmp, lhs, op1_range, trio))
 	return false;
     }
 
@@ -1172,29 +1165,16 @@  gori_compute::compute_operand2_range (vrange &r,
 
   src.get_operand (op1_range, op1);
   src.get_operand (op2_range, op2);
-  relation_kind k = VREL_VARYING;
-  relation_kind op_op = (op1 == op2) ? VREL_EQ : VREL_VARYING;
+
+  relation_trio trio;
   if (rel)
-    {
-      if (lhs_name == rel->op1 () && op2 == rel->op2 ())
-	k = rel->kind ();
-      else if (lhs_name == rel->op2 () && op2 == rel->op1 ())
-	k = relation_swap (rel->kind ());
-      else if (op1 == rel->op1 () && op2 == rel->op2 ())
-	{
-	  op_op = rel->kind ();
-	  refine_using_relation (op1, op1_range, op2, op2_range, src, op_op);
-	}
-      else if (op1 == rel->op2 () && op2 == rel->op1 ())
-	{
-	  op_op = relation_swap (rel->kind ());
-	  refine_using_relation (op1, op1_range, op2, op2_range, src, op_op);
-	}
-    }
+    trio = rel->create_trio (lhs_name, op1, op2);
+  relation_kind op_op = trio.op1_op2 ();
+  if (op_op != VREL_VARYING)
+    refine_using_relation (op1, op1_range, op2, op2_range, src, op_op);
 
   // Intersect with range for op2 based on lhs and op1.
-  if (!handler.calc_op2 (tmp, lhs, op1_range, relation_trio (k, VREL_VARYING,
-							     op_op)))
+  if (!handler.calc_op2 (tmp, lhs, op1_range, trio))
     return false;
 
   unsigned idx;
diff --git a/gcc/range-op.cc b/gcc/range-op.cc
index 6e5754e9130..ed2dd1eb99c 100644
--- a/gcc/range-op.cc
+++ b/gcc/range-op.cc
@@ -1460,7 +1460,7 @@  operator_plus::op1_range (irange &r, tree type,
   if (!minus)
     return false;
   bool res = minus.fold_range (r, type, lhs, op2);
-  relation_kind rel = trio.lhs_op2 ();
+  relation_kind rel = trio.lhs_op1 ();
   // Check for a relation refinement.
   if (res)
     adjust_op1_for_overflow (r, op2, rel, true /* PLUS_EXPR */);
@@ -1632,7 +1632,7 @@  operator_minus::op1_range (irange &r, tree type,
   if (!minus)
     return false;
   bool res = minus.fold_range (r, type, lhs, op2);
-  relation_kind rel = trio.lhs_op2 ();
+  relation_kind rel = trio.lhs_op1 ();
   if (res)
     adjust_op1_for_overflow (r, op2, rel, false /* PLUS_EXPR */);
   return res;
diff --git a/gcc/value-relation.cc b/gcc/value-relation.cc
index 5ca8a7eb0d9..f5b1e67e420 100644
--- a/gcc/value-relation.cc
+++ b/gcc/value-relation.cc
@@ -883,6 +883,40 @@  value_relation::apply_transitive (const value_relation &rel)
   return false;
 }
 
+// Create a trio from this value relation given LHS, OP1 and OP2.
+
+relation_trio
+value_relation::create_trio (tree lhs, tree op1, tree op2)
+{
+  relation_kind lhs_1;
+  if (lhs == name1 && op1 == name2)
+    lhs_1 = related;
+  else if (lhs == name2 && op1 == name1)
+    lhs_1 = relation_swap (related);
+  else
+    lhs_1 = VREL_VARYING;
+
+  relation_kind lhs_2;
+  if (lhs == name1 && op2 == name2)
+    lhs_2 = related;
+  else if (lhs == name2 && op2 == name1)
+    lhs_2 = relation_swap (related);
+  else
+    lhs_2 = VREL_VARYING;
+
+  relation_kind op_op;
+  if (op1 == name1 && op2 == name2)
+    op_op = related;
+  else if (op1 == name2 && op2 == name1)
+    op_op = relation_swap (related);
+  else if  (op1 == op2)
+    op_op = VREL_EQ;
+  else
+    op_op = VREL_VARYING;
+
+  return relation_trio (lhs_1, lhs_2, op_op);
+}
+
 // Dump the relation to file F.
 
 void
diff --git a/gcc/value-relation.h b/gcc/value-relation.h
index 664fd71c925..340f9c42554 100644
--- a/gcc/value-relation.h
+++ b/gcc/value-relation.h
@@ -426,6 +426,7 @@  public:
   inline tree op1 () const { return name1; }
   inline tree op2 () const { return name2; }
 
+  relation_trio create_trio (tree lhs, tree op1, tree op2);
   bool union_ (value_relation &p);
   bool intersect (value_relation &p);
   void negate ();
-- 
2.39.0