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 for printing as proof of
concept. It is also of use in a follow on patch for finding "nearest"
relations.
Bootstrapped on x86_64-pc-linux-gnu with no regressions. Pushed.
Andrew
From bf2e0fb97183d46a84d283b795067d586d874556 Mon Sep 17 00:00:00 2001
From: Andrew MacLeod <amacl...@redhat.com>
Date: Mon, 10 Feb 2025 16:14:17 -0500
Subject: [PATCH 6/9] 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.
---
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 08449b72d9a..c7ced445ad7 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 23cfb41c635..1081877ccca 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.
--
2.45.0