https://gcc.gnu.org/g:8d0ec97fc6629f2d2bac00e1926a9aea9ef81a0c

commit r16-249-g8d0ec97fc6629f2d2bac00e1926a9aea9ef81a0c
Author: Andrew MacLeod <amacl...@redhat.com>
Date:   Mon Feb 10 16:14:17 2025 -0500

    Add a Relation iterator to the relation oracle.
    
    This patch adds a relation iterator to query the oracle to list either
    all the relations on exit to a block, or just ones involving a specified
    SSA_NAME.   The oracle then uses this iterator internally as well.
    
            * value-relation.cc (value_relation::swap): New.
            (value_relation::negate): Remove.
            (dom_oracle::next_relation): New.
            (block_relation_iterator::block_relation_iterator): New.
            (block_relation_iterator::get_next_relation): New.
            (dom_oracle::dump): Use iterator.
            * value-relation.h (relation_oracle::next_relation): New.
            (dom_oracle::next_relation): New prototype.
            (class block_relation_iterator): New.
            (FOR_EACH_RELATION_BB): New.
            (FOR_EACH_RELATION_NAME): New.

Diff:
---
 gcc/value-relation.cc | 90 +++++++++++++++++++++++++++++++++++++++++++++++----
 gcc/value-relation.h  | 35 ++++++++++++++++++--
 2 files changed, 117 insertions(+), 8 deletions(-)

diff --git a/gcc/value-relation.cc b/gcc/value-relation.cc
index 08449b72d9a9..c7ced445ad76 100644
--- a/gcc/value-relation.cc
+++ b/gcc/value-relation.cc
@@ -780,15 +780,20 @@ equiv_oracle::dump (FILE *f) const
 
 
 // --------------------------------------------------------------------------
-// Negate the current relation.
+
+// Adjust the relation by Swapping the operands and relation.
 
 void
-value_relation::negate ()
+value_relation::swap ()
 {
-  related = relation_negate (related);
+  related = relation_swap (related);
+  tree tmp = name1;
+  name1 = name2;
+  name2 = tmp;
 }
 
 // Perform an intersection between 2 relations. *this &&= p.
+// Return false if the relations cannot be intersected.
 
 bool
 value_relation::intersect (value_relation &p)
@@ -951,6 +956,79 @@ public:
   relation_chain *m_next;
 };
 
+// Given relation record PTR in block BB, return the next relation in the
+// list.  If PTR is NULL, retreive the first relation in BB.
+// If NAME is sprecified, return only relations which include NAME.
+// Return NULL when there are no relations left.
+
+relation_chain *
+dom_oracle::next_relation (basic_block bb, relation_chain *ptr,
+                          tree name) const
+{
+  relation_chain *p;
+  // No value_relation pointer is used to intialize the iterator.
+  if (!ptr)
+    {
+      int bbi = bb->index;
+      if (bbi >= (int)m_relations.length())
+       return NULL;
+      else
+       p = m_relations[bbi].m_head;
+    }
+  else
+    p = ptr->m_next;
+
+  if (name)
+    for ( ; p; p = p->m_next)
+      if (p->op1 () == name || p->op2 () == name)
+       break;
+  return p;
+}
+
+// Instatiate a block relation iterator to iterate over the relations
+// on exit from block BB in ORACLE.  Limit this to relations involving NAME
+// if specified.  Return the first such relation in VR if there is one.
+
+block_relation_iterator::block_relation_iterator (const relation_oracle 
*oracle,
+                                                 basic_block bb,
+                                                 value_relation &vr,
+                                                 tree name)
+{
+  m_oracle = oracle;
+  m_bb = bb;
+  m_name = name;
+  m_ptr = oracle->next_relation (bb, NULL, m_name);
+  if (m_ptr)
+    {
+      m_done = false;
+      vr = *m_ptr;
+    }
+  else
+    m_done = true;
+}
+
+// Retreive the next relation from the iterator and return it in VR.
+
+void
+block_relation_iterator::get_next_relation (value_relation &vr)
+{
+  m_ptr = m_oracle->next_relation (m_bb, m_ptr, m_name);
+  if (m_ptr)
+    {
+      vr = *m_ptr;
+      if (m_name)
+       {
+         if (vr.op1 () != m_name)
+           {
+             gcc_checking_assert (vr.op2 () == m_name);
+             vr.swap ();
+           }
+       }
+    }
+  else
+    m_done = true;
+}
+
 // ------------------------------------------------------------------------
 
 // Find the relation between any ssa_name in B1 and any name in B2 in LIST.
@@ -1441,11 +1519,11 @@ dom_oracle::dump (FILE *f, basic_block bb) const
   if (!m_relations[bb->index].m_names)
     return;
 
-  relation_chain *ptr = m_relations[bb->index].m_head;
-  for (; ptr; ptr = ptr->m_next)
+  value_relation vr;
+  FOR_EACH_RELATION_BB (this, bb, vr)
     {
       fprintf (f, "Relational : ");
-      ptr->dump (f);
+      vr.dump (f);
       fprintf (f, "\n");
     }
 }
diff --git a/gcc/value-relation.h b/gcc/value-relation.h
index 23cfb41c6357..1081877ccca7 100644
--- a/gcc/value-relation.h
+++ b/gcc/value-relation.h
@@ -114,6 +114,11 @@ public:
   void debug () const;
 protected:
   friend class equiv_relation_iterator;
+  friend class block_relation_iterator;
+  virtual class relation_chain *next_relation (basic_block,
+                                              relation_chain *,
+                                              tree) const
+    { return NULL; }
   // Return equivalency set for an SSA name in a basic block.
   virtual const_bitmap equiv_set (tree, basic_block) { return NULL; }
   // Return partial equivalency record for an SSA name.
@@ -228,7 +233,9 @@ public:
 
   void dump (FILE *f, basic_block bb) const final override;
   void dump (FILE *f) const final override;
-private:
+protected:
+  virtual relation_chain *next_relation (basic_block, relation_chain *,
+                                        tree) const;
   bool m_do_trans_p;
   bitmap m_tmp, m_tmp2;
   bitmap m_relation_set;  // Index by ssa-name. True if a relation exists
@@ -431,7 +438,7 @@ public:
   relation_trio create_trio (tree lhs, tree op1, tree op2);
   bool union_ (value_relation &p);
   bool intersect (value_relation &p);
-  void negate ();
+  void swap ();
   bool apply_transitive (const value_relation &rel);
 
   void dump (FILE *f) const;
@@ -470,6 +477,30 @@ value_relation::value_relation (relation_kind kind, tree 
n1, tree n2)
   set_relation (kind, n1, n2);
 }
 
+
+class block_relation_iterator {
+public:
+  block_relation_iterator (const relation_oracle *oracle, basic_block bb,
+                          value_relation &, tree name = NULL);
+  void get_next_relation (value_relation &vr);
+  const relation_oracle *m_oracle;
+  basic_block m_bb;
+  relation_chain *m_ptr;
+  bool m_done;
+  tree m_name;
+};
+
+#define FOR_EACH_RELATION_BB(oracle, bb, vr)                   \
+  for (block_relation_iterator iter (oracle, bb, vr);          \
+       !iter.m_done;                                           \
+       iter.get_next_relation (vr))
+
+#define FOR_EACH_RELATION_NAME(oracle, bb, name, vr)           \
+  for (block_relation_iterator iter (oracle, bb, vr, name);    \
+       !iter.m_done;                                           \
+       iter.get_next_relation (vr))
+
+
 // Return the number of bits associated with partial equivalency T.
 // Return 0 if this is not a supported partial equivalency relation.

Reply via email to