Skip to content

Commit 784bd61

Browse files
authored
[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.
1 parent b7d4735 commit 784bd61

File tree

2 files changed

+11
-7
lines changed

2 files changed

+11
-7
lines changed

clang/include/clang/Basic/SourceManager.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,8 @@ class SourceManager : public RefCountedBase<SourceManager> {
719719
/// Positive FileIDs are indexes into this table. Entry 0 indicates an invalid
720720
/// expansion.
721721
SmallVector<SrcMgr::SLocEntry, 0> LocalSLocEntryTable;
722+
/// An in-parallel offset table, merely used for speeding up FileID lookup.
723+
SmallVector<SourceLocation::UIntTy> LocalLocOffsetTable;
722724

723725
/// The table of SLocEntries that are loaded from other modules.
724726
///

clang/lib/Basic/SourceManager.cpp

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,7 @@ SourceManager::~SourceManager() {
329329
void SourceManager::clearIDTables() {
330330
MainFileID = FileID();
331331
LocalSLocEntryTable.clear();
332+
LocalLocOffsetTable.clear();
332333
LoadedSLocEntryTable.clear();
333334
SLocEntryLoaded.clear();
334335
SLocEntryOffsetLoaded.clear();
@@ -628,9 +629,11 @@ FileID SourceManager::createFileIDImpl(ContentCache &File, StringRef Filename,
628629
noteSLocAddressSpaceUsage(Diag);
629630
return FileID();
630631
}
632+
assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
631633
LocalSLocEntryTable.push_back(
632634
SLocEntry::get(NextLocalOffset,
633635
FileInfo::get(IncludePos, File, FileCharacter, Filename)));
636+
LocalLocOffsetTable.push_back(NextLocalOffset);
634637
LastLookupStartOffset = NextLocalOffset;
635638
// We do a +1 here because we want a SourceLocation that means "the end of the
636639
// file", e.g. for the "no newline at the end of the file" diagnostic.
@@ -684,7 +687,9 @@ SourceManager::createExpansionLocImpl(const ExpansionInfo &Info,
684687
SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] = true;
685688
return SourceLocation::getMacroLoc(LoadedOffset);
686689
}
690+
assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
687691
LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info));
692+
LocalLocOffsetTable.push_back(NextLocalOffset);
688693
if (NextLocalOffset + Length + 1 <= NextLocalOffset ||
689694
NextLocalOffset + Length + 1 > CurrentLoadedOffset) {
690695
Diag.Report(diag::err_sloc_space_too_large);
@@ -807,6 +812,7 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const {
807812
assert(SLocOffset < NextLocalOffset && "Bad function choice");
808813
assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && SLocOffset > 0 &&
809814
"Invalid SLocOffset");
815+
assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
810816
assert(LastFileIDLookup.ID >= 0 && "Only cache local file sloc entry");
811817

812818
// After the first and second level caches, I see two common sorts of
@@ -837,8 +843,8 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const {
837843
unsigned NumProbes = 0;
838844
while (true) {
839845
--GreaterIndex;
840-
assert(GreaterIndex < LocalSLocEntryTable.size());
841-
if (LocalSLocEntryTable[GreaterIndex].getOffset() <= SLocOffset) {
846+
assert(GreaterIndex < LocalLocOffsetTable.size());
847+
if (LocalLocOffsetTable[GreaterIndex] <= SLocOffset) {
842848
FileID Res = FileID::get(int(GreaterIndex));
843849
// Remember it. We have good locality across FileID lookups.
844850
LastFileIDLookup = Res;
@@ -858,11 +864,7 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const {
858864
++NumBinaryProbes;
859865

860866
unsigned MiddleIndex = LessIndex + (GreaterIndex - LessIndex) / 2;
861-
862-
SourceLocation::UIntTy MidOffset =
863-
LocalSLocEntryTable[MiddleIndex].getOffset();
864-
865-
if (MidOffset <= SLocOffset)
867+
if (LocalLocOffsetTable[MiddleIndex] <= SLocOffset)
866868
LessIndex = MiddleIndex + 1;
867869
else
868870
GreaterIndex = MiddleIndex;

0 commit comments

Comments
 (0)