[Mlir-commits] [mlir] ece20ef - [mlir][emitc] Apply type converter to memref element types in -convert-memref-to-emitc (#203742)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Thu Jun 18 10:32:23 PDT 2026
Author: Jeremy Kun
Date: 2026-06-18T17:32:19Z
New Revision: ece20ef68083e29fe450a8f188ce90fbd2bb6356
URL: https://github.com/llvm/llvm-project/commit/ece20ef68083e29fe450a8f188ce90fbd2bb6356
DIFF: https://github.com/llvm/llvm-project/commit/ece20ef68083e29fe450a8f188ce90fbd2bb6356.diff
LOG: [mlir][emitc] Apply type converter to memref element types in -convert-memref-to-emitc (#203742)
This change fixes a few places where the memref-to-emitc
conversion didn't properly convert memref element types.
This PR updates both memref.alloc and memref.copy to convert the memref
element type when using the element type for `sizeof` calls, as well as
generating the output pointer type (just for `alloc`).
This was missed because there are no `convert-to-emitc` tests that use a
type converter with custom types, so I added such a registration to the
test dialect. It is worth noting that, while this patch only affects
`-convert-memref-to-emitc`, the change has no impact without the
additional type converter registrations in `-convert-to-emitc` because
there are no builtin types that have nontrivial emit conversions today.
As a drive-by improvement, I deduped a "total size in bytes" calculation
that was happening in the lowerings for both `memref.alloc` and
`memref.copy`.
Added:
mlir/test/Conversion/MemRefToEmitC/memref-with-custom-types.mlir
Modified:
mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
mlir/test/lib/Dialect/Test/CMakeLists.txt
mlir/test/lib/Dialect/Test/TestDialectInterfaces.cpp
utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel
Removed:
################################################################################
diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
index 3e55f572d1418..8acb737f0e9b8 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
@@ -101,14 +101,16 @@ Type convertMemRefType(MemRefType opTy, const TypeConverter *typeConverter) {
}
static Value calculateMemrefTotalSizeBytes(Location loc, MemRefType memrefType,
- OpBuilder &builder) {
+ OpBuilder &builder,
+ Type convertedElementType) {
assert(isMemRefTypeLegalForEmitC(memrefType) &&
"incompatible memref type for EmitC conversion");
+
emitc::CallOpaqueOp elementSize = emitc::CallOpaqueOp::create(
builder, loc, emitc::SizeTType::get(builder.getContext()),
builder.getStringAttr("sizeof"), ValueRange{},
ArrayAttr::get(builder.getContext(),
- {TypeAttr::get(memrefType.getElementType())}));
+ {TypeAttr::get(convertedElementType)}));
IndexType indexType = builder.getIndexType();
int64_t numElements = llvm::product_of(memrefType.getShape());
@@ -185,23 +187,15 @@ struct ConvertAlloc final : public OpConversionPattern<memref::AllocOp> {
}
Type sizeTType = emitc::SizeTType::get(rewriter.getContext());
- Type elementType = memrefType.getElementType();
- IndexType indexType = rewriter.getIndexType();
- emitc::CallOpaqueOp sizeofElementOp = emitc::CallOpaqueOp::create(
- rewriter, loc, sizeTType, rewriter.getStringAttr("sizeof"),
- ValueRange{},
- ArrayAttr::get(rewriter.getContext(), {TypeAttr::get(elementType)}));
-
- int64_t numElements = 1;
- for (int64_t dimSize : memrefType.getShape()) {
- numElements *= dimSize;
+ Type elementType =
+ getTypeConverter()->convertType(memrefType.getElementType());
+ if (!elementType) {
+ return rewriter.notifyMatchFailure(
+ loc, "failed to convert memref element type");
}
- Value numElementsValue = emitc::ConstantOp::create(
- rewriter, loc, indexType, rewriter.getIndexAttr(numElements));
-
+ IndexType indexType = rewriter.getIndexType();
Value totalSizeBytes =
- emitc::MulOp::create(rewriter, loc, sizeTType,
- sizeofElementOp.getResult(0), numElementsValue);
+ calculateMemrefTotalSizeBytes(loc, memrefType, rewriter, elementType);
emitc::CallOpaqueOp allocCall;
StringAttr allocFunctionName;
@@ -296,11 +290,21 @@ struct ConvertCopy final : public OpConversionPattern<memref::CopyOp> {
emitc::AddressOfOp targetPtr =
createPointerFromEmitcArray(loc, rewriter, targetArrayValue);
- emitc::CallOpaqueOp memCpyCall = emitc::CallOpaqueOp::create(
- rewriter, loc, TypeRange{}, "memcpy",
- ValueRange{
- targetPtr.getResult(), srcPtr.getResult(),
- calculateMemrefTotalSizeBytes(loc, srcMemrefType, rewriter)});
+ Type convertedElementType =
+ getTypeConverter()->convertType(srcMemrefType.getElementType());
+ if (!convertedElementType) {
+ return rewriter.notifyMatchFailure(
+ loc, "failed to convert memref element type");
+ }
+ Value totalSizeInBytes = calculateMemrefTotalSizeBytes(
+ loc, srcMemrefType, rewriter, convertedElementType);
+ emitc::CallOpaqueOp memCpyCall =
+ emitc::CallOpaqueOp::create(rewriter, loc, TypeRange{}, "memcpy",
+ ValueRange{
+ targetPtr.getResult(),
+ srcPtr.getResult(),
+ totalSizeInBytes,
+ });
rewriter.replaceOp(copyOp, memCpyCall.getResults());
diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-with-custom-types.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-with-custom-types.mlir
new file mode 100644
index 0000000000000..4cc874633d456
--- /dev/null
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-with-custom-types.mlir
@@ -0,0 +1,46 @@
+// Note that we use `-convert-to-emitc` instead of `-convert-memref-to-emitc`
+// to include the custom type converter registration for the test dialect.
+
+// RUN: mlir-opt -convert-to-emitc -split-input-file %s | FileCheck %s
+
+// CHECK-LABEL: emitc.func @alloc_with_custom_element_type()
+func.func @alloc_with_custom_element_type() {
+ // CHECK: call_opaque "sizeof"() <{args = [!emitc.opaque<"TestElementT">]}> : () -> !emitc.size_t
+ // CHECK: cast
+ // CHECK-SAME: !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<!emitc.opaque<"TestElementT">>
+ %0 = memref.alloc() : memref<10x!test.memref_element>
+ return
+}
+
+// -----
+
+// CHECK-LABEL: emitc.func @copy_with_custom_element_type(
+func.func @copy_with_custom_element_type(%arg0: memref<10x!test.memref_element>, %arg1: memref<10x!test.memref_element>) {
+ // CHECK: call_opaque "memcpy"
+ // CHECK-SAME: (!emitc.ptr<!emitc.opaque<"TestElementT">>, !emitc.ptr<!emitc.opaque<"TestElementT">>, !emitc.size_t) -> ()
+ memref.copy %arg0, %arg1 : memref<10x!test.memref_element> to memref<10x!test.memref_element>
+ return
+}
+
+// -----
+
+// CHECK-LABEL: emitc.func @store_with_custom_element_type(
+func.func @store_with_custom_element_type(%v : !test.memref_element, %i: index) {
+ %alloc = memref.alloc() : memref<4x!test.memref_element>
+ // CHECK: assign
+ // CHECK-SAME: <!emitc.opaque<"TestElementT">>
+ memref.store %v, %alloc[%i] : memref<4x!test.memref_element>
+ return
+}
+
+// -----
+
+// CHECK-LABEL: emitc.func @load_with_custom_element_type(
+func.func @load_with_custom_element_type(%i: index) -> !test.memref_element {
+ %alloc = memref.alloc() : memref<4x!test.memref_element>
+ // CHECK: load
+ // CHECK-SAME: <!emitc.opaque<"TestElementT">>
+ %v = memref.load %alloc[%i] : memref<4x!test.memref_element>
+ return %v : !test.memref_element
+}
+
diff --git a/mlir/test/lib/Dialect/Test/CMakeLists.txt b/mlir/test/lib/Dialect/Test/CMakeLists.txt
index 9354a85d984c9..4c4721193322b 100644
--- a/mlir/test/lib/Dialect/Test/CMakeLists.txt
+++ b/mlir/test/lib/Dialect/Test/CMakeLists.txt
@@ -68,6 +68,7 @@ add_mlir_library(MLIRTestDialect
MLIRTestOpsIncGen
MLIRTestOpsSyntaxIncGen
MLIRTestOpsShardGen
+ MLIRConvertToEmitCPatternInterfaceIncGen
)
mlir_target_link_libraries(MLIRTestDialect PUBLIC
MLIRControlFlowInterfaces
@@ -77,6 +78,7 @@ mlir_target_link_libraries(MLIRTestDialect PUBLIC
MLIRDestinationStyleOpInterface
MLIRDialect
MLIRDLTIDialect
+ MLIREmitCDialect
MLIRFuncDialect
MLIRFunctionInterfaces
MLIRFuncTransforms
diff --git a/mlir/test/lib/Dialect/Test/TestDialectInterfaces.cpp b/mlir/test/lib/Dialect/Test/TestDialectInterfaces.cpp
index 1c9dbe1640687..04d956cce2eea 100644
--- a/mlir/test/lib/Dialect/Test/TestDialectInterfaces.cpp
+++ b/mlir/test/lib/Dialect/Test/TestDialectInterfaces.cpp
@@ -8,9 +8,13 @@
#include "TestDialect.h"
#include "TestOps.h"
+#include "TestTypes.h"
+#include "mlir/Conversion/ConvertToEmitC/ToEmitCInterface.h"
#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h"
+#include "mlir/Dialect/EmitC/IR/EmitC.h"
#include "mlir/Interfaces/FoldInterfaces.h"
#include "mlir/Reducer/ReductionPatternInterface.h"
+#include "mlir/Transforms/DialectConversion.h"
#include "mlir/Transforms/InliningUtils.h"
using namespace mlir;
@@ -432,6 +436,20 @@ struct TestReductionPatternInterface : public DialectReductionPatternInterface {
}
};
+struct TestToEmitCDialectInterface : public ConvertToEmitCPatternInterface {
+ explicit TestToEmitCDialectInterface(Dialect *dialect)
+ : ConvertToEmitCPatternInterface(dialect) {}
+
+ void populateConvertToEmitCConversionPatterns(
+ ConversionTarget &target, TypeConverter &typeConverter,
+ RewritePatternSet &patterns,
+ ::std::optional<bool> lowerToCpp) const final {
+ typeConverter.addConversion([](test::TestMemRefElementTypeType type) {
+ return emitc::OpaqueType::get(type.getContext(), "TestElementT");
+ });
+ }
+};
+
} // namespace
void TestDialect::registerInterfaces() {
@@ -440,4 +458,5 @@ void TestDialect::registerInterfaces() {
addInterfaces<TestDialectFoldInterface, TestInlinerInterface,
TestReductionPatternInterface, TestBytecodeDialectInterface>();
+ addInterface<TestToEmitCDialectInterface>();
}
diff --git a/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel b/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel
index f00a4eee0c6b2..0a0d373def04b 100644
--- a/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel
+++ b/utils/bazel/llvm-project-overlay/mlir/test/BUILD.bazel
@@ -401,12 +401,14 @@ cc_library(
"//mlir:ControlFlowDialect",
"//mlir:ControlFlowInterfaces",
"//mlir:ControlFlowTransforms",
+ "//mlir:ConvertToEmitCInterface",
"//mlir:DLTIDialect",
"//mlir:DataLayoutInterfaces",
"//mlir:DerivedAttributeOpInterface",
"//mlir:DestinationStyleOpInterface",
"//mlir:Dialect",
"//mlir:DialectUtils",
+ "//mlir:EmitCDialect",
"//mlir:FromLLVMIRTranslation",
"//mlir:FuncDialect",
"//mlir:FuncTransforms",
More information about the Mlir-commits
mailing list