aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/IPA/CallGraph.cpp
diff options
context:
space:
mode:
authorChris Lattner <sabre@nondot.org>2009-08-31 07:23:46 +0000
committerChris Lattner <sabre@nondot.org>2009-08-31 07:23:46 +0000
commitbe577659d3c1222cc58c33628c0baddb94d241ab (patch)
tree368cb0f8a6d7b34fe9c676debf76b63df465d5ef /lib/Analysis/IPA/CallGraph.cpp
parentb0b822c44935f9381b4b32baa6324d445067f98a (diff)
Step #1 to giving Callgraph some sane invariants. The problems with callgraph
stem from the fact that we have two types of passes that need to update it: 1. callgraphscc and module passes that are explicitly aware of it 2. Functionpasses (and loop passes etc) that are interlaced with CGSCC passes by the CGSCC Passmgr. In the case of #1, we can reasonably expect the passes to update the call graph just like any analysis. However, functionpasses are not and generally should not be CG aware. This has caused us no end of problems, so this takes a new approach. Logically, the CGSCC Pass manager can rescan every function after it runs a function pass over it to see if the functionpass made any updates to the IR that affect the callgraph. This allows it to catch new calls introduced by the functionpass. In practice, doing this would be slow. This implementation keeps track of whether or not the current scc is dirtied by a function pass, and, if so, delays updating the callgraph until it is actually needed again. This was we avoid extraneous rescans, but we still have good invariants when the callgraph is needed. Step #2 of the "give Callgraph some sane invariants" is to change CallGraphNode to use a CallBackVH for the callsite entry of the CallGraphNode. This way we can immediately remove entries from the callgraph when a FunctionPass is active instead of having dangling pointers. The current pass tries to tolerate these dangling pointers, but it is just an evil hack. This is related to PR3601/4835/4029. This also reverts r80541, a hack working around the sad lack of invariants. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@80566 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/IPA/CallGraph.cpp')
-rw-r--r--lib/Analysis/IPA/CallGraph.cpp58
1 files changed, 34 insertions, 24 deletions
diff --git a/lib/Analysis/IPA/CallGraph.cpp b/lib/Analysis/IPA/CallGraph.cpp
index 6490642f77..5757bfd897 100644
--- a/lib/Analysis/IPA/CallGraph.cpp
+++ b/lib/Analysis/IPA/CallGraph.cpp
@@ -239,23 +239,33 @@ void CallGraphNode::dump() const { print(errs()); }
/// specified call site. Note that this method takes linear time, so it
/// should be used sparingly.
void CallGraphNode::removeCallEdgeFor(CallSite CS) {
- // Scan for the call site. Note that we aren't guaranteed to find the call
- // site in this node, even in reasonable situations. Passes like instcombine
- // can adjust callsites (e.g. folding bitcasts into calls to make them direct)
- // which can introduce new call sites. Since instcombine is not callgraph
- // aware, it doesn't know to tell CallGraph about this change.
- for (CalledFunctionsVector::iterator I = CalledFunctions.begin();
- I != CalledFunctions.end(); ++I) {
- if (I->first != CS) continue;
-
- I->second->DropRef();
- *I = CalledFunctions.back();
- CalledFunctions.pop_back();
- return;
+ for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) {
+ assert(I != CalledFunctions.end() && "Cannot find callsite to remove!");
+ if (I->first == CS) {
+ I->second->DropRef();
+ *I = CalledFunctions.back();
+ CalledFunctions.pop_back();
+ return;
+ }
+ }
+}
+
+// FIXME: REMOVE THIS WHEN HACK IS REMOVED FROM CGSCCPASSMGR.
+void CallGraphNode::removeCallEdgeFor(Instruction *CS) {
+ for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) {
+ assert(I != CalledFunctions.end() && "Cannot find callsite to remove!");
+ if (I->first.getInstruction() == CS) {
+ I->second->DropRef();
+ *I = CalledFunctions.back();
+ CalledFunctions.pop_back();
+ return;
+ }
}
+
}
+
// removeAnyCallEdgeTo - This method removes any call edges from this node to
// the specified callee function. This takes more time to execute than
// removeCallEdgeTo, so it should not be used unless necessary.
@@ -291,18 +301,18 @@ void CallGraphNode::replaceCallSite(CallSite Old, CallSite New,
CallGraphNode *NewCallee) {
for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) {
assert(I != CalledFunctions.end() && "Cannot find callsite to replace!");
- if (I->first == Old) {
- I->first = New;
-
- // If the callee is changing, not just the callsite, then update it as
- // well.
- if (NewCallee) {
- I->second->DropRef();
- I->second = NewCallee;
- I->second->AddRef();
- }
- return;
+ if (I->first != Old) continue;
+
+ I->first = New;
+
+ // If the callee is changing, not just the callsite, then update it as
+ // well.
+ if (NewCallee) {
+ I->second->DropRef();
+ I->second = NewCallee;
+ I->second->AddRef();
}
+ return;
}
}