Skip to content

Commit fbb3762

Browse files
committed
[cxx-interop] Improve performance of importing C++ namespaces
When ClangImporter calls Clang to import a module, Clang calls `SwiftLookupTableWriter::writeExtensionContents` for each namespace redecl, which called `addEntryToLookupTable` (a few frames omitted) which iterated over all of the namespace redecls, doing duplicate work. This caused the complexity to degrade from linear to quadratic. `SwiftDeclConverter::VisitNamespaceDecl` is still called once per namespace, not per redecl, so we need to iterate over all the redecls there. This dramatically improves the build time for SwiftCompilerSources when importing Clang headers in addition to LLVM headers.
1 parent 8165806 commit fbb3762

File tree

2 files changed

+22
-20
lines changed

2 files changed

+22
-20
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1129,11 +1129,13 @@ namespace {
11291129
for (auto redecl : decl->redecls())
11301130
Impl.ImportedDecls[{redecl, getVersion()}] = enumDecl;
11311131

1132-
// Because a namespaces's decl context is the bridging header, make sure
1133-
// we add them to the bridging header lookup table.
1134-
addEntryToLookupTable(*Impl.BridgingHeaderLookupTable,
1135-
const_cast<clang::NamespaceDecl *>(decl),
1136-
Impl.getNameImporter());
1132+
for (auto redecl : decl->redecls()) {
1133+
// Because a namespaces's decl context is the bridging header, make sure
1134+
// we add them to the bridging header lookup table.
1135+
addEntryToLookupTable(*Impl.BridgingHeaderLookupTable,
1136+
const_cast<clang::NamespaceDecl *>(redecl),
1137+
Impl.getNameImporter());
1138+
}
11371139

11381140
return enumDecl;
11391141
}

lib/ClangImporter/SwiftLookupTable.cpp

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1960,21 +1960,21 @@ void importer::addEntryToLookupTable(SwiftLookupTable &table,
19601960
llvm::SmallPtrSet<clang::Decl *, 8> alreadyAdded;
19611961
alreadyAdded.insert(named->getCanonicalDecl());
19621962

1963-
for (auto redecl : named->redecls()) {
1964-
auto dc = cast<clang::DeclContext>(redecl);
1965-
for (auto member : dc->decls()) {
1966-
auto canonicalMember = member->getCanonicalDecl();
1967-
if (!alreadyAdded.insert(canonicalMember).second)
1968-
continue;
1969-
1970-
if (auto namedMember = dyn_cast<clang::NamedDecl>(canonicalMember)) {
1971-
// Make sure we're looking at the definition, otherwise, there won't
1972-
// be any members to add.
1973-
if (auto recordDecl = dyn_cast<clang::RecordDecl>(namedMember))
1974-
if (auto def = recordDecl->getDefinition())
1975-
namedMember = def;
1976-
addEntryToLookupTable(table, namedMember, nameImporter);
1977-
}
1963+
auto dc = cast<clang::DeclContext>(named);
1964+
for (auto member : dc->decls()) {
1965+
auto canonicalMember = isa<clang::NamespaceDecl>(member)
1966+
? member
1967+
: member->getCanonicalDecl();
1968+
if (!alreadyAdded.insert(canonicalMember).second)
1969+
continue;
1970+
1971+
if (auto namedMember = dyn_cast<clang::NamedDecl>(canonicalMember)) {
1972+
// Make sure we're looking at the definition, otherwise, there won't
1973+
// be any members to add.
1974+
if (auto recordDecl = dyn_cast<clang::RecordDecl>(namedMember))
1975+
if (auto def = recordDecl->getDefinition())
1976+
namedMember = def;
1977+
addEntryToLookupTable(table, namedMember, nameImporter);
19781978
}
19791979
}
19801980
}

0 commit comments

Comments
 (0)