Merge CallGraph and BasicCallGraph.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@193734 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Rafael Espindola
2013-10-31 03:03:55 +00:00
parent 93324a6793
commit c143c7573b
11 changed files with 138 additions and 217 deletions

View File

@ -69,13 +69,36 @@ class CallGraphNode;
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
// CallGraph class definition // CallGraph class definition
// //
class CallGraph { class CallGraph : public ModulePass {
protected:
Module *Mod; // The module this call graph represents Module *Mod; // The module this call graph represents
typedef std::map<const Function *, CallGraphNode *> FunctionMapTy; typedef std::map<const Function *, CallGraphNode *> FunctionMapTy;
FunctionMapTy FunctionMap; // Map from a function to its node FunctionMapTy FunctionMap; // Map from a function to its node
// Root is root of the call graph, or the external node if a 'main' function
// couldn't be found.
//
CallGraphNode *Root;
// ExternalCallingNode - This node has edges to all external functions and
// those internal functions that have their address taken.
CallGraphNode *ExternalCallingNode;
// CallsExternalNode - This node has edges to it from all functions making
// indirect calls or calling an external function.
CallGraphNode *CallsExternalNode;
/// Replace the function represented by this node by another.
/// This does not rescan the body of the function, so it is suitable when
/// splicing the body of one function to another while also updating all
/// callers from the old function to the new.
///
void spliceFunction(const Function *From, const Function *To);
// Add a function to the call graph, and link the node to all of the functions
// that it calls.
void addToCallGraph(Function *F);
public: public:
static char ID; // Class identification, replacement for typeinfo static char ID; // Class identification, replacement for typeinfo
//===--------------------------------------------------------------------- //===---------------------------------------------------------------------
@ -107,15 +130,14 @@ public:
} }
/// Returns the CallGraphNode which is used to represent undetermined calls /// Returns the CallGraphNode which is used to represent undetermined calls
/// into the callgraph. Override this if you want behavioral inheritance. /// into the callgraph.
virtual CallGraphNode* getExternalCallingNode() const { return 0; } CallGraphNode *getExternalCallingNode() const { return ExternalCallingNode; }
virtual CallGraphNode* getCallsExternalNode() const { return 0; } CallGraphNode *getCallsExternalNode() const { return CallsExternalNode; }
/// Return the root/main method in the module, or some other root node, such /// Return the root/main method in the module, or some other root node, such
/// as the externalcallingnode. Overload these if you behavioral /// as the externalcallingnode.
/// inheritance. CallGraphNode *getRoot() { return Root; }
virtual CallGraphNode* getRoot() { return 0; } const CallGraphNode *getRoot() const { return Root; }
virtual const CallGraphNode* getRoot() const { return 0; }
//===--------------------------------------------------------------------- //===---------------------------------------------------------------------
// Functions to keep a call graph up to date with a function that has been // Functions to keep a call graph up to date with a function that has been
@ -129,41 +151,20 @@ public:
/// do this is to dropAllReferences before calling this. /// do this is to dropAllReferences before calling this.
/// ///
Function *removeFunctionFromModule(CallGraphNode *CGN); Function *removeFunctionFromModule(CallGraphNode *CGN);
Function *removeFunctionFromModule(Function *F) {
return removeFunctionFromModule((*this)[F]);
}
/// getOrInsertFunction - This method is identical to calling operator[], but /// getOrInsertFunction - This method is identical to calling operator[], but
/// it will insert a new CallGraphNode for the specified function if one does /// it will insert a new CallGraphNode for the specified function if one does
/// not already exist. /// not already exist.
CallGraphNode *getOrInsertFunction(const Function *F); CallGraphNode *getOrInsertFunction(const Function *F);
/// spliceFunction - Replace the function represented by this node by another. CallGraph();
/// This does not rescan the body of the function, so it is suitable when virtual ~CallGraph() { releaseMemory(); }
/// splicing the body of one function to another while also updating all virtual void getAnalysisUsage(AnalysisUsage &AU) const;
/// callers from the old function to the new. virtual bool runOnModule(Module &M);
/// virtual void releaseMemory();
void spliceFunction(const Function *From, const Function *To);
//===--------------------------------------------------------------------- void print(raw_ostream &o, const Module *) const;
// Pass infrastructure interface glue code.
//
protected:
CallGraph() {}
public:
virtual ~CallGraph() { }
/// initialize - Call this method before calling other methods,
/// re/initializes the state of the CallGraph.
///
void initialize(Module &M);
void print(raw_ostream &o, Module *) const;
void dump() const; void dump() const;
protected:
// destroy - Release memory for the call graph
virtual void destroy();
}; };
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//

View File

@ -72,7 +72,7 @@ void initializeAlwaysInlinerPass(PassRegistry&);
void initializeArgPromotionPass(PassRegistry&); void initializeArgPromotionPass(PassRegistry&);
void initializeBarrierNoopPass(PassRegistry&); void initializeBarrierNoopPass(PassRegistry&);
void initializeBasicAliasAnalysisPass(PassRegistry&); void initializeBasicAliasAnalysisPass(PassRegistry&);
void initializeBasicCallGraphPass(PassRegistry&); void initializeCallGraphPass(PassRegistry&);
void initializeBasicTTIPass(PassRegistry&); void initializeBasicTTIPass(PassRegistry&);
void initializeBlockExtractorPassPass(PassRegistry&); void initializeBlockExtractorPassPass(PassRegistry&);
void initializeBlockFrequencyInfoPass(PassRegistry&); void initializeBlockFrequencyInfoPass(PassRegistry&);
@ -90,7 +90,6 @@ void initializeFlattenCFGPassPass(PassRegistry&);
void initializeStructurizeCFGPass(PassRegistry&); void initializeStructurizeCFGPass(PassRegistry&);
void initializeCFGViewerPass(PassRegistry&); void initializeCFGViewerPass(PassRegistry&);
void initializeCalculateSpillWeightsPass(PassRegistry&); void initializeCalculateSpillWeightsPass(PassRegistry&);
void initializeCallGraphAnalysisGroup(PassRegistry&);
void initializeCodeGenPreparePass(PassRegistry&); void initializeCodeGenPreparePass(PassRegistry&);
void initializeConstantMergePass(PassRegistry&); void initializeConstantMergePass(PassRegistry&);
void initializeConstantPropagationPass(PassRegistry&); void initializeConstantPropagationPass(PassRegistry&);

View File

@ -6,11 +6,6 @@
// License. See LICENSE.TXT for details. // License. See LICENSE.TXT for details.
// //
//===----------------------------------------------------------------------===// //===----------------------------------------------------------------------===//
//
// This file implements the CallGraph class and provides the BasicCallGraph
// default implementation.
//
//===----------------------------------------------------------------------===//
#include "llvm/Analysis/CallGraph.h" #include "llvm/Analysis/CallGraph.h"
#include "llvm/IR/Instructions.h" #include "llvm/IR/Instructions.h"
@ -21,101 +16,12 @@
#include "llvm/Support/raw_ostream.h" #include "llvm/Support/raw_ostream.h"
using namespace llvm; using namespace llvm;
namespace { CallGraph::CallGraph()
: ModulePass(ID), Root(0), ExternalCallingNode(0), CallsExternalNode(0) {
//===----------------------------------------------------------------------===// initializeCallGraphPass(*PassRegistry::getPassRegistry());
// BasicCallGraph class definition
//
class BasicCallGraph : public ModulePass, public CallGraph {
// Root is root of the call graph, or the external node if a 'main' function
// couldn't be found.
//
CallGraphNode *Root;
// ExternalCallingNode - This node has edges to all external functions and
// those internal functions that have their address taken.
CallGraphNode *ExternalCallingNode;
// CallsExternalNode - This node has edges to it from all functions making
// indirect calls or calling an external function.
CallGraphNode *CallsExternalNode;
public:
static char ID; // Class identification, replacement for typeinfo
BasicCallGraph() : ModulePass(ID), Root(0),
ExternalCallingNode(0), CallsExternalNode(0) {
initializeBasicCallGraphPass(*PassRegistry::getPassRegistry());
}
~BasicCallGraph() {
destroy();
} }
// runOnModule - Compute the call graph for the specified module. void CallGraph::addToCallGraph(Function *F) {
virtual bool runOnModule(Module &M) {
CallGraph::initialize(M);
ExternalCallingNode = getOrInsertFunction(0);
assert(!CallsExternalNode);
CallsExternalNode = new CallGraphNode(0);
Root = 0;
// Add every function to the call graph.
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
addToCallGraph(I);
// If we didn't find a main function, use the external call graph node
if (Root == 0) Root = ExternalCallingNode;
return false;
}
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesAll();
}
virtual void print(raw_ostream &OS, const Module *) const {
OS << "CallGraph Root is: ";
if (Function *F = getRoot()->getFunction())
OS << F->getName() << "\n";
else {
OS << "<<null function: 0x" << getRoot() << ">>\n";
}
CallGraph::print(OS, 0);
}
virtual void releaseMemory() {
destroy();
}
/// getAdjustedAnalysisPointer - This method is used when a pass implements
/// an analysis interface through multiple inheritance. If needed, it should
/// override this to adjust the this pointer as needed for the specified pass
/// info.
virtual void *getAdjustedAnalysisPointer(AnalysisID PI) {
if (PI == &CallGraph::ID)
return (CallGraph*)this;
return this;
}
CallGraphNode* getExternalCallingNode() const { return ExternalCallingNode; }
CallGraphNode* getCallsExternalNode() const { return CallsExternalNode; }
// getRoot - Return the root of the call graph, which is either main, or if
// main cannot be found, the external node.
//
CallGraphNode *getRoot() { return Root; }
const CallGraphNode *getRoot() const { return Root; }
private:
//===---------------------------------------------------------------------
// Implementation of CallGraph construction
//
// addToCallGraph - Add a function to the call graph, and link the node to all
// of the functions that it calls.
//
void addToCallGraph(Function *F) {
CallGraphNode *Node = getOrInsertFunction(F); CallGraphNode *Node = getOrInsertFunction(F);
// If this function has external linkage, anything could call it. // If this function has external linkage, anything could call it.
@ -142,8 +48,8 @@ private:
// Look for calls by this function. // Look for calls by this function.
for (Function::iterator BB = F->begin(), BBE = F->end(); BB != BBE; ++BB) for (Function::iterator BB = F->begin(), BBE = F->end(); BB != BBE; ++BB)
for (BasicBlock::iterator II = BB->begin(), IE = BB->end(); for (BasicBlock::iterator II = BB->begin(), IE = BB->end(); II != IE;
II != IE; ++II) { ++II) {
CallSite CS(cast<Value>(II)); CallSite CS(cast<Value>(II));
if (CS) { if (CS) {
const Function *Callee = CS.getCalledFunction(); const Function *Callee = CS.getCalledFunction();
@ -156,34 +62,43 @@ private:
} }
} }
// void CallGraph::getAnalysisUsage(AnalysisUsage &AU) const {
// destroy - Release memory for the call graph AU.setPreservesAll();
virtual void destroy() { }
bool CallGraph::runOnModule(Module &M) {
Mod = &M;
ExternalCallingNode = getOrInsertFunction(0);
assert(!CallsExternalNode);
CallsExternalNode = new CallGraphNode(0);
Root = 0;
// Add every function to the call graph.
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
addToCallGraph(I);
// If we didn't find a main function, use the external call graph node
if (Root == 0)
Root = ExternalCallingNode;
return false;
}
INITIALIZE_PASS(CallGraph, "basiccg", "CallGraph Construction", false, true)
char CallGraph::ID = 0;
void CallGraph::releaseMemory() {
/// CallsExternalNode is not in the function map, delete it explicitly. /// CallsExternalNode is not in the function map, delete it explicitly.
if (CallsExternalNode) { if (CallsExternalNode) {
CallsExternalNode->allReferencesDropped(); CallsExternalNode->allReferencesDropped();
delete CallsExternalNode; delete CallsExternalNode;
CallsExternalNode = 0; CallsExternalNode = 0;
} }
CallGraph::destroy();
}
};
} //End anonymous namespace if (FunctionMap.empty())
return;
INITIALIZE_ANALYSIS_GROUP(CallGraph, "Call Graph", BasicCallGraph)
INITIALIZE_AG_PASS(BasicCallGraph, CallGraph, "basiccg",
"Basic CallGraph Construction", false, true, true)
char CallGraph::ID = 0;
char BasicCallGraph::ID = 0;
void CallGraph::initialize(Module &M) {
Mod = &M;
}
void CallGraph::destroy() {
if (FunctionMap.empty()) return;
// Reset all node's use counts to zero before deleting them to prevent an // Reset all node's use counts to zero before deleting them to prevent an
// assertion from firing. // assertion from firing.
@ -199,7 +114,14 @@ void CallGraph::destroy() {
FunctionMap.clear(); FunctionMap.clear();
} }
void CallGraph::print(raw_ostream &OS, Module*) const { void CallGraph::print(raw_ostream &OS, const Module*) const {
OS << "CallGraph Root is: ";
if (Function *F = Root->getFunction())
OS << F->getName() << "\n";
else {
OS << "<<null function: 0x" << Root << ">>\n";
}
for (CallGraph::const_iterator I = begin(), E = end(); I != E; ++I) for (CallGraph::const_iterator I = begin(), E = end(); I != E; ++I)
I->second->print(OS); I->second->print(OS);
} }

View File

@ -189,7 +189,7 @@ char GlobalsModRef::ID = 0;
INITIALIZE_AG_PASS_BEGIN(GlobalsModRef, AliasAnalysis, INITIALIZE_AG_PASS_BEGIN(GlobalsModRef, AliasAnalysis,
"globalsmodref-aa", "Simple mod/ref analysis for globals", "globalsmodref-aa", "Simple mod/ref analysis for globals",
false, true, false) false, true, false)
INITIALIZE_AG_DEPENDENCY(CallGraph) INITIALIZE_PASS_DEPENDENCY(CallGraph)
INITIALIZE_AG_PASS_END(GlobalsModRef, AliasAnalysis, INITIALIZE_AG_PASS_END(GlobalsModRef, AliasAnalysis,
"globalsmodref-aa", "Simple mod/ref analysis for globals", "globalsmodref-aa", "Simple mod/ref analysis for globals",
false, true, false) false, true, false)

View File

@ -19,8 +19,7 @@ using namespace llvm;
/// initializeIPA - Initialize all passes linked into the IPA library. /// initializeIPA - Initialize all passes linked into the IPA library.
void llvm::initializeIPA(PassRegistry &Registry) { void llvm::initializeIPA(PassRegistry &Registry) {
initializeBasicCallGraphPass(Registry); initializeCallGraphPass(Registry);
initializeCallGraphAnalysisGroup(Registry);
initializeCallGraphPrinterPass(Registry); initializeCallGraphPrinterPass(Registry);
initializeCallGraphViewerPass(Registry); initializeCallGraphViewerPass(Registry);
initializeFindUsedTypesPass(Registry); initializeFindUsedTypesPass(Registry);

View File

@ -88,7 +88,7 @@ char ArgPromotion::ID = 0;
INITIALIZE_PASS_BEGIN(ArgPromotion, "argpromotion", INITIALIZE_PASS_BEGIN(ArgPromotion, "argpromotion",
"Promote 'by reference' arguments to scalars", false, false) "Promote 'by reference' arguments to scalars", false, false)
INITIALIZE_AG_DEPENDENCY(AliasAnalysis) INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
INITIALIZE_AG_DEPENDENCY(CallGraph) INITIALIZE_PASS_DEPENDENCY(CallGraph)
INITIALIZE_PASS_END(ArgPromotion, "argpromotion", INITIALIZE_PASS_END(ArgPromotion, "argpromotion",
"Promote 'by reference' arguments to scalars", false, false) "Promote 'by reference' arguments to scalars", false, false)

View File

@ -137,7 +137,7 @@ char FunctionAttrs::ID = 0;
INITIALIZE_PASS_BEGIN(FunctionAttrs, "functionattrs", INITIALIZE_PASS_BEGIN(FunctionAttrs, "functionattrs",
"Deduce function attributes", false, false) "Deduce function attributes", false, false)
INITIALIZE_AG_DEPENDENCY(AliasAnalysis) INITIALIZE_AG_DEPENDENCY(AliasAnalysis)
INITIALIZE_AG_DEPENDENCY(CallGraph) INITIALIZE_PASS_DEPENDENCY(CallGraph)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfo) INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfo)
INITIALIZE_PASS_END(FunctionAttrs, "functionattrs", INITIALIZE_PASS_END(FunctionAttrs, "functionattrs",
"Deduce function attributes", false, false) "Deduce function attributes", false, false)

View File

@ -63,7 +63,7 @@ public:
char AlwaysInliner::ID = 0; char AlwaysInliner::ID = 0;
INITIALIZE_PASS_BEGIN(AlwaysInliner, "always-inline", INITIALIZE_PASS_BEGIN(AlwaysInliner, "always-inline",
"Inliner for always_inline functions", false, false) "Inliner for always_inline functions", false, false)
INITIALIZE_AG_DEPENDENCY(CallGraph) INITIALIZE_PASS_DEPENDENCY(CallGraph)
INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis) INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis)
INITIALIZE_PASS_END(AlwaysInliner, "always-inline", INITIALIZE_PASS_END(AlwaysInliner, "always-inline",
"Inliner for always_inline functions", false, false) "Inliner for always_inline functions", false, false)

View File

@ -61,7 +61,7 @@ public:
char SimpleInliner::ID = 0; char SimpleInliner::ID = 0;
INITIALIZE_PASS_BEGIN(SimpleInliner, "inline", INITIALIZE_PASS_BEGIN(SimpleInliner, "inline",
"Function Integration/Inlining", false, false) "Function Integration/Inlining", false, false)
INITIALIZE_AG_DEPENDENCY(CallGraph) INITIALIZE_PASS_DEPENDENCY(CallGraph)
INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis) INITIALIZE_PASS_DEPENDENCY(InlineCostAnalysis)
INITIALIZE_PASS_END(SimpleInliner, "inline", INITIALIZE_PASS_END(SimpleInliner, "inline",
"Function Integration/Inlining", false, false) "Function Integration/Inlining", false, false)

View File

@ -51,7 +51,7 @@ namespace {
char PruneEH::ID = 0; char PruneEH::ID = 0;
INITIALIZE_PASS_BEGIN(PruneEH, "prune-eh", INITIALIZE_PASS_BEGIN(PruneEH, "prune-eh",
"Remove unused exception handling info", false, false) "Remove unused exception handling info", false, false)
INITIALIZE_AG_DEPENDENCY(CallGraph) INITIALIZE_PASS_DEPENDENCY(CallGraph)
INITIALIZE_PASS_END(PruneEH, "prune-eh", INITIALIZE_PASS_END(PruneEH, "prune-eh",
"Remove unused exception handling info", false, false) "Remove unused exception handling info", false, false)

View File

@ -543,7 +543,7 @@ namespace llvm {
INITIALIZE_PASS(ModuleNDM, "mndm", "mndm", false, false) INITIALIZE_PASS(ModuleNDM, "mndm", "mndm", false, false)
INITIALIZE_PASS_BEGIN(CGPass, "cgp","cgp", false, false) INITIALIZE_PASS_BEGIN(CGPass, "cgp","cgp", false, false)
INITIALIZE_AG_DEPENDENCY(CallGraph) INITIALIZE_PASS_DEPENDENCY(CallGraph)
INITIALIZE_PASS_END(CGPass, "cgp","cgp", false, false) INITIALIZE_PASS_END(CGPass, "cgp","cgp", false, false)
INITIALIZE_PASS(FPass, "fp","fp", false, false) INITIALIZE_PASS(FPass, "fp","fp", false, false)
INITIALIZE_PASS_BEGIN(LPass, "lp","lp", false, false) INITIALIZE_PASS_BEGIN(LPass, "lp","lp", false, false)