diff options
author | Douglas Gregor <dgregor@apple.com> | 2013-01-25 22:25:23 +0000 |
---|---|---|
committer | Douglas Gregor <dgregor@apple.com> | 2013-01-25 22:25:23 +0000 |
commit | d07865b42dcb32154c75134fded51b38cc55a0c4 (patch) | |
tree | 80b256b1e5115d5116ef9a7ad8737ad8bc25474b /lib | |
parent | 3d115cfd1b9c48155d478b1f2f14dba1b6ba9a91 (diff) |
Optimize ModuleManager::visit() by precomputing the visitation order
and limiting ourselves to two memory allocations. 10% speedup in
-fsyntax-only time for modules.
With this change, we can actually see some performance different from
the global module index, but it's still about 1%.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@173512 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Serialization/ModuleManager.cpp | 147 |
1 files changed, 82 insertions, 65 deletions
diff --git a/lib/Serialization/ModuleManager.cpp b/lib/Serialization/ModuleManager.cpp index c600c053b5..f3fe2b96d5 100644 --- a/lib/Serialization/ModuleManager.cpp +++ b/lib/Serialization/ModuleManager.cpp @@ -149,77 +149,94 @@ ModuleManager::~ModuleManager() { void ModuleManager::visit(bool (*Visitor)(ModuleFile &M, void *UserData), void *UserData) { - unsigned N = size(); - - // Record the number of incoming edges for each module. When we - // encounter a module with no incoming edges, push it into the queue - // to seed the queue. - SmallVector<ModuleFile *, 4> Queue; - Queue.reserve(N); - llvm::SmallVector<unsigned, 4> UnusedIncomingEdges; - UnusedIncomingEdges.reserve(size()); - for (ModuleIterator M = begin(), MEnd = end(); M != MEnd; ++M) { - if (unsigned Size = (*M)->ImportedBy.size()) - UnusedIncomingEdges.push_back(Size); - else { - UnusedIncomingEdges.push_back(0); - Queue.push_back(*M); + // If the visitation number array is the wrong size, resize it and recompute + // an order. + if (VisitOrder.size() != Chain.size()) { + unsigned N = size(); + VisitOrder.clear(); + VisitOrder.reserve(N); + + // Record the number of incoming edges for each module. When we + // encounter a module with no incoming edges, push it into the queue + // to seed the queue. + SmallVector<ModuleFile *, 4> Queue; + Queue.reserve(N); + llvm::SmallVector<unsigned, 4> UnusedIncomingEdges; + UnusedIncomingEdges.reserve(size()); + for (ModuleIterator M = begin(), MEnd = end(); M != MEnd; ++M) { + if (unsigned Size = (*M)->ImportedBy.size()) + UnusedIncomingEdges.push_back(Size); + else { + UnusedIncomingEdges.push_back(0); + Queue.push_back(*M); + } + } + + // Traverse the graph, making sure to visit a module before visiting any + // of its dependencies. + unsigned QueueStart = 0; + while (QueueStart < Queue.size()) { + ModuleFile *CurrentModule = Queue[QueueStart++]; + VisitOrder.push_back(CurrentModule); + + // For any module that this module depends on, push it on the + // stack (if it hasn't already been marked as visited). + for (llvm::SetVector<ModuleFile *>::iterator + M = CurrentModule->Imports.begin(), + MEnd = CurrentModule->Imports.end(); + M != MEnd; ++M) { + // Remove our current module as an impediment to visiting the + // module we depend on. If we were the last unvisited module + // that depends on this particular module, push it into the + // queue to be visited. + unsigned &NumUnusedEdges = UnusedIncomingEdges[(*M)->Index]; + if (NumUnusedEdges && (--NumUnusedEdges == 0)) + Queue.push_back(*M); + } } + + assert(VisitOrder.size() == N && "Visitation order is wrong?"); } - llvm::SmallVector<bool, 4> Skipped(size(), false); - unsigned QueueStart = 0; - while (QueueStart < Queue.size()) { - ModuleFile *CurrentModule = Queue[QueueStart++]; - - // Check whether this module should be skipped. - if (Skipped[CurrentModule->Index]) + SmallVector<ModuleFile *, 4> Stack; + SmallVector<bool, 4> Visited(size(), false); + + for (unsigned I = 0, N = VisitOrder.size(); I != N; ++I) { + ModuleFile *CurrentModule = VisitOrder[I]; + // Should we skip this module file? + if (Visited[CurrentModule->Index]) continue; - Skipped[CurrentModule->Index] = true; - - if (Visitor(*CurrentModule, UserData)) { - // The visitor has requested that cut off visitation of any - // module that the current module depends on. To indicate this - // behavior, we mark all of the reachable modules as "skipped". - SmallVector<ModuleFile *, 4> Stack; - Stack.push_back(CurrentModule); - Skipped[CurrentModule->Index] = true; - while (!Stack.empty()) { - ModuleFile *NextModule = Stack.back(); - Stack.pop_back(); - - // For any module that this module depends on, push it on the - // stack (if it hasn't already been marked as visited). - for (llvm::SetVector<ModuleFile *>::iterator - M = NextModule->Imports.begin(), - MEnd = NextModule->Imports.end(); - M != MEnd; ++M) { - if (!Skipped[(*M)->Index]) { - Stack.push_back(*M); - Skipped[(*M)->Index] = true; - } + + // Visit the module. + Visited[CurrentModule->Index] = true; + if (!Visitor(*CurrentModule, UserData)) + continue; + + // The visitor has requested that cut off visitation of any + // module that the current module depends on. To indicate this + // behavior, we mark all of the reachable modules as having been visited. + ModuleFile *NextModule = CurrentModule; + Stack.reserve(size()); + do { + // For any module that this module depends on, push it on the + // stack (if it hasn't already been marked as visited). + for (llvm::SetVector<ModuleFile *>::iterator + M = NextModule->Imports.begin(), + MEnd = NextModule->Imports.end(); + M != MEnd; ++M) { + if (!Visited[(*M)->Index]) { + Stack.push_back(*M); + Visited[(*M)->Index] = true; } } - continue; - } - - // For any module that this module depends on, push it on the - // stack (if it hasn't already been marked as visited). - for (llvm::SetVector<ModuleFile *>::iterator - M = CurrentModule->Imports.begin(), - MEnd = CurrentModule->Imports.end(); - M != MEnd; ++M) { - if (Skipped[(*M)->Index]) - continue; - - // Remove our current module as an impediment to visiting the - // module we depend on. If we were the last unvisited module - // that depends on this particular module, push it into the - // queue to be visited. - unsigned &NumUnusedEdges = UnusedIncomingEdges[(*M)->Index]; - if (NumUnusedEdges && (--NumUnusedEdges == 0)) - Queue.push_back(*M); - } + + if (Stack.empty()) + break; + + // Pop the next module off the stack. + NextModule = Stack.back(); + Stack.pop_back(); + } while (true); } } |