Skip to content

Commit

Permalink
[Dominators] Add NearestCommonDominator verification
Browse files Browse the repository at this point in the history
Summary:
This patch adds another verification function for checking correctness of findNearestCommonDominator.
For every edge from U to V in the input graph, `NCD(U, V) == IDom(V) or V` -- the new function checks this condition.

Reviewers: dberlin, sanjoy, chandlerc

Reviewed By: dberlin

Subscribers: llvm-commits

Differential Revision: https://reviews.llvm.org/D34575

llvm-svn: 306893
  • Loading branch information
kuhar committed Jun 30, 2017
1 parent b88303a commit 3214633
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 3 deletions.
5 changes: 3 additions & 2 deletions llvm/include/llvm/Support/GenericDomTree.h
Expand Up @@ -407,7 +407,7 @@ template <class NodeT> class DominatorTreeBase {

/// findNearestCommonDominator - Find nearest common dominator basic block
/// for basic block A and B. If there is no such block then return NULL.
NodeT *findNearestCommonDominator(NodeT *A, NodeT *B) {
NodeT *findNearestCommonDominator(NodeT *A, NodeT *B) const {
assert(A->getParent() == B->getParent() &&
"Two blocks are not in same function");

Expand All @@ -433,7 +433,8 @@ template <class NodeT> class DominatorTreeBase {
return NodeA ? NodeA->getBlock() : nullptr;
}

const NodeT *findNearestCommonDominator(const NodeT *A, const NodeT *B) {
const NodeT *findNearestCommonDominator(const NodeT *A,
const NodeT *B) const {
// Cast away the const qualifiers here. This is ok since
// const is re-introduced on the return type.
return findNearestCommonDominator(const_cast<NodeT *>(A),
Expand Down
42 changes: 41 additions & 1 deletion llvm/include/llvm/Support/GenericDomTreeConstruction.h
Expand Up @@ -280,6 +280,7 @@ struct SemiNCAInfo {
}

void doFullDFSWalk(const DomTreeT &DT) {
NumToNode.push_back(nullptr);
unsigned Num = 0;
for (auto *Root : DT.Roots)
if (!DT.isPostDominator())
Expand Down Expand Up @@ -351,6 +352,44 @@ struct SemiNCAInfo {
return true;
}

// Checks if for every edge From -> To in the graph
// NCD(From, To) == IDom(To) or To.
bool verifyNCD(const DomTreeT &DT) {
clear();
doFullDFSWalk(DT);

for (auto &BlockToInfo : NodeToInfo) {
auto &Info = BlockToInfo.second;

const NodePtr From = NumToNode[Info.Parent];
if (!From) continue;

const NodePtr To = BlockToInfo.first;
const TreeNodePtr ToTN = DT.getNode(To);
assert(ToTN);

const NodePtr NCD = DT.findNearestCommonDominator(From, To);
const TreeNodePtr NCDTN = NCD ? DT.getNode(NCD) : nullptr;
const TreeNodePtr ToIDom = ToTN->getIDom();
if (NCDTN != ToTN && NCDTN != ToIDom) {
errs() << "NearestCommonDominator verification failed:\n\tNCD(From:";
PrintBlockOrNullptr(errs(), From);
errs() << ", To:";
PrintBlockOrNullptr(errs(), To);
errs() << ") = ";
PrintBlockOrNullptr(errs(), NCD);
errs() << ",\t (should be To or IDom[To]: ";
PrintBlockOrNullptr(errs(), ToIDom ? ToIDom->getBlock() : nullptr);
errs() << ")\n";
errs().flush();

return false;
}
}

return true;
}

// Checks if the tree has the parent property: if for all edges from V to W in
// the input graph, such that V is reachable, the parent of W in the tree is
// an ancestor of V in the tree.
Expand Down Expand Up @@ -439,7 +478,8 @@ bool Verify(const DominatorTreeBaseByGraphTraits<GraphTraits<NodeT>> &DT) {
SemiNCAInfo<typename std::remove_pointer<NodePtr>::type> SNCA;

return SNCA.verifyReachability(DT) && SNCA.VerifyLevels(DT) &&
SNCA.verifyParentProperty(DT) && SNCA.verifySiblingProperty(DT);
SNCA.verifyNCD(DT) && SNCA.verifyParentProperty(DT) &&
SNCA.verifySiblingProperty(DT);
}

} // namespace DomTreeBuilder
Expand Down

0 comments on commit 3214633

Please sign in to comment.