diff --git a/llvm/include/llvm/Support/GenericDomTree.h b/llvm/include/llvm/Support/GenericDomTree.h --- a/llvm/include/llvm/Support/GenericDomTree.h +++ b/llvm/include/llvm/Support/GenericDomTree.h @@ -305,6 +305,10 @@ CfgBlockRef findNearestCommonDominatorBlock(CfgBlockRef A, CfgBlockRef B) const; + const GenericDomTreeNodeBase * + climbLhsUntilSiblings(const GenericDomTreeNodeBase *A, + const GenericDomTreeNodeBase *B) const; + void updateDFSNumbers() const; private: @@ -495,6 +499,12 @@ return dom->getBlock(); } + const TreeNode *climbLhsUntilSiblings(const TreeNode *A, + const TreeNode *B) const { + return static_cast( + GenericDominatorTreeBase::climbLhsUntilSiblings(A, B)); + } + //===--------------------------------------------------------------------===// // API to update (Post)DominatorTree information based on modifications to // the CFG... diff --git a/llvm/lib/Support/GenericDomTree.cpp b/llvm/lib/Support/GenericDomTree.cpp --- a/llvm/lib/Support/GenericDomTree.cpp +++ b/llvm/lib/Support/GenericDomTree.cpp @@ -214,6 +214,60 @@ return Dom ? Dom->getBlock() : CfgBlockRef(); } +/// climbLhsUntilSiblings - Under the assumption that \p B is the sibling +/// of some ancestor of \p A in the tree, find that ancestor. Also handles +/// the degenerate case where \p A itself is a sibling of \p B, or +/// \p A is a descendant of \p B. +/// +/// Given an edge A -> B in the control flow graph where B is _not_ dominated +/// by A, this returns either B (if B dominates A) or a sibling of B that +/// dominates A. +/// +/// Example 1: +/// +/// * +/// / \ +/// R B +/// | +/// * +/// | +/// A +/// +/// --> return R +/// +/// Example 2: +/// +/// * +/// / \ +/// A B +/// +/// --> return A +/// +/// Example 3: +/// +/// * +/// | +/// B +/// | +/// * +/// | +/// A +/// +/// --> return B +const GenericDomTreeNodeBase *GenericDominatorTreeBase::climbLhsUntilSiblings( + const GenericDomTreeNodeBase *A, const GenericDomTreeNodeBase *B) const { + assert(A && B && "Pointers are not valid"); + + // Use level information to go up the tree until the levels match. + assert(A->getLevel() >= B->getLevel()); + while (A->getLevel() > B->getLevel()) + A = A->IDom; + + assert(A->IDom == B->IDom); + + return A; +} + /// updateDFSNumbers - Assign In and Out numbers to the nodes while walking /// dominator tree in dfs order. void GenericDominatorTreeBase::updateDFSNumbers() const {