summaryrefslogtreecommitdiffstats
path: root/lib/Analysis/IPA/CallGraphSCCPass.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-09-01 18:32:03 +0000
committerChris Lattner <sabre@nondot.org>2009-09-01 18:32:03 +0000
commit5a6a363527f9f66ff23f2d281f4fdc6c2084f2d3 (patch)
treed60cc27ecba8cbcec2d20dc54586d6c508750aa7 /lib/Analysis/IPA/CallGraphSCCPass.cpp
parent7ab42aec4266ef1b474ae03f3cb94ce509aa94a7 (diff)
downloadexternal_llvm-5a6a363527f9f66ff23f2d281f4fdc6c2084f2d3.zip
external_llvm-5a6a363527f9f66ff23f2d281f4fdc6c2084f2d3.tar.gz
external_llvm-5a6a363527f9f66ff23f2d281f4fdc6c2084f2d3.tar.bz2
doxygenate RefreshCallGraph, add a new 'verification mode', and run it after
CGSCC passes make change to ensure they are updating the callgraph correctly (when assertions are enabled). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@80698 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/IPA/CallGraphSCCPass.cpp')
-rw-r--r--lib/Analysis/IPA/CallGraphSCCPass.cpp41
1 files changed, 37 insertions, 4 deletions
diff --git a/lib/Analysis/IPA/CallGraphSCCPass.cpp b/lib/Analysis/IPA/CallGraphSCCPass.cpp
index 7e9fd30..a7d1183 100644
--- a/lib/Analysis/IPA/CallGraphSCCPass.cpp
+++ b/lib/Analysis/IPA/CallGraphSCCPass.cpp
@@ -78,7 +78,8 @@ public:
private:
bool RunPassOnSCC(Pass *P, std::vector<CallGraphNode*> &CurSCC,
CallGraph &CG, bool &CallGraphUpToDate);
- void RefreshCallGraph(std::vector<CallGraphNode*> &CurSCC, CallGraph &CG);
+ void RefreshCallGraph(std::vector<CallGraphNode*> &CurSCC, CallGraph &CG,
+ bool IsCheckingMode);
};
} // end anonymous namespace.
@@ -90,13 +91,21 @@ bool CGPassManager::RunPassOnSCC(Pass *P, std::vector<CallGraphNode*> &CurSCC,
bool Changed = false;
if (CallGraphSCCPass *CGSP = dynamic_cast<CallGraphSCCPass*>(P)) {
if (!CallGraphUpToDate) {
- RefreshCallGraph(CurSCC, CG);
+ RefreshCallGraph(CurSCC, CG, false);
CallGraphUpToDate = true;
}
StartPassTimer(P);
Changed = CGSP->runOnSCC(CurSCC);
StopPassTimer(P);
+
+ // After the CGSCCPass is done, when assertions are enabled, use
+ // RefreshCallGraph to verify that the callgraph was correctly updated.
+#ifndef NDEBUG
+ if (Changed)
+ RefreshCallGraph(CurSCC, CG, true);
+#endif
+
return Changed;
}
@@ -123,8 +132,14 @@ bool CGPassManager::RunPassOnSCC(Pass *P, std::vector<CallGraphNode*> &CurSCC,
return Changed;
}
+
+/// RefreshCallGraph - Scan the functions in the specified CFG and resync the
+/// callgraph with the call sites found in it. This is used after
+/// FunctionPasses have potentially munged the callgraph, and can be used after
+/// CallGraphSCC passes to verify that they correctly updated the callgraph.
+///
void CGPassManager::RefreshCallGraph(std::vector<CallGraphNode*> &CurSCC,
- CallGraph &CG) {
+ CallGraph &CG, bool CheckingMode) {
DenseMap<Value*, CallGraphNode*> CallSites;
DEBUG(errs() << "CGSCCPASSMGR: Refreshing SCC with " << CurSCC.size()
@@ -158,6 +173,9 @@ void CGPassManager::RefreshCallGraph(std::vector<CallGraphNode*> &CurSCC,
// pass RAUW'd a call with another value. This can happen when
// constant folding happens of well known functions etc.
CallSite::get(I->first).getInstruction() == 0) {
+ assert(!CheckingMode &&
+ "CallGraphSCCPass did not update the CallGraph correctly!");
+
// Just remove the edge from the set of callees.
CGN->removeCallEdge(I);
E = CGN->end();
@@ -190,6 +208,18 @@ void CGPassManager::RefreshCallGraph(std::vector<CallGraphNode*> &CurSCC,
if (ExistingNode->getFunction() == CS.getCalledFunction())
continue;
+ // If we are in checking mode, we are not allowed to actually mutate
+ // the callgraph. If this is a case where we can infer that the
+ // callgraph is less precise than it could be (e.g. an indirect call
+ // site could be turned direct), don't reject it in checking mode, and
+ // don't tweak it to be more precise.
+ if (CheckingMode && CS.getCalledFunction() &&
+ ExistingNode->getFunction() == 0)
+ continue;
+
+ assert(!CheckingMode &&
+ "CallGraphSCCPass did not update the CallGraph correctly!");
+
// If not, we either went from a direct call to indirect, indirect to
// direct, or direct to different direct.
CallGraphNode *CalleeNode;
@@ -203,6 +233,9 @@ void CGPassManager::RefreshCallGraph(std::vector<CallGraphNode*> &CurSCC,
continue;
}
+ assert(!CheckingMode &&
+ "CallGraphSCCPass did not update the CallGraph correctly!");
+
// If the call site didn't exist in the CGN yet, add it. We assume that
// newly introduced call sites won't be indirect. This could be fixed
// in the future.
@@ -289,7 +322,7 @@ bool CGPassManager::runOnModule(Module &M) {
// If the callgraph was left out of date (because the last pass run was a
// functionpass), refresh it before we move on to the next SCC.
if (!CallGraphUpToDate)
- RefreshCallGraph(CurSCC, CG);
+ RefreshCallGraph(CurSCC, CG, false);
}
Changed |= doFinalization(CG);
return Changed;