[analyzer] Rely on LLVM Dominators in Clang dominator computation.
(Previously, Clang used it's implementation of dominators.) The patch is contributed by Guoping Long! llvm-svn: 145858
This commit is contained in:
parent
5c10794254
commit
02a1fc1da6
|
@ -1,4 +1,4 @@
|
|||
//==- Dominators.h - Construct the Dominance Tree Given CFG -----*- C++ --*-==//
|
||||
//==- Dominators.h - Implementation of dominators tree for Clang CFG C++ -*-==//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
|
@ -7,74 +7,205 @@
|
|||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file implements a simple, fast dominance algorithm for source-level
|
||||
// CFGs.
|
||||
// This file implements the dominators tree functionality for Clang CFGs.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_DOMINATORS_H
|
||||
#define LLVM_CLANG_DOMINATORS_H
|
||||
|
||||
#include "clang/Analysis/CFG.h"
|
||||
#include "clang/Analysis/AnalysisContext.h"
|
||||
#include "llvm/ADT/DenseMap.h"
|
||||
|
||||
#include "llvm/Module.h"
|
||||
#include "llvm/ADT/GraphTraits.h"
|
||||
#include "clang/Analysis/CFG.h"
|
||||
#include "llvm/Analysis/Dominators.h"
|
||||
#include "llvm/Analysis/DominatorInternals.h"
|
||||
|
||||
namespace clang {
|
||||
|
||||
class CFG;
|
||||
class CFGBlock;
|
||||
typedef llvm::DomTreeNodeBase<CFGBlock> DomTreeNode;
|
||||
|
||||
/// \brief Concrete subclass of DominatorTreeBase for Clang
|
||||
/// This class implements the dominators tree functionality given a Clang CFG.
|
||||
///
|
||||
class DominatorTree : public ManagedAnalysis {
|
||||
typedef llvm::DenseMap<const CFGBlock *, CFGBlock*> CFGBlockMapTy;
|
||||
|
||||
public:
|
||||
DominatorTree(AnalysisDeclContext &ac)
|
||||
: AC(ac) {}
|
||||
llvm::DominatorTreeBase<CFGBlock>* DT;
|
||||
|
||||
virtual ~DominatorTree();
|
||||
DominatorTree() {
|
||||
DT = new llvm::DominatorTreeBase<CFGBlock>(false);
|
||||
}
|
||||
|
||||
/// Return the immediate dominator node given a CFGBlock.
|
||||
/// For entry block, the dominator is itself.
|
||||
/// This is the same as using operator[] on this class.
|
||||
CFGBlock *getNode(const CFGBlock *B) const;
|
||||
~DominatorTree() {
|
||||
delete DT;
|
||||
}
|
||||
|
||||
/// This returns the Entry Block for the given CFG
|
||||
CFGBlock *getRootNode() { return RootNode; }
|
||||
const CFGBlock *getRootNode() const { return RootNode; }
|
||||
llvm::DominatorTreeBase<CFGBlock>& getBase() { return *DT; }
|
||||
|
||||
/// Returns true iff A dominates B and A != B.
|
||||
/// Note that this is not a constant time operation.
|
||||
bool properlyDominates(const CFGBlock *A, const CFGBlock *B) const;
|
||||
|
||||
/// Returns true iff A dominates B.
|
||||
bool dominates(const CFGBlock *A, const CFGBlock *B) const;
|
||||
|
||||
/// Find nearest common dominator for blocks A and B.
|
||||
/// Common dominator always exists, ex: entry block.
|
||||
const CFGBlock *findNearestCommonDominator(const CFGBlock *A,
|
||||
const CFGBlock *B) const;
|
||||
|
||||
/// Constructs immediate dominator tree for a given CFG based on the algorithm
|
||||
/// described in this paper:
|
||||
/// \brief This method returns the root CFGBlock of the dominators tree.
|
||||
///
|
||||
/// 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 BuildDominatorTree();
|
||||
inline CFGBlock *getRoot() const {
|
||||
return DT->getRoot();
|
||||
}
|
||||
|
||||
/// Dump the immediate dominance tree
|
||||
void dump();
|
||||
/// \brief This method returns the root DomTreeNode, which is the wrapper
|
||||
/// for CFGBlock.
|
||||
inline DomTreeNode *getRootNode() const {
|
||||
return DT->getRootNode();
|
||||
}
|
||||
|
||||
/// \brief This method compares two dominator trees.
|
||||
/// The method returns false if the other dominator tree matches this
|
||||
/// dominator tree, otherwise returns true.
|
||||
///
|
||||
inline bool compare(DominatorTree &Other) const {
|
||||
DomTreeNode *R = getRootNode();
|
||||
DomTreeNode *OtherR = Other.getRootNode();
|
||||
|
||||
if (!R || !OtherR || R->getBlock() != OtherR->getBlock())
|
||||
return true;
|
||||
|
||||
if (DT->compare(Other.getBase()))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief This method builds the dominator tree for a given CFG
|
||||
/// The CFG information is passed via AnalysisDeclContext
|
||||
///
|
||||
void buildDominatorTree(AnalysisDeclContext &AC) {
|
||||
cfg = AC.getCFG();
|
||||
DT->recalculate(*cfg);
|
||||
}
|
||||
|
||||
/// \brief This method dumps immediate dominators for each block,
|
||||
/// mainly used for debug purposes.
|
||||
///
|
||||
void dump() {
|
||||
llvm::errs() << "Immediate dominance tree (Node#,IDom#):\n";
|
||||
for (CFG::const_iterator I = cfg->begin(),
|
||||
E = cfg->end(); I != E; ++I) {
|
||||
if(DT->getNode(*I)->getIDom())
|
||||
llvm::errs() << "(" << (*I)->getBlockID()
|
||||
<< ","
|
||||
<< DT->getNode(*I)->getIDom()->getBlock()->getBlockID()
|
||||
<< ")\n";
|
||||
else llvm::errs() << "(" << (*I)->getBlockID()
|
||||
<< "," << (*I)->getBlockID() << ")\n";
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief This method tests if one CFGBlock dominates the other.
|
||||
/// The method return true if A dominates B, false otherwise.
|
||||
/// Note a block always dominates itself.
|
||||
///
|
||||
inline bool dominates(const CFGBlock* A, const CFGBlock* B) const {
|
||||
return DT->dominates(A, B);
|
||||
}
|
||||
|
||||
/// \brief This method tests if one CFGBlock properly dominates the other.
|
||||
/// The method return true if A properly dominates B, false otherwise.
|
||||
///
|
||||
bool properlyDominates(const CFGBlock*A, const CFGBlock*B) const {
|
||||
return DT->properlyDominates(A, B);
|
||||
}
|
||||
|
||||
/// \brief This method finds the nearest common dominator CFG block
|
||||
/// for CFG block A and B. If there is no such block then return NULL.
|
||||
///
|
||||
inline CFGBlock *findNearestCommonDominator(CFGBlock *A, CFGBlock *B) {
|
||||
return DT->findNearestCommonDominator(A, B);
|
||||
}
|
||||
|
||||
inline const CFGBlock *findNearestCommonDominator(const CFGBlock *A,
|
||||
const CFGBlock *B) {
|
||||
return DT->findNearestCommonDominator(A, B);
|
||||
}
|
||||
|
||||
/// \brief This method is used to update the dominator
|
||||
/// tree information when a node's immediate dominator changes.
|
||||
///
|
||||
inline void changeImmediateDominator(CFGBlock *N, CFGBlock *NewIDom) {
|
||||
DT->changeImmediateDominator(N, NewIDom);
|
||||
}
|
||||
|
||||
/// \brief This method tests if the given CFGBlock can be reachable from root.
|
||||
/// Returns true if reachable, false otherwise.
|
||||
///
|
||||
bool isReachableFromEntry(const CFGBlock *A) {
|
||||
return DT->isReachableFromEntry(A);
|
||||
}
|
||||
|
||||
/// \brief This method releases the memory held by the dominator tree.
|
||||
///
|
||||
virtual void releaseMemory() {
|
||||
DT->releaseMemory();
|
||||
}
|
||||
|
||||
/// \brief This method converts the dominator tree to human readable form.
|
||||
///
|
||||
virtual void print(raw_ostream &OS, const llvm::Module* M= 0) const {
|
||||
DT->print(OS);
|
||||
}
|
||||
|
||||
private:
|
||||
AnalysisDeclContext &AC;
|
||||
CFGBlock *RootNode;
|
||||
CFGBlockMapTy IDoms;
|
||||
CFG *cfg;
|
||||
};
|
||||
|
||||
void WriteAsOperand(raw_ostream &OS, const CFGBlock *BB,
|
||||
bool t) {
|
||||
OS << "BB#" << BB->getBlockID();
|
||||
}
|
||||
|
||||
} // end namespace clang
|
||||
|
||||
#endif
|
||||
//===-------------------------------------
|
||||
/// DominatorTree GraphTraits specialization so the DominatorTree can be
|
||||
/// iterable by generic graph iterators.
|
||||
///
|
||||
namespace llvm {
|
||||
template <> struct GraphTraits< ::clang::DomTreeNode* > {
|
||||
typedef ::clang::DomTreeNode NodeType;
|
||||
typedef NodeType::iterator ChildIteratorType;
|
||||
|
||||
static NodeType *getEntryNode(NodeType *N) {
|
||||
return N;
|
||||
}
|
||||
static inline ChildIteratorType child_begin(NodeType *N) {
|
||||
return N->begin();
|
||||
}
|
||||
static inline ChildIteratorType child_end(NodeType *N) {
|
||||
return N->end();
|
||||
}
|
||||
|
||||
typedef df_iterator< ::clang::DomTreeNode* > nodes_iterator;
|
||||
|
||||
static nodes_iterator nodes_begin(::clang::DomTreeNode *N) {
|
||||
return df_begin(getEntryNode(N));
|
||||
}
|
||||
|
||||
static nodes_iterator nodes_end(::clang::DomTreeNode *N) {
|
||||
return df_end(getEntryNode(N));
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct GraphTraits< ::clang::DominatorTree* >
|
||||
: public GraphTraits< ::clang::DomTreeNode* > {
|
||||
static NodeType *getEntryNode(::clang::DominatorTree *DT) {
|
||||
return DT->getRootNode();
|
||||
}
|
||||
|
||||
static nodes_iterator nodes_begin(::clang::DominatorTree *N) {
|
||||
return df_begin(getEntryNode(N));
|
||||
}
|
||||
|
||||
static nodes_iterator nodes_end(::clang::DominatorTree *N) {
|
||||
return df_end(getEntryNode(N));
|
||||
}
|
||||
};
|
||||
} // end namespace llvm
|
||||
|
||||
#endif
|
||||
|
|
|
@ -344,10 +344,14 @@ class CFGBlock {
|
|||
/// storage if the memory usage of CFGBlock becomes an issue.
|
||||
unsigned HasNoReturnElement : 1;
|
||||
|
||||
/// Parent - The parent CFG that owns this CFGBlock.
|
||||
CFG *Parent;
|
||||
|
||||
public:
|
||||
explicit CFGBlock(unsigned blockid, BumpVectorContext &C)
|
||||
: Elements(C), Label(NULL), Terminator(NULL), LoopTarget(NULL),
|
||||
BlockID(blockid), Preds(C, 1), Succs(C, 1), HasNoReturnElement(false) {}
|
||||
explicit CFGBlock(unsigned blockid, BumpVectorContext &C, CFG *parent)
|
||||
: Elements(C), Label(NULL), Terminator(NULL), LoopTarget(NULL),
|
||||
BlockID(blockid), Preds(C, 1), Succs(C, 1), HasNoReturnElement(false),
|
||||
Parent(parent) {}
|
||||
~CFGBlock() {}
|
||||
|
||||
// Statement iterators
|
||||
|
@ -489,6 +493,8 @@ public:
|
|||
|
||||
unsigned getBlockID() const { return BlockID; }
|
||||
|
||||
CFG *getParent() const { return Parent; }
|
||||
|
||||
void dump(const CFG *cfg, const LangOptions &LO) const;
|
||||
void print(raw_ostream &OS, const CFG* cfg, const LangOptions &LO) const;
|
||||
void printTerminator(raw_ostream &OS, const LangOptions &LO) const;
|
||||
|
@ -583,6 +589,55 @@ public:
|
|||
,AddImplicitDtors(false) {}
|
||||
};
|
||||
|
||||
/// \brief Provides a custom implementation of the iterator class to have the
|
||||
/// same interface as Function::iterator - iterator returns CFGBlock
|
||||
/// (not a pointer to CFGBlock).
|
||||
class graph_iterator {
|
||||
public:
|
||||
typedef const CFGBlock value_type;
|
||||
typedef value_type& reference;
|
||||
typedef value_type* pointer;
|
||||
typedef BumpVector<CFGBlock*>::iterator ImplTy;
|
||||
|
||||
graph_iterator(const ImplTy &i) : I(i) {}
|
||||
|
||||
bool operator==(const graph_iterator &X) const { return I == X.I; }
|
||||
bool operator!=(const graph_iterator &X) const { return I != X.I; }
|
||||
|
||||
reference operator*() const { return **I; }
|
||||
pointer operator->() const { return *I; }
|
||||
operator CFGBlock* () { return *I; }
|
||||
|
||||
graph_iterator &operator++() { ++I; return *this; }
|
||||
graph_iterator &operator--() { --I; return *this; }
|
||||
|
||||
private:
|
||||
ImplTy I;
|
||||
};
|
||||
|
||||
class const_graph_iterator {
|
||||
public:
|
||||
typedef const CFGBlock value_type;
|
||||
typedef value_type& reference;
|
||||
typedef value_type* pointer;
|
||||
typedef BumpVector<CFGBlock*>::const_iterator ImplTy;
|
||||
|
||||
const_graph_iterator(const ImplTy &i) : I(i) {}
|
||||
|
||||
bool operator==(const const_graph_iterator &X) const { return I == X.I; }
|
||||
bool operator!=(const const_graph_iterator &X) const { return I != X.I; }
|
||||
|
||||
reference operator*() const { return **I; }
|
||||
pointer operator->() const { return *I; }
|
||||
operator CFGBlock* () const { return *I; }
|
||||
|
||||
const_graph_iterator &operator++() { ++I; return *this; }
|
||||
const_graph_iterator &operator--() { --I; return *this; }
|
||||
|
||||
private:
|
||||
ImplTy I;
|
||||
};
|
||||
|
||||
/// buildCFG - Builds a CFG from an AST. The responsibility to free the
|
||||
/// constructed CFG belongs to the caller.
|
||||
static CFG* buildCFG(const Decl *D, Stmt *AST, ASTContext *C,
|
||||
|
@ -619,6 +674,15 @@ public:
|
|||
const_iterator begin() const { return Blocks.begin(); }
|
||||
const_iterator end() const { return Blocks.end(); }
|
||||
|
||||
graph_iterator nodes_begin() { return graph_iterator(Blocks.begin()); }
|
||||
graph_iterator nodes_end() { return graph_iterator(Blocks.end()); }
|
||||
const_graph_iterator nodes_begin() const {
|
||||
return const_graph_iterator(Blocks.begin());
|
||||
}
|
||||
const_graph_iterator nodes_end() const {
|
||||
return const_graph_iterator(Blocks.end());
|
||||
}
|
||||
|
||||
reverse_iterator rbegin() { return Blocks.rbegin(); }
|
||||
reverse_iterator rend() { return Blocks.rend(); }
|
||||
const_reverse_iterator rbegin() const { return Blocks.rbegin(); }
|
||||
|
@ -681,6 +745,11 @@ public:
|
|||
/// start at 0).
|
||||
unsigned getNumBlockIDs() const { return NumBlockIDs; }
|
||||
|
||||
/// size - Return the total number of CFGBlocks within the CFG
|
||||
/// This is simply a renaming of the getNumBlockIDs(). This is necessary
|
||||
/// because the dominator implementation needs such an interface.
|
||||
unsigned size() const { return NumBlockIDs; }
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// CFG Debugging: Pretty-Printing and Visualization.
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
@ -781,6 +850,20 @@ template <> struct GraphTraits< const ::clang::CFGBlock *> {
|
|||
{ return N->succ_end(); }
|
||||
};
|
||||
|
||||
template <> struct GraphTraits<Inverse< ::clang::CFGBlock*> > {
|
||||
typedef ::clang::CFGBlock NodeType;
|
||||
typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType;
|
||||
|
||||
static NodeType *getEntryNode(Inverse< ::clang::CFGBlock*> G)
|
||||
{ return G.Graph; }
|
||||
|
||||
static inline ChildIteratorType child_begin(NodeType* N)
|
||||
{ return N->pred_begin(); }
|
||||
|
||||
static inline ChildIteratorType child_end(NodeType* N)
|
||||
{ return N->pred_end(); }
|
||||
};
|
||||
|
||||
template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > {
|
||||
typedef const ::clang::CFGBlock NodeType;
|
||||
typedef ::clang::CFGBlock::const_pred_iterator ChildIteratorType;
|
||||
|
@ -800,37 +883,55 @@ template <> struct GraphTraits<Inverse<const ::clang::CFGBlock*> > {
|
|||
template <> struct GraphTraits< ::clang::CFG* >
|
||||
: public GraphTraits< ::clang::CFGBlock *> {
|
||||
|
||||
typedef ::clang::CFG::iterator nodes_iterator;
|
||||
typedef ::clang::CFG::graph_iterator nodes_iterator;
|
||||
|
||||
static NodeType *getEntryNode(::clang::CFG* F) { return &F->getEntry(); }
|
||||
static nodes_iterator nodes_begin(::clang::CFG* F) { return F->begin(); }
|
||||
static nodes_iterator nodes_end(::clang::CFG* F) { return F->end(); }
|
||||
static NodeType *getEntryNode(::clang::CFG* F) { return &F->getEntry(); }
|
||||
static nodes_iterator nodes_begin(::clang::CFG* F) { return F->nodes_begin();}
|
||||
static nodes_iterator nodes_end(::clang::CFG* F) { return F->nodes_end(); }
|
||||
static unsigned size(::clang::CFG* F) { return F->size(); }
|
||||
};
|
||||
|
||||
template <> struct GraphTraits<const ::clang::CFG* >
|
||||
: public GraphTraits<const ::clang::CFGBlock *> {
|
||||
|
||||
typedef ::clang::CFG::const_iterator nodes_iterator;
|
||||
typedef ::clang::CFG::const_graph_iterator nodes_iterator;
|
||||
|
||||
static NodeType *getEntryNode( const ::clang::CFG* F) {
|
||||
return &F->getEntry();
|
||||
}
|
||||
static nodes_iterator nodes_begin( const ::clang::CFG* F) {
|
||||
return F->begin();
|
||||
return F->nodes_begin();
|
||||
}
|
||||
static nodes_iterator nodes_end( const ::clang::CFG* F) {
|
||||
return F->end();
|
||||
return F->nodes_end();
|
||||
}
|
||||
static unsigned size(const ::clang::CFG* F) {
|
||||
return F->size();
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct GraphTraits<Inverse< ::clang::CFG*> >
|
||||
: public GraphTraits<Inverse< ::clang::CFGBlock*> > {
|
||||
|
||||
typedef ::clang::CFG::graph_iterator nodes_iterator;
|
||||
|
||||
static NodeType *getEntryNode( ::clang::CFG* F) { return &F->getExit(); }
|
||||
static nodes_iterator nodes_begin( ::clang::CFG* F) {return F->nodes_begin();}
|
||||
static nodes_iterator nodes_end( ::clang::CFG* F) { return F->nodes_end(); }
|
||||
};
|
||||
|
||||
template <> struct GraphTraits<Inverse<const ::clang::CFG*> >
|
||||
: public GraphTraits<Inverse<const ::clang::CFGBlock*> > {
|
||||
|
||||
typedef ::clang::CFG::const_iterator nodes_iterator;
|
||||
typedef ::clang::CFG::const_graph_iterator nodes_iterator;
|
||||
|
||||
static NodeType *getEntryNode(const ::clang::CFG* F) { return &F->getExit(); }
|
||||
static nodes_iterator nodes_begin(const ::clang::CFG* F) { return F->begin();}
|
||||
static nodes_iterator nodes_end(const ::clang::CFG* F) { return F->end(); }
|
||||
static nodes_iterator nodes_begin(const ::clang::CFG* F) {
|
||||
return F->nodes_begin();
|
||||
}
|
||||
static nodes_iterator nodes_end(const ::clang::CFG* F) {
|
||||
return F->nodes_end();
|
||||
}
|
||||
};
|
||||
} // end llvm namespace
|
||||
#endif
|
||||
|
|
|
@ -3039,7 +3039,7 @@ CFGBlock *CFG::createBlock() {
|
|||
|
||||
// Create the block.
|
||||
CFGBlock *Mem = getAllocator().Allocate<CFGBlock>();
|
||||
new (Mem) CFGBlock(NumBlockIDs++, BlkBVC);
|
||||
new (Mem) CFGBlock(NumBlockIDs++, BlkBVC, this);
|
||||
Blocks.push_back(Mem, BlkBVC);
|
||||
|
||||
// If this is the first block, set it as the Entry and Exit.
|
||||
|
|
|
@ -6,7 +6,6 @@ add_clang_library(clangAnalysis
|
|||
CFGReachabilityAnalysis.cpp
|
||||
CFGStmtMap.cpp
|
||||
CocoaConventions.cpp
|
||||
Dominators.cpp
|
||||
FormatString.cpp
|
||||
LiveVariables.cpp
|
||||
PostOrderCFGView.cpp
|
||||
|
|
|
@ -1,160 +0,0 @@
|
|||
//==- 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";
|
||||
}
|
||||
}
|
||||
|
|
@ -30,8 +30,8 @@ public:
|
|||
void checkASTCodeBody(const Decl *D, AnalysisManager& mgr,
|
||||
BugReporter &BR) const {
|
||||
if (AnalysisDeclContext *AC = mgr.getAnalysisDeclContext(D)) {
|
||||
DominatorTree dom(*AC);
|
||||
dom.BuildDominatorTree();
|
||||
DominatorTree dom;
|
||||
dom.buildDominatorTree(*AC);
|
||||
dom.dump();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue