Skip to content

Commit 3881fb9

Browse files
committed
[clang] SourceManager: Cache offsets for LastFileIDLookup to speed up getFileID (llvm#146782)
`getFileID` is a hot method. By caching the offset range in `LastFileIDLookup`, we can more quickly check whether a given offset falls within it, avoiding calling `isOffsetInFileID`. https://llvm-compile-time-tracker.com/compare.php?from=0588e8188c647460b641b09467fe6b13a8d510d5&to=64843a500f0191b79a8109da9acd7e80d961c7a3&stat=instructions:u
1 parent 86eca47 commit 3881fb9

File tree

2 files changed

+21
-11
lines changed

2 files changed

+21
-11
lines changed

clang/include/clang/Basic/SourceManager.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -767,6 +767,8 @@ class SourceManager : public RefCountedBase<SourceManager> {
767767
/// LastFileIDLookup records the last FileID looked up or created, because it
768768
/// is very common to look up many tokens from the same file.
769769
mutable FileID LastFileIDLookup;
770+
mutable SourceLocation::UIntTy LastLookupStartOffset;
771+
mutable SourceLocation::UIntTy LastLookupEndOffset; // exclude
770772

771773
/// Holds information for \#line directives.
772774
///
@@ -1904,9 +1906,8 @@ class SourceManager : public RefCountedBase<SourceManager> {
19041906

19051907
FileID getFileID(SourceLocation::UIntTy SLocOffset) const {
19061908
// If our one-entry cache covers this offset, just return it.
1907-
if (isOffsetInFileID(LastFileIDLookup, SLocOffset))
1909+
if (SLocOffset >= LastLookupStartOffset && SLocOffset < LastLookupEndOffset)
19081910
return LastFileIDLookup;
1909-
19101911
return getFileIDSlow(SLocOffset);
19111912
}
19121913

clang/lib/Basic/SourceManager.cpp

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,7 @@ void SourceManager::clearIDTables() {
335335
LastLineNoFileIDQuery = FileID();
336336
LastLineNoContentCache = nullptr;
337337
LastFileIDLookup = FileID();
338+
LastLookupStartOffset = LastLookupEndOffset = 0;
338339

339340
IncludedLocMap.clear();
340341
if (LineTable)
@@ -640,9 +641,11 @@ FileID SourceManager::createFileIDImpl(ContentCache &File, StringRef Filename,
640641
LocalSLocEntryTable.push_back(
641642
SLocEntry::get(NextLocalOffset,
642643
FileInfo::get(IncludePos, File, FileCharacter, Filename)));
644+
LastLookupStartOffset = NextLocalOffset;
643645
// We do a +1 here because we want a SourceLocation that means "the end of the
644646
// file", e.g. for the "no newline at the end of the file" diagnostic.
645647
NextLocalOffset += FileSize + 1;
648+
LastLookupEndOffset = NextLocalOffset;
646649
updateSlocUsageStats();
647650

648651
// Set LastFileIDLookup to the newly created file. The next getFileID call is
@@ -812,8 +815,9 @@ FileID SourceManager::getFileIDSlow(SourceLocation::UIntTy SLocOffset) const {
812815
/// loaded one.
813816
FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const {
814817
assert(SLocOffset < NextLocalOffset && "Bad function choice");
815-
assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() &&
818+
assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && SLocOffset > 0 &&
816819
"Invalid SLocOffset");
820+
assert(LastFileIDLookup.ID >= 0 && "Only cache local file sloc entry");
817821

818822
// After the first and second level caches, I see two common sorts of
819823
// behavior: 1) a lot of searched FileID's are "near" the cached file
@@ -833,13 +837,11 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const {
833837
unsigned LessIndex = 0;
834838
// upper bound of the search range.
835839
unsigned GreaterIndex = LocalSLocEntryTable.size();
836-
if (LastFileIDLookup.ID >= 0) {
837-
// Use the LastFileIDLookup to prune the search space.
838-
if (LocalSLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset)
839-
LessIndex = LastFileIDLookup.ID;
840-
else
841-
GreaterIndex = LastFileIDLookup.ID;
842-
}
840+
// Use the LastFileIDLookup to prune the search space.
841+
if (LastLookupStartOffset < SLocOffset)
842+
LessIndex = LastFileIDLookup.ID;
843+
else
844+
GreaterIndex = LastFileIDLookup.ID;
843845

844846
// Find the FileID that contains this.
845847
unsigned NumProbes = 0;
@@ -850,7 +852,12 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const {
850852
FileID Res = FileID::get(int(GreaterIndex));
851853
// Remember it. We have good locality across FileID lookups.
852854
LastFileIDLookup = Res;
853-
NumLinearScans += NumProbes+1;
855+
LastLookupStartOffset = LocalSLocEntryTable[GreaterIndex].getOffset();
856+
LastLookupEndOffset =
857+
GreaterIndex + 1 >= LocalSLocEntryTable.size()
858+
? NextLocalOffset
859+
: LocalSLocEntryTable[GreaterIndex + 1].getOffset();
860+
NumLinearScans += NumProbes + 1;
854861
return Res;
855862
}
856863
if (++NumProbes == 8)
@@ -874,6 +881,8 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const {
874881
// At this point, LessIndex is the index of the *first element greater than*
875882
// SLocOffset. The element we are actually looking for is the one immediately
876883
// before it.
884+
LastLookupStartOffset = LocalSLocEntryTable[LessIndex - 1].getOffset();
885+
LastLookupEndOffset = LocalSLocEntryTable[LessIndex].getOffset();
877886
return LastFileIDLookup = FileID::get(LessIndex - 1);
878887
}
879888

0 commit comments

Comments
 (0)