diff options
author | Jan Svoboda <jan_svoboda@apple.com> | 2023-10-06 23:52:19 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-10-06 14:52:19 -0700 |
commit | 537344fc502474545d332bf5592db257cc568250 (patch) | |
tree | 682c5ad7a1dc993f3857d32646ab4405c3a99a85 /clang/lib/Basic/SourceManager.cpp | |
parent | 8eff5e4b696d2b70e46bcea7a81288a823906f20 (diff) | |
download | llvm-537344fc502474545d332bf5592db257cc568250.zip llvm-537344fc502474545d332bf5592db257cc568250.tar.gz llvm-537344fc502474545d332bf5592db257cc568250.tar.bz2 |
[clang][modules] Move `SLocEntry` search into `ASTReader` (#66966)
In `SourceManager::getFileID()`, Clang performs binary search over its
buffer of `SLocEntries`. For modules, this binary search fully
deserializes the entire `SLocEntry` block for each visited entry. For
some entries, that includes decompressing the associated buffer (e.g.
the predefines buffer, macro expansion buffers, contents of volatile
files), which shows up in profiles of the dependency scanner.
This patch moves the binary search over loaded entries into `ASTReader`,
which can perform cheaper partial deserialization during the binary
search, reducing the wall time of dependency scans by ~3%. This also
reduces the number of retired instructions by ~1.4% on regular
(implicit) modules compilation.
Note that this patch drops the optimizations based on the last lookup ID
(pruning the search space and performing linear search before resorting
to the full binary search). Instead, it reduces the search space by
asking `ASTReader::GlobalSLocOffsetMap` for the containing `ModuleFile`
and only does binary search over entries of single module file.
Diffstat (limited to 'clang/lib/Basic/SourceManager.cpp')
-rw-r--r-- | clang/lib/Basic/SourceManager.cpp | 70 |
1 files changed, 5 insertions, 65 deletions
diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index b8e7650..4ce8926 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -337,6 +337,7 @@ void SourceManager::clearIDTables() { LocalSLocEntryTable.clear(); LoadedSLocEntryTable.clear(); SLocEntryLoaded.clear(); + SLocEntryOffsetLoaded.clear(); LastLineNoFileIDQuery = FileID(); LastLineNoContentCache = nullptr; LastFileIDLookup = FileID(); @@ -459,6 +460,7 @@ SourceManager::AllocateLoadedSLocEntries(unsigned NumSLocEntries, } LoadedSLocEntryTable.resize(LoadedSLocEntryTable.size() + NumSLocEntries); SLocEntryLoaded.resize(LoadedSLocEntryTable.size()); + SLocEntryOffsetLoaded.resize(LoadedSLocEntryTable.size()); CurrentLoadedOffset -= TotalSize; int BaseID = -int(LoadedSLocEntryTable.size()) - 1; LoadedSLocEntryAllocBegin.push_back(FileID::get(BaseID)); @@ -597,7 +599,7 @@ FileID SourceManager::createFileIDImpl(ContentCache &File, StringRef Filename, assert(!SLocEntryLoaded[Index] && "FileID already loaded"); LoadedSLocEntryTable[Index] = SLocEntry::get( LoadedOffset, FileInfo::get(IncludePos, File, FileCharacter, Filename)); - SLocEntryLoaded[Index] = true; + SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] = true; return FileID::get(LoadedID); } unsigned FileSize = File.getSize(); @@ -657,7 +659,7 @@ SourceManager::createExpansionLocImpl(const ExpansionInfo &Info, assert(Index < LoadedSLocEntryTable.size() && "FileID out of range"); assert(!SLocEntryLoaded[Index] && "FileID already loaded"); LoadedSLocEntryTable[Index] = SLocEntry::get(LoadedOffset, Info); - SLocEntryLoaded[Index] = true; + SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] = true; return SourceLocation::getMacroLoc(LoadedOffset); } LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info)); @@ -858,69 +860,7 @@ FileID SourceManager::getFileIDLoaded(SourceLocation::UIntTy SLocOffset) const { return FileID(); } - // Essentially the same as the local case, but the loaded array is sorted - // in the other direction (decreasing order). - // GreaterIndex is the one where the offset is greater, which is actually a - // lower index! - unsigned GreaterIndex = 0; - unsigned LessIndex = LoadedSLocEntryTable.size(); - if (LastFileIDLookup.ID < 0) { - // Prune the search space. - int LastID = LastFileIDLookup.ID; - if (getLoadedSLocEntryByID(LastID).getOffset() > SLocOffset) - GreaterIndex = - (-LastID - 2) + 1; // Exclude LastID, else we would have hit the cache - else - LessIndex = -LastID - 2; - } - - // First do a linear scan from the last lookup position, if possible. - unsigned NumProbes; - bool Invalid = false; - for (NumProbes = 0; NumProbes < 8; ++NumProbes, ++GreaterIndex) { - // Make sure the entry is loaded! - const SrcMgr::SLocEntry &E = getLoadedSLocEntry(GreaterIndex, &Invalid); - if (Invalid) - return FileID(); // invalid entry. - if (E.getOffset() <= SLocOffset) { - FileID Res = FileID::get(-int(GreaterIndex) - 2); - LastFileIDLookup = Res; - NumLinearScans += NumProbes + 1; - return Res; - } - } - - // Linear scan failed. Do the binary search. - NumProbes = 0; - while (true) { - ++NumProbes; - unsigned MiddleIndex = (LessIndex - GreaterIndex) / 2 + GreaterIndex; - const SrcMgr::SLocEntry &E = getLoadedSLocEntry(MiddleIndex, &Invalid); - if (Invalid) - return FileID(); // invalid entry. - - if (E.getOffset() > SLocOffset) { - if (GreaterIndex == MiddleIndex) { - assert(0 && "binary search missed the entry"); - return FileID(); - } - GreaterIndex = MiddleIndex; - continue; - } - - if (isOffsetInFileID(FileID::get(-int(MiddleIndex) - 2), SLocOffset)) { - FileID Res = FileID::get(-int(MiddleIndex) - 2); - LastFileIDLookup = Res; - NumBinaryProbes += NumProbes; - return Res; - } - - if (LessIndex == MiddleIndex) { - assert(0 && "binary search missed the entry"); - return FileID(); - } - LessIndex = MiddleIndex; - } + return FileID::get(ExternalSLocEntries->getSLocEntryID(SLocOffset)); } SourceLocation SourceManager:: |