https://github.com/hokein updated https://github.com/llvm/llvm-project/pull/146782
>From 50c6fcb2a1167b65255d2edce9ef34789b85a7a5 Mon Sep 17 00:00:00 2001 From: Haojian Wu <hokein...@gmail.com> Date: Wed, 2 Jul 2025 16:22:48 +0200 Subject: [PATCH 1/3] Cache the Offset for LastFileIDLookup. --- clang/include/clang/Basic/SourceManager.h | 5 +++-- clang/lib/Basic/SourceManager.cpp | 24 +++++++++++++++-------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h index eefd4885534c8..a90cc70825ffd 100644 --- a/clang/include/clang/Basic/SourceManager.h +++ b/clang/include/clang/Basic/SourceManager.h @@ -767,6 +767,8 @@ class SourceManager : public RefCountedBase<SourceManager> { /// LastFileIDLookup records the last FileID looked up or created, because it /// is very common to look up many tokens from the same file. mutable FileID LastFileIDLookup; + mutable SourceLocation::UIntTy LastLookupStartOffset; + mutable SourceLocation::UIntTy LastLookupEndOffset; // exclude /// Holds information for \#line directives. /// @@ -1901,9 +1903,8 @@ class SourceManager : public RefCountedBase<SourceManager> { FileID getFileID(SourceLocation::UIntTy SLocOffset) const { // If our one-entry cache covers this offset, just return it. - if (isOffsetInFileID(LastFileIDLookup, SLocOffset)) + if (SLocOffset >= LastLookupStartOffset && SLocOffset < LastLookupEndOffset) return LastFileIDLookup; - return getFileIDSlow(SLocOffset); } diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index 82096421f8579..8c1d9662d4579 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -334,6 +334,7 @@ void SourceManager::clearIDTables() { LastLineNoFileIDQuery = FileID(); LastLineNoContentCache = nullptr; LastFileIDLookup = FileID(); + LastLookupStartOffset = LastLookupEndOffset = 0; IncludedLocMap.clear(); if (LineTable) @@ -639,9 +640,11 @@ FileID SourceManager::createFileIDImpl(ContentCache &File, StringRef Filename, LocalSLocEntryTable.push_back( SLocEntry::get(NextLocalOffset, FileInfo::get(IncludePos, File, FileCharacter, Filename))); + 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. NextLocalOffset += FileSize + 1; + LastLookupEndOffset = NextLocalOffset; updateSlocUsageStats(); // Set LastFileIDLookup to the newly created file. The next getFileID call is @@ -832,13 +835,11 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const { unsigned LessIndex = 0; // upper bound of the search range. unsigned GreaterIndex = LocalSLocEntryTable.size(); - if (LastFileIDLookup.ID >= 0) { - // Use the LastFileIDLookup to prune the search space. - if (LocalSLocEntryTable[LastFileIDLookup.ID].getOffset() < SLocOffset) - LessIndex = LastFileIDLookup.ID; - else - GreaterIndex = LastFileIDLookup.ID; - } + // Use the LastFileIDLookup to prune the search space. + if (LastLookupStartOffset < SLocOffset) + LessIndex = LastFileIDLookup.ID; + else + GreaterIndex = LastFileIDLookup.ID; // Find the FileID that contains this. unsigned NumProbes = 0; @@ -849,7 +850,12 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const { FileID Res = FileID::get(int(GreaterIndex)); // Remember it. We have good locality across FileID lookups. LastFileIDLookup = Res; - NumLinearScans += NumProbes+1; + LastLookupStartOffset = LocalSLocEntryTable[GreaterIndex].getOffset(); + LastLookupEndOffset = + GreaterIndex + 1 >= LocalSLocEntryTable.size() + ? NextLocalOffset + : LocalSLocEntryTable[GreaterIndex + 1].getOffset(); + NumLinearScans += NumProbes + 1; return Res; } if (++NumProbes == 8) @@ -873,6 +879,8 @@ FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const { // At this point, LessIndex is the index of the *first element greater than* // SLocOffset. The element we are actually looking for is the one immediately // before it. + LastLookupStartOffset = LocalSLocEntryTable[LessIndex - 1].getOffset(); + LastLookupEndOffset = LocalSLocEntryTable[LessIndex].getOffset(); return LastFileIDLookup = FileID::get(LessIndex - 1); } >From 1ad5668b6f8e0a54fa258144a765ed3ea0ea8ad0 Mon Sep 17 00:00:00 2001 From: Haojian Wu <hokein...@gmail.com> Date: Thu, 3 Jul 2025 10:53:10 +0200 Subject: [PATCH 2/3] Address review comments. --- clang/include/clang/Basic/SourceManager.h | 6 +++++- clang/lib/Basic/SourceManager.cpp | 3 ++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h index a90cc70825ffd..111141a33901c 100644 --- a/clang/include/clang/Basic/SourceManager.h +++ b/clang/include/clang/Basic/SourceManager.h @@ -1903,7 +1903,7 @@ class SourceManager : public RefCountedBase<SourceManager> { FileID getFileID(SourceLocation::UIntTy SLocOffset) const { // If our one-entry cache covers this offset, just return it. - if (SLocOffset >= LastLookupStartOffset && SLocOffset < LastLookupEndOffset) + if (isOffsetInFileID(LastFileIDLookup, SLocOffset)) return LastFileIDLookup; return getFileIDSlow(SLocOffset); } @@ -1927,6 +1927,10 @@ class SourceManager : public RefCountedBase<SourceManager> { /// specified SourceLocation offset. This is a very hot method. inline bool isOffsetInFileID(FileID FID, SourceLocation::UIntTy SLocOffset) const { + if (FID == LastFileIDLookup) + return SLocOffset >= LastLookupStartOffset && + SLocOffset < LastLookupEndOffset; + const SrcMgr::SLocEntry &Entry = getSLocEntry(FID); // If the entry is after the offset, it can't contain it. if (SLocOffset < Entry.getOffset()) return false; diff --git a/clang/lib/Basic/SourceManager.cpp b/clang/lib/Basic/SourceManager.cpp index 8c1d9662d4579..873b4be234a85 100644 --- a/clang/lib/Basic/SourceManager.cpp +++ b/clang/lib/Basic/SourceManager.cpp @@ -814,8 +814,9 @@ FileID SourceManager::getFileIDSlow(SourceLocation::UIntTy SLocOffset) const { /// loaded one. FileID SourceManager::getFileIDLocal(SourceLocation::UIntTy SLocOffset) const { assert(SLocOffset < NextLocalOffset && "Bad function choice"); - assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && + assert(SLocOffset >= LocalSLocEntryTable[0].getOffset() && SLocOffset > 0 && "Invalid SLocOffset"); + assert(LastFileIDLookup.ID >= 0 && "Only cache local file sloc entry"); // After the first and second level caches, I see two common sorts of // behavior: 1) a lot of searched FileID's are "near" the cached file >From 5e7d73428986f652786c0076027f385a4fcc2609 Mon Sep 17 00:00:00 2001 From: Haojian Wu <hokein...@gmail.com> Date: Thu, 3 Jul 2025 16:21:54 +0200 Subject: [PATCH 3/3] Revert the change in isOffsetInFileID. --- clang/include/clang/Basic/SourceManager.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/clang/include/clang/Basic/SourceManager.h b/clang/include/clang/Basic/SourceManager.h index 111141a33901c..a90cc70825ffd 100644 --- a/clang/include/clang/Basic/SourceManager.h +++ b/clang/include/clang/Basic/SourceManager.h @@ -1903,7 +1903,7 @@ class SourceManager : public RefCountedBase<SourceManager> { FileID getFileID(SourceLocation::UIntTy SLocOffset) const { // If our one-entry cache covers this offset, just return it. - if (isOffsetInFileID(LastFileIDLookup, SLocOffset)) + if (SLocOffset >= LastLookupStartOffset && SLocOffset < LastLookupEndOffset) return LastFileIDLookup; return getFileIDSlow(SLocOffset); } @@ -1927,10 +1927,6 @@ class SourceManager : public RefCountedBase<SourceManager> { /// specified SourceLocation offset. This is a very hot method. inline bool isOffsetInFileID(FileID FID, SourceLocation::UIntTy SLocOffset) const { - if (FID == LastFileIDLookup) - return SLocOffset >= LastLookupStartOffset && - SLocOffset < LastLookupEndOffset; - const SrcMgr::SLocEntry &Entry = getSLocEntry(FID); // If the entry is after the offset, it can't contain it. if (SLocOffset < Entry.getOffset()) return false; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits