mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-25 16:24:23 +00:00
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:
@ -29,9 +29,10 @@ namespace llvm {
|
|||||||
class CallGraphNode;
|
class CallGraphNode;
|
||||||
class CallGraph;
|
class CallGraph;
|
||||||
class PMStack;
|
class PMStack;
|
||||||
|
class CallGraphSCC;
|
||||||
struct CallGraphSCCPass : public Pass {
|
|
||||||
|
class CallGraphSCCPass : public Pass {
|
||||||
|
public:
|
||||||
explicit CallGraphSCCPass(intptr_t pid) : Pass(PT_CallGraphSCC, pid) {}
|
explicit CallGraphSCCPass(intptr_t pid) : Pass(PT_CallGraphSCC, pid) {}
|
||||||
explicit CallGraphSCCPass(void *pid) : Pass(PT_CallGraphSCC, pid) {}
|
explicit CallGraphSCCPass(void *pid) : Pass(PT_CallGraphSCC, pid) {}
|
||||||
|
|
||||||
@ -53,7 +54,7 @@ struct CallGraphSCCPass : public Pass {
|
|||||||
/// SCC passes that add or delete functions to the SCC are required to update
|
/// SCC passes that add or delete functions to the SCC are required to update
|
||||||
/// the SCC list, otherwise stale pointers may be dereferenced.
|
/// the SCC list, otherwise stale pointers may be dereferenced.
|
||||||
///
|
///
|
||||||
virtual bool runOnSCC(std::vector<CallGraphNode *> &SCC) = 0;
|
virtual bool runOnSCC(CallGraphSCC &SCC) = 0;
|
||||||
|
|
||||||
/// doFinalization - This method is called after the SCC's of the program has
|
/// doFinalization - This method is called after the SCC's of the program has
|
||||||
/// been processed, allowing the pass to do final cleanup as necessary.
|
/// been processed, allowing the pass to do final cleanup as necessary.
|
||||||
@ -63,7 +64,7 @@ struct CallGraphSCCPass : public Pass {
|
|||||||
|
|
||||||
/// Assign pass manager to manager this pass
|
/// Assign pass manager to manager this pass
|
||||||
virtual void assignPassManager(PMStack &PMS,
|
virtual void assignPassManager(PMStack &PMS,
|
||||||
PassManagerType PMT = PMT_CallGraphPassManager);
|
PassManagerType PMT =PMT_CallGraphPassManager);
|
||||||
|
|
||||||
/// Return what kind of Pass Manager can manage this pass.
|
/// Return what kind of Pass Manager can manage this pass.
|
||||||
virtual PassManagerType getPotentialPassManagerType() const {
|
virtual PassManagerType getPotentialPassManagerType() const {
|
||||||
@ -76,6 +77,37 @@ struct CallGraphSCCPass : public Pass {
|
|||||||
virtual void getAnalysisUsage(AnalysisUsage &Info) const;
|
virtual void getAnalysisUsage(AnalysisUsage &Info) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// CallGraphSCC - This is a single SCC that a CallGraphSCCPass is run on.
|
||||||
|
class CallGraphSCC {
|
||||||
|
void *Context; // The CGPassManager object that is vending this.
|
||||||
|
std::vector<CallGraphNode*> Nodes;
|
||||||
|
public:
|
||||||
|
CallGraphSCC(void *context) : Context(context) {}
|
||||||
|
|
||||||
|
void initialize(CallGraphNode*const*I, CallGraphNode*const*E) {
|
||||||
|
Nodes.assign(I, E);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSingular() const { return Nodes.size() == 1; }
|
||||||
|
unsigned size() const { return Nodes.size(); }
|
||||||
|
|
||||||
|
/// ReplaceNode - This informs the SCC and the pass manager that the specified
|
||||||
|
/// Old node has been deleted, and New is to be used in its place.
|
||||||
|
void ReplaceNode(CallGraphNode *Old, CallGraphNode *New) {
|
||||||
|
assert(Old != New && "Should not replace node with self");
|
||||||
|
for (unsigned i = 0, e = Nodes.size(); i != e; ++i)
|
||||||
|
if (Nodes[i] == Old) {
|
||||||
|
Nodes[i] = New;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
assert(0 && "Node not in SCC");
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef std::vector<CallGraphNode*>::const_iterator iterator;
|
||||||
|
iterator begin() const { return Nodes.begin(); }
|
||||||
|
iterator end() const { return Nodes.end(); }
|
||||||
|
};
|
||||||
|
|
||||||
} // End llvm namespace
|
} // End llvm namespace
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -40,7 +40,7 @@ struct Inliner : public CallGraphSCCPass {
|
|||||||
|
|
||||||
// Main run interface method, this implements the interface required by the
|
// Main run interface method, this implements the interface required by the
|
||||||
// Pass class.
|
// Pass class.
|
||||||
virtual bool runOnSCC(std::vector<CallGraphNode *> &SCC);
|
virtual bool runOnSCC(CallGraphSCC &SCC);
|
||||||
|
|
||||||
// doFinalization - Remove now-dead linkonce functions at the end of
|
// doFinalization - Remove now-dead linkonce functions at the end of
|
||||||
// processing to avoid breaking the SCC traversal.
|
// processing to avoid breaking the SCC traversal.
|
||||||
@ -77,7 +77,7 @@ struct Inliner : public CallGraphSCCPass {
|
|||||||
|
|
||||||
/// growCachedCostInfo - update the cached cost info for Caller after Callee
|
/// growCachedCostInfo - update the cached cost info for Caller after Callee
|
||||||
/// has been inlined.
|
/// has been inlined.
|
||||||
virtual void growCachedCostInfo(Function* Caller, Function* Callee) = 0;
|
virtual void growCachedCostInfo(Function *Caller, Function *Callee) = 0;
|
||||||
|
|
||||||
/// removeDeadFunctions - Remove dead functions that are not included in
|
/// removeDeadFunctions - Remove dead functions that are not included in
|
||||||
/// DNR (Do Not Remove) list.
|
/// DNR (Do Not Remove) list.
|
||||||
|
@ -81,9 +81,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool RunPassOnSCC(Pass *P, std::vector<CallGraphNode*> &CurSCC,
|
bool RunPassOnSCC(Pass *P, CallGraphSCC &CurSCC,
|
||||||
CallGraph &CG, bool &CallGraphUpToDate);
|
CallGraph &CG, bool &CallGraphUpToDate);
|
||||||
void RefreshCallGraph(std::vector<CallGraphNode*> &CurSCC, CallGraph &CG,
|
void RefreshCallGraph(CallGraphSCC &CurSCC, CallGraph &CG,
|
||||||
bool IsCheckingMode);
|
bool IsCheckingMode);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -92,7 +92,7 @@ private:
|
|||||||
char CGPassManager::ID = 0;
|
char CGPassManager::ID = 0;
|
||||||
|
|
||||||
|
|
||||||
bool CGPassManager::RunPassOnSCC(Pass *P, std::vector<CallGraphNode*> &CurSCC,
|
bool CGPassManager::RunPassOnSCC(Pass *P, CallGraphSCC &CurSCC,
|
||||||
CallGraph &CG, bool &CallGraphUpToDate) {
|
CallGraph &CG, bool &CallGraphUpToDate) {
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
PMDataManager *PM = P->getAsPMDataManager();
|
PMDataManager *PM = P->getAsPMDataManager();
|
||||||
@ -125,8 +125,9 @@ bool CGPassManager::RunPassOnSCC(Pass *P, std::vector<CallGraphNode*> &CurSCC,
|
|||||||
FPPassManager *FPP = (FPPassManager*)P;
|
FPPassManager *FPP = (FPPassManager*)P;
|
||||||
|
|
||||||
// Run pass P on all functions in the current SCC.
|
// Run pass P on all functions in the current SCC.
|
||||||
for (unsigned i = 0, e = CurSCC.size(); i != e; ++i) {
|
for (CallGraphSCC::iterator I = CurSCC.begin(), E = CurSCC.end();
|
||||||
if (Function *F = CurSCC[i]->getFunction()) {
|
I != E; ++I) {
|
||||||
|
if (Function *F = (*I)->getFunction()) {
|
||||||
dumpPassInfo(P, EXECUTION_MSG, ON_FUNCTION_MSG, F->getName());
|
dumpPassInfo(P, EXECUTION_MSG, ON_FUNCTION_MSG, F->getName());
|
||||||
TimeRegion PassTimer(getPassTimer(FPP));
|
TimeRegion PassTimer(getPassTimer(FPP));
|
||||||
Changed |= FPP->runOnFunction(*F);
|
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
|
/// FunctionPasses have potentially munged the callgraph, and can be used after
|
||||||
/// CallGraphSCC passes to verify that they correctly updated the callgraph.
|
/// 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) {
|
CallGraph &CG, bool CheckingMode) {
|
||||||
DenseMap<Value*, CallGraphNode*> CallSites;
|
DenseMap<Value*, CallGraphNode*> CallSites;
|
||||||
|
|
||||||
DEBUG(dbgs() << "CGSCCPASSMGR: Refreshing SCC with " << CurSCC.size()
|
DEBUG(dbgs() << "CGSCCPASSMGR: Refreshing SCC with " << CurSCC.size()
|
||||||
<< " nodes:\n";
|
<< " nodes:\n";
|
||||||
for (unsigned i = 0, e = CurSCC.size(); i != e; ++i)
|
for (CallGraphSCC::iterator I = CurSCC.begin(), E = CurSCC.end();
|
||||||
CurSCC[i]->dump();
|
I != E; ++I)
|
||||||
|
(*I)->dump();
|
||||||
);
|
);
|
||||||
|
|
||||||
bool MadeChange = false;
|
bool MadeChange = false;
|
||||||
|
|
||||||
// Scan all functions in the SCC.
|
// Scan all functions in the SCC.
|
||||||
for (unsigned sccidx = 0, e = CurSCC.size(); sccidx != e; ++sccidx) {
|
unsigned FunctionNo = 0;
|
||||||
CallGraphNode *CGN = CurSCC[sccidx];
|
for (CallGraphSCC::iterator SCCIdx = CurSCC.begin(), E = CurSCC.end();
|
||||||
|
SCCIdx != E; ++SCCIdx, ++FunctionNo) {
|
||||||
|
CallGraphNode *CGN = *SCCIdx;
|
||||||
Function *F = CGN->getFunction();
|
Function *F = CGN->getFunction();
|
||||||
if (F == 0 || F->isDeclaration()) continue;
|
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
|
// Periodically do an explicit clear to remove tombstones when processing
|
||||||
// large scc's.
|
// large scc's.
|
||||||
if ((sccidx & 15) == 0)
|
if ((FunctionNo & 15) == 15)
|
||||||
CallSites.clear();
|
CallSites.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
DEBUG(if (MadeChange) {
|
DEBUG(if (MadeChange) {
|
||||||
dbgs() << "CGSCCPASSMGR: Refreshed SCC is now:\n";
|
dbgs() << "CGSCCPASSMGR: Refreshed SCC is now:\n";
|
||||||
for (unsigned i = 0, e = CurSCC.size(); i != e; ++i)
|
for (CallGraphSCC::iterator I = CurSCC.begin(), E = CurSCC.end();
|
||||||
CurSCC[i]->dump();
|
I != E; ++I)
|
||||||
|
(*I)->dump();
|
||||||
} else {
|
} else {
|
||||||
dbgs() << "CGSCCPASSMGR: SCC Refresh didn't change call graph.\n";
|
dbgs() << "CGSCCPASSMGR: SCC Refresh didn't change call graph.\n";
|
||||||
}
|
}
|
||||||
@ -302,14 +307,15 @@ bool CGPassManager::runOnModule(Module &M) {
|
|||||||
CallGraph &CG = getAnalysis<CallGraph>();
|
CallGraph &CG = getAnalysis<CallGraph>();
|
||||||
bool Changed = doInitialization(CG);
|
bool Changed = doInitialization(CG);
|
||||||
|
|
||||||
std::vector<CallGraphNode*> CurSCC;
|
CallGraphSCC CurSCC(this);
|
||||||
|
|
||||||
// Walk the callgraph in bottom-up SCC order.
|
// Walk the callgraph in bottom-up SCC order.
|
||||||
for (scc_iterator<CallGraph*> CGI = scc_begin(&CG), E = scc_end(&CG);
|
for (scc_iterator<CallGraph*> CGI = scc_begin(&CG), E = scc_end(&CG);
|
||||||
CGI != E;) {
|
CGI != E;) {
|
||||||
// Copy the current SCC and increment past it so that the pass can hack
|
// 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.
|
// 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;
|
++CGI;
|
||||||
|
|
||||||
|
|
||||||
@ -333,9 +339,10 @@ bool CGPassManager::runOnModule(Module &M) {
|
|||||||
std::string Functions;
|
std::string Functions;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
raw_string_ostream OS(Functions);
|
raw_string_ostream OS(Functions);
|
||||||
for (unsigned i = 0, e = CurSCC.size(); i != e; ++i) {
|
for (CallGraphSCC::iterator I = CurSCC.begin(), E = CurSCC.end();
|
||||||
if (i) OS << ", ";
|
I != E; ++I) {
|
||||||
CurSCC[i]->print(OS);
|
if (I != CurSCC.begin()) OS << ", ";
|
||||||
|
(*I)->print(OS);
|
||||||
}
|
}
|
||||||
OS.flush();
|
OS.flush();
|
||||||
#endif
|
#endif
|
||||||
@ -397,6 +404,12 @@ bool CGPassManager::doFinalization(CallGraph &CG) {
|
|||||||
return Changed;
|
return Changed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
// CallGraphSCC Implementation
|
||||||
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
// CallGraphSCCPass Implementation
|
// CallGraphSCCPass Implementation
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
@ -468,10 +481,10 @@ namespace {
|
|||||||
AU.setPreservesAll();
|
AU.setPreservesAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool runOnSCC(std::vector<CallGraphNode *> &SCC) {
|
bool runOnSCC(CallGraphSCC &SCC) {
|
||||||
Out << Banner;
|
Out << Banner;
|
||||||
for (unsigned i = 0, e = SCC.size(); i != e; ++i)
|
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I)
|
||||||
SCC[i]->getFunction()->print(Out);
|
(*I)->getFunction()->print(Out);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -64,7 +64,7 @@ namespace {
|
|||||||
CallGraphSCCPass::getAnalysisUsage(AU);
|
CallGraphSCCPass::getAnalysisUsage(AU);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool runOnSCC(std::vector<CallGraphNode *> &SCC);
|
virtual bool runOnSCC(CallGraphSCC &SCC);
|
||||||
static char ID; // Pass identification, replacement for typeid
|
static char ID; // Pass identification, replacement for typeid
|
||||||
explicit ArgPromotion(unsigned maxElements = 3)
|
explicit ArgPromotion(unsigned maxElements = 3)
|
||||||
: CallGraphSCCPass(&ID), maxElements(maxElements) {}
|
: CallGraphSCCPass(&ID), maxElements(maxElements) {}
|
||||||
@ -91,17 +91,18 @@ Pass *llvm::createArgumentPromotionPass(unsigned maxElements) {
|
|||||||
return new ArgPromotion(maxElements);
|
return new ArgPromotion(maxElements);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ArgPromotion::runOnSCC(std::vector<CallGraphNode *> &SCC) {
|
bool ArgPromotion::runOnSCC(CallGraphSCC &SCC) {
|
||||||
bool Changed = false, LocalChange;
|
bool Changed = false, LocalChange;
|
||||||
|
|
||||||
do { // Iterate until we stop promoting from this SCC.
|
do { // Iterate until we stop promoting from this SCC.
|
||||||
LocalChange = false;
|
LocalChange = false;
|
||||||
// Attempt to promote arguments from all functions in this SCC.
|
// Attempt to promote arguments from all functions in this SCC.
|
||||||
for (unsigned i = 0, e = SCC.size(); i != e; ++i)
|
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
|
||||||
if (CallGraphNode *CGN = PromoteArguments(SCC[i])) {
|
if (CallGraphNode *CGN = PromoteArguments(*I)) {
|
||||||
LocalChange = true;
|
LocalChange = true;
|
||||||
SCC[i] = CGN;
|
SCC.ReplaceNode(*I, CGN);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
Changed |= LocalChange; // Remember that we changed something.
|
Changed |= LocalChange; // Remember that we changed something.
|
||||||
} while (LocalChange);
|
} while (LocalChange);
|
||||||
|
|
||||||
|
@ -44,20 +44,20 @@ namespace {
|
|||||||
FunctionAttrs() : CallGraphSCCPass(&ID) {}
|
FunctionAttrs() : CallGraphSCCPass(&ID) {}
|
||||||
|
|
||||||
// runOnSCC - Analyze the SCC, performing the transformation if possible.
|
// 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.
|
// 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.
|
// 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?
|
// IsFunctionMallocLike - Does this function allocate new memory?
|
||||||
bool IsFunctionMallocLike(Function *F,
|
bool IsFunctionMallocLike(Function *F,
|
||||||
SmallPtrSet<Function*, 8> &) const;
|
SmallPtrSet<Function*, 8> &) const;
|
||||||
|
|
||||||
// AddNoAliasAttrs - Deduce noalias attributes for the SCC.
|
// 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 {
|
virtual void getAnalysisUsage(AnalysisUsage &AU) const {
|
||||||
AU.setPreservesCFG();
|
AU.setPreservesCFG();
|
||||||
@ -123,19 +123,19 @@ bool FunctionAttrs::PointsToLocalMemory(Value *V) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// AddReadAttrs - Deduce readonly/readnone attributes for the SCC.
|
/// 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;
|
SmallPtrSet<Function*, 8> SCCNodes;
|
||||||
|
|
||||||
// Fill SCCNodes with the elements of the SCC. Used for quickly
|
// Fill SCCNodes with the elements of the SCC. Used for quickly
|
||||||
// looking up whether a given CallGraphNode is in this SCC.
|
// looking up whether a given CallGraphNode is in this SCC.
|
||||||
for (unsigned i = 0, e = SCC.size(); i != e; ++i)
|
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I)
|
||||||
SCCNodes.insert(SCC[i]->getFunction());
|
SCCNodes.insert((*I)->getFunction());
|
||||||
|
|
||||||
// Check if any of the functions in the SCC read or write memory. If they
|
// 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.
|
// write memory then they can't be marked readnone or readonly.
|
||||||
bool ReadsMemory = false;
|
bool ReadsMemory = false;
|
||||||
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
|
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
|
||||||
Function *F = SCC[i]->getFunction();
|
Function *F = (*I)->getFunction();
|
||||||
|
|
||||||
if (F == 0)
|
if (F == 0)
|
||||||
// External node - may write memory. Just give up.
|
// 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.
|
// Success! Functions in this SCC do not access memory, or only read memory.
|
||||||
// Give them the appropriate attribute.
|
// Give them the appropriate attribute.
|
||||||
bool MadeChange = false;
|
bool MadeChange = false;
|
||||||
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
|
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
|
||||||
Function *F = SCC[i]->getFunction();
|
Function *F = (*I)->getFunction();
|
||||||
|
|
||||||
if (F->doesNotAccessMemory())
|
if (F->doesNotAccessMemory())
|
||||||
// Already perfect!
|
// Already perfect!
|
||||||
@ -239,13 +239,13 @@ bool FunctionAttrs::AddReadAttrs(const std::vector<CallGraphNode *> &SCC) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// AddNoCaptureAttrs - Deduce nocapture attributes for the 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;
|
bool Changed = false;
|
||||||
|
|
||||||
// Check each function in turn, determining which pointer arguments are not
|
// Check each function in turn, determining which pointer arguments are not
|
||||||
// captured.
|
// captured.
|
||||||
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
|
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
|
||||||
Function *F = SCC[i]->getFunction();
|
Function *F = (*I)->getFunction();
|
||||||
|
|
||||||
if (F == 0)
|
if (F == 0)
|
||||||
// External node - skip it;
|
// External node - skip it;
|
||||||
@ -334,18 +334,18 @@ bool FunctionAttrs::IsFunctionMallocLike(Function *F,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// AddNoAliasAttrs - Deduce noalias attributes for the SCC.
|
/// 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;
|
SmallPtrSet<Function*, 8> SCCNodes;
|
||||||
|
|
||||||
// Fill SCCNodes with the elements of the SCC. Used for quickly
|
// Fill SCCNodes with the elements of the SCC. Used for quickly
|
||||||
// looking up whether a given CallGraphNode is in this SCC.
|
// looking up whether a given CallGraphNode is in this SCC.
|
||||||
for (unsigned i = 0, e = SCC.size(); i != e; ++i)
|
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I)
|
||||||
SCCNodes.insert(SCC[i]->getFunction());
|
SCCNodes.insert((*I)->getFunction());
|
||||||
|
|
||||||
// Check each function in turn, determining which functions return noalias
|
// Check each function in turn, determining which functions return noalias
|
||||||
// pointers.
|
// pointers.
|
||||||
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
|
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
|
||||||
Function *F = SCC[i]->getFunction();
|
Function *F = (*I)->getFunction();
|
||||||
|
|
||||||
if (F == 0)
|
if (F == 0)
|
||||||
// External node - skip it;
|
// External node - skip it;
|
||||||
@ -370,8 +370,8 @@ bool FunctionAttrs::AddNoAliasAttrs(const std::vector<CallGraphNode *> &SCC) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool MadeChange = false;
|
bool MadeChange = false;
|
||||||
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
|
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
|
||||||
Function *F = SCC[i]->getFunction();
|
Function *F = (*I)->getFunction();
|
||||||
if (F->doesNotAlias(0) || !F->getReturnType()->isPointerTy())
|
if (F->doesNotAlias(0) || !F->getReturnType()->isPointerTy())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -383,7 +383,7 @@ bool FunctionAttrs::AddNoAliasAttrs(const std::vector<CallGraphNode *> &SCC) {
|
|||||||
return MadeChange;
|
return MadeChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FunctionAttrs::runOnSCC(std::vector<CallGraphNode *> &SCC) {
|
bool FunctionAttrs::runOnSCC(CallGraphSCC &SCC) {
|
||||||
bool Changed = AddReadAttrs(SCC);
|
bool Changed = AddReadAttrs(SCC);
|
||||||
Changed |= AddNoCaptureAttrs(SCC);
|
Changed |= AddNoCaptureAttrs(SCC);
|
||||||
Changed |= AddNoAliasAttrs(SCC);
|
Changed |= AddNoAliasAttrs(SCC);
|
||||||
|
@ -292,14 +292,14 @@ bool Inliner::shouldInline(CallSite CS) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Inliner::runOnSCC(std::vector<CallGraphNode*> &SCC) {
|
bool Inliner::runOnSCC(CallGraphSCC &SCC) {
|
||||||
CallGraph &CG = getAnalysis<CallGraph>();
|
CallGraph &CG = getAnalysis<CallGraph>();
|
||||||
const TargetData *TD = getAnalysisIfAvailable<TargetData>();
|
const TargetData *TD = getAnalysisIfAvailable<TargetData>();
|
||||||
|
|
||||||
SmallPtrSet<Function*, 8> SCCFunctions;
|
SmallPtrSet<Function*, 8> SCCFunctions;
|
||||||
DEBUG(dbgs() << "Inliner visiting SCC:");
|
DEBUG(dbgs() << "Inliner visiting SCC:");
|
||||||
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
|
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
|
||||||
Function *F = SCC[i]->getFunction();
|
Function *F = (*I)->getFunction();
|
||||||
if (F) SCCFunctions.insert(F);
|
if (F) SCCFunctions.insert(F);
|
||||||
DEBUG(dbgs() << " " << (F ? F->getName() : "INDIRECTNODE"));
|
DEBUG(dbgs() << " " << (F ? F->getName() : "INDIRECTNODE"));
|
||||||
}
|
}
|
||||||
@ -309,8 +309,8 @@ bool Inliner::runOnSCC(std::vector<CallGraphNode*> &SCC) {
|
|||||||
// from inlining other functions.
|
// from inlining other functions.
|
||||||
SmallVector<CallSite, 16> CallSites;
|
SmallVector<CallSite, 16> CallSites;
|
||||||
|
|
||||||
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
|
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
|
||||||
Function *F = SCC[i]->getFunction();
|
Function *F = (*I)->getFunction();
|
||||||
if (!F) continue;
|
if (!F) continue;
|
||||||
|
|
||||||
for (Function::iterator BB = F->begin(), E = F->end(); BB != E; ++BB)
|
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
|
// 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
|
// move a call site to a function in this SCC before the
|
||||||
// 'FirstCallInSCC' barrier.
|
// 'FirstCallInSCC' barrier.
|
||||||
if (SCC.size() == 1) {
|
if (SCC.isSingular()) {
|
||||||
std::swap(CallSites[CSi], CallSites.back());
|
std::swap(CallSites[CSi], CallSites.back());
|
||||||
CallSites.pop_back();
|
CallSites.pop_back();
|
||||||
} else {
|
} else {
|
||||||
|
@ -40,7 +40,7 @@ namespace {
|
|||||||
PruneEH() : CallGraphSCCPass(&ID) {}
|
PruneEH() : CallGraphSCCPass(&ID) {}
|
||||||
|
|
||||||
// runOnSCC - Analyze the SCC, performing the transformation if possible.
|
// runOnSCC - Analyze the SCC, performing the transformation if possible.
|
||||||
bool runOnSCC(std::vector<CallGraphNode *> &SCC);
|
bool runOnSCC(CallGraphSCC &SCC);
|
||||||
|
|
||||||
bool SimplifyFunction(Function *F);
|
bool SimplifyFunction(Function *F);
|
||||||
void DeleteBasicBlock(BasicBlock *BB);
|
void DeleteBasicBlock(BasicBlock *BB);
|
||||||
@ -54,20 +54,20 @@ X("prune-eh", "Remove unused exception handling info");
|
|||||||
Pass *llvm::createPruneEHPass() { return new PruneEH(); }
|
Pass *llvm::createPruneEHPass() { return new PruneEH(); }
|
||||||
|
|
||||||
|
|
||||||
bool PruneEH::runOnSCC(std::vector<CallGraphNode *> &SCC) {
|
bool PruneEH::runOnSCC(CallGraphSCC &SCC) {
|
||||||
SmallPtrSet<CallGraphNode *, 8> SCCNodes;
|
SmallPtrSet<CallGraphNode *, 8> SCCNodes;
|
||||||
CallGraph &CG = getAnalysis<CallGraph>();
|
CallGraph &CG = getAnalysis<CallGraph>();
|
||||||
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
|
||||||
// looking up whether a given CallGraphNode is in this SCC.
|
// looking up whether a given CallGraphNode is in this SCC.
|
||||||
for (unsigned i = 0, e = SCC.size(); i != e; ++i)
|
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I)
|
||||||
SCCNodes.insert(SCC[i]);
|
SCCNodes.insert(*I);
|
||||||
|
|
||||||
// First pass, scan all of the functions in the SCC, simplifying them
|
// First pass, scan all of the functions in the SCC, simplifying them
|
||||||
// according to what we know.
|
// according to what we know.
|
||||||
for (unsigned i = 0, e = SCC.size(); i != e; ++i)
|
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I)
|
||||||
if (Function *F = SCC[i]->getFunction())
|
if (Function *F = (*I)->getFunction())
|
||||||
MadeChange |= SimplifyFunction(F);
|
MadeChange |= SimplifyFunction(F);
|
||||||
|
|
||||||
// Next, check to see if any callees might throw or if there are any external
|
// 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.
|
// obviously the SCC might throw.
|
||||||
//
|
//
|
||||||
bool SCCMightUnwind = false, SCCMightReturn = false;
|
bool SCCMightUnwind = false, SCCMightReturn = false;
|
||||||
for (unsigned i = 0, e = SCC.size();
|
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end();
|
||||||
(!SCCMightUnwind || !SCCMightReturn) && i != e; ++i) {
|
(!SCCMightUnwind || !SCCMightReturn) && I != E; ++I) {
|
||||||
Function *F = SCC[i]->getFunction();
|
Function *F = (*I)->getFunction();
|
||||||
if (F == 0) {
|
if (F == 0) {
|
||||||
SCCMightUnwind = true;
|
SCCMightUnwind = true;
|
||||||
SCCMightReturn = 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 the SCC doesn't unwind or doesn't throw, note this fact.
|
||||||
if (!SCCMightUnwind || !SCCMightReturn)
|
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;
|
Attributes NewAttributes = Attribute::None;
|
||||||
|
|
||||||
if (!SCCMightUnwind)
|
if (!SCCMightUnwind)
|
||||||
@ -140,19 +140,20 @@ bool PruneEH::runOnSCC(std::vector<CallGraphNode *> &SCC) {
|
|||||||
if (!SCCMightReturn)
|
if (!SCCMightReturn)
|
||||||
NewAttributes |= Attribute::NoReturn;
|
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);
|
const AttrListPtr &NPAL = PAL.addAttr(~0, NewAttributes);
|
||||||
if (PAL != NPAL) {
|
if (PAL != NPAL) {
|
||||||
MadeChange = true;
|
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
|
// Convert any invoke instructions to non-throwing functions in this node
|
||||||
// into call instructions with a branch. This makes the exception blocks
|
// into call instructions with a branch. This makes the exception blocks
|
||||||
// dead.
|
// dead.
|
||||||
if (Function *F = SCC[i]->getFunction())
|
if (Function *F = (*I)->getFunction())
|
||||||
MadeChange |= SimplifyFunction(F);
|
MadeChange |= SimplifyFunction(F);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ namespace {
|
|||||||
CallGraphSCCPass::getAnalysisUsage(AU);
|
CallGraphSCCPass::getAnalysisUsage(AU);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual bool runOnSCC(std::vector<CallGraphNode *> &SCC);
|
virtual bool runOnSCC(CallGraphSCC &SCC);
|
||||||
static char ID; // Pass identification, replacement for typeid
|
static char ID; // Pass identification, replacement for typeid
|
||||||
SRETPromotion() : CallGraphSCCPass(&ID) {}
|
SRETPromotion() : CallGraphSCCPass(&ID) {}
|
||||||
|
|
||||||
@ -69,12 +69,12 @@ Pass *llvm::createStructRetPromotionPass() {
|
|||||||
return new SRETPromotion();
|
return new SRETPromotion();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SRETPromotion::runOnSCC(std::vector<CallGraphNode *> &SCC) {
|
bool SRETPromotion::runOnSCC(CallGraphSCC &SCC) {
|
||||||
bool Changed = false;
|
bool Changed = false;
|
||||||
|
|
||||||
for (unsigned i = 0, e = SCC.size(); i != e; ++i)
|
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I)
|
||||||
if (CallGraphNode *NewNode = PromoteReturn(SCC[i])) {
|
if (CallGraphNode *NewNode = PromoteReturn(*I)) {
|
||||||
SCC[i] = NewNode;
|
SCC.ReplaceNode(*I, NewNode);
|
||||||
Changed = true;
|
Changed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,15 +141,14 @@ struct CallGraphSCCPassPrinter : public CallGraphSCCPass {
|
|||||||
CallGraphSCCPassPrinter(const PassInfo *PI) :
|
CallGraphSCCPassPrinter(const PassInfo *PI) :
|
||||||
CallGraphSCCPass(&ID), PassToPrint(PI) {}
|
CallGraphSCCPass(&ID), PassToPrint(PI) {}
|
||||||
|
|
||||||
virtual bool runOnSCC(std::vector<CallGraphNode *>&SCC) {
|
virtual bool runOnSCC(CallGraphSCC &SCC) {
|
||||||
if (!Quiet) {
|
if (!Quiet) {
|
||||||
outs() << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
|
outs() << "Printing analysis '" << PassToPrint->getPassName() << "':\n";
|
||||||
|
|
||||||
for (unsigned i = 0, e = SCC.size(); i != e; ++i) {
|
for (CallGraphSCC::iterator I = SCC.begin(), E = SCC.end(); I != E; ++I) {
|
||||||
Function *F = SCC[i]->getFunction();
|
Function *F = (*I)->getFunction();
|
||||||
if (F) {
|
if (F)
|
||||||
getAnalysisID<Pass>(PassToPrint).print(outs(), F->getParent());
|
getAnalysisID<Pass>(PassToPrint).print(outs(), F->getParent());
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Get and print pass...
|
// Get and print pass...
|
||||||
|
@ -154,7 +154,7 @@ namespace llvm {
|
|||||||
|
|
||||||
struct CGPass : public PassTest<CallGraph, CallGraphSCCPass> {
|
struct CGPass : public PassTest<CallGraph, CallGraphSCCPass> {
|
||||||
public:
|
public:
|
||||||
virtual bool runOnSCC(std::vector<CallGraphNode*> &SCMM) {
|
virtual bool runOnSCC(CallGraphSCC &SCMM) {
|
||||||
EXPECT_TRUE(getAnalysisIfAvailable<TargetData>());
|
EXPECT_TRUE(getAnalysisIfAvailable<TargetData>());
|
||||||
run();
|
run();
|
||||||
return false;
|
return false;
|
||||||
|
Reference in New Issue
Block a user