mirror of
https://github.com/RPCS3/llvm.git
synced 2024-12-15 07:59:57 +00:00
[LCG] Re-implement the basic isParentOf, isAncestorOf, isChildOf, and
isDescendantOf methods on RefSCCs in terms of the forward edges rather than the parent sets. This is technically slower, but probably not interestingly slower, and all of these routines were already so expensive that they're guarded behind both !NDEBUG and EXPENSIVE_CHECKS. This removes another non-critical usage of parent sets. I've also added some comments to try and help clarify to any potential users the costs of these routines. They're mostly useful for debugging, asserts, or other queries. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@310170 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
95f263eb86
commit
8d16ccbe0f
@ -631,20 +631,34 @@ public:
|
|||||||
return make_range(parent_begin(), parent_end());
|
return make_range(parent_begin(), parent_end());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test if this RefSCC is a parent of \a C.
|
/// Test if this RefSCC is a parent of \a RC.
|
||||||
bool isParentOf(const RefSCC &C) const { return C.isChildOf(*this); }
|
///
|
||||||
|
/// CAUTION: This method walks every edge in the \c RefSCC, it can be very
|
||||||
|
/// expensive.
|
||||||
|
bool isParentOf(const RefSCC &RC) const;
|
||||||
|
|
||||||
/// Test if this RefSCC is an ancestor of \a C.
|
/// Test if this RefSCC is an ancestor of \a RC.
|
||||||
bool isAncestorOf(const RefSCC &C) const { return C.isDescendantOf(*this); }
|
///
|
||||||
|
/// CAUTION: This method walks the directed graph of edges as far as
|
||||||
|
/// necessary to find a possible path to the argument. In the worst case
|
||||||
|
/// this may walk the entire graph and can be extremely expensive.
|
||||||
|
bool isAncestorOf(const RefSCC &RC) const;
|
||||||
|
|
||||||
/// Test if this RefSCC is a child of \a C.
|
/// Test if this RefSCC is a child of \a RC.
|
||||||
bool isChildOf(const RefSCC &C) const {
|
///
|
||||||
return Parents.count(const_cast<RefSCC *>(&C));
|
/// CAUTION: This method walks every edge in the argument \c RefSCC, it can
|
||||||
|
/// be very expensive.
|
||||||
|
bool isChildOf(const RefSCC &RC) const { return RC.isParentOf(*this); }
|
||||||
|
|
||||||
|
/// Test if this RefSCC is a descendant of \a RC.
|
||||||
|
///
|
||||||
|
/// CAUTION: This method walks the directed graph of edges as far as
|
||||||
|
/// necessary to find a possible path from the argument. In the worst case
|
||||||
|
/// this may walk the entire graph and can be extremely expensive.
|
||||||
|
bool isDescendantOf(const RefSCC &RC) const {
|
||||||
|
return RC.isAncestorOf(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Test if this RefSCC is a descendant of \a C.
|
|
||||||
bool isDescendantOf(const RefSCC &C) const;
|
|
||||||
|
|
||||||
/// Provide a short name by printing this RefSCC to a std::string.
|
/// Provide a short name by printing this RefSCC to a std::string.
|
||||||
///
|
///
|
||||||
/// This copes with the fact that we don't have a name per-se for an RefSCC
|
/// This copes with the fact that we don't have a name per-se for an RefSCC
|
||||||
|
@ -334,17 +334,44 @@ void LazyCallGraph::RefSCC::verify() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool LazyCallGraph::RefSCC::isDescendantOf(const RefSCC &C) const {
|
bool LazyCallGraph::RefSCC::isParentOf(const RefSCC &RC) const {
|
||||||
// Walk up the parents of this SCC and verify that we eventually find C.
|
if (&RC == this)
|
||||||
SmallVector<const RefSCC *, 4> AncestorWorklist;
|
return false;
|
||||||
AncestorWorklist.push_back(this);
|
|
||||||
|
// Search all edges to see if this is a parent.
|
||||||
|
for (SCC &C : *this)
|
||||||
|
for (Node &N : C)
|
||||||
|
for (Edge &E : *N)
|
||||||
|
if (G->lookupRefSCC(E.getNode()) == &RC)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool LazyCallGraph::RefSCC::isAncestorOf(const RefSCC &RC) const {
|
||||||
|
if (&RC == this)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// For each descendant of this RefSCC, see if one of its children is the
|
||||||
|
// argument. If not, add that descendant to the worklist and continue
|
||||||
|
// searching.
|
||||||
|
SmallVector<const RefSCC *, 4> Worklist;
|
||||||
|
SmallPtrSet<const RefSCC *, 4> Visited;
|
||||||
|
Worklist.push_back(this);
|
||||||
|
Visited.insert(this);
|
||||||
do {
|
do {
|
||||||
const RefSCC *AncestorC = AncestorWorklist.pop_back_val();
|
const RefSCC &DescendantRC = *Worklist.pop_back_val();
|
||||||
if (AncestorC->isChildOf(C))
|
for (SCC &C : DescendantRC)
|
||||||
return true;
|
for (Node &N : C)
|
||||||
for (const RefSCC *ParentC : AncestorC->Parents)
|
for (Edge &E : *N) {
|
||||||
AncestorWorklist.push_back(ParentC);
|
auto *ChildRC = G->lookupRefSCC(E.getNode());
|
||||||
} while (!AncestorWorklist.empty());
|
if (ChildRC == &RC)
|
||||||
|
return true;
|
||||||
|
if (!ChildRC || !Visited.insert(ChildRC).second)
|
||||||
|
continue;
|
||||||
|
Worklist.push_back(ChildRC);
|
||||||
|
}
|
||||||
|
} while (!Worklist.empty());
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user