Skip to content

Commit 8ece0b1

Browse files
committed
[clang] Speedup getFileIDLocal with a separate offset table. (llvm#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 3881fb9 commit 8ece0b1

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();
@@ -638,9 +639,11 @@ FileID SourceManager::createFileIDImpl(ContentCache &File, StringRef Filename,
638639
noteSLocAddressSpaceUsage(Diag);
639640
return FileID();
640641
}
642+
assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
641643
LocalSLocEntryTable.push_back(
642644
SLocEntry::get(NextLocalOffset,
643645
FileInfo::get(IncludePos, File, FileCharacter, Filename)));
646+
LocalLocOffsetTable.push_back(NextLocalOffset);
644647
LastLookupStartOffset = NextLocalOffset;
645648
// We do a +1 here because we want a SourceLocation that means "the end of the
646649
// file", e.g. for the "no newline at the end of the file" diagnostic.
@@ -694,7 +697,9 @@ SourceManager::createExpansionLocImpl(const ExpansionInfo &Info,
694697
SLocEntryLoaded[Index] = SLocEntryOffsetLoaded[Index] = true;
695698
return SourceLocation::getMacroLoc(LoadedOffset);
696699
}
700+
assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
697701
LocalSLocEntryTable.push_back(SLocEntry::get(NextLocalOffset, Info));
702+
LocalLocOffsetTable.push_back(NextLocalOffset);
698703
if (NextLocalOffset + Length + 1 <= NextLocalOffset ||
699704
NextLocalOffset + Length + 1 > CurrentLoadedOffset) {
700705
Diag.Report(diag::err_sloc_space_too_large);
@@ -817,6 +822,7 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const {
817822
assert(SLocOffset < NextLocalOffset && "Bad function choice");
818823
assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && SLocOffset > 0 &&
819824
"Invalid SLocOffset");
825+
assert(LocalSLocEntryTable.size() == LocalLocOffsetTable.size());
820826
assert(LastFileIDLookup.ID >= 0 && "Only cache local file sloc entry");
821827

822828
// After the first and second level caches, I see two common sorts of
@@ -847,8 +853,8 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const {
847853
unsigned NumProbes = 0;
848854
while (true) {
849855
--GreaterIndex;
850-
assert(GreaterIndex < LocalSLocEntryTable.size());
851-
if (LocalSLocEntryTable[GreaterIndex].getOffset() <= SLocOffset) {
856+
assert(GreaterIndex < LocalLocOffsetTable.size());
857+
if (LocalLocOffsetTable[GreaterIndex] <= SLocOffset) {
852858
FileID Res = FileID::get(int(GreaterIndex));
853859
// Remember it. We have good locality across FileID lookups.
854860
LastFileIDLookup = Res;
@@ -868,11 +874,7 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const {
868874
++NumBinaryProbes;
869875

870876
unsigned MiddleIndex = LessIndex + (GreaterIndex - LessIndex) / 2;
871-
872-
SourceLocation::UIntTy MidOffset =
873-
LocalSLocEntryTable[MiddleIndex].getOffset();
874-
875-
if (MidOffset <= SLocOffset)
877+
if (LocalLocOffsetTable[MiddleIndex] <= SLocOffset)
876878
LessIndex = MiddleIndex + 1;
877879
else
878880
GreaterIndex = MiddleIndex;

0 commit comments

Comments
 (0)