[Mlir-commits] [mlir] [mlir-c] Add mlirDialectMaterializeConstant (PR #206553)

Maksim Levental llvmlistbot at llvm.org
Wed Sep 23 21:21:33 PDT 2026


https://github.com/makslevental updated https://github.com/llvm/llvm-project/pull/206553

>From d4aaf37a0cbe578fead44a8d7e4e60963fcbee9a Mon Sep 17 00:00:00 2001
From: makslevental <maksim.levental at gmail.com>
Date: Mon, 29 Jun 2026 11:12:25 -0700
Subject: [PATCH 1/2] [mlir-c] Add mlirDialectMaterializeConstant

---
 mlir/include/mlir-c/Rewrite.h        | 13 +++++++
 mlir/lib/CAPI/Transforms/Rewrite.cpp | 12 +++++++
 mlir/test/CAPI/rewrite.c             | 54 ++++++++++++++++++++++++++++
 3 files changed, 79 insertions(+)

diff --git a/mlir/include/mlir-c/Rewrite.h b/mlir/include/mlir-c/Rewrite.h
index 0e5562477d4f4..5e4caacd1901d 100644
--- a/mlir/include/mlir-c/Rewrite.h
+++ b/mlir/include/mlir-c/Rewrite.h
@@ -348,6 +348,19 @@ mlirIRRewriterCreateFromOp(MlirOperation op);
 /// responsibility of the user to only pass an IRRewriter class.
 MLIR_CAPI_EXPORTED void mlirIRRewriterDestroy(MlirRewriterBase rewriter);
 
+//===----------------------------------------------------------------------===//
+/// Dialect constant materialization API
+//===----------------------------------------------------------------------===//
+
+/// Materializes a constant for the given attribute `value` and `type` using the
+/// dialect's `materializeConstant` hook. The operation is created with the
+/// given rewriter (used as an OpBuilder) at its current insertion point,
+/// without changing that insertion point. Returns a null operation if the
+/// dialect does not support materializing the given constant.
+MLIR_CAPI_EXPORTED MlirOperation mlirDialectMaterializeConstant(
+    MlirDialect dialect, MlirRewriterBase rewriter, MlirAttribute value,
+    MlirType type, MlirLocation loc);
+
 //===----------------------------------------------------------------------===//
 /// FrozenRewritePatternSet API
 //===----------------------------------------------------------------------===//
diff --git a/mlir/lib/CAPI/Transforms/Rewrite.cpp b/mlir/lib/CAPI/Transforms/Rewrite.cpp
index e54c7dcd7271a..cd8dccbd053c0 100644
--- a/mlir/lib/CAPI/Transforms/Rewrite.cpp
+++ b/mlir/lib/CAPI/Transforms/Rewrite.cpp
@@ -304,6 +304,18 @@ void mlirIRRewriterDestroy(MlirRewriterBase rewriter) {
   delete static_cast<IRRewriter *>(unwrap(rewriter));
 }
 
+//===----------------------------------------------------------------------===//
+/// Dialect constant materialization API
+//===----------------------------------------------------------------------===//
+
+MlirOperation mlirDialectMaterializeConstant(MlirDialect dialect,
+                                             MlirRewriterBase rewriter,
+                                             MlirAttribute value, MlirType type,
+                                             MlirLocation loc) {
+  return wrap(unwrap(dialect)->materializeConstant(
+      *unwrap(rewriter), unwrap(value), unwrap(type), unwrap(loc)));
+}
+
 //===----------------------------------------------------------------------===//
 /// RewritePatternSet and FrozenRewritePatternSet API
 //===----------------------------------------------------------------------===//
diff --git a/mlir/test/CAPI/rewrite.c b/mlir/test/CAPI/rewrite.c
index 60f5dca31b9ef..3d2fa8fb85b82 100644
--- a/mlir/test/CAPI/rewrite.c
+++ b/mlir/test/CAPI/rewrite.c
@@ -10,8 +10,10 @@
 // RUN: mlir-capi-rewrite-test 2>&1 | FileCheck %s
 
 #include "mlir-c/Rewrite.h"
+#include "mlir-c/BuiltinAttributes.h"
 #include "mlir-c/BuiltinTypes.h"
 #include "mlir-c/IR.h"
+#include "mlir-c/RegisterEverything.h"
 
 #include <assert.h>
 #include <inttypes.h>
@@ -1960,6 +1962,57 @@ void testTypeConverter1ToNConversionErasure(MlirContext ctx) {
   fprintf(stderr, "testTypeConverter1ToNConversionErasure: PASSED\n");
 }
 
+void testDialectMaterializeConstant(MlirContext ctx) {
+  // CHECK-LABEL: @testDialectMaterializeConstant
+  fprintf(stderr, "@testDialectMaterializeConstant\n");
+
+  MlirDialectRegistry registry = mlirDialectRegistryCreate();
+  mlirRegisterAllDialects(registry);
+  mlirContextAppendDialectRegistry(ctx, registry);
+  mlirDialectRegistryDestroy(registry);
+
+  MlirDialect arith =
+      mlirContextGetOrLoadDialect(ctx, mlirStringRefCreateFromCString("arith"));
+  mlirContextGetOrLoadDialect(ctx, mlirStringRefCreateFromCString("func"));
+
+  const char *moduleString = "func.func @f() {\n"
+                             "  return\n"
+                             "}\n";
+  MlirModule module =
+      mlirModuleCreateParse(ctx, mlirStringRefCreateFromCString(moduleString));
+  MlirBlock body = mlirModuleGetBody(module);
+  MlirOperation funcOp = mlirBlockGetFirstOperation(body);
+  MlirRegion funcRegion = mlirOperationGetRegion(funcOp, 0);
+  MlirBlock funcBody = mlirRegionGetFirstBlock(funcRegion);
+
+  MlirRewriterBase rewriter = mlirIRRewriterCreate(ctx);
+  mlirRewriterBaseSetInsertionPointToStart(rewriter, funcBody);
+
+  // Materialize an i32 constant of value 42 using the arith dialect's hook.
+  MlirType i32 = mlirIntegerTypeGet(ctx, 32);
+  MlirAttribute value = mlirIntegerAttrGet(i32, 42);
+  MlirLocation loc = mlirLocationUnknownGet(ctx);
+  MlirOperation constOp =
+      mlirDialectMaterializeConstant(arith, rewriter, value, i32, loc);
+  assert(!mlirOperationIsNull(constOp));
+  mlirOperationDump(constOp);
+  // CHECK: arith.constant 42 : i32
+
+  // A dialect that does not materialize the given constant returns null. The
+  // func dialect has no constant materializer, so it returns a null operation.
+  MlirDialect func =
+      mlirContextGetOrLoadDialect(ctx, mlirStringRefCreateFromCString("func"));
+  MlirOperation none =
+      mlirDialectMaterializeConstant(func, rewriter, value, i32, loc);
+  assert(mlirOperationIsNull(none));
+
+  mlirIRRewriterDestroy(rewriter);
+  mlirModuleDestroy(module);
+
+  // CHECK: testDialectMaterializeConstant: PASSED
+  fprintf(stderr, "testDialectMaterializeConstant: PASSED\n");
+}
+
 int main(void) {
   MlirContext ctx = mlirContextCreate();
   mlirContextSetAllowUnregisteredDialects(ctx, true);
@@ -1988,6 +2041,7 @@ int main(void) {
   testConversionReplaceOpWithMultipleRanges(ctx);
   testTypeConverter1ToNOperandRequires1ToNCallback(ctx);
   testTypeConverter1ToNConversionErasure(ctx);
+  testDialectMaterializeConstant(ctx);
 
   mlirContextDestroy(ctx);
   return 0;

>From 0040e3c93a10968eda594679fd9286c9529e6373 Mon Sep 17 00:00:00 2001
From: makslevental <maksim.levental at gmail.com>
Date: Wed, 23 Sep 2026 20:44:32 -0700
Subject: [PATCH 2/2] [mlir-c] Fix testDialectMaterializeConstant review
 comments

Correct the misleading comment about the func dialect (it does have a
constant materializer; it just declines an i32 IntegerAttr), and assert
the documented insertion-point contract: the op lands in the current
insertion block and the rewriter's insertion point is preserved.
---
 mlir/test/CAPI/CMakeLists.txt |  3 ++-
 mlir/test/CAPI/rewrite.c      | 24 ++++++++++++------------
 2 files changed, 14 insertions(+), 13 deletions(-)

diff --git a/mlir/test/CAPI/CMakeLists.txt b/mlir/test/CAPI/CMakeLists.txt
index 211e321a9b763..d29e7744527ef 100644
--- a/mlir/test/CAPI/CMakeLists.txt
+++ b/mlir/test/CAPI/CMakeLists.txt
@@ -100,8 +100,9 @@ _add_capi_test_executable(mlir-capi-quant-test
 _add_capi_test_executable(mlir-capi-rewrite-test
   rewrite.c
   LINK_LIBS PRIVATE
+    MLIRCAPIArith
+    MLIRCAPIFunc
     MLIRCAPIIR
-    MLIRCAPIRegisterEverything
     MLIRCAPITransforms
 )
 
diff --git a/mlir/test/CAPI/rewrite.c b/mlir/test/CAPI/rewrite.c
index 3d2fa8fb85b82..75f268c3c4cc5 100644
--- a/mlir/test/CAPI/rewrite.c
+++ b/mlir/test/CAPI/rewrite.c
@@ -12,8 +12,9 @@
 #include "mlir-c/Rewrite.h"
 #include "mlir-c/BuiltinAttributes.h"
 #include "mlir-c/BuiltinTypes.h"
+#include "mlir-c/Dialect/Arith.h"
+#include "mlir-c/Dialect/Func.h"
 #include "mlir-c/IR.h"
-#include "mlir-c/RegisterEverything.h"
 
 #include <assert.h>
 #include <inttypes.h>
@@ -1966,14 +1967,10 @@ void testDialectMaterializeConstant(MlirContext ctx) {
   // CHECK-LABEL: @testDialectMaterializeConstant
   fprintf(stderr, "@testDialectMaterializeConstant\n");
 
-  MlirDialectRegistry registry = mlirDialectRegistryCreate();
-  mlirRegisterAllDialects(registry);
-  mlirContextAppendDialectRegistry(ctx, registry);
-  mlirDialectRegistryDestroy(registry);
-
   MlirDialect arith =
-      mlirContextGetOrLoadDialect(ctx, mlirStringRefCreateFromCString("arith"));
-  mlirContextGetOrLoadDialect(ctx, mlirStringRefCreateFromCString("func"));
+      mlirDialectHandleLoadDialect(mlirGetDialectHandle__arith__(), ctx);
+  MlirDialect func =
+      mlirDialectHandleLoadDialect(mlirGetDialectHandle__func__(), ctx);
 
   const char *moduleString = "func.func @f() {\n"
                              "  return\n"
@@ -1995,13 +1992,16 @@ void testDialectMaterializeConstant(MlirContext ctx) {
   MlirOperation constOp =
       mlirDialectMaterializeConstant(arith, rewriter, value, i32, loc);
   assert(!mlirOperationIsNull(constOp));
+  // The op is created at the current insertion point without changing it: it
+  // lands in funcBody, and the rewriter still points there afterwards.
+  assert(mlirBlockEqual(mlirOperationGetBlock(constOp), funcBody));
+  assert(mlirBlockEqual(mlirRewriterBaseGetInsertionBlock(rewriter), funcBody));
   mlirOperationDump(constOp);
   // CHECK: arith.constant 42 : i32
 
-  // A dialect that does not materialize the given constant returns null. The
-  // func dialect has no constant materializer, so it returns a null operation.
-  MlirDialect func =
-      mlirContextGetOrLoadDialect(ctx, mlirStringRefCreateFromCString("func"));
+  // A dialect whose materializer declines the given attribute/type returns
+  // null. The func dialect has a constant materializer, but it only builds
+  // func.constant from a symbol ref, so an i32 IntegerAttr yields null.
   MlirOperation none =
       mlirDialectMaterializeConstant(func, rewriter, value, i32, loc);
   assert(mlirOperationIsNull(none));



More information about the Mlir-commits mailing list