summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaLookup.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2016-02-17 21:52:44 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2016-02-17 21:52:44 +0000
commit4083e038e918ccc1a5800f424c3e814bdd425e79 (patch)
treef254d8df01cd7aecb0931cbcbc83d47129756e76 /clang/lib/Sema/SemaLookup.cpp
parentd4590c7304575702731b00749ae22e1298a98eba (diff)
downloadbcm5719-llvm-4083e038e918ccc1a5800f424c3e814bdd425e79.tar.gz
bcm5719-llvm-4083e038e918ccc1a5800f424c3e814bdd425e79.zip
[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. llvm-svn: 261161
Diffstat (limited to 'clang/lib/Sema/SemaLookup.cpp')
-rw-r--r--clang/lib/Sema/SemaLookup.cpp21
1 files changed, 21 insertions, 0 deletions
diff --git a/clang/lib/Sema/SemaLookup.cpp b/clang/lib/Sema/SemaLookup.cpp
index 3efcf5a3e41..a35c7600ab5 100644
--- a/clang/lib/Sema/SemaLookup.cpp
+++ b/clang/lib/Sema/SemaLookup.cpp
@@ -1566,6 +1566,10 @@ static NamedDecl *findAcceptableDecl(Sema &SemaRef, NamedDecl *D) {
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(Sema &SemaRef, NamedDecl *D) {
}
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);
}
OpenPOWER on IntegriCloud