@@ -555,7 +555,25 @@ namespace {
555555
556556using MacroDefinitionsMap =
557557 llvm::StringMap<std::pair<StringRef, bool /* IsUndef*/ >>;
558- using DeclsMap = llvm::DenseMap<DeclarationName, SmallVector<NamedDecl *, 8 >>;
558+
559+ class DeclsSet {
560+ SmallVector<NamedDecl *, 64 > Decls;
561+ llvm::SmallPtrSet<NamedDecl *, 8 > Found;
562+
563+ public:
564+ operator ArrayRef<NamedDecl *>() const { return Decls; }
565+
566+ bool empty () const { return Decls.empty (); }
567+
568+ bool insert (NamedDecl *ND) {
569+ auto [_, Inserted] = Found.insert (ND);
570+ if (Inserted)
571+ Decls.push_back (ND);
572+ return Inserted;
573+ }
574+ };
575+
576+ using DeclsMap = llvm::DenseMap<DeclarationName, DeclsSet>;
559577
560578} // namespace
561579
@@ -8702,14 +8720,23 @@ bool ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
87028720 return false ;
87038721
87048722 // Load the list of declarations.
8705- SmallVector<NamedDecl *, 64 > Decls;
8706- llvm::SmallPtrSet<NamedDecl *, 8 > Found;
8723+ DeclsSet DS;
87078724
87088725 auto Find = [&, this ](auto &&Table, auto &&Key) {
87098726 for (GlobalDeclID ID : Table.find (Key)) {
87108727 NamedDecl *ND = cast<NamedDecl>(GetDecl (ID));
8711- if (ND->getDeclName () == Name && Found.insert (ND).second )
8712- Decls.push_back (ND);
8728+ if (ND->getDeclName () != Name)
8729+ continue ;
8730+ // Special case for namespaces: There can be a lot of redeclarations of
8731+ // some namespaces, and we import a "key declaration" per imported module.
8732+ // Since all declarations of a namespace are essentially interchangeable,
8733+ // we can optimize namespace look-up by only storing the key declaration
8734+ // of the current TU, rather than storing N key declarations where N is
8735+ // the # of imported modules that declare that namespace.
8736+ // TODO: Try to generalize this optimization to other redeclarable decls.
8737+ if (isa<NamespaceDecl>(ND))
8738+ ND = cast<NamedDecl>(getKeyDeclaration (ND));
8739+ DS.insert (ND);
87138740 }
87148741 };
87158742
@@ -8744,8 +8771,8 @@ bool ASTReader::FindExternalVisibleDeclsByName(const DeclContext *DC,
87448771 Find (It->second .Table , Name);
87458772 }
87468773
8747- SetExternalVisibleDeclsForName (DC, Name, Decls );
8748- return !Decls .empty ();
8774+ SetExternalVisibleDeclsForName (DC, Name, DS );
8775+ return !DS .empty ();
87498776}
87508777
87518778void ASTReader::completeVisibleDeclsMap (const DeclContext *DC) {
@@ -8763,7 +8790,16 @@ void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) {
87638790
87648791 for (GlobalDeclID ID : It->second .Table .findAll ()) {
87658792 NamedDecl *ND = cast<NamedDecl>(GetDecl (ID));
8766- Decls[ND->getDeclName ()].push_back (ND);
8793+ // Special case for namespaces: There can be a lot of redeclarations of
8794+ // some namespaces, and we import a "key declaration" per imported module.
8795+ // Since all declarations of a namespace are essentially interchangeable,
8796+ // we can optimize namespace look-up by only storing the key declaration
8797+ // of the current TU, rather than storing N key declarations where N is
8798+ // the # of imported modules that declare that namespace.
8799+ // TODO: Try to generalize this optimization to other redeclarable decls.
8800+ if (isa<NamespaceDecl>(ND))
8801+ ND = cast<NamedDecl>(getKeyDeclaration (ND));
8802+ Decls[ND->getDeclName ()].insert (ND);
87678803 }
87688804
87698805 // FIXME: Why a PCH test is failing if we remove the iterator after findAll?
@@ -8773,9 +8809,9 @@ void ASTReader::completeVisibleDeclsMap(const DeclContext *DC) {
87738809 findAll (ModuleLocalLookups, NumModuleLocalVisibleDeclContexts);
87748810 findAll (TULocalLookups, NumTULocalVisibleDeclContexts);
87758811
8776- for (DeclsMap::iterator I = Decls. begin (), E = Decls. end (); I != E; ++I) {
8777- SetExternalVisibleDeclsForName (DC, I-> first , I-> second );
8778- }
8812+ for (auto &[Name, DS] : Decls)
8813+ SetExternalVisibleDeclsForName (DC, Name, DS );
8814+
87798815 const_cast <DeclContext *>(DC)->setHasExternalVisibleStorage (false );
87808816}
87818817
0 commit comments