Skip to content
Snippets Groups Projects
Commit 7fe8dcef authored by Anna Zaks's avatar Anna Zaks
Browse files

[analyzer] Use BFS over call graph when analysing functions.

BFS should give slightly better performance. Ex: Suppose, we have two
roots R1 and R2. A callee function C is reachable through both. However,
C is not inlined when analyzing R1 due to inline stack depth limit. With
DFS, C will be analyzed as top level even though it would be analyzed as
inlined through R2. On the other hand, BFS could avoid analyzing C as
top level.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@152652 91177308-0d34-0410-b5e6-96231b3b80d8
parent a2e589e6
No related branches found
No related tags found
No related merge requests found
......@@ -43,6 +43,8 @@
#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/Statistic.h"
#include <queue>
using namespace clang;
using namespace ento;
using llvm::SmallPtrSet;
......@@ -282,31 +284,45 @@ void AnalysisConsumer::HandleDeclsGallGraph(TranslationUnitDecl *TU) {
NumFunctionTopLevel++;
}
// TODO: Sort TopLevelFunctions.
std::queue<CallGraphNode*> BFSQueue;
for (llvm::SmallVector<CallGraphNode*, 24>::iterator
TI = TopLevelFunctions.begin(), TE = TopLevelFunctions.end();
TI != TE; ++TI)
BFSQueue.push(*TI);
// DFS over all of the top level nodes. Use external Visited set, which is
// BFS over all of the functions, while skipping the ones inlined into
// the previously processed functions. Use external Visited set, which is
// also modified when we inline a function.
SmallPtrSet<CallGraphNode*,24> Visited;
for (llvm::SmallVector<CallGraphNode*, 24>::iterator
TI = TopLevelFunctions.begin(), TE = TopLevelFunctions.end();
TI != TE; ++TI) {
for (llvm::df_ext_iterator<CallGraphNode*, SmallPtrSet<CallGraphNode*,24> >
DFI = llvm::df_ext_begin(*TI, Visited),
E = llvm::df_ext_end(*TI, Visited);
DFI != E; ++DFI) {
SetOfDecls VisitedCallees;
Decl *D = (*DFI)->getDecl();
assert(D);
HandleCode(D, ANALYSIS_PATH,
(Mgr->InliningMode == All ? 0 : &VisitedCallees));
// Add the visited callees to the global visited set.
for (SetOfDecls::const_iterator I = VisitedCallees.begin(),
E = VisitedCallees.end(); I != E; ++I) {
CallGraphNode *VN = CG.getNode(*I);
if (VN)
Visited.insert(VN);
}
while(!BFSQueue.empty()) {
CallGraphNode *N = BFSQueue.front();
BFSQueue.pop();
// Skip the functions which have been processed already or previously
// inlined.
if (Visited.count(N))
continue;
// Analyze the function.
SetOfDecls VisitedCallees;
Decl *D = N->getDecl();
assert(D);
HandleCode(D, ANALYSIS_PATH,
(Mgr->InliningMode == All ? 0 : &VisitedCallees));
// Add the visited callees to the global visited set.
for (SetOfDecls::const_iterator I = VisitedCallees.begin(),
E = VisitedCallees.end(); I != E; ++I) {
CallGraphNode *VN = CG.getNode(*I);
if (VN)
Visited.insert(VN);
}
Visited.insert(N);
// Push the children into the queue.
for (CallGraphNode::const_iterator CI = N->begin(),
CE = N->end(); CI != CE; ++CI) {
BFSQueue.push(*CI);
}
}
}
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment