public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r13-2974] Refine ranges using relations in GORI.
@ 2022-09-29 22:34 Andrew Macleod
  0 siblings, 0 replies; only message in thread
From: Andrew Macleod @ 2022-09-29 22:34 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:67166c9ec35d58efd0225b74730983aa480a88f1

commit r13-2974-g67166c9ec35d58efd0225b74730983aa480a88f1
Author: Andrew MacLeod <amacleod@redhat.com>
Date:   Thu Sep 22 18:17:20 2022 -0400

    Refine ranges using relations in GORI.
    
    This allows GORI to recognize when a relation passed in applies to the
    2 operands of the current statement.  Check to see if further range
    refinement is possible before proceeding.
    
            * gimple-range-gori.cc (gori_compute::refine_using_relation): New.
            (gori_compute::compute_operand1_range): Invoke
            refine_using_relation when applicable.
            (gori_compute::compute_operand2_range): Ditto.
            * gimple-range-gori.h (class gori_compute): Adjust prototypes.

Diff:
---
 gcc/gimple-range-gori.cc | 146 ++++++++++++++++++++++++++++++++++++++++++++++-
 gcc/gimple-range-gori.h  |   3 +
 2 files changed, 146 insertions(+), 3 deletions(-)

diff --git a/gcc/gimple-range-gori.cc b/gcc/gimple-range-gori.cc
index 57a7e820749..b37d03cddda 100644
--- a/gcc/gimple-range-gori.cc
+++ b/gcc/gimple-range-gori.cc
@@ -934,6 +934,115 @@ gori_compute::compute_logical_operands (vrange &true_range, vrange &false_range,
     src.get_operand (false_range, name);
 }
 
+
+// This routine will try to refine the ranges of OP1 and OP2 given a relation
+// K between them.  In order to perform this refinement, one of the operands
+// must be in the definition chain of the other.  The use is refined using
+// op1/op2_range on the statement, and the defintion is then recalculated
+// using the relation.
+
+bool
+gori_compute::refine_using_relation (tree op1, vrange &op1_range,
+			       tree op2, vrange &op2_range,
+			       fur_source &src, relation_kind k)
+{
+  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);
+
+  bool change = false;
+  bool op1_def_p = in_chain_p (op2, op1);
+  if (!op1_def_p)
+    if (!in_chain_p (op1, op2))
+      return false;
+
+  tree def_op = op1_def_p ? op1 : op2;
+  tree use_op = op1_def_p ? op2 : op1;
+
+  if (!op1_def_p)
+    k = relation_swap (k);
+
+  // op1_def is true if we want to look up op1, otherwise we want op2.
+  // if neither is the case, we returned in the above check.
+
+  gimple *def_stmt = SSA_NAME_DEF_STMT (def_op);
+  gimple_range_op_handler op_handler (def_stmt);
+  if (!op_handler)
+    return false;
+  tree def_op1 = op_handler.operand1 ();
+  tree def_op2 = op_handler.operand2 ();
+  // if the def isn't binary, the relation will not be useful.
+  if (!def_op2)
+    return false;
+
+  // Determine if op2 is directly referenced as an operand.
+  if (def_op1 == use_op)
+    {
+      // def_stmt has op1 in the 1st operand position.
+      Value_Range other_op (TREE_TYPE (def_op2));
+      src.get_operand (other_op, def_op2);
+
+      // Using op1_range as the LHS, and relation REL, evaluate op2.
+      tree type = TREE_TYPE (def_op1);
+      Value_Range new_result (type);
+      if (!op_handler.op1_range (new_result, type,
+				 op1_def_p ? op1_range : op2_range,
+				 other_op, k))
+	return false;
+      if (op1_def_p)
+	{
+	  change |= op2_range.intersect (new_result);
+	  // Recalculate op2.
+	  if (op_handler.fold_range (new_result, type, op2_range, other_op))
+	    {
+	      change |= op1_range.intersect (new_result);
+	    }
+	}
+      else
+	{
+	  change |= op1_range.intersect (new_result);
+	  // Recalculate op1.
+	  if (op_handler.fold_range (new_result, type, op1_range, other_op))
+	    {
+	      change |= op2_range.intersect (new_result);
+	    }
+	}
+    }
+  else if (def_op2 == use_op)
+    {
+      // def_stmt has op1 in the 1st operand position.
+      Value_Range other_op (TREE_TYPE (def_op1));
+      src.get_operand (other_op, def_op1);
+
+      // Using op1_range as the LHS, and relation REL, evaluate op2.
+      tree type = TREE_TYPE (def_op2);
+      Value_Range new_result (type);
+      if (!op_handler.op2_range (new_result, type,
+				 op1_def_p ? op1_range : op2_range,
+				 other_op, k))
+	return false;
+      if (op1_def_p)
+	{
+	  change |= op2_range.intersect (new_result);
+	  // Recalculate op1.
+	  if (op_handler.fold_range (new_result, type, other_op, op2_range))
+	    {
+	      change |= op1_range.intersect (new_result);
+	    }
+	}
+      else
+	{
+	  change |= op1_range.intersect (new_result);
+	  // Recalculate op2.
+	  if (op_handler.fold_range (new_result, type, other_op, op1_range))
+	    {
+	      change |= op2_range.intersect (new_result);
+	    }
+	}
+    }
+  return change;
+}
+
 // Calculate a range for NAME from the operand 1 position of STMT
 // assuming the result of the statement is LHS.  Return the range in
 // R, or false if no range could be calculated.
@@ -947,6 +1056,7 @@ gori_compute::compute_operand1_range (vrange &r,
   gimple *stmt = handler.stmt ();
   tree op1 = handler.operand1 ();
   tree op2 = handler.operand2 ();
+  tree lhs_name = gimple_get_lhs (stmt);
 
   Value_Range op1_range (TREE_TYPE (op1));
   Value_Range tmp (TREE_TYPE (op1));
@@ -959,7 +1069,21 @@ gori_compute::compute_operand1_range (vrange &r,
   if (op2)
     {
       src.get_operand (op2_range, op2);
-      if (!handler.calc_op1 (tmp, lhs, op2_range))
+      relation_kind k = 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 ())
+	   refine_using_relation (op1, op1_range, op2, op2_range, src,
+				  rel->kind ());
+	 else if (op1 == rel->op2 () && op2 == rel->op1 ())
+	   refine_using_relation (op1, op1_range, op2, op2_range, src,
+				  relation_swap (rel->kind ()));
+       }
+      if (!handler.calc_op1 (tmp, lhs, op2_range, k))
 	return false;
     }
   else
@@ -967,7 +1091,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))
+      if (!handler.calc_op1 (tmp, lhs, op1_range, VREL_VARYING))
 	return false;
     }
 
@@ -1030,6 +1154,7 @@ gori_compute::compute_operand2_range (vrange &r,
   gimple *stmt = handler.stmt ();
   tree op1 = handler.operand1 ();
   tree op2 = handler.operand2 ();
+  tree lhs_name = gimple_get_lhs (stmt);
 
   Value_Range op1_range (TREE_TYPE (op1));
   Value_Range op2_range (TREE_TYPE (op2));
@@ -1037,9 +1162,24 @@ gori_compute::compute_operand2_range (vrange &r,
 
   src.get_operand (op1_range, op1);
   src.get_operand (op2_range, op2);
+  relation_kind k = VREL_VARYING;
+  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 ())
+       refine_using_relation (op1, op1_range, op2, op2_range, src,
+			      rel->kind ());
+      else if (op1 == rel->op2 () && op2 == rel->op1 ())
+       refine_using_relation (op1, op1_range, op2, op2_range, src,
+			      relation_swap (rel->kind ()));
+    }
+
 
   // Intersect with range for op2 based on lhs and op1.
-  if (!handler.calc_op2 (tmp, lhs, op1_range))
+  if (!handler.calc_op2 (tmp, lhs, op1_range, k))
     return false;
 
   unsigned idx;
diff --git a/gcc/gimple-range-gori.h b/gcc/gimple-range-gori.h
index 1fff3e6255a..c7a32162a1b 100644
--- a/gcc/gimple-range-gori.h
+++ b/gcc/gimple-range-gori.h
@@ -166,6 +166,9 @@ public:
   bool has_edge_range_p (tree name, edge e);
   void dump (FILE *f);
 private:
+  bool refine_using_relation (tree op1, vrange &op1_range,
+			      tree op2, vrange &op2_range,
+			      fur_source &src, relation_kind k);
   bool may_recompute_p (tree name, edge e);
   bool may_recompute_p (tree name, basic_block bb = NULL);
   bool compute_operand_range (vrange &r, gimple *stmt, const vrange &lhs,

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-09-29 22:34 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-09-29 22:34 [gcc r13-2974] Refine ranges using relations in GORI Andrew Macleod

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).