[clang] 784bd61 - [clang] Speedup getFileIDLocal with a separate offset table. (#146604)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jul 7 00:42:41 PDT 2025
Author: Haojian Wu
Date: 2025-07-07T09:42:38+02:00
New Revision: 784bd61fc497b11a6d8d30abb6157c8a3597ffbf
URL: https://github.com/llvm/llvm-project/commit/784bd61fc497b11a6d8d30abb6157c8a3597ffbf
DIFF: https://github.com/llvm/llvm-project/commit/784bd61fc497b11a6d8d30abb6157c8a3597ffbf.diff
LOG: [clang] Speedup getFileIDLocal with a separate offset table. (#146604)
The `SLocEntry` structure is 24 bytes, and the binary search only needs
the offset. Loading an entry's offset might pull the entire SLocEntry
object into the CPU cache.
To make the binary search much more cache-efficient, we use a separate
offset table.
See
https://llvm-compile-time-tracker.com/compare.php?from=650d0151c623c123e4e9736fe50421624a329260&to=6af564c0d75aff28a2784a8554448c0679877792&stat=instructions:u.
Added:
Modified:
clang/include/clang/Basic/SourceManager.h
clang/lib/Basic/SourceManager.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h
index a90cc70825ffd..ed967fd47dc83 100644
--- a/clang/include/clang/Basic/SourceManager.h
+++ b/clang/include/clang/Basic/SourceManager.h
@@ -719,6 +719,8 @@ class SourceManager : public RefCountedBase<SourceManager> {
/// Positive FileIDs are indexes into this table. Entry 0 indicates an invalid
/// expansion.
SmallVector<SrcMgr::SLocEntry, 0> LocalSLocEntryTable;
+ /// An in-parallel offset table, merely used for speeding up FileID lookup.
+ SmallVector<SourceLocation::UIntTy> LocalLocOffsetTable;
/// The table of SLocEntries that are loaded from other modules.
///
diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp
index 7d1b23bbc3b2c..79a0d9d28c40b 100644
--- a/clang/lib/Basic/SourceManager.cpp
+++ b/clang/lib/Basic/SourceManager.cpp
@@ -329,6 +329,7 @@ SourceManager::~SourceManager() {
void SourceManager::clearIDTables() {
MainFileID = FileID();
LocalSLocEntryTable.clear();
+ LocalLocOffsetTable.clear();
LoadedSLocEntryTable.clear();
SLocEntryLoaded.clear();
SLocEntryOffsetLoaded.clear();
@@ -628,9 +629,11 @@ FileID SourceManager::createFileIDImpl(ContentCache &File, StringRef Filename,
noteSLocAddressSpaceUsage(Diag);
return FileID();
}
+ assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
LocalSLocEntryTable.push_back(
SLocEntry::get(NextLocalOffset,
FileInfo::get(IncludePos, File, FileCharacter, Filename)));
+ LocalLocOffsetTable.push_back(NextLocalOffset);
LastLookupStartOffset = NextLocalOffset;
// We do a +1 here because we want a SourceLocation that means "the end of the
// file", e.g. for the "no newline at the end of the file" diagnostic.
@@ -684,7 +687,9 @@ SourceManager::createExpansionLocImpl(const ExpansionInfo &Info,
SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] = true;
return SourceLocation::getMacroLoc(LoadedOffset);
}
+ assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info));
+ LocalLocOffsetTable.push_back(NextLocalOffset);
if (NextLocalOffset + Length + 1 <= NextLocalOffset ||
NextLocalOffset + Length + 1 > CurrentLoadedOffset) {
Diag.Report(diag::err_sloc_space_too_large);
@@ -807,6 +812,7 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const {
assert(SLocOffset < NextLocalOffset && "Bad function choice");
assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && SLocOffset > 0 &&
"Invalid SLocOffset");
+ assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
assert(LastFileIDLookup.ID >= 0 && "Only cache local file sloc entry");
// After the first and second level caches, I see two common sorts of
@@ -837,8 +843,8 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const {
unsigned NumProbes = 0;
while (true) {
--GreaterIndex;
- assert(GreaterIndex < LocalSLocEntryTable.size());
- if (LocalSLocEntryTable[GreaterIndex].getOffset() <= SLocOffset) {
+ assert(GreaterIndex < LocalLocOffsetTable.size());
+ if (LocalLocOffsetTable[GreaterIndex] <= SLocOffset) {
FileID Res = FileID::get(int(GreaterIndex));
// Remember it. We have good locality across FileID lookups.
LastFileIDLookup = Res;
@@ -858,11 +864,7 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const {
++NumBinaryProbes;
unsigned MiddleIndex = LessIndex + (GreaterIndex - LessIndex) / 2;
-
- SourceLocation::UIntTy MidOffset =
- LocalSLocEntryTable[MiddleIndex].getOffset();
-
- if (MidOffset <= SLocOffset)
+ if (LocalLocOffsetTable[MiddleIndex] <= SLocOffset)
LessIndex = MiddleIndex + 1;
else
GreaterIndex = MiddleIndex;
More information about the cfe-commits
mailing list