Index: include/llvm/IR/Dominators.h =================================================================== --- include/llvm/IR/Dominators.h +++ include/llvm/IR/Dominators.h @@ -42,6 +42,11 @@ DominatorTreeBaseByGraphTraits>> &DT, Function &F); +extern template bool Verify( + const DominatorTreeBaseByGraphTraits> &DT); +extern template bool Verify>( + const DominatorTreeBaseByGraphTraits>> &DT); + using DomTreeNode = DomTreeNodeBase; class BasicBlockEdge { Index: include/llvm/Support/GenericDomTree.h =================================================================== --- include/llvm/Support/GenericDomTree.h +++ include/llvm/Support/GenericDomTree.h @@ -205,6 +205,9 @@ template void Calculate(DominatorTreeBaseByGraphTraits> &DT, FuncT &F); +template +bool Verify(const DominatorTreeBaseByGraphTraits> &DT); + /// \brief Core dominator tree base class. /// /// This class is a generic template over graph nodes. It is instantiated for @@ -255,10 +258,10 @@ DenseMap IDoms; // Vertex - Map the DFS number to the NodeT* - std::vector Vertex; + mutable std::vector Vertex; // Info - Collection of information used during the computation of idoms. - DenseMap Info; + mutable DenseMap Info; void reset() { DomTreeNodes.clear(); @@ -329,6 +332,7 @@ } public: + using NodePtr = DomTreeNodeBase *; explicit DominatorTreeBase(bool isPostDom) : DominatorBase(isPostDom) {} @@ -680,17 +684,32 @@ unsigned LastLinked); template - friend unsigned ReverseDFSPass(DominatorTreeBaseByGraphTraits &DT, + friend unsigned ReverseDFSPass(const DominatorTreeBaseByGraphTraits &DT, typename GraphT::NodeRef V, unsigned N); template - friend unsigned DFSPass(DominatorTreeBaseByGraphTraits &DT, + friend unsigned DFSPass(const DominatorTreeBaseByGraphTraits &DT, typename GraphT::NodeRef V, unsigned N); template friend void Calculate(DominatorTreeBaseByGraphTraits> &DT, FuncT &F); + template + friend void RunDFS(const DominatorTreeBaseByGraphTraits &DT); + + template + friend bool VerifyReachability(const DominatorTreeBaseByGraphTraits &DT); + + template + friend bool VerifyParentProperty(const DominatorTreeBaseByGraphTraits &DT); + + template + friend bool VerifySiblingProperty(const DominatorTreeBaseByGraphTraits &DT); + + template + friend bool Verify(const DominatorTreeBaseByGraphTraits> &DT); + DomTreeNodeBase *getNodeForBlock(NodeT *BB) { if (DomTreeNodeBase *Node = getNode(BB)) return Node; @@ -763,6 +782,12 @@ DFSInfoValid = true; } + /// verify - checks parent and sibling property + bool verify() const { + return this->isPostDominator() ? Verify>(*this) + : Verify(*this); + } + /// recalculate - compute a dominator tree for the given function template void recalculate(FT &F) { using TraitsTy = GraphTraits; @@ -775,6 +800,7 @@ addRoot(entry); Calculate(*this, F); + Verify(*this); } else { // Initialize the roots list for (auto *Node : nodes(&F)) @@ -782,6 +808,7 @@ addRoot(Node); Calculate>(*this, F); + Verify>(*this); } } }; Index: include/llvm/Support/GenericDomTreeConstruction.h =================================================================== --- include/llvm/Support/GenericDomTreeConstruction.h +++ include/llvm/Support/GenericDomTreeConstruction.h @@ -27,6 +27,7 @@ #include "llvm/ADT/DepthFirstIterator.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Support/GenericDomTree.h" +#include "llvm/Support/raw_ostream.h" namespace llvm { @@ -49,7 +50,7 @@ }; template -unsigned ReverseDFSPass(DominatorTreeBaseByGraphTraits &DT, +unsigned ReverseDFSPass(const DominatorTreeBaseByGraphTraits &DT, typename GraphT::NodeRef V, unsigned N) { df_iterator_dom_storage< typename GraphT::NodeRef, @@ -76,7 +77,7 @@ return N; } template -unsigned DFSPass(DominatorTreeBaseByGraphTraits &DT, +unsigned DFSPass(const DominatorTreeBaseByGraphTraits &DT, typename GraphT::NodeRef V, unsigned N) { df_iterator_dom_storage< typename GraphT::NodeRef, @@ -279,6 +280,123 @@ DT.updateDFSNumbers(); } + + +template +void RunDFS(const DominatorTreeBaseByGraphTraits &DT) { + unsigned Num = 0; + for (auto *Root : DT.Roots) + if (!DT.isPostDominator()) + Num = DFSPass(DT, Root, Num); + else + Num = ReverseDFSPass(DT, Root, Num); + + DT.Vertex.clear(); +} + +template +bool VerifyReachability(const DominatorTreeBaseByGraphTraits &DT) { + using BlockPtr = typename GraphT::NodeRef; + using NodePtr = + DomTreeNodeBase::type> *; + + DT.Info.clear(); + RunDFS(DT); + + for (auto &NodeToTN : DT.DomTreeNodes) { + const NodePtr TN = NodeToTN.second.get(); + const BlockPtr BB = TN->getBlock(); + if (!BB) + continue; + + if (DT.Info.count(BB) == 0) { + errs() << "DomTree node not found by DFS walk!\n"; + errs().flush(); + DT.Info.clear(); + return false; + } + } + + DT.Info.clear(); + return true; +} + +template +bool VerifyParentProperty(const DominatorTreeBaseByGraphTraits &DT) { + using BlockPtr = typename GraphT::NodeRef; + using NodePtr = + DomTreeNodeBase::type> *; + for (auto &NodeToTN : DT.DomTreeNodes) { + const NodePtr TN = NodeToTN.second.get(); + const BlockPtr BB = TN->getBlock(); + if (!BB || TN->getChildren().empty()) + continue; + + DT.Info.clear(); + DT.Info.insert({BB, {}}); + RunDFS(DT); + + for (NodePtr Child : TN->getChildren()) + if (DT.Info.count(Child->getBlock()) != 0) { + errs() << "Child reachable after its parent is removed!\n"; + errs().flush(); + DT.Info.clear(); + return false; + } + } + + DT.Info.clear(); + return true; +} + +template +bool VerifySiblingProperty(const DominatorTreeBaseByGraphTraits &DT) { + using BlockPtr = typename GraphT::NodeRef; + using NodePtr = + DomTreeNodeBase::type> *; + + for (auto &NodeToTN : DT.DomTreeNodes) { + const NodePtr TN = NodeToTN.second.get(); + const BlockPtr BB = TN->getBlock(); + if (!BB || TN->getChildren().empty()) + continue; + + const auto& Siblings = TN->getChildren(); + for (const NodePtr N : Siblings) { + for (const NodePtr S : Siblings) { + if (S == N) + continue; + + DT.Info.clear(); + DT.Info.insert({S->getBlock(), {}}); + RunDFS(DT); + + if (DT.Info.count(N->getBlock()) == 0) { + errs() << "Node not reachable when its sibling is removed!\n"; + errs().flush(); + DT.Info.clear(); + return false; + } + } + } + } + + DT.Info.clear(); + return true; +} + +template +bool Verify(const DominatorTreeBaseByGraphTraits> &DT) { + bool Correct = VerifyReachability>(DT) && + VerifyParentProperty>(DT) && + VerifySiblingProperty>(DT); + if (Correct) + return true; + + errs() << "\n~~~~~~~~~~~~~~~~~~\n\t\tIncorrect DomTree!\n~~~~~~~~~~~~~~~~\n"; + return false; +} + } #endif Index: lib/IR/Dominators.cpp =================================================================== --- lib/IR/Dominators.cpp +++ lib/IR/Dominators.cpp @@ -73,6 +73,14 @@ GraphTraits>::NodeRef>::type> &DT, Function &F); +template bool llvm::Verify( + const DominatorTreeBase< + typename std::remove_pointer::NodeRef>::type> + &DT); +template bool llvm::Verify>( + const DominatorTreeBase>::NodeRef>::type> &DT); + bool DominatorTree::invalidate(Function &F, const PreservedAnalyses &PA, FunctionAnalysisManager::Invalidator &) { // Check whether the analysis, all analyses on functions, or the function's @@ -285,6 +293,9 @@ } void DominatorTree::verifyDomTree() const { + if (!verify()) + abort(); + Function &F = *getRoot()->getParent(); DominatorTree OtherDT;