Author: rsmith Date: Wed Feb 17 15:52:44 2016 New Revision: 261161 URL: http://llvm.org/viewvc/llvm-project?rev=261161&view=rev Log: [modules] Cache 'acceptable decl' lookups for namespaces. In projects with thousands of modules, each of which declares the same namespace, linearly scanning the redecl chain looking for a visible declaration (once for each leaf module, for each use) performs very poorly. Namespace visibility can only decrease when we leave a module during a module build step, and we never care *which* visible declaration of a namespace we find, so we can cache this very effectively.
This results in a 35x speedup on one of our internal build steps (2m -> 3.5s), but is hard to unit test because it requires a very large number of modules. Ideas for a test appreciated! No functionality change intended other than the speedup. Modified: cfe/trunk/include/clang/Sema/Sema.h cfe/trunk/lib/Sema/SemaDecl.cpp cfe/trunk/lib/Sema/SemaLookup.cpp Modified: cfe/trunk/include/clang/Sema/Sema.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Sema/Sema.h?rev=261161&r1=261160&r2=261161&view=diff ============================================================================== --- cfe/trunk/include/clang/Sema/Sema.h (original) +++ cfe/trunk/include/clang/Sema/Sema.h Wed Feb 17 15:52:44 2016 @@ -6617,6 +6617,10 @@ public: /// template defined within it. llvm::DenseSet<Module*> &getLookupModules(); + /// \brief Map from the most recent declaration of a namespace to the most + /// recent visible declaration of that namespace. + llvm::DenseMap<NamedDecl*, NamedDecl*> VisibleNamespaceCache; + /// \brief Whether we are in a SFINAE context that is not associated with /// template instantiation. /// Modified: cfe/trunk/lib/Sema/SemaDecl.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=261161&r1=261160&r2=261161&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaDecl.cpp (original) +++ cfe/trunk/lib/Sema/SemaDecl.cpp Wed Feb 17 15:52:44 2016 @@ -14826,6 +14826,9 @@ void Sema::ActOnModuleEnd(SourceLocation VisibleModules = std::move(VisibleModulesStack.back()); VisibleModulesStack.pop_back(); VisibleModules.setVisible(Mod, DirectiveLoc); + // Leaving a module hides namespace names, so our visible namespace cache + // is now out of date. + VisibleNamespaceCache.clear(); } } Modified: cfe/trunk/lib/Sema/SemaLookup.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaLookup.cpp?rev=261161&r1=261160&r2=261161&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaLookup.cpp (original) +++ cfe/trunk/lib/Sema/SemaLookup.cpp Wed Feb 17 15:52:44 2016 @@ -1566,6 +1566,10 @@ static NamedDecl *findAcceptableDecl(Sem assert(!LookupResult::isVisible(SemaRef, D) && "not in slow case"); for (auto RD : D->redecls()) { + // Don't bother with extra checks if we already know this one isn't visible. + if (RD == D) + continue; + if (auto ND = dyn_cast<NamedDecl>(RD)) { // FIXME: This is wrong in the case where the previous declaration is not // visible in the same scope as D. This needs to be done much more @@ -1579,6 +1583,23 @@ static NamedDecl *findAcceptableDecl(Sem } NamedDecl *LookupResult::getAcceptableDeclSlow(NamedDecl *D) const { + if (auto *ND = dyn_cast<NamespaceDecl>(D)) { + // Namespaces are a bit of a special case: we expect there to be a lot of + // redeclarations of some namespaces, all declarations of a namespace are + // essentially interchangeable, all declarations are found by name lookup + // if any is, and namespaces are never looked up during template + // instantiation. So we benefit from caching the check in this case, and + // it is correct to do so. + auto *Key = ND->getCanonicalDecl(); + if (auto *Acceptable = getSema().VisibleNamespaceCache.lookup(Key)) + return Acceptable; + auto *Acceptable = + isVisible(getSema(), Key) ? Key : findAcceptableDecl(getSema(), Key); + if (Acceptable) + getSema().VisibleNamespaceCache.insert(std::make_pair(Key, Acceptable)); + return Acceptable; + } + return findAcceptableDecl(getSema(), D); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits