[llvm] [mlir] [Support] Faster line and column lookup in SourceMgr (PR #195881)
via llvm-commits
llvm-commits at lists.llvm.org
Tue May 5 14:10:22 PDT 2026
Albert =?utf-8?q?Havliček?= <havlialb at fit.cvut.cz>,
Albert =?utf-8?q?Havliček?= <havlialb at fit.cvut.cz>,
Albert =?utf-8?q?Havliček?= <havlialb at fit.cvut.cz>
Message-ID:
In-Reply-To: <llvm.org/llvm/llvm-project/pull/195881 at github.com>
https://github.com/Bertik23 updated https://github.com/llvm/llvm-project/pull/195881
>From fc946c71697982aff25b5ec9accbfacdfc080036 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Albert=20Havli=C4=8Dek?= <havlialb at fit.cvut.cz>
Date: Tue, 5 May 2026 17:59:49 +0200
Subject: [PATCH 1/4] [Support] Faster line and column lookup
---
llvm/include/llvm/Support/SourceMgr.h | 9 ++++++
llvm/lib/Support/SourceMgr.cpp | 46 +++++++++++++++++++++++----
2 files changed, 49 insertions(+), 6 deletions(-)
diff --git a/llvm/include/llvm/Support/SourceMgr.h b/llvm/include/llvm/Support/SourceMgr.h
index 02e694cad8697..ec598336dc9b1 100644
--- a/llvm/include/llvm/Support/SourceMgr.h
+++ b/llvm/include/llvm/Support/SourceMgr.h
@@ -71,6 +71,15 @@ class SourceMgr {
template <typename T>
unsigned getLineNumberSpecialized(const char *Ptr) const;
+ /// Look up a given \p Ptr in the buffer, determining which line and column
+ /// it came from. This method has O(log n) complexity, where n is the number
+ /// of lines in the buffer.
+ LLVM_ABI std::pair<unsigned, unsigned>
+ getLineAndColumn(const char *Ptr) const;
+ template <typename T>
+ std::pair<unsigned, unsigned>
+ getLineAndColumnSpecialized(const char *Ptr) const;
+
/// Return a pointer to the first character of the specified line number or
/// null if the line number is invalid.
LLVM_ABI const char *getPointerForLineNumber(unsigned LineNo) const;
diff --git a/llvm/lib/Support/SourceMgr.cpp b/llvm/lib/Support/SourceMgr.cpp
index 299615a6c8041..85428403626fb 100644
--- a/llvm/lib/Support/SourceMgr.cpp
+++ b/llvm/lib/Support/SourceMgr.cpp
@@ -151,6 +151,45 @@ unsigned SourceMgr::SrcBuffer::getLineNumber(const char *Ptr) const {
return getLineNumberSpecialized<uint64_t>(Ptr);
}
+template <typename T>
+std::pair<unsigned, unsigned>
+SourceMgr::SrcBuffer::getLineAndColumnSpecialized(const char *Ptr) const {
+ std::vector<T> &Offsets =
+ GetOrCreateOffsetCache<T>(OffsetCache, Buffer.get());
+
+ const char *BufStart = Buffer->getBufferStart();
+ assert(Ptr >= BufStart && Ptr <= Buffer->getBufferEnd());
+ ptrdiff_t PtrDiff = Ptr - BufStart;
+ assert(PtrDiff >= 0 &&
+ static_cast<size_t>(PtrDiff) <= std::numeric_limits<T>::max());
+ T PtrOffset = static_cast<T>(PtrDiff);
+
+ // llvm::lower_bound gives the number of EOL before PtrOffset. Add 1 to get
+ // the line number.
+ auto I = llvm::lower_bound(Offsets, PtrOffset);
+ unsigned LineNo = I - Offsets.begin() + 1;
+
+ // The column number is the distance from the previous EOL (or the start of
+ // the buffer) to the pointer.
+ T LineStartOffs = (I == Offsets.begin()) ? 0 : (I[-1] + 1);
+ unsigned ColNo = PtrOffset - LineStartOffs + 1;
+ return {LineNo, ColNo};
+}
+
+/// Look up a given \p Ptr in the buffer, determining which line and column
+/// it came from.
+LLVM_ABI std::pair<unsigned, unsigned>
+SourceMgr::SrcBuffer::getLineAndColumn(const char *Ptr) const {
+ size_t Sz = Buffer->getBufferSize();
+ if (Sz <= std::numeric_limits<uint8_t>::max())
+ return getLineAndColumnSpecialized<uint8_t>(Ptr);
+ if (Sz <= std::numeric_limits<uint16_t>::max())
+ return getLineAndColumnSpecialized<uint16_t>(Ptr);
+ if (Sz <= std::numeric_limits<uint32_t>::max())
+ return getLineAndColumnSpecialized<uint32_t>(Ptr);
+ return getLineAndColumnSpecialized<uint64_t>(Ptr);
+}
+
template <typename T>
const char *SourceMgr::SrcBuffer::getPointerForLineNumberSpecialized(
unsigned LineNo) const {
@@ -217,12 +256,7 @@ SourceMgr::getLineAndColumn(SMLoc Loc, unsigned BufferID) const {
auto &SB = getBufferInfo(BufferID);
const char *Ptr = Loc.getPointer();
- unsigned LineNo = SB.getLineNumber(Ptr);
- const char *BufStart = SB.Buffer->getBufferStart();
- size_t NewlineOffs = StringRef(BufStart, Ptr - BufStart).find_last_of("\n\r");
- if (NewlineOffs == StringRef::npos)
- NewlineOffs = ~(size_t)0;
- return {LineNo, Ptr - BufStart - NewlineOffs};
+ return SB.getLineAndColumn(Ptr);
}
// FIXME: Note that the formatting of source locations is spread between
>From 50b2f2aba230f77bf6574548356e06e13aaeeb58 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Albert=20Havli=C4=8Dek?= <havlialb at fit.cvut.cz>
Date: Tue, 5 May 2026 18:03:51 +0200
Subject: [PATCH 2/4] [Support] Update comments about time complexity of
getLineAndColumn
---
llvm/include/llvm/Support/SourceMgr.h | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/Support/SourceMgr.h b/llvm/include/llvm/Support/SourceMgr.h
index ec598336dc9b1..842163cd96e06 100644
--- a/llvm/include/llvm/Support/SourceMgr.h
+++ b/llvm/include/llvm/Support/SourceMgr.h
@@ -217,13 +217,15 @@ class SourceMgr {
LLVM_ABI unsigned FindBufferContainingLoc(SMLoc Loc) const;
/// Find the line number for the specified location in the specified file.
- /// This is not a fast method.
+ /// This method has O(log n) complexity, where n is the number of lines in the
+ /// buffer.
unsigned FindLineNumber(SMLoc Loc, unsigned BufferID = 0) const {
return getLineAndColumn(Loc, BufferID).first;
}
/// Find the line and column number for the specified location in the
- /// specified file. This is not a fast method.
+ /// specified file. This method has O(log n) complexity, where n is the number
+ /// of lines in the
LLVM_ABI std::pair<unsigned, unsigned>
getLineAndColumn(SMLoc Loc, unsigned BufferID = 0) const;
>From f15d187b62a1104d66064cad5e9c0c0774a30684 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Albert=20Havli=C4=8Dek?= <havlialb at fit.cvut.cz>
Date: Tue, 5 May 2026 18:36:16 +0200
Subject: [PATCH 3/4] [Support] Remove now unused functions
---
llvm/include/llvm/Support/SourceMgr.h | 6 ------
llvm/lib/Support/SourceMgr.cpp | 31 ---------------------------
2 files changed, 37 deletions(-)
diff --git a/llvm/include/llvm/Support/SourceMgr.h b/llvm/include/llvm/Support/SourceMgr.h
index 842163cd96e06..ec0b4edb295d4 100644
--- a/llvm/include/llvm/Support/SourceMgr.h
+++ b/llvm/include/llvm/Support/SourceMgr.h
@@ -65,12 +65,6 @@ class SourceMgr {
/// dynamically based on the size of Buffer.
mutable void *OffsetCache = nullptr;
- /// Look up a given \p Ptr in the buffer, determining which line it came
- /// from.
- LLVM_ABI unsigned getLineNumber(const char *Ptr) const;
- template <typename T>
- unsigned getLineNumberSpecialized(const char *Ptr) const;
-
/// Look up a given \p Ptr in the buffer, determining which line and column
/// it came from. This method has O(log n) complexity, where n is the number
/// of lines in the buffer.
diff --git a/llvm/lib/Support/SourceMgr.cpp b/llvm/lib/Support/SourceMgr.cpp
index 85428403626fb..2704025060e03 100644
--- a/llvm/lib/Support/SourceMgr.cpp
+++ b/llvm/lib/Support/SourceMgr.cpp
@@ -120,37 +120,6 @@ static std::vector<T> &GetOrCreateOffsetCache(void *&OffsetCache,
return *Offsets;
}
-template <typename T>
-unsigned SourceMgr::SrcBuffer::getLineNumberSpecialized(const char *Ptr) const {
- std::vector<T> &Offsets =
- GetOrCreateOffsetCache<T>(OffsetCache, Buffer.get());
-
- const char *BufStart = Buffer->getBufferStart();
- assert(Ptr >= BufStart && Ptr <= Buffer->getBufferEnd());
- ptrdiff_t PtrDiff = Ptr - BufStart;
- assert(PtrDiff >= 0 &&
- static_cast<size_t>(PtrDiff) <= std::numeric_limits<T>::max());
- T PtrOffset = static_cast<T>(PtrDiff);
-
- // llvm::lower_bound gives the number of EOL before PtrOffset. Add 1 to get
- // the line number.
- return llvm::lower_bound(Offsets, PtrOffset) - Offsets.begin() + 1;
-}
-
-/// Look up a given \p Ptr in the buffer, determining which line it came
-/// from.
-unsigned SourceMgr::SrcBuffer::getLineNumber(const char *Ptr) const {
- size_t Sz = Buffer->getBufferSize();
- if (Sz <= std::numeric_limits<uint8_t>::max())
- return getLineNumberSpecialized<uint8_t>(Ptr);
- else if (Sz <= std::numeric_limits<uint16_t>::max())
- return getLineNumberSpecialized<uint16_t>(Ptr);
- else if (Sz <= std::numeric_limits<uint32_t>::max())
- return getLineNumberSpecialized<uint32_t>(Ptr);
- else
- return getLineNumberSpecialized<uint64_t>(Ptr);
-}
-
template <typename T>
std::pair<unsigned, unsigned>
SourceMgr::SrcBuffer::getLineAndColumnSpecialized(const char *Ptr) const {
>From c108d8d24b5470159c3194335874d76fa0cdf2a3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Albert=20Havli=C4=8Dek?= <havlialb at fit.cvut.cz>
Date: Tue, 5 May 2026 22:29:00 +0200
Subject: [PATCH 4/4] [MLIR] Use public API of SourceMgr to get line and column
location
---
mlir/lib/AsmParser/Lexer.cpp | 7 +------
mlir/lib/Tools/PDLL/CodeGen/MLIRGen.cpp | 7 +------
2 files changed, 2 insertions(+), 12 deletions(-)
diff --git a/mlir/lib/AsmParser/Lexer.cpp b/mlir/lib/AsmParser/Lexer.cpp
index 8f53529823e23..185baaa63c739 100644
--- a/mlir/lib/AsmParser/Lexer.cpp
+++ b/mlir/lib/AsmParser/Lexer.cpp
@@ -63,12 +63,7 @@ Location Lexer::getEncodedSourceLocation(SMLoc loc) {
auto &sourceMgr = getSourceMgr();
unsigned mainFileID = sourceMgr.getMainFileID();
- // TODO: Fix performance issues in SourceMgr::getLineAndColumn so that we can
- // use it here.
- auto &bufferInfo = sourceMgr.getBufferInfo(mainFileID);
- unsigned lineNo = bufferInfo.getLineNumber(loc.getPointer());
- unsigned column =
- (loc.getPointer() - bufferInfo.getPointerForLineNumber(lineNo)) + 1;
+ auto [lineNo, column] = sourceMgr.getLineAndColumn(loc.getPointer());
auto *buffer = sourceMgr.getMemoryBuffer(mainFileID);
return FileLineColLoc::get(context, buffer->getBufferIdentifier(), lineNo,
diff --git a/mlir/lib/Tools/PDLL/CodeGen/MLIRGen.cpp b/mlir/lib/Tools/PDLL/CodeGen/MLIRGen.cpp
index 0677828b635d4..08c085b5f279c 100644
--- a/mlir/lib/Tools/PDLL/CodeGen/MLIRGen.cpp
+++ b/mlir/lib/Tools/PDLL/CodeGen/MLIRGen.cpp
@@ -147,12 +147,7 @@ OwningOpRef<ModuleOp> CodeGen::generate(const ast::Module &module) {
Location CodeGen::genLoc(llvm::SMLoc loc) {
unsigned fileID = sourceMgr.FindBufferContainingLoc(loc);
- // TODO: Fix performance issues in SourceMgr::getLineAndColumn so that we can
- // use it here.
- auto &bufferInfo = sourceMgr.getBufferInfo(fileID);
- unsigned lineNo = bufferInfo.getLineNumber(loc.getPointer());
- unsigned column =
- (loc.getPointer() - bufferInfo.getPointerForLineNumber(lineNo)) + 1;
+ auto [lineNo, column] = sourceMgr.getLineAndColumn(loc);
auto *buffer = sourceMgr.getMemoryBuffer(fileID);
return FileLineColLoc::get(builder.getContext(),
More information about the llvm-commits
mailing list