[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