[Mlir-commits] [mlir] [mlir][CAPI] Add MlirOpFoldResult type to C API (PR #187247)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Wed Mar 18 05:16:58 PDT 2026


https://github.com/edg-l updated https://github.com/llvm/llvm-project/pull/187247

>From 820bcc478e5f739cb20aea50f7548bb44320c167 Mon Sep 17 00:00:00 2001
From: Edgar Luque <git at edgl.dev>
Date: Wed, 18 Mar 2026 13:02:24 +0100
Subject: [PATCH] [mlir][CAPI] Add MlirOpFoldResult type to C API

Exposes OpFoldResult (a Value|Attribute union) to the C API. This type
is needed for fold callbacks on dynamic operations and is used
throughout MLIR's folding infrastructure.

New functions:
- mlirOpFoldResultFromAttribute / mlirOpFoldResultFromValue
- mlirOpFoldResultIsAttribute / mlirOpFoldResultIsValue
- mlirOpFoldResultGetAttribute / mlirOpFoldResultGetValue

The opaque struct stores the PointerUnion's opaque value directly,
matching the pattern used by MlirAttribute and MlirValue.

Tests added to mlir/test/CAPI/ir.c covering round-trip for both
attribute and value variants.
---
 mlir/include/mlir-c/IR.h    | 32 ++++++++++++++++++++++++++++
 mlir/include/mlir/CAPI/IR.h | 12 +++++++++++
 mlir/lib/CAPI/IR/IR.cpp     | 28 +++++++++++++++++++++++++
 mlir/test/CAPI/ir.c         | 42 +++++++++++++++++++++++++++++++++++++
 4 files changed, 114 insertions(+)

diff --git a/mlir/include/mlir-c/IR.h b/mlir/include/mlir-c/IR.h
index 805f0ffaaf7ce..01455408578e4 100644
--- a/mlir/include/mlir-c/IR.h
+++ b/mlir/include/mlir-c/IR.h
@@ -64,6 +64,7 @@ DEFINE_C_API_STRUCT(MlirAttribute, const void);
 DEFINE_C_API_STRUCT(MlirIdentifier, const void);
 DEFINE_C_API_STRUCT(MlirLocation, const void);
 DEFINE_C_API_STRUCT(MlirModule, const void);
+DEFINE_C_API_STRUCT(MlirOpFoldResult, const void);
 DEFINE_C_API_STRUCT(MlirType, const void);
 DEFINE_C_API_STRUCT(MlirValue, const void);
 
@@ -1211,6 +1212,37 @@ MLIR_CAPI_EXPORTED void mlirAttributeDump(MlirAttribute attr);
 MLIR_CAPI_EXPORTED MlirNamedAttribute mlirNamedAttributeGet(MlirIdentifier name,
                                                             MlirAttribute attr);
 
+//===----------------------------------------------------------------------===//
+// OpFoldResult API.
+//===----------------------------------------------------------------------===//
+
+/// Returns true if the given OpFoldResult is null.
+static inline bool mlirOpFoldResultIsNull(MlirOpFoldResult result) {
+  return !result.ptr;
+}
+
+/// Creates an OpFoldResult from an attribute.
+MLIR_CAPI_EXPORTED MlirOpFoldResult
+mlirOpFoldResultFromAttribute(MlirAttribute attr);
+
+/// Creates an OpFoldResult from a value.
+MLIR_CAPI_EXPORTED MlirOpFoldResult mlirOpFoldResultFromValue(MlirValue value);
+
+/// Returns true if the OpFoldResult contains an attribute.
+MLIR_CAPI_EXPORTED bool mlirOpFoldResultIsAttribute(MlirOpFoldResult result);
+
+/// Returns true if the OpFoldResult contains a value.
+MLIR_CAPI_EXPORTED bool mlirOpFoldResultIsValue(MlirOpFoldResult result);
+
+/// Returns the attribute contained in the OpFoldResult. Asserts if the
+/// OpFoldResult does not contain an attribute.
+MLIR_CAPI_EXPORTED MlirAttribute
+mlirOpFoldResultGetAttribute(MlirOpFoldResult result);
+
+/// Returns the value contained in the OpFoldResult. Asserts if the
+/// OpFoldResult does not contain a value.
+MLIR_CAPI_EXPORTED MlirValue mlirOpFoldResultGetValue(MlirOpFoldResult result);
+
 //===----------------------------------------------------------------------===//
 // Identifier API.
 //===----------------------------------------------------------------------===//
diff --git a/mlir/include/mlir/CAPI/IR.h b/mlir/include/mlir/CAPI/IR.h
index 1836cb0acb67e..f17192c9d8e68 100644
--- a/mlir/include/mlir/CAPI/IR.h
+++ b/mlir/include/mlir/CAPI/IR.h
@@ -19,6 +19,7 @@
 #include "mlir/CAPI/Wrap.h"
 #include "mlir/IR/BuiltinOps.h"
 #include "mlir/IR/MLIRContext.h"
+#include "mlir/IR/OpDefinition.h"
 #include "mlir/IR/Operation.h"
 
 DEFINE_C_API_PTR_METHODS(MlirAsmState, mlir::AsmState)
@@ -40,4 +41,15 @@ DEFINE_C_API_METHODS(MlirModule, mlir::ModuleOp)
 DEFINE_C_API_METHODS(MlirType, mlir::Type)
 DEFINE_C_API_METHODS(MlirValue, mlir::Value)
 
+static inline MlirOpFoldResult wrap(mlir::OpFoldResult ofr) {
+  return MlirOpFoldResult{ofr.getOpaqueValue()};
+}
+static inline mlir::OpFoldResult unwrap(MlirOpFoldResult result) {
+  using PU = llvm::PointerUnion<mlir::Attribute, mlir::Value>;
+  PU pu = PU::getFromOpaqueValue(const_cast<void *>(result.ptr));
+  if (llvm::isa<mlir::Attribute>(pu))
+    return llvm::cast<mlir::Attribute>(pu);
+  return llvm::cast<mlir::Value>(pu);
+}
+
 #endif // MLIR_CAPI_IR_H
diff --git a/mlir/lib/CAPI/IR/IR.cpp b/mlir/lib/CAPI/IR/IR.cpp
index 29f9287279b8f..dd50bbbca0d8b 100644
--- a/mlir/lib/CAPI/IR/IR.cpp
+++ b/mlir/lib/CAPI/IR/IR.cpp
@@ -1317,6 +1317,34 @@ MlirNamedAttribute mlirNamedAttributeGet(MlirIdentifier name,
   return MlirNamedAttribute{name, attr};
 }
 
+//===----------------------------------------------------------------------===//
+// OpFoldResult API.
+//===----------------------------------------------------------------------===//
+
+MlirOpFoldResult mlirOpFoldResultFromAttribute(MlirAttribute attr) {
+  return wrap(OpFoldResult(unwrap(attr)));
+}
+
+MlirOpFoldResult mlirOpFoldResultFromValue(MlirValue value) {
+  return wrap(OpFoldResult(unwrap(value)));
+}
+
+bool mlirOpFoldResultIsAttribute(MlirOpFoldResult result) {
+  return llvm::isa<Attribute>(unwrap(result));
+}
+
+bool mlirOpFoldResultIsValue(MlirOpFoldResult result) {
+  return llvm::isa<Value>(unwrap(result));
+}
+
+MlirAttribute mlirOpFoldResultGetAttribute(MlirOpFoldResult result) {
+  return wrap(llvm::cast<Attribute>(unwrap(result)));
+}
+
+MlirValue mlirOpFoldResultGetValue(MlirOpFoldResult result) {
+  return wrap(llvm::cast<Value>(unwrap(result)));
+}
+
 //===----------------------------------------------------------------------===//
 // Identifier API.
 //===----------------------------------------------------------------------===//
diff --git a/mlir/test/CAPI/ir.c b/mlir/test/CAPI/ir.c
index 5487d1d9cf654..24a38e1b951e4 100644
--- a/mlir/test/CAPI/ir.c
+++ b/mlir/test/CAPI/ir.c
@@ -2508,6 +2508,46 @@ int testBlockPredecessorsSuccessors(MlirContext ctx) {
   return 0;
 }
 
+void testOpFoldResult(MlirContext ctx) {
+  fprintf(stderr, "@testOpFoldResult\n");
+  // CHECK-LABEL: @testOpFoldResult
+
+  // Test OpFoldResult from attribute.
+  MlirAttribute attr = mlirIntegerAttrGet(mlirIntegerTypeGet(ctx, 32), 42);
+  MlirOpFoldResult ofrAttr = mlirOpFoldResultFromAttribute(attr);
+
+  // CHECK: ofrAttr isAttribute: 1
+  fprintf(stderr, "ofrAttr isAttribute: %d\n",
+          mlirOpFoldResultIsAttribute(ofrAttr));
+  // CHECK: ofrAttr isValue: 0
+  fprintf(stderr, "ofrAttr isValue: %d\n", mlirOpFoldResultIsValue(ofrAttr));
+
+  // Round-trip: extract the attribute back.
+  MlirAttribute extracted = mlirOpFoldResultGetAttribute(ofrAttr);
+  // CHECK: attr round-trip: 1
+  fprintf(stderr, "attr round-trip: %d\n", mlirAttributeEqual(attr, extracted));
+
+  // Test OpFoldResult from value (using a block argument).
+  MlirType i32 = mlirIntegerTypeGet(ctx, 32);
+  MlirLocation loc = mlirLocationUnknownGet(ctx);
+  MlirBlock block = mlirBlockCreate(1, &i32, &loc);
+  MlirValue arg = mlirBlockGetArgument(block, 0);
+  MlirOpFoldResult ofrValue = mlirOpFoldResultFromValue(arg);
+
+  // CHECK: ofrValue isValue: 1
+  fprintf(stderr, "ofrValue isValue: %d\n", mlirOpFoldResultIsValue(ofrValue));
+  // CHECK: ofrValue isAttribute: 0
+  fprintf(stderr, "ofrValue isAttribute: %d\n",
+          mlirOpFoldResultIsAttribute(ofrValue));
+
+  // Round-trip: extract the value back.
+  MlirValue extractedVal = mlirOpFoldResultGetValue(ofrValue);
+  // CHECK: value round-trip: 1
+  fprintf(stderr, "value round-trip: %d\n", mlirValueEqual(arg, extractedVal));
+
+  mlirBlockDestroy(block);
+}
+
 int main(void) {
   MlirContext ctx = mlirContextCreate();
   registerAllUpstreamDialects(ctx);
@@ -2557,6 +2597,8 @@ int main(void) {
   if (testBlockPredecessorsSuccessors(ctx))
     return 17;
 
+  testOpFoldResult(ctx);
+
   // CHECK: DESTROY MAIN CONTEXT
   // CHECK: reportResourceDelete: resource_i64_blob
   fprintf(stderr, "DESTROY MAIN CONTEXT\n");



More information about the Mlir-commits mailing list