mirror of
https://github.com/RPCS3/llvm.git
synced 2024-11-24 12:20:00 +00:00
[PM] Split the CallGraph out from the ModulePass which creates the
CallGraph. This makes the CallGraph a totally generic analysis object that is the container for the graph data structure and the primary interface for querying and manipulating it. The pass logic is separated into its own class. For compatibility reasons, the pass provides wrapper methods for most of the methods on CallGraph -- they all just forward. This will allow the new pass manager infrastructure to provide its own analysis pass that constructs the same CallGraph object and makes it available. The idea is that in the new pass manager, the analysis pass's 'run' method returns a concrete analysis 'result'. Here, that result is a 'CallGraph'. The 'run' method will typically do only minimal work, deferring much of the work into the implementation of the result object in order to be lazy about computing things, but when (like DomTree) there is *some* up-front computation, the analysis does it prior to handing the result back to the querying pass. I know some of this is fairly ugly. I'm happy to change it around if folks can suggest a cleaner interim state, but there is going to be some amount of unavoidable ugliness during the transition period. The good thing is that this is very limited and will naturally go away when the old pass infrastructure goes away. It won't hang around to bother us later. Next up is the initial new-PM-style call graph analysis. =] git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@195722 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
bdd300b22c
commit
54fec07ec0
@ -53,6 +53,7 @@
|
|||||||
#define LLVM_ANALYSIS_CALLGRAPH_H
|
#define LLVM_ANALYSIS_CALLGRAPH_H
|
||||||
|
|
||||||
#include "llvm/ADT/GraphTraits.h"
|
#include "llvm/ADT/GraphTraits.h"
|
||||||
|
#include "llvm/ADT/OwningPtr.h"
|
||||||
#include "llvm/ADT/STLExtras.h"
|
#include "llvm/ADT/STLExtras.h"
|
||||||
#include "llvm/IR/Function.h"
|
#include "llvm/IR/Function.h"
|
||||||
#include "llvm/Pass.h"
|
#include "llvm/Pass.h"
|
||||||
@ -67,15 +68,13 @@ class Function;
|
|||||||
class Module;
|
class Module;
|
||||||
class CallGraphNode;
|
class CallGraphNode;
|
||||||
|
|
||||||
/// \brief The basic data container for the call graph and the \c ModulePass
|
/// \brief The basic data container for the call graph of a \c Module of IR.
|
||||||
/// which produces it.
|
|
||||||
///
|
///
|
||||||
/// This class exposes both the interface to the call graph container and the
|
/// This class exposes both the interface to the call graph for a module of IR.
|
||||||
/// module pass which runs over a module of IR and produces the call graph.
|
|
||||||
///
|
///
|
||||||
/// The core call graph itself can also be updated to reflect changes to the IR.
|
/// The core call graph itself can also be updated to reflect changes to the IR.
|
||||||
class CallGraph : public ModulePass {
|
class CallGraph {
|
||||||
Module *M;
|
Module &M;
|
||||||
|
|
||||||
typedef std::map<const Function *, CallGraphNode *> FunctionMapTy;
|
typedef std::map<const Function *, CallGraphNode *> FunctionMapTy;
|
||||||
|
|
||||||
@ -106,13 +105,17 @@ class CallGraph : public ModulePass {
|
|||||||
void addToCallGraph(Function *F);
|
void addToCallGraph(Function *F);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static char ID; // Class identification, replacement for typeinfo
|
CallGraph(Module &M);
|
||||||
|
~CallGraph();
|
||||||
|
|
||||||
|
void print(raw_ostream &OS) const;
|
||||||
|
void dump() const;
|
||||||
|
|
||||||
typedef FunctionMapTy::iterator iterator;
|
typedef FunctionMapTy::iterator iterator;
|
||||||
typedef FunctionMapTy::const_iterator const_iterator;
|
typedef FunctionMapTy::const_iterator const_iterator;
|
||||||
|
|
||||||
/// \brief Returns the module the call graph corresponds to.
|
/// \brief Returns the module the call graph corresponds to.
|
||||||
Module &getModule() const { return *M; }
|
Module &getModule() const { return M; }
|
||||||
|
|
||||||
inline iterator begin() { return FunctionMap.begin(); }
|
inline iterator begin() { return FunctionMap.begin(); }
|
||||||
inline iterator end() { return FunctionMap.end(); }
|
inline iterator end() { return FunctionMap.end(); }
|
||||||
@ -160,20 +163,6 @@ public:
|
|||||||
/// \brief Similar to operator[], but this will insert a new CallGraphNode for
|
/// \brief Similar to operator[], but this will insert a new CallGraphNode for
|
||||||
/// \c F if one does not already exist.
|
/// \c F if one does not already exist.
|
||||||
CallGraphNode *getOrInsertFunction(const Function *F);
|
CallGraphNode *getOrInsertFunction(const Function *F);
|
||||||
|
|
||||||
CallGraph();
|
|
||||||
virtual ~CallGraph() { releaseMemory(); }
|
|
||||||
|
|
||||||
//===---------------------------------------------------------------------
|
|
||||||
// Implementation of the ModulePass interface needed here.
|
|
||||||
//
|
|
||||||
|
|
||||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
|
||||||
virtual bool runOnModule(Module &M);
|
|
||||||
virtual void releaseMemory();
|
|
||||||
|
|
||||||
void print(raw_ostream &o, const Module *) const;
|
|
||||||
void dump() const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief A node in the call graph for a module.
|
/// \brief A node in the call graph for a module.
|
||||||
@ -303,6 +292,94 @@ public:
|
|||||||
void allReferencesDropped() { NumReferences = 0; }
|
void allReferencesDropped() { NumReferences = 0; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \brief The \c ModulePass which wraps up a \c CallGraph and the logic to
|
||||||
|
/// build it.
|
||||||
|
///
|
||||||
|
/// This class exposes both the interface to the call graph container and the
|
||||||
|
/// module pass which runs over a module of IR and produces the call graph. The
|
||||||
|
/// call graph interface is entirelly a wrapper around a \c CallGraph object
|
||||||
|
/// which is stored internally for each module.
|
||||||
|
class CallGraphWrapperPass : public ModulePass {
|
||||||
|
OwningPtr<CallGraph> G;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static char ID; // Class identification, replacement for typeinfo
|
||||||
|
|
||||||
|
CallGraphWrapperPass();
|
||||||
|
virtual ~CallGraphWrapperPass();
|
||||||
|
|
||||||
|
/// \brief The internal \c CallGraph around which the rest of this interface
|
||||||
|
/// is wrapped.
|
||||||
|
const CallGraph &getCallGraph() const { return *G; }
|
||||||
|
CallGraph &getCallGraph() { return *G; }
|
||||||
|
|
||||||
|
typedef CallGraph::iterator iterator;
|
||||||
|
typedef CallGraph::const_iterator const_iterator;
|
||||||
|
|
||||||
|
/// \brief Returns the module the call graph corresponds to.
|
||||||
|
Module &getModule() const { return G->getModule(); }
|
||||||
|
|
||||||
|
inline iterator begin() { return G->begin(); }
|
||||||
|
inline iterator end() { return G->end(); }
|
||||||
|
inline const_iterator begin() const { return G->begin(); }
|
||||||
|
inline const_iterator end() const { return G->end(); }
|
||||||
|
|
||||||
|
/// \brief Returns the call graph node for the provided function.
|
||||||
|
inline const CallGraphNode *operator[](const Function *F) const {
|
||||||
|
return (*G)[F];
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Returns the call graph node for the provided function.
|
||||||
|
inline CallGraphNode *operator[](const Function *F) { return (*G)[F]; }
|
||||||
|
|
||||||
|
/// \brief Returns the \c CallGraphNode which is used to represent
|
||||||
|
/// undetermined calls into the callgraph.
|
||||||
|
CallGraphNode *getExternalCallingNode() const {
|
||||||
|
return G->getExternalCallingNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
CallGraphNode *getCallsExternalNode() const {
|
||||||
|
return G->getCallsExternalNode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Returns the root/main method in the module, or some other root
|
||||||
|
/// node, such as the externalcallingnode.
|
||||||
|
CallGraphNode *getRoot() { return G->getRoot(); }
|
||||||
|
const CallGraphNode *getRoot() const { return G->getRoot(); }
|
||||||
|
|
||||||
|
//===---------------------------------------------------------------------
|
||||||
|
// Functions to keep a call graph up to date with a function that has been
|
||||||
|
// modified.
|
||||||
|
//
|
||||||
|
|
||||||
|
/// \brief Unlink the function from this module, returning it.
|
||||||
|
///
|
||||||
|
/// Because this removes the function from the module, the call graph node is
|
||||||
|
/// destroyed. This is only valid if the function does not call any other
|
||||||
|
/// functions (ie, there are no edges in it's CGN). The easiest way to do
|
||||||
|
/// this is to dropAllReferences before calling this.
|
||||||
|
Function *removeFunctionFromModule(CallGraphNode *CGN) {
|
||||||
|
return G->removeFunctionFromModule(CGN);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// \brief Similar to operator[], but this will insert a new CallGraphNode for
|
||||||
|
/// \c F if one does not already exist.
|
||||||
|
CallGraphNode *getOrInsertFunction(const Function *F) {
|
||||||
|
return G->getOrInsertFunction(F);
|
||||||
|
}
|
||||||
|
|
||||||
|
//===---------------------------------------------------------------------
|
||||||
|
// Implementation of the ModulePass interface needed here.
|
||||||
|
//
|
||||||
|
|
||||||
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const;
|
||||||
|
virtual bool runOnModule(Module &M);
|
||||||
|
virtual void releaseMemory();
|
||||||
|
|
||||||
|
void print(raw_ostream &o, const Module *) const;
|
||||||
|
void dump() const;
|
||||||
|
};
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// GraphTraits specializations for call graphs so that they can be treated as
|
// GraphTraits specializations for call graphs so that they can be treated as
|
||||||
// graphs by the generic graph algorithms.
|
// graphs by the generic graph algorithms.
|
||||||
|
@ -73,7 +73,7 @@ void initializeArgPromotionPass(PassRegistry&);
|
|||||||
void initializeSampleProfileLoaderPass(PassRegistry&);
|
void initializeSampleProfileLoaderPass(PassRegistry&);
|
||||||
void initializeBarrierNoopPass(PassRegistry&);
|
void initializeBarrierNoopPass(PassRegistry&);
|
||||||
void initializeBasicAliasAnalysisPass(PassRegistry&);
|
void initializeBasicAliasAnalysisPass(PassRegistry&);
|
||||||
void initializeCallGraphPass(PassRegistry&);
|
void initializeCallGraphWrapperPassPass(PassRegistry &);
|
||||||
void initializeBasicTTIPass(PassRegistry&);
|
void initializeBasicTTIPass(PassRegistry&);
|
||||||
void initializeBlockExtractorPassPass(PassRegistry&);
|
void initializeBlockExtractorPassPass(PassRegistry&);
|
||||||
void initializeBlockFrequencyInfoPass(PassRegistry&);
|
void initializeBlockFrequencyInfoPass(PassRegistry&);
|
||||||
|
@ -16,9 +16,37 @@
|
|||||||
#include "llvm/Support/raw_ostream.h"
|
#include "llvm/Support/raw_ostream.h"
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
CallGraph::CallGraph()
|
//===----------------------------------------------------------------------===//
|
||||||
: ModulePass(ID), Root(0), ExternalCallingNode(0), CallsExternalNode(0) {
|
// Implementations of the CallGraph class methods.
|
||||||
initializeCallGraphPass(*PassRegistry::getPassRegistry());
|
//
|
||||||
|
|
||||||
|
CallGraph::CallGraph(Module &M)
|
||||||
|
: M(M), Root(0), ExternalCallingNode(getOrInsertFunction(0)),
|
||||||
|
CallsExternalNode(new CallGraphNode(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;
|
||||||
|
}
|
||||||
|
|
||||||
|
CallGraph::~CallGraph() {
|
||||||
|
// CallsExternalNode is not in the function map, delete it explicitly.
|
||||||
|
CallsExternalNode->allReferencesDropped();
|
||||||
|
delete CallsExternalNode;
|
||||||
|
|
||||||
|
// Reset all node's use counts to zero before deleting them to prevent an
|
||||||
|
// assertion from firing.
|
||||||
|
#ifndef NDEBUG
|
||||||
|
for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
|
||||||
|
I != E; ++I)
|
||||||
|
I->second->allReferencesDropped();
|
||||||
|
#endif
|
||||||
|
for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
|
||||||
|
I != E; ++I)
|
||||||
|
delete I->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallGraph::addToCallGraph(Function *F) {
|
void CallGraph::addToCallGraph(Function *F) {
|
||||||
@ -62,59 +90,7 @@ void CallGraph::addToCallGraph(Function *F) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CallGraph::getAnalysisUsage(AnalysisUsage &AU) const {
|
void CallGraph::print(raw_ostream &OS) const {
|
||||||
AU.setPreservesAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CallGraph::runOnModule(Module &M) {
|
|
||||||
this->M = &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.
|
|
||||||
if (CallsExternalNode) {
|
|
||||||
CallsExternalNode->allReferencesDropped();
|
|
||||||
delete CallsExternalNode;
|
|
||||||
CallsExternalNode = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FunctionMap.empty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
// Reset all node's use counts to zero before deleting them to prevent an
|
|
||||||
// assertion from firing.
|
|
||||||
#ifndef NDEBUG
|
|
||||||
for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
|
|
||||||
I != E; ++I)
|
|
||||||
I->second->allReferencesDropped();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
|
|
||||||
I != E; ++I)
|
|
||||||
delete I->second;
|
|
||||||
FunctionMap.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CallGraph::print(raw_ostream &OS, const Module*) const {
|
|
||||||
OS << "CallGraph Root is: ";
|
OS << "CallGraph Root is: ";
|
||||||
if (Function *F = Root->getFunction())
|
if (Function *F = Root->getFunction())
|
||||||
OS << F->getName() << "\n";
|
OS << F->getName() << "\n";
|
||||||
@ -125,15 +101,10 @@ void CallGraph::print(raw_ostream &OS, const Module*) const {
|
|||||||
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);
|
||||||
}
|
}
|
||||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
|
||||||
void CallGraph::dump() const {
|
|
||||||
print(dbgs(), 0);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
||||||
// Implementations of public modification methods
|
void CallGraph::dump() const { print(dbgs()); }
|
||||||
//
|
#endif
|
||||||
|
|
||||||
// removeFunctionFromModule - Unlink the function from this module, returning
|
// removeFunctionFromModule - Unlink the function from this module, returning
|
||||||
// it. Because this removes the function from the module, the call graph node
|
// it. Because this removes the function from the module, the call graph node
|
||||||
@ -148,7 +119,7 @@ Function *CallGraph::removeFunctionFromModule(CallGraphNode *CGN) {
|
|||||||
delete CGN; // Delete the call graph node for this func
|
delete CGN; // Delete the call graph node for this func
|
||||||
FunctionMap.erase(F); // Remove the call graph node from the map
|
FunctionMap.erase(F); // Remove the call graph node from the map
|
||||||
|
|
||||||
M->getFunctionList().remove(F);
|
M.getFunctionList().remove(F);
|
||||||
return F;
|
return F;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,12 +143,17 @@ void CallGraph::spliceFunction(const Function *From, const Function *To) {
|
|||||||
// not already exist.
|
// not already exist.
|
||||||
CallGraphNode *CallGraph::getOrInsertFunction(const Function *F) {
|
CallGraphNode *CallGraph::getOrInsertFunction(const Function *F) {
|
||||||
CallGraphNode *&CGN = FunctionMap[F];
|
CallGraphNode *&CGN = FunctionMap[F];
|
||||||
if (CGN) return CGN;
|
if (CGN)
|
||||||
|
return CGN;
|
||||||
assert((!F || F->getParent() == M) && "Function not in current module!");
|
|
||||||
|
assert((!F || F->getParent() == &M) && "Function not in current module!");
|
||||||
return CGN = new CallGraphNode(const_cast<Function*>(F));
|
return CGN = new CallGraphNode(const_cast<Function*>(F));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Implementations of the CallGraphNode class methods.
|
||||||
|
//
|
||||||
|
|
||||||
void CallGraphNode::print(raw_ostream &OS) const {
|
void CallGraphNode::print(raw_ostream &OS) const {
|
||||||
if (Function *F = getFunction())
|
if (Function *F = getFunction())
|
||||||
OS << "Call graph node for function: '" << F->getName() << "'";
|
OS << "Call graph node for function: '" << F->getName() << "'";
|
||||||
@ -260,5 +236,46 @@ void CallGraphNode::replaceCallEdge(CallSite CS,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// Implementations of the CallGraphWrapperPass class methods.
|
||||||
|
//
|
||||||
|
|
||||||
|
CallGraphWrapperPass::CallGraphWrapperPass() : ModulePass(ID) {
|
||||||
|
initializeCallGraphWrapperPassPass(*PassRegistry::getPassRegistry());
|
||||||
|
}
|
||||||
|
|
||||||
|
CallGraphWrapperPass::~CallGraphWrapperPass() {}
|
||||||
|
|
||||||
|
void CallGraphWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
|
AU.setPreservesAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CallGraphWrapperPass::runOnModule(Module &M) {
|
||||||
|
// All the real work is done in the constructor for the CallGraph.
|
||||||
|
G.reset(new CallGraph(M));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
INITIALIZE_PASS(CallGraphWrapperPass, "basiccg", "CallGraph Construction",
|
||||||
|
false, true)
|
||||||
|
|
||||||
|
char CallGraphWrapperPass::ID = 0;
|
||||||
|
|
||||||
|
void CallGraphWrapperPass::releaseMemory() { G.reset(0); }
|
||||||
|
|
||||||
|
void CallGraphWrapperPass::print(raw_ostream &OS, const Module *) const {
|
||||||
|
if (!G) {
|
||||||
|
OS << "No call graph has been built!\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Just delegate.
|
||||||
|
G->print(OS);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
||||||
|
void CallGraphWrapperPass::dump() const { print(dbgs(), 0); }
|
||||||
|
#endif
|
||||||
|
|
||||||
// Enuse that users of CallGraph.h also link with this file
|
// Enuse that users of CallGraph.h also link with this file
|
||||||
DEFINING_FILE_FOR(CallGraph)
|
DEFINING_FILE_FOR(CallGraph)
|
||||||
|
@ -60,7 +60,7 @@ public:
|
|||||||
/// Pass Manager itself does not invalidate any analysis info.
|
/// Pass Manager itself does not invalidate any analysis info.
|
||||||
void getAnalysisUsage(AnalysisUsage &Info) const {
|
void getAnalysisUsage(AnalysisUsage &Info) const {
|
||||||
// CGPassManager walks SCC and it needs CallGraph.
|
// CGPassManager walks SCC and it needs CallGraph.
|
||||||
Info.addRequired<CallGraph>();
|
Info.addRequired<CallGraphWrapperPass>();
|
||||||
Info.setPreservesAll();
|
Info.setPreservesAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -424,7 +424,7 @@ bool CGPassManager::RunAllPassesOnSCC(CallGraphSCC &CurSCC, CallGraph &CG,
|
|||||||
/// run - Execute all of the passes scheduled for execution. Keep track of
|
/// run - Execute all of the passes scheduled for execution. Keep track of
|
||||||
/// whether any of the passes modifies the module, and if so, return true.
|
/// whether any of the passes modifies the module, and if so, return true.
|
||||||
bool CGPassManager::runOnModule(Module &M) {
|
bool CGPassManager::runOnModule(Module &M) {
|
||||||
CallGraph &CG = getAnalysis<CallGraph>();
|
CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
|
||||||
bool Changed = doInitialization(CG);
|
bool Changed = doInitialization(CG);
|
||||||
|
|
||||||
// Walk the callgraph in bottom-up SCC order.
|
// Walk the callgraph in bottom-up SCC order.
|
||||||
@ -570,8 +570,8 @@ void CallGraphSCCPass::assignPassManager(PMStack &PMS,
|
|||||||
/// the call graph. If the derived class implements this method, it should
|
/// the call graph. If the derived class implements this method, it should
|
||||||
/// always explicitly call the implementation here.
|
/// always explicitly call the implementation here.
|
||||||
void CallGraphSCCPass::getAnalysisUsage(AnalysisUsage &AU) const {
|
void CallGraphSCCPass::getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
AU.addRequired<CallGraph>();
|
AU.addRequired<CallGraphWrapperPass>();
|
||||||
AU.addPreserved<CallGraph>();
|
AU.addPreserved<CallGraphWrapperPass>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,24 +35,38 @@ template <> struct DOTGraphTraits<CallGraph *> : public DefaultDOTGraphTraits {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct AnalysisCallGraphWrapperPassTraits {
|
||||||
|
static CallGraph *getGraph(CallGraphWrapperPass *P) {
|
||||||
|
return &P->getCallGraph();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // end llvm namespace
|
} // end llvm namespace
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct CallGraphViewer : public DOTGraphTraitsModuleViewer<CallGraph, true> {
|
struct CallGraphViewer
|
||||||
|
: public DOTGraphTraitsModuleViewer<CallGraphWrapperPass, true, CallGraph *,
|
||||||
|
AnalysisCallGraphWrapperPassTraits> {
|
||||||
static char ID;
|
static char ID;
|
||||||
|
|
||||||
CallGraphViewer()
|
CallGraphViewer()
|
||||||
: DOTGraphTraitsModuleViewer<CallGraph, true>("callgraph", ID) {
|
: DOTGraphTraitsModuleViewer<CallGraphWrapperPass, true, CallGraph *,
|
||||||
|
AnalysisCallGraphWrapperPassTraits>(
|
||||||
|
"callgraph", ID) {
|
||||||
initializeCallGraphViewerPass(*PassRegistry::getPassRegistry());
|
initializeCallGraphViewerPass(*PassRegistry::getPassRegistry());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct CallGraphPrinter : public DOTGraphTraitsModulePrinter<CallGraph, true> {
|
struct CallGraphPrinter : public DOTGraphTraitsModulePrinter<
|
||||||
|
CallGraphWrapperPass, true, CallGraph *,
|
||||||
|
AnalysisCallGraphWrapperPassTraits> {
|
||||||
static char ID;
|
static char ID;
|
||||||
|
|
||||||
CallGraphPrinter()
|
CallGraphPrinter()
|
||||||
: DOTGraphTraitsModulePrinter<CallGraph, true>("callgraph", ID) {
|
: DOTGraphTraitsModulePrinter<CallGraphWrapperPass, true, CallGraph *,
|
||||||
|
AnalysisCallGraphWrapperPassTraits>(
|
||||||
|
"callgraph", ID) {
|
||||||
initializeCallGraphPrinterPass(*PassRegistry::getPassRegistry());
|
initializeCallGraphPrinterPass(*PassRegistry::getPassRegistry());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -95,15 +95,19 @@ namespace {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool runOnModule(Module &M) {
|
bool runOnModule(Module &M) {
|
||||||
InitializeAliasAnalysis(this); // set up super class
|
InitializeAliasAnalysis(this);
|
||||||
AnalyzeGlobals(M); // find non-addr taken globals
|
|
||||||
AnalyzeCallGraph(getAnalysis<CallGraph>(), M); // Propagate on CG
|
// Find non-addr taken globals.
|
||||||
|
AnalyzeGlobals(M);
|
||||||
|
|
||||||
|
// Propagate on CG.
|
||||||
|
AnalyzeCallGraph(getAnalysis<CallGraphWrapperPass>().getCallGraph(), M);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
AliasAnalysis::getAnalysisUsage(AU);
|
AliasAnalysis::getAnalysisUsage(AU);
|
||||||
AU.addRequired<CallGraph>();
|
AU.addRequired<CallGraphWrapperPass>();
|
||||||
AU.setPreservesAll(); // Does not transform code
|
AU.setPreservesAll(); // Does not transform code
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -189,7 +193,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_PASS_DEPENDENCY(CallGraph)
|
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
|
||||||
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)
|
||||||
|
@ -19,7 +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) {
|
||||||
initializeCallGraphPass(Registry);
|
initializeCallGraphWrapperPassPass(Registry);
|
||||||
initializeCallGraphPrinterPass(Registry);
|
initializeCallGraphPrinterPass(Registry);
|
||||||
initializeCallGraphViewerPass(Registry);
|
initializeCallGraphViewerPass(Registry);
|
||||||
initializeFindUsedTypesPass(Registry);
|
initializeFindUsedTypesPass(Registry);
|
||||||
|
@ -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_PASS_DEPENDENCY(CallGraph)
|
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
|
||||||
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)
|
||||||
|
|
||||||
@ -621,8 +621,8 @@ CallGraphNode *ArgPromotion::DoPromotion(Function *F,
|
|||||||
|
|
||||||
// Get the callgraph information that we need to update to reflect our
|
// Get the callgraph information that we need to update to reflect our
|
||||||
// changes.
|
// changes.
|
||||||
CallGraph &CG = getAnalysis<CallGraph>();
|
CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
|
||||||
|
|
||||||
// Get a new callgraph node for NF.
|
// Get a new callgraph node for NF.
|
||||||
CallGraphNode *NF_CGN = CG.getOrInsertFunction(NF);
|
CallGraphNode *NF_CGN = CG.getOrInsertFunction(NF);
|
||||||
|
|
||||||
|
@ -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_PASS_DEPENDENCY(CallGraph)
|
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
|
||||||
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)
|
||||||
|
@ -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_PASS_DEPENDENCY(CallGraph)
|
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
|
||||||
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)
|
||||||
|
@ -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_PASS_DEPENDENCY(CallGraph)
|
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
|
||||||
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)
|
||||||
|
@ -395,7 +395,7 @@ static bool InlineHistoryIncludes(Function *F, int InlineHistoryID,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool Inliner::runOnSCC(CallGraphSCC &SCC) {
|
bool Inliner::runOnSCC(CallGraphSCC &SCC) {
|
||||||
CallGraph &CG = getAnalysis<CallGraph>();
|
CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
|
||||||
const DataLayout *TD = getAnalysisIfAvailable<DataLayout>();
|
const DataLayout *TD = getAnalysisIfAvailable<DataLayout>();
|
||||||
const TargetLibraryInfo *TLI = getAnalysisIfAvailable<TargetLibraryInfo>();
|
const TargetLibraryInfo *TLI = getAnalysisIfAvailable<TargetLibraryInfo>();
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ namespace {
|
|||||||
|
|
||||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
AU.setPreservesCFG();
|
AU.setPreservesCFG();
|
||||||
AU.addPreserved<CallGraph>();
|
AU.addPreserved<CallGraphWrapperPass>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
@ -127,7 +127,8 @@ static bool shouldInternalize(const GlobalValue &GV,
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool InternalizePass::runOnModule(Module &M) {
|
bool InternalizePass::runOnModule(Module &M) {
|
||||||
CallGraph *CG = getAnalysisIfAvailable<CallGraph>();
|
CallGraphWrapperPass *CGPass = getAnalysisIfAvailable<CallGraphWrapperPass>();
|
||||||
|
CallGraph *CG = CGPass ? &CGPass->getCallGraph() : 0;
|
||||||
CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : 0;
|
CallGraphNode *ExternalNode = CG ? CG->getExternalCallingNode() : 0;
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
|
|
||||||
|
@ -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_PASS_DEPENDENCY(CallGraph)
|
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
|
||||||
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)
|
||||||
|
|
||||||
@ -60,7 +60,7 @@ Pass *llvm::createPruneEHPass() { return new PruneEH(); }
|
|||||||
|
|
||||||
bool PruneEH::runOnSCC(CallGraphSCC &SCC) {
|
bool PruneEH::runOnSCC(CallGraphSCC &SCC) {
|
||||||
SmallPtrSet<CallGraphNode *, 8> SCCNodes;
|
SmallPtrSet<CallGraphNode *, 8> SCCNodes;
|
||||||
CallGraph &CG = getAnalysis<CallGraph>();
|
CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
|
||||||
bool MadeChange = false;
|
bool MadeChange = false;
|
||||||
|
|
||||||
// Fill SCCNodes with the elements of the SCC. Used for quickly
|
// Fill SCCNodes with the elements of the SCC. Used for quickly
|
||||||
@ -234,7 +234,7 @@ bool PruneEH::SimplifyFunction(Function *F) {
|
|||||||
/// exist in the BB.
|
/// exist in the BB.
|
||||||
void PruneEH::DeleteBasicBlock(BasicBlock *BB) {
|
void PruneEH::DeleteBasicBlock(BasicBlock *BB) {
|
||||||
assert(pred_begin(BB) == pred_end(BB) && "BB is not dead!");
|
assert(pred_begin(BB) == pred_end(BB) && "BB is not dead!");
|
||||||
CallGraph &CG = getAnalysis<CallGraph>();
|
CallGraph &CG = getAnalysis<CallGraphWrapperPass>().getCallGraph();
|
||||||
|
|
||||||
CallGraphNode *CGN = CG[BB->getParent()];
|
CallGraphNode *CGN = CG[BB->getParent()];
|
||||||
for (BasicBlock::iterator I = BB->end(), E = BB->begin(); I != E; ) {
|
for (BasicBlock::iterator I = BB->end(), E = BB->begin(); I != E; ) {
|
||||||
|
@ -80,10 +80,10 @@ namespace {
|
|||||||
|
|
||||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
AU.setPreservesAll();
|
AU.setPreservesAll();
|
||||||
AU.addRequiredTransitive<CallGraph>();
|
AU.addRequiredTransitive<CallGraphWrapperPass>();
|
||||||
}
|
}
|
||||||
virtual bool runOnModule(Module &M) {
|
virtual bool runOnModule(Module &M) {
|
||||||
getAnalysis<CallGraph>().print(errs(), &M);
|
getAnalysis<CallGraphWrapperPass>().print(errs(), &M);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -58,7 +58,7 @@ namespace {
|
|||||||
// getAnalysisUsage - This pass requires the CallGraph.
|
// getAnalysisUsage - This pass requires the CallGraph.
|
||||||
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
AU.setPreservesAll();
|
AU.setPreservesAll();
|
||||||
AU.addRequired<CallGraph>();
|
AU.addRequired<CallGraphWrapperPass>();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -92,7 +92,7 @@ bool CFGSCC::runOnFunction(Function &F) {
|
|||||||
|
|
||||||
// run - Print out SCCs in the call graph for the specified module.
|
// run - Print out SCCs in the call graph for the specified module.
|
||||||
bool CallGraphSCC::runOnModule(Module &M) {
|
bool CallGraphSCC::runOnModule(Module &M) {
|
||||||
CallGraphNode* rootNode = getAnalysis<CallGraph>().getRoot();
|
CallGraphNode *rootNode = getAnalysis<CallGraphWrapperPass>().getRoot();
|
||||||
unsigned sccNum = 0;
|
unsigned sccNum = 0;
|
||||||
errs() << "SCCs for the program in PostOrder:";
|
errs() << "SCCs for the program in PostOrder:";
|
||||||
for (scc_iterator<CallGraphNode*> SCCI = scc_begin(rootNode),
|
for (scc_iterator<CallGraphNode*> SCCI = scc_begin(rootNode),
|
||||||
|
@ -550,7 +550,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_PASS_DEPENDENCY(CallGraph)
|
INITIALIZE_PASS_DEPENDENCY(CallGraphWrapperPass)
|
||||||
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)
|
||||||
|
Loading…
Reference in New Issue
Block a user