[Mlir-commits] [mlir] 7e19707 - [mlir][ODS] Copy constant generated interface model prototypes (#226323)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Tue Sep 29 06:47:55 PDT 2026
Author: Mehdi Amini
Date: 2026-09-29T13:47:48Z
New Revision: 7e19707aeebbd0ae3101ddc7347fef7a865154f4
URL: https://github.com/llvm/llvm-project/commit/7e19707aeebbd0ae3101ddc7347fef7a865154f4
DIFF: https://github.com/llvm/llvm-project/commit/7e19707aeebbd0ae3101ddc7347fef7a865154f4.diff
LOG: [mlir][ODS] Copy constant generated interface model prototypes (#226323)
Generate constexpr constructors for interface models whose concept is a
table of callbacks. Construct exact generated models from a static
prototype; keep external and fallback models on their existing path.
In OpenMPDialect.cpp this saves about 0.22B compiler instructions and
10.5KB of text.
Assisted-by: Codex
Added:
Modified:
mlir/include/mlir/Support/InterfaceSupport.h
mlir/test/mlir-tblgen/op-interface.td
mlir/tools/mlir-tblgen/OpInterfacesGen.cpp
Removed:
################################################################################
diff --git a/mlir/include/mlir/Support/InterfaceSupport.h b/mlir/include/mlir/Support/InterfaceSupport.h
index 6f654f1785713..8ab691454f64b 100644
--- a/mlir/include/mlir/Support/InterfaceSupport.h
+++ b/mlir/include/mlir/Support/InterfaceSupport.h
@@ -18,6 +18,8 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/Support/TypeName.h"
+#include <type_traits>
+
namespace mlir {
namespace detail {
//===----------------------------------------------------------------------===//
@@ -157,6 +159,16 @@ class InterfaceMap {
template <typename T>
using detect_initialize_method = llvm::is_detected<has_initialize_method, T>;
+ // Only exact generated models with trivial copy construction can be copied
+ // from a constant prototype. Derived models may carry additional state or
+ // use a custom constructor to configure callbacks.
+ template <typename T, typename = void>
+ struct IsConstexprGeneratedModel : std::false_type {};
+ template <typename T>
+ struct IsConstexprGeneratedModel<T, std::void_t<typename T::GeneratedModel>>
+ : std::bool_constant<std::is_same_v<T, typename T::GeneratedModel> &&
+ std::is_trivially_copy_constructible_v<T>> {};
+
public:
InterfaceMap() = default;
InterfaceMap(InterfaceMap &&) = default;
@@ -228,9 +240,19 @@ class InterfaceMap {
// static_assert(std::is_trivially_destructible_v<InterfaceModel>,
// "interface models must be trivially destructible");
- // Build the interface model, optionally initializing if necessary.
- InterfaceModel *model =
- new (malloc(sizeof(InterfaceModel))) InterfaceModel();
+ // Generated models contain a fixed table of callbacks. Copy a constant
+ // prototype so the callbacks need not be set up for each model.
+ InterfaceModel *model;
+ if constexpr (IsConstexprGeneratedModel<InterfaceModel>::value) {
+ static constexpr InterfaceModel prototype;
+ model = new (malloc(sizeof(InterfaceModel))) InterfaceModel(prototype);
+ } else {
+ // Construct fallback, external, and custom models normally; they may
+ // need more than a copy of the generated callback table.
+ model = new (malloc(sizeof(InterfaceModel))) InterfaceModel();
+ }
+ // Run model-specific initialization after either path, including links to
+ // registered base interfaces.
if constexpr (detect_initialize_method<InterfaceModel>::value)
model->initializeInterfaceConcept(*this);
diff --git a/mlir/test/mlir-tblgen/op-interface.td b/mlir/test/mlir-tblgen/op-interface.td
index b156fe195a7ed..e12ede40e029a 100644
--- a/mlir/test/mlir-tblgen/op-interface.td
+++ b/mlir/test/mlir-tblgen/op-interface.td
@@ -184,9 +184,12 @@ def DeclareMethodsWithDefaultOp : Op<TestDialect, "declare_methods_op",
// DECL-LABEL: TestOpInterfaceInterfaceTraits
// DECL: static int shared_shared_body_foo(const Concept *impl, ::mlir::Operation *tablegen_opaque_val, int input);
// DECL: class Model : public Concept
-// DECL: Model() : Concept{foo, body_foo, Concept::shared_shared_body_foo, mixed_body_foo, default_foo}
+// DECL: using GeneratedModel = Model;
+// DECL: constexpr Model() : Concept{foo, body_foo, Concept::shared_shared_body_foo, mixed_body_foo, default_foo}
// DECL: static inline int foo(
// DECL: class FallbackModel : public Concept
+// DECL-NOT: using GeneratedModel = Model;
+// DECL: FallbackModel() : Concept{foo, body_foo, shared_body_foo, mixed_body_foo, default_foo}
// DECL: static inline int foo(
// DECL: class TestOpInterface : public ::mlir::OpInterface<TestOpInterface, detail::TestOpInterfaceInterfaceTraits>
diff --git a/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp b/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp
index 764357720ddab..3f62969312de8 100644
--- a/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp
+++ b/mlir/tools/mlir-tblgen/OpInterfacesGen.cpp
@@ -316,11 +316,16 @@ void InterfaceGenerator::emitModelDecl(const Interface &interface) {
os << " class " << modelClass << " : public Concept {\n public:\n";
os << " using Interface = " << interface.getFullyQualifiedName()
<< ";\n";
+ if (StringRef(modelClass) == "Model")
+ os << " using GeneratedModel = Model;\n";
// The Concept's function-pointer members and these wrapper signatures are
// named by the unique name so that overloaded interface methods stay
// distinct here; only the forward target (the concrete model call) uses the
// shared source name. Do not collapse these to getName().
- os << " " << modelClass << "() : Concept{";
+ os << " ";
+ if (StringRef(modelClass) == "Model")
+ os << "constexpr ";
+ os << modelClass << "() : Concept{";
llvm::interleaveComma(
interface.getMethods(), os, [&](const InterfaceMethod &method) {
if (StringRef(modelClass) == "Model" &&
More information about the Mlir-commits
mailing list