[Mlir-commits] [mlir] [mlir] Store registered op info only in the by name map (PR #236949)
Arseniy Obolenskiy
llvmlistbot at llvm.org
Fri Oct 30 03:03:24 PDT 2026
https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/236949
>From 1a502a7fd0820b591f33a991c7bad8a43de8af7b Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Thu, 29 Oct 2026 22:08:09 +0100
Subject: [PATCH 1/2] [mlir] Store registered op info only in the by name map
Loading a dialect inserted each op into two string maps
Insert it into one and take its entries from a bump allocator instead of one malloc each
This speeds up context setup, which is noticable for short runs on small inputs
---
mlir/lib/IR/MLIRContext.cpp | 27 +++++++++++++--------------
1 file changed, 13 insertions(+), 14 deletions(-)
diff --git a/mlir/lib/IR/MLIRContext.cpp b/mlir/lib/IR/MLIRContext.cpp
index 350680692a6e0f..cd474d18d08858 100644
--- a/mlir/lib/IR/MLIRContext.cpp
+++ b/mlir/lib/IR/MLIRContext.cpp
@@ -187,7 +187,8 @@ class MLIRContextImpl {
/// A vector of operation info specifically for registered operations.
llvm::DenseMap<TypeID, RegisteredOperationName> registeredOperations;
- llvm::StringMap<RegisteredOperationName> registeredOperationsByName;
+ llvm::StringMap<std::unique_ptr<OperationName::Impl>, llvm::BumpPtrAllocator>
+ registeredOperationsByName;
/// This is a sorted container of registered operations for a deterministic
/// and efficient `getRegisteredOperations` implementation.
@@ -915,18 +916,18 @@ OperationName::Impl::Impl(StringRef name, Dialect *dialect, TypeID typeID,
OperationName::OperationName(StringRef name, MLIRContext *context) {
MLIRContextImpl &ctxImpl = context->getImpl();
+ // Check the registered info map first. In the overwhelmingly common case,
+ // the entry will be in here and it also removes the need to acquire any
+ // locks.
+ auto registeredIt = ctxImpl.registeredOperationsByName.find(name);
+ if (LLVM_LIKELY(registeredIt != ctxImpl.registeredOperationsByName.end())) {
+ impl = registeredIt->second.get();
+ return;
+ }
+
// Check for an existing name in read-only mode.
bool isMultithreadingEnabled = context->isMultithreadingEnabled();
if (isMultithreadingEnabled) {
- // Check the registered info map first. In the overwhelmingly common case,
- // the entry will be in here and it also removes the need to acquire any
- // locks.
- auto registeredIt = ctxImpl.registeredOperationsByName.find(name);
- if (LLVM_LIKELY(registeredIt != ctxImpl.registeredOperationsByName.end())) {
- impl = registeredIt->second.impl;
- return;
- }
-
llvm::sys::SmartScopedReader<true> contextLock(ctxImpl.operationInfoMutex);
auto it = ctxImpl.operations.find(name);
if (it != ctxImpl.operations.end()) {
@@ -1065,7 +1066,7 @@ RegisteredOperationName::lookup(StringRef name, MLIRContext *ctx) {
auto &impl = ctx->getImpl();
auto it = impl.registeredOperationsByName.find(name);
if (it != impl.registeredOperationsByName.end())
- return it->getValue();
+ return RegisteredOperationName(it->second.get());
return std::nullopt;
}
@@ -1091,15 +1092,13 @@ void RegisteredOperationName::insert(
impl->attributeNames = cachedAttrNames;
}
StringRef name = impl->getName().strref();
- // Insert the operation info if it doesn't exist yet.
- ctxImpl.operations[name] = std::move(ownedImpl);
// Update the registered info for this operation.
auto emplaced = ctxImpl.registeredOperations.try_emplace(
impl->getTypeID(), RegisteredOperationName(impl));
assert(emplaced.second && "operation name registration must be successful");
auto emplacedByName = ctxImpl.registeredOperationsByName.try_emplace(
- name, RegisteredOperationName(impl));
+ name, std::move(ownedImpl));
(void)emplacedByName;
assert(emplacedByName.second &&
"operation name registration must be successful");
>From f8c10567a6a54ec5c5285d39d41f1a6c832af699 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Fri, 30 Oct 2026 11:03:12 +0100
Subject: [PATCH 2/2] Address comments
---
mlir/lib/IR/MLIRContext.cpp | 27 ++++++++++++++-------------
1 file changed, 14 insertions(+), 13 deletions(-)
diff --git a/mlir/lib/IR/MLIRContext.cpp b/mlir/lib/IR/MLIRContext.cpp
index cd474d18d08858..f5a878edd53612 100644
--- a/mlir/lib/IR/MLIRContext.cpp
+++ b/mlir/lib/IR/MLIRContext.cpp
@@ -182,8 +182,10 @@ class MLIRContextImpl {
/// An allocator used for AbstractAttribute and AbstractType objects.
llvm::BumpPtrAllocator abstractDialectSymbolAllocator;
- /// This is a mapping from operation name to the operation info describing it.
- llvm::StringMap<std::unique_ptr<OperationName::Impl>> operations;
+ /// This is a mapping from unregistered operation name to the operation info
+ /// describing it.
+ llvm::StringMap<std::unique_ptr<OperationName::Impl>>
+ unregisteredOperationsByName;
/// A vector of operation info specifically for registered operations.
llvm::DenseMap<TypeID, RegisteredOperationName> registeredOperations;
@@ -272,7 +274,8 @@ class MLIRContextImpl {
/// Bundled state dynamically allocated when in a transient scope.
struct TransientScopeState {
- /// Set of operation names in `operations` at snapshot time.
+ /// Set of operation names in `unregisteredOperationsByName` at snapshot
+ /// time.
llvm::DenseSet<StringRef> baseOperations;
/// Number of entries in `dialectReferencingStrAttrs` per dialect at
@@ -706,10 +709,10 @@ void MLIRContext::beginTransientScope() {
ctxImpl.affineUniquer.beginTransientScope();
ctxImpl.distinctAttributeAllocator.beginTransientScope();
- // Record base operations in operations map.
+ // Record base unregistered operations.
{
llvm::sys::SmartScopedReader<true> contextLock(ctxImpl.operationInfoMutex);
- for (const auto &entry : ctxImpl.operations)
+ for (const auto &entry : ctxImpl.unregisteredOperationsByName)
ctxImpl.transientState->baseOperations.insert(entry.first());
}
@@ -736,13 +739,11 @@ void MLIRContext::endTransientScope() {
{
llvm::sys::SmartScopedWriter<true> contextLock(ctxImpl.operationInfoMutex);
SmallVector<StringRef> opsToErase;
- for (const auto &entry : ctxImpl.operations) {
- if (!entry.second->isRegistered() &&
- !ctxImpl.transientState->baseOperations.contains(entry.first()))
+ for (const auto &entry : ctxImpl.unregisteredOperationsByName)
+ if (!ctxImpl.transientState->baseOperations.contains(entry.first()))
opsToErase.push_back(entry.first());
- }
for (StringRef op : opsToErase)
- ctxImpl.operations.erase(op);
+ ctxImpl.unregisteredOperationsByName.erase(op);
}
// Restore dialect referencing string attributes before destroying the
@@ -929,8 +930,8 @@ OperationName::OperationName(StringRef name, MLIRContext *context) {
bool isMultithreadingEnabled = context->isMultithreadingEnabled();
if (isMultithreadingEnabled) {
llvm::sys::SmartScopedReader<true> contextLock(ctxImpl.operationInfoMutex);
- auto it = ctxImpl.operations.find(name);
- if (it != ctxImpl.operations.end()) {
+ auto it = ctxImpl.unregisteredOperationsByName.find(name);
+ if (it != ctxImpl.unregisteredOperationsByName.end()) {
impl = it->second.get();
return;
}
@@ -939,7 +940,7 @@ OperationName::OperationName(StringRef name, MLIRContext *context) {
// Acquire a writer-lock so that we can safely create the new instance.
ScopedWriterLock lock(ctxImpl.operationInfoMutex, isMultithreadingEnabled);
- auto it = ctxImpl.operations.try_emplace(name);
+ auto it = ctxImpl.unregisteredOperationsByName.try_emplace(name);
if (it.second) {
auto nameAttr = StringAttr::get(context, name);
it.first->second = std::make_unique<UnregisteredOpModel>(
More information about the Mlir-commits
mailing list