public:
static char ID; // Class identification, replacement for typeinfo
//===---------------------------------------------------------------------
- // Accessors...
+ // Accessors.
//
typedef FunctionMapTy::iterator iterator;
typedef FunctionMapTy::const_iterator const_iterator;
CallGraphNode *getOrInsertFunction(const Function *F);
//===---------------------------------------------------------------------
- // Pass infrastructure interface glue code...
+ // Pass infrastructure interface glue code.
//
protected:
CallGraph() {}
Function *F;
typedef std::pair<CallSite,CallGraphNode*> CallRecord;
std::vector<CallRecord> CalledFunctions;
+
+ /// NumReferences - This is the number of times that this CallGraphNode occurs
+ /// in the CalledFunctions array of this or other CallGraphNodes.
+ unsigned NumReferences;
- CallGraphNode(const CallGraphNode &); // Do not implement
+ CallGraphNode(const CallGraphNode &); // DO NOT IMPLEMENT
+ void operator=(const CallGraphNode &); // DO NOT IMPLEMENT
+
+ void DropRef() { --NumReferences; }
+ void AddRef() { ++NumReferences; }
public:
typedef std::vector<CallRecord> CalledFunctionsVector;
+
+ // CallGraphNode ctor - Create a node for the specified function.
+ inline CallGraphNode(Function *f) : F(f), NumReferences(0) {}
+
//===---------------------------------------------------------------------
- // Accessor methods...
+ // Accessor methods.
//
typedef std::vector<CallRecord>::iterator iterator;
typedef std::vector<CallRecord>::const_iterator const_iterator;
- // getFunction - Return the function that this call graph node represents...
+ // getFunction - Return the function that this call graph node represents.
Function *getFunction() const { return F; }
inline iterator begin() { return CalledFunctions.begin(); }
inline bool empty() const { return CalledFunctions.empty(); }
inline unsigned size() const { return (unsigned)CalledFunctions.size(); }
- // Subscripting operator - Return the i'th called function...
+ /// getNumReferences - Return the number of other CallGraphNodes in this
+ /// CallGraph that reference this node in their callee list.
+ unsigned getNumReferences() const { return NumReferences; }
+
+ // Subscripting operator - Return the i'th called function.
//
CallGraphNode *operator[](unsigned i) const {
+ assert(i < CalledFunctions.size() && "Invalid index");
return CalledFunctions[i].second;
}
/// removeAllCalledFunctions - As the name implies, this removes all edges
/// from this CallGraphNode to any functions it calls.
void removeAllCalledFunctions() {
- CalledFunctions.clear();
+ while (!CalledFunctions.empty()) {
+ CalledFunctions.back().second->DropRef();
+ CalledFunctions.pop_back();
+ }
}
/// stealCalledFunctionsFrom - Move all the callee information from N to this
/// one.
void addCalledFunction(CallSite CS, CallGraphNode *M) {
CalledFunctions.push_back(std::make_pair(CS, M));
+ M->AddRef();
}
/// removeCallEdgeFor - This method removes the edge in the node for the
/// New CallSite instead. Note that this method takes linear time, so it
/// should be used sparingly.
void replaceCallSite(CallSite Old, CallSite New, CallGraphNode *NewCallee);
-
- friend class CallGraph;
-
- // CallGraphNode ctor - Create a node for the specified function.
- inline CallGraphNode(Function *f) : F(f) {}
};
//===----------------------------------------------------------------------===//
CallsExternalNode = new CallGraphNode(0);
Root = 0;
- // Add every function to the call graph...
+ // Add every function to the call graph.
for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
addToCallGraph(I);
}
void CallGraph::destroy() {
- if (!FunctionMap.empty()) {
- for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
- I != E; ++I)
- delete I->second;
- FunctionMap.clear();
- }
+ if (FunctionMap.empty()) return;
+
+ for (FunctionMapTy::iterator I = FunctionMap.begin(), E = FunctionMap.end();
+ I != E; ++I)
+ delete I->second;
+ FunctionMap.clear();
}
void CallGraph::print(raw_ostream &OS, Module*) const {
void CallGraphNode::print(raw_ostream &OS) const {
if (Function *F = getFunction())
- OS << "Call graph node for function: '" << F->getName()
- << "'<<0x" << this << ">>\n";
+ OS << "Call graph node for function: '" << F->getName() << "'";
else
- OS << "Call graph node <<null function: 0x" << this << ">>:\n";
+ OS << "Call graph node <<null function>>";
+
+ OS << "<<0x" << this << ">> #uses=" << getNumReferences() << '\n';
for (const_iterator I = begin(), E = end(); I != E; ++I)
if (Function *FI = I->second->getFunction())
for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) {
assert(I != CalledFunctions.end() && "Cannot find callsite to remove!");
if (I->first == CS) {
- CalledFunctions.erase(I);
+ I->second->DropRef();
+ *I = CalledFunctions.back();
+ CalledFunctions.pop_back();
return;
}
}
void CallGraphNode::removeAnyCallEdgeTo(CallGraphNode *Callee) {
for (unsigned i = 0, e = CalledFunctions.size(); i != e; ++i)
if (CalledFunctions[i].second == Callee) {
+ Callee->DropRef();
CalledFunctions[i] = CalledFunctions.back();
CalledFunctions.pop_back();
--i; --e;
for (CalledFunctionsVector::iterator I = CalledFunctions.begin(); ; ++I) {
assert(I != CalledFunctions.end() && "Cannot find callee to remove!");
CallRecord &CR = *I;
- if (CR.second == Callee && !CR.first.getInstruction()) {
- CalledFunctions.erase(I);
+ if (CR.second == Callee && CR.first.getInstruction() == 0) {
+ Callee->DropRef();
+ *I = CalledFunctions.back();
+ CalledFunctions.pop_back();
return;
}
}
// If the callee is changing, not just the callsite, then update it as
// well.
- if (NewCallee)
+ if (NewCallee) {
+ I->second->DropRef();
I->second = NewCallee;
+ I->second->AddRef();
+ }
return;
}
}
// If we inlined the last possible call site to the function, delete the
// function body now.
- if (Callee->use_empty() &&
- (Callee->hasLocalLinkage() ||
- Callee->hasAvailableExternallyLinkage()) &&
- !SCCFunctions.count(Callee)) {
+ if (Callee->use_empty() && Callee->hasLocalLinkage() &&
+ !SCCFunctions.count(Callee) &&
+ // The function may be apparently dead, but if there are indirect
+ // callgraph references to the node, we cannot delete it yet, this
+ // could invalidate the CGSCC iterator.
+ CG[Callee]->getNumReferences() == 0) {
DEBUG(errs() << " -> Deleting dead function: "
<< Callee->getName() << "\n");
CallGraphNode *CalleeNode = CG[Callee];
// from the program. Insert the dead ones in the FunctionsToRemove set.
for (CallGraph::iterator I = CG.begin(), E = CG.end(); I != E; ++I) {
CallGraphNode *CGN = I->second;
- if (CGN == 0 || CGN->getFunction() == 0)
+ if (CGN->getFunction() == 0)
continue;
Function *F = CGN->getFunction();
if (DNR && DNR->count(F))
continue;
- if (!F->hasLinkOnceLinkage() && !F->hasLocalLinkage())
+ if (!F->hasLinkOnceLinkage() && !F->hasLocalLinkage() &&
+ !F->hasAvailableExternallyLinkage())
continue;
if (!F->use_empty())
continue;
--- /dev/null
+; RUN: llvm-as < %s | opt -inline | llvm-dis
+; PR4834
+
+define i32 @main() {
+ %funcall1_ = call fastcc i32 ()* ()* @f1()
+ %executecommandptr1_ = call i32 %funcall1_()
+ ret i32 %executecommandptr1_
+}
+
+define internal fastcc i32 ()* @f1() nounwind readnone {
+ ret i32 ()* @f2
+}
+
+define internal i32 @f2() nounwind readnone {
+ ret i32 1
+}