introduce a new CallGraphSCC class, and pass it around

to CallGraphSCCPass's instead of passing around a
std::vector<CallGraphNode*>.  No functionality change,
but now we have a much tidier interface.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@101558 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner
2010-04-16 22:42:17 +00:00
parent c7b65914e0
commit 2decb22222
10 changed files with 132 additions and 86 deletions

View File

@@ -81,9 +81,9 @@ public:
}
private:
bool RunPassOnSCC(Pass *P, std::vector<CallGraphNode*> &CurSCC,
bool RunPassOnSCC(Pass *P, CallGraphSCC &CurSCC,
CallGraph &CG, bool &CallGraphUpToDate);
void RefreshCallGraph(std::vector<CallGraphNode*> &CurSCC, CallGraph &CG,
void RefreshCallGraph(CallGraphSCC &CurSCC, CallGraph &CG,
bool IsCheckingMode);
};
@@ -92,7 +92,7 @@ private:
char CGPassManager::ID = 0;
bool CGPassManager::RunPassOnSCC(Pass *P, std::vector<CallGraphNode*> &CurSCC,
bool CGPassManager::RunPassOnSCC(Pass *P, CallGraphSCC &CurSCC,
CallGraph &CG, bool &CallGraphUpToDate) {
bool Changed = false;
PMDataManager *PM = P->getAsPMDataManager();
@@ -125,8 +125,9 @@ bool CGPassManager::RunPassOnSCC(Pass *P, std::vector<CallGraphNode*> &CurSCC,
FPPassManager *FPP = (FPPassManager*)P;
// Run pass P on all functions in the current SCC.
for (unsigned i = 0, e = CurSCC.size(); i != e; ++i) {
if (Function *F = CurSCC[i]->getFunction()) {
for (CallGraphSCC::iterator I = CurSCC.begin(), E = CurSCC.end();
I != E; ++I) {
if (Function *F = (*I)->getFunction()) {
dumpPassInfo(P, EXECUTION_MSG, ON_FUNCTION_MSG, F->getName());
TimeRegion PassTimer(getPassTimer(FPP));
Changed |= FPP->runOnFunction(*F);
@@ -149,21 +150,24 @@ bool CGPassManager::RunPassOnSCC(Pass *P, std::vector<CallGraphNode*> &CurSCC,
/// 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,
void CGPassManager::RefreshCallGraph(CallGraphSCC &CurSCC,
CallGraph &CG, bool CheckingMode) {
DenseMap<Value*, CallGraphNode*> CallSites;
DEBUG(dbgs() << "CGSCCPASSMGR: Refreshing SCC with " << CurSCC.size()
<< " nodes:\n";
for (unsigned i = 0, e = CurSCC.size(); i != e; ++i)
CurSCC[i]->dump();
for (CallGraphSCC::iterator I = CurSCC.begin(), E = CurSCC.end();
I != E; ++I)
(*I)->dump();
);
bool MadeChange = false;
// Scan all functions in the SCC.
for (unsigned sccidx = 0, e = CurSCC.size(); sccidx != e; ++sccidx) {
CallGraphNode *CGN = CurSCC[sccidx];
unsigned FunctionNo = 0;
for (CallGraphSCC::iterator SCCIdx = CurSCC.begin(), E = CurSCC.end();
SCCIdx != E; ++SCCIdx, ++FunctionNo) {
CallGraphNode *CGN = *SCCIdx;
Function *F = CGN->getFunction();
if (F == 0 || F->isDeclaration()) continue;
@@ -282,14 +286,15 @@ void CGPassManager::RefreshCallGraph(std::vector<CallGraphNode*> &CurSCC,
// Periodically do an explicit clear to remove tombstones when processing
// large scc's.
if ((sccidx & 15) == 0)
if ((FunctionNo & 15) == 15)
CallSites.clear();
}
DEBUG(if (MadeChange) {
dbgs() << "CGSCCPASSMGR: Refreshed SCC is now:\n";
for (unsigned i = 0, e = CurSCC.size(); i != e; ++i)
CurSCC[i]->dump();
for (CallGraphSCC::iterator I = CurSCC.begin(), E = CurSCC.end();
I != E; ++I)
(*I)->dump();
} else {
dbgs() << "CGSCCPASSMGR: SCC Refresh didn't change call graph.\n";
}
@@ -302,14 +307,15 @@ bool CGPassManager::runOnModule(Module &M) {
CallGraph &CG = getAnalysis<CallGraph>();
bool Changed = doInitialization(CG);
std::vector<CallGraphNode*> CurSCC;
CallGraphSCC CurSCC(this);
// Walk the callgraph in bottom-up SCC order.
for (scc_iterator<CallGraph*> CGI = scc_begin(&CG), E = scc_end(&CG);
CGI != E;) {
// Copy the current SCC and increment past it so that the pass can hack
// on the SCC if it wants to without invalidating our iterator.
CurSCC = *CGI;
std::vector<CallGraphNode*> &NodeVec = *CGI;
CurSCC.initialize(&NodeVec[0], &NodeVec[0]+NodeVec.size());
++CGI;
@@ -333,9 +339,10 @@ bool CGPassManager::runOnModule(Module &M) {
std::string Functions;
#ifndef NDEBUG
raw_string_ostream OS(Functions);
for (unsigned i = 0, e = CurSCC.size(); i != e; ++i) {
if (i) OS << ", ";
CurSCC[i]->print(OS);
for (CallGraphSCC::iterator I = CurSCC.begin(), E = CurSCC.end();
I != E; ++I) {
if (I != CurSCC.begin()) OS << ", ";
(*I)->print(OS);
}
OS.flush();
#endif
@@ -397,6 +404,12 @@ bool CGPassManager::doFinalization(CallGraph &CG) {
return Changed;
}
//===----------------------------------------------------------------------===//
// CallGraphSCC Implementation
//===----------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// CallGraphSCCPass Implementation
//===----------------------------------------------------------------------===//
@@ -468,10 +481,10 @@ namespace {
AU.setPreservesAll();
}
bool runOnSCC(std::vector<CallGraphNode *> &SCC) {
bool runOnSCC(CallGraphSCC &SCC) {
Out << Banner;
for (unsigned i = 0, e = SCC.size(); i != e; ++i)
SCC[i]->getFunction()->print(Out);
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I)
(*I)->getFunction()->print(Out);
return false;
}
};

View File

@@ -64,7 +64,7 @@ namespace {
CallGraphSCCPass::getAnalysisUsage(AU);
}
virtual bool runOnSCC(std::vector<CallGraphNode *> &SCC);
virtual bool runOnSCC(CallGraphSCC &SCC);
static char ID; // Pass identification, replacement for typeid
explicit ArgPromotion(unsigned maxElements = 3)
: CallGraphSCCPass(&ID), maxElements(maxElements) {}
@@ -91,17 +91,18 @@ Pass *llvm::createArgumentPromotionPass(unsigned maxElements) {
return new ArgPromotion(maxElements);
}
bool ArgPromotion::runOnSCC(std::vector<CallGraphNode *> &SCC) {
bool ArgPromotion::runOnSCC(CallGraphSCC &SCC) {
bool Changed = false, LocalChange;
do { // Iterate until we stop promoting from this SCC.
LocalChange = false;
// Attempt to promote arguments from all functions in this SCC.
for (unsigned i = 0, e = SCC.size(); i != e; ++i)
if (CallGraphNode *CGN = PromoteArguments(SCC[i])) {
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
if (CallGraphNode *CGN = PromoteArguments(*I)) {
LocalChange = true;
SCC[i] = CGN;
SCC.ReplaceNode(*I, CGN);
}
}
Changed |= LocalChange; // Remember that we changed something.
} while (LocalChange);

View File

@@ -44,20 +44,20 @@ namespace {
FunctionAttrs() : CallGraphSCCPass(&ID) {}
// runOnSCC - Analyze the SCC, performing the transformation if possible.
bool runOnSCC(std::vector<CallGraphNode *> &SCC);
bool runOnSCC(CallGraphSCC &SCC);
// AddReadAttrs - Deduce readonly/readnone attributes for the SCC.
bool AddReadAttrs(const std::vector<CallGraphNode *> &SCC);
bool AddReadAttrs(const CallGraphSCC &SCC);
// AddNoCaptureAttrs - Deduce nocapture attributes for the SCC.
bool AddNoCaptureAttrs(const std::vector<CallGraphNode *> &SCC);
bool AddNoCaptureAttrs(const CallGraphSCC &SCC);
// IsFunctionMallocLike - Does this function allocate new memory?
bool IsFunctionMallocLike(Function *F,
SmallPtrSet<Function*, 8> &) const;
// AddNoAliasAttrs - Deduce noalias attributes for the SCC.
bool AddNoAliasAttrs(const std::vector<CallGraphNode *> &SCC);
bool AddNoAliasAttrs(const CallGraphSCC &SCC);
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
AU.setPreservesCFG();
@@ -123,19 +123,19 @@ bool FunctionAttrs::PointsToLocalMemory(Value *V) {
}
/// AddReadAttrs - Deduce readonly/readnone attributes for the SCC.
bool FunctionAttrs::AddReadAttrs(const std::vector<CallGraphNode *> &SCC) {
bool FunctionAttrs::AddReadAttrs(const CallGraphSCC &SCC) {
SmallPtrSet<Function*, 8> SCCNodes;
// Fill SCCNodes with the elements of the SCC. Used for quickly
// looking up whether a given CallGraphNode is in this SCC.
for (unsigned i = 0, e = SCC.size(); i != e; ++i)
SCCNodes.insert(SCC[i]->getFunction());
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I)
SCCNodes.insert((*I)->getFunction());
// Check if any of the functions in the SCC read or write memory. If they
// write memory then they can't be marked readnone or readonly.
bool ReadsMemory = false;
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
Function *F = SCC[i]->getFunction();
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
Function *F = (*I)->getFunction();
if (F == 0)
// External node - may write memory. Just give up.
@@ -210,8 +210,8 @@ bool FunctionAttrs::AddReadAttrs(const std::vector<CallGraphNode *> &SCC) {
// Success! Functions in this SCC do not access memory, or only read memory.
// Give them the appropriate attribute.
bool MadeChange = false;
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
Function *F = SCC[i]->getFunction();
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
Function *F = (*I)->getFunction();
if (F->doesNotAccessMemory())
// Already perfect!
@@ -239,13 +239,13 @@ bool FunctionAttrs::AddReadAttrs(const std::vector<CallGraphNode *> &SCC) {
}
/// AddNoCaptureAttrs - Deduce nocapture attributes for the SCC.
bool FunctionAttrs::AddNoCaptureAttrs(const std::vector<CallGraphNode *> &SCC) {
bool FunctionAttrs::AddNoCaptureAttrs(const CallGraphSCC &SCC) {
bool Changed = false;
// Check each function in turn, determining which pointer arguments are not
// captured.
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
Function *F = SCC[i]->getFunction();
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
Function *F = (*I)->getFunction();
if (F == 0)
// External node - skip it;
@@ -334,18 +334,18 @@ bool FunctionAttrs::IsFunctionMallocLike(Function *F,
}
/// AddNoAliasAttrs - Deduce noalias attributes for the SCC.
bool FunctionAttrs::AddNoAliasAttrs(const std::vector<CallGraphNode *> &SCC) {
bool FunctionAttrs::AddNoAliasAttrs(const CallGraphSCC &SCC) {
SmallPtrSet<Function*, 8> SCCNodes;
// Fill SCCNodes with the elements of the SCC. Used for quickly
// looking up whether a given CallGraphNode is in this SCC.
for (unsigned i = 0, e = SCC.size(); i != e; ++i)
SCCNodes.insert(SCC[i]->getFunction());
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I)
SCCNodes.insert((*I)->getFunction());
// Check each function in turn, determining which functions return noalias
// pointers.
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
Function *F = SCC[i]->getFunction();
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
Function *F = (*I)->getFunction();
if (F == 0)
// External node - skip it;
@@ -370,8 +370,8 @@ bool FunctionAttrs::AddNoAliasAttrs(const std::vector<CallGraphNode *> &SCC) {
}
bool MadeChange = false;
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
Function *F = SCC[i]->getFunction();
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
Function *F = (*I)->getFunction();
if (F->doesNotAlias(0) || !F->getReturnType()->isPointerTy())
continue;
@@ -383,7 +383,7 @@ bool FunctionAttrs::AddNoAliasAttrs(const std::vector<CallGraphNode *> &SCC) {
return MadeChange;
}
bool FunctionAttrs::runOnSCC(std::vector<CallGraphNode *> &SCC) {
bool FunctionAttrs::runOnSCC(CallGraphSCC &SCC) {
bool Changed = AddReadAttrs(SCC);
Changed |= AddNoCaptureAttrs(SCC);
Changed |= AddNoAliasAttrs(SCC);

View File

@@ -292,14 +292,14 @@ bool Inliner::shouldInline(CallSite CS) {
return true;
}
bool Inliner::runOnSCC(std::vector<CallGraphNode*> &SCC) {
bool Inliner::runOnSCC(CallGraphSCC &SCC) {
CallGraph &CG = getAnalysis<CallGraph>();
const TargetData *TD = getAnalysisIfAvailable<TargetData>();
SmallPtrSet<Function*, 8> SCCFunctions;
DEBUG(dbgs() << "Inliner visiting SCC:");
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
Function *F = SCC[i]->getFunction();
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
Function *F = (*I)->getFunction();
if (F) SCCFunctions.insert(F);
DEBUG(dbgs() << " " << (F ? F->getName() : "INDIRECTNODE"));
}
@@ -309,8 +309,8 @@ bool Inliner::runOnSCC(std::vector<CallGraphNode*> &SCC) {
// from inlining other functions.
SmallVector<CallSite, 16> CallSites;
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
Function *F = SCC[i]->getFunction();
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
Function *F = (*I)->getFunction();
if (!F) continue;
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
@@ -417,7 +417,7 @@ bool Inliner::runOnSCC(std::vector<CallGraphNode*> &SCC) {
// swap/pop_back for efficiency, but do not use it if doing so would
// move a call site to a function in this SCC before the
// 'FirstCallInSCC' barrier.
if (SCC.size() == 1) {
if (SCC.isSingular()) {
std::swap(CallSites[CSi], CallSites.back());
CallSites.pop_back();
} else {

View File

@@ -40,7 +40,7 @@ namespace {
PruneEH() : CallGraphSCCPass(&ID) {}
// runOnSCC - Analyze the SCC, performing the transformation if possible.
bool runOnSCC(std::vector<CallGraphNode *> &SCC);
bool runOnSCC(CallGraphSCC &SCC);
bool SimplifyFunction(Function *F);
void DeleteBasicBlock(BasicBlock *BB);
@@ -54,20 +54,20 @@ X("prune-eh", "Remove unused exception handling info");
Pass *llvm::createPruneEHPass() { return new PruneEH(); }
bool PruneEH::runOnSCC(std::vector<CallGraphNode *> &SCC) {
bool PruneEH::runOnSCC(CallGraphSCC &SCC) {
SmallPtrSet<CallGraphNode *, 8> SCCNodes;
CallGraph &CG = getAnalysis<CallGraph>();
bool MadeChange = false;
// Fill SCCNodes with the elements of the SCC. Used for quickly
// looking up whether a given CallGraphNode is in this SCC.
for (unsigned i = 0, e = SCC.size(); i != e; ++i)
SCCNodes.insert(SCC[i]);
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I)
SCCNodes.insert(*I);
// First pass, scan all of the functions in the SCC, simplifying them
// according to what we know.
for (unsigned i = 0, e = SCC.size(); i != e; ++i)
if (Function *F = SCC[i]->getFunction())
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I)
if (Function *F = (*I)->getFunction())
MadeChange |= SimplifyFunction(F);
// Next, check to see if any callees might throw or if there are any external
@@ -78,9 +78,9 @@ bool PruneEH::runOnSCC(std::vector<CallGraphNode *> &SCC) {
// obviously the SCC might throw.
//
bool SCCMightUnwind = false, SCCMightReturn = false;
for (unsigned i = 0, e = SCC.size();
(!SCCMightUnwind || !SCCMightReturn) && i != e; ++i) {
Function *F = SCC[i]->getFunction();
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end();
(!SCCMightUnwind || !SCCMightReturn) && I != E; ++I) {
Function *F = (*I)->getFunction();
if (F == 0) {
SCCMightUnwind = true;
SCCMightReturn = true;
@@ -132,7 +132,7 @@ bool PruneEH::runOnSCC(std::vector<CallGraphNode *> &SCC) {
// If the SCC doesn't unwind or doesn't throw, note this fact.
if (!SCCMightUnwind || !SCCMightReturn)
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
Attributes NewAttributes = Attribute::None;
if (!SCCMightUnwind)
@@ -140,19 +140,20 @@ bool PruneEH::runOnSCC(std::vector<CallGraphNode *> &SCC) {
if (!SCCMightReturn)
NewAttributes |= Attribute::NoReturn;
const AttrListPtr &PAL = SCC[i]->getFunction()->getAttributes();
Function *F = (*I)->getFunction();
const AttrListPtr &PAL = F->getAttributes();
const AttrListPtr &NPAL = PAL.addAttr(~0, NewAttributes);
if (PAL != NPAL) {
MadeChange = true;
SCC[i]->getFunction()->setAttributes(NPAL);
F->setAttributes(NPAL);
}
}
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
// Convert any invoke instructions to non-throwing functions in this node
// into call instructions with a branch. This makes the exception blocks
// dead.
if (Function *F = SCC[i]->getFunction())
if (Function *F = (*I)->getFunction())
MadeChange |= SimplifyFunction(F);
}

View File

@@ -48,7 +48,7 @@ namespace {
CallGraphSCCPass::getAnalysisUsage(AU);
}
virtual bool runOnSCC(std::vector<CallGraphNode *> &SCC);
virtual bool runOnSCC(CallGraphSCC &SCC);
static char ID; // Pass identification, replacement for typeid
SRETPromotion() : CallGraphSCCPass(&ID) {}
@@ -69,12 +69,12 @@ Pass *llvm::createStructRetPromotionPass() {
return new SRETPromotion();
}
bool SRETPromotion::runOnSCC(std::vector<CallGraphNode *> &SCC) {
bool SRETPromotion::runOnSCC(CallGraphSCC &SCC) {
bool Changed = false;
for (unsigned i = 0, e = SCC.size(); i != e; ++i)
if (CallGraphNode *NewNode = PromoteReturn(SCC[i])) {
SCC[i] = NewNode;
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I)
if (CallGraphNode *NewNode = PromoteReturn(*I)) {
SCC.ReplaceNode(*I, NewNode);
Changed = true;
}