diff options
author | Ted Kremenek <kremenek@apple.com> | 2011-10-25 00:25:24 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2011-10-25 00:25:24 +0000 |
commit | 58f6f1e37ab32fdd0c8bab6771d8e09bc139e9ed (patch) | |
tree | 4870052ce90ffe5ef45acfbee07db4fddd9572bb /lib/Analysis/Dominators.cpp | |
parent | 98326ede499696f85d9f7bc1fbc7a628fc22f1ec (diff) |
Add source-level dominators analysis. Patch by Guoping Long!
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@142885 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/Dominators.cpp')
-rw-r--r-- | lib/Analysis/Dominators.cpp | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/lib/Analysis/Dominators.cpp b/lib/Analysis/Dominators.cpp new file mode 100644 index 0000000000..62b72287f9 --- /dev/null +++ b/lib/Analysis/Dominators.cpp @@ -0,0 +1,160 @@ +//==- Dominators.cpp - Construct the Dominance Tree Given CFG ----*- C++ --*-==// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file implements a simple, fast dominance algorithm for source-level CFGs. +// +//===----------------------------------------------------------------------===// + +#include "clang/Analysis/Analyses/Dominators.h" +#include "clang/Analysis/CFG.h" +#include "clang/Analysis/AnalysisContext.h" +#include "clang/Analysis/Analyses/PostOrderCFGView.h" + +using namespace clang; + +DominatorTree::~DominatorTree() { + IDoms.clear(); + RootNode = 0; +} + +CFGBlock * DominatorTree::getNode(const CFGBlock *B) const { + CFGBlockMapTy::const_iterator I = IDoms.find(B); + return I != IDoms.end() ? I->second : 0; +} + +bool DominatorTree::properlyDominates(const CFGBlock *A, + const CFGBlock *B) const { + if (0 == A || 0 == B || A == B) + return false; + + // The EntryBlock dominates every other block. + if (A == RootNode) + return true; + + // Note: The dominator of the EntryBlock is itself. + CFGBlock *IDom = getNode(B); + while (IDom != A && IDom != RootNode) + IDom = getNode(IDom); + + return IDom != RootNode; +} + +bool DominatorTree::dominates(const CFGBlock *A, + const CFGBlock *B) const { + if (A == B) + return true; + + return properlyDominates(A, B); +} + +const CFGBlock * DominatorTree::findNearestCommonDominator + (const CFGBlock *A, const CFGBlock *B) const { + //If A dominates B, then A is the nearest common dominator + if (dominates(A, B)) + return A; + + //If B dominates A, then B is the nearest common dominator + if (dominates(B, A)) + return B; + + //Collect all A's dominators + llvm::SmallPtrSet<CFGBlock *, 16> ADoms; + ADoms.insert(RootNode); + CFGBlock *ADom = getNode(A); + while (ADom != RootNode) { + ADoms.insert(ADom); + ADom = getNode(ADom); + } + + //Check all B's dominators against ADoms + CFGBlock *BDom = getNode(B); + while (BDom != RootNode){ + if (ADoms.count(BDom) != 0) + return BDom; + + BDom = getNode(BDom); + } + + //The RootNode dominates every other node + return RootNode; +} + +/// Constructs immediate dominator tree for a given CFG based on the algorithm +/// described in this paper: +/// +/// A Simple, Fast Dominance Algorithm +/// Keith D. Cooper, Timothy J. Harvey and Ken Kennedy +/// Software-Practice and Expreience, 2001;4:1-10. +/// +/// This implementation is simple and runs faster in practice than the classis +/// Lengauer-Tarjan algorithm. For detailed discussions, refer to the paper. +void DominatorTree::BuildDominatorTree() { + CFG *cfg = AC.getCFG(); + CFGBlock *EntryBlk = &cfg->getEntry(); + + //Sort all CFGBlocks in reverse order + PostOrderCFGView *rpocfg = AC.getAnalysis<PostOrderCFGView>(); + + //Set the root of the dominance tree + RootNode = EntryBlk; + + //Compute the immediate dominator for each CFGBlock + IDoms[EntryBlk] = EntryBlk; + bool changed = true; + while (changed){ + changed = false; + + for (PostOrderCFGView::iterator I = rpocfg->begin(), + E = rpocfg->end(); I != E; ++I){ + if (EntryBlk == *I) + continue; + if (const CFGBlock *B = *I) { + //Compute immediate dominance information for CFGBlock B + CFGBlock *IDom = 0; + for (CFGBlock::const_pred_iterator J = B->pred_begin(), + K = B->pred_end(); J != K; ++J) + if( CFGBlock *P = *J) { + if (IDoms.find(P) == IDoms.end()) + continue; + if (!IDom) + IDom = P; + else { + //intersect IDom and P + CFGBlock *B1 = IDom, *B2 = P; + while (B1 != B2) { + while ((rpocfg->getComparator())(B2,B1)) + B1 = IDoms[B1]; + while ((rpocfg->getComparator())(B1,B2)) + B2 = IDoms[B2]; + } + IDom = B1; + } + } + if (IDoms[B] != IDom) { + IDoms[B] = IDom; + changed = true; + } + } + } + }//while +} + +void DominatorTree::dump() { + CFG *cfg = AC.getCFG(); + + llvm::errs() << "Immediate dominance tree (Node#,IDom#):\n"; + for (CFG::const_iterator I = cfg->begin(), + E = cfg->end(); I != E; ++I) { + assert(IDoms[(*I)] && + "Failed to find the immediate dominator for all CFG blocks."); + llvm::errs() << "(" << (*I)->getBlockID() + << "," << IDoms[(*I)]->getBlockID() << ")\n"; + } +} + |