[Mlir-commits] [mlir] 18cc9aa - [mlir][emitc] Add a common type converter (#203763)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Mon Jun 15 22:33:24 PDT 2026
Author: Gil Rapaport
Date: 2026-06-16T08:33:18+03:00
New Revision: 18cc9aa9c92be7d89d3e0877e7148782c14fd05a
URL: https://github.com/llvm/llvm-project/commit/18cc9aa9c92be7d89d3e0877e7148782c14fd05a
DIFF: https://github.com/llvm/llvm-project/commit/18cc9aa9c92be7d89d3e0877e7148782c14fd05a.diff
LOG: [mlir][emitc] Add a common type converter (#203763)
MemRef type conversion is currently implemented as part of the memref
dialect lowering pass, which means e.g. that func-to-emitc cannot lower
functions taking MemRef types as arguments.
This patch refactors the existing type conversions in EmitC's lowering
passes into a structure similar to the LLVM dialect by adding a common
EmitC type converter and using it across dialect-specfic EmitC lowering
passes and the generic convert-to-emitc pass.
Assisted-by: Copilot
Added:
mlir/include/mlir/Conversion/EmitCCommon/TypeConverter.h
mlir/lib/Conversion/EmitCCommon/CMakeLists.txt
mlir/lib/Conversion/EmitCCommon/TypeConverter.cpp
Modified:
mlir/include/mlir/Conversion/MemRefToEmitC/MemRefToEmitC.h
mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp
mlir/lib/Conversion/ArithToEmitC/ArithToEmitCPass.cpp
mlir/lib/Conversion/ArithToEmitC/CMakeLists.txt
mlir/lib/Conversion/CMakeLists.txt
mlir/lib/Conversion/ConvertToEmitC/CMakeLists.txt
mlir/lib/Conversion/ConvertToEmitC/ConvertToEmitCPass.cpp
mlir/lib/Conversion/FuncToEmitC/CMakeLists.txt
mlir/lib/Conversion/FuncToEmitC/FuncToEmitCPass.cpp
mlir/lib/Conversion/MemRefToEmitC/CMakeLists.txt
mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp
mlir/lib/Conversion/SCFToEmitC/CMakeLists.txt
mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
Removed:
################################################################################
diff --git a/mlir/include/mlir/Conversion/EmitCCommon/TypeConverter.h b/mlir/include/mlir/Conversion/EmitCCommon/TypeConverter.h
new file mode 100644
index 0000000000000..9db077d662846
--- /dev/null
+++ b/mlir/include/mlir/Conversion/EmitCCommon/TypeConverter.h
@@ -0,0 +1,31 @@
+//===- TypeConverter.h - Convert builtin to EmitC dialect types -*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Provides a type converter configuration for converting common builtin types
+// to the EmitC dialect.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_CONVERSION_EMITCCOMMON_TYPECONVERTER_H
+#define MLIR_CONVERSION_EMITCCOMMON_TYPECONVERTER_H
+
+#include "mlir/Transforms/DialectConversion.h"
+
+namespace mlir {
+
+/// Conversion from common builtin types to the EmitC dialect.
+class EmitCTypeConverter : public TypeConverter {
+public:
+ using TypeConverter::convertType;
+
+ explicit EmitCTypeConverter(MLIRContext *ctx);
+};
+
+} // namespace mlir
+
+#endif // MLIR_CONVERSION_EMITCCOMMON_TYPECONVERTER_H
diff --git a/mlir/include/mlir/Conversion/MemRefToEmitC/MemRefToEmitC.h b/mlir/include/mlir/Conversion/MemRefToEmitC/MemRefToEmitC.h
index 64c9ce091dcd0..061cf842e28ae 100644
--- a/mlir/include/mlir/Conversion/MemRefToEmitC/MemRefToEmitC.h
+++ b/mlir/include/mlir/Conversion/MemRefToEmitC/MemRefToEmitC.h
@@ -22,8 +22,6 @@ class DialectRegistry;
class RewritePatternSet;
class TypeConverter;
-void populateMemRefToEmitCTypeConversion(TypeConverter &typeConverter);
-
void populateMemRefToEmitCConversionPatterns(RewritePatternSet &patterns,
const TypeConverter &converter);
diff --git a/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp b/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp
index 5b074130925a4..91dde9018a288 100644
--- a/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp
+++ b/mlir/lib/Conversion/ArithToEmitC/ArithToEmitC.cpp
@@ -59,6 +59,9 @@ class ArithConstantOpConversionPattern
matchAndRewrite(arith::ConstantOp arithConst,
arith::ConstantOp::Adaptor adaptor,
ConversionPatternRewriter &rewriter) const override {
+ if (isa<MemRefType>(arithConst.getType()))
+ return rewriter.notifyMatchFailure(arithConst,
+ "memref constants are not supported");
Type newTy = this->getTypeConverter()->convertType(arithConst.getType());
if (!newTy)
return rewriter.notifyMatchFailure(arithConst, "type conversion failed");
diff --git a/mlir/lib/Conversion/ArithToEmitC/ArithToEmitCPass.cpp b/mlir/lib/Conversion/ArithToEmitC/ArithToEmitCPass.cpp
index 5ab1627ec40f3..e19a7b4d105cd 100644
--- a/mlir/lib/Conversion/ArithToEmitC/ArithToEmitCPass.cpp
+++ b/mlir/lib/Conversion/ArithToEmitC/ArithToEmitCPass.cpp
@@ -14,6 +14,7 @@
#include "mlir/Conversion/ArithToEmitC/ArithToEmitCPass.h"
#include "mlir/Conversion/ArithToEmitC/ArithToEmitC.h"
+#include "mlir/Conversion/EmitCCommon/TypeConverter.h"
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/EmitC/IR/EmitC.h"
#include "mlir/Pass/Pass.h"
@@ -41,13 +42,7 @@ void ConvertArithToEmitC::runOnOperation() {
RewritePatternSet patterns(&getContext());
- TypeConverter typeConverter;
- // Fallback for other types.
- typeConverter.addConversion([](Type type) -> std::optional<Type> {
- if (!emitc::isSupportedEmitCType(type))
- return {};
- return type;
- });
+ EmitCTypeConverter typeConverter(&getContext());
populateArithToEmitCPatterns(typeConverter, patterns);
diff --git a/mlir/lib/Conversion/ArithToEmitC/CMakeLists.txt b/mlir/lib/Conversion/ArithToEmitC/CMakeLists.txt
index 730a4b341673d..46f9aacbb14e1 100644
--- a/mlir/lib/Conversion/ArithToEmitC/CMakeLists.txt
+++ b/mlir/lib/Conversion/ArithToEmitC/CMakeLists.txt
@@ -10,6 +10,7 @@ add_mlir_conversion_library(MLIRArithToEmitC
LINK_LIBS PUBLIC
MLIRArithDialect
+ MLIREmitCCommonConversion
MLIREmitCDialect
MLIREmitCTransforms
MLIRPass
diff --git a/mlir/lib/Conversion/CMakeLists.txt b/mlir/lib/Conversion/CMakeLists.txt
index f5e0bcf613e59..b43ed905505fa 100644
--- a/mlir/lib/Conversion/CMakeLists.txt
+++ b/mlir/lib/Conversion/CMakeLists.txt
@@ -21,6 +21,7 @@ add_subdirectory(ComplexToStandard)
add_subdirectory(ControlFlowToLLVM)
add_subdirectory(ControlFlowToSCF)
add_subdirectory(ControlFlowToSPIRV)
+add_subdirectory(EmitCCommon)
add_subdirectory(ConvertToEmitC)
add_subdirectory(ConvertToLLVM)
add_subdirectory(FuncToEmitC)
diff --git a/mlir/lib/Conversion/ConvertToEmitC/CMakeLists.txt b/mlir/lib/Conversion/ConvertToEmitC/CMakeLists.txt
index 014ab26345033..e893d5cd1d35e 100644
--- a/mlir/lib/Conversion/ConvertToEmitC/CMakeLists.txt
+++ b/mlir/lib/Conversion/ConvertToEmitC/CMakeLists.txt
@@ -10,6 +10,7 @@ add_mlir_conversion_library(MLIRConvertToEmitC
LINK_LIBS PUBLIC
MLIRArithToEmitC
+ MLIREmitCCommonConversion
MLIRFuncToEmitC
MLIRMemRefToEmitC
MLIRPass
diff --git a/mlir/lib/Conversion/ConvertToEmitC/ConvertToEmitCPass.cpp b/mlir/lib/Conversion/ConvertToEmitC/ConvertToEmitCPass.cpp
index 4f060eafa14cc..ca66af051a4e8 100644
--- a/mlir/lib/Conversion/ConvertToEmitC/ConvertToEmitCPass.cpp
+++ b/mlir/lib/Conversion/ConvertToEmitC/ConvertToEmitCPass.cpp
@@ -9,6 +9,7 @@
#include "mlir/Conversion/ConvertToEmitC/ConvertToEmitCPass.h"
#include "mlir/Conversion/ConvertToEmitC/ToEmitCInterface.h"
+#include "mlir/Conversion/EmitCCommon/TypeConverter.h"
#include "mlir/Dialect/EmitC/IR/EmitC.h"
#include "mlir/Pass/Pass.h"
#include "mlir/Transforms/DialectConversion.h"
@@ -112,14 +113,7 @@ struct StaticConvertToEmitC : public ConvertToEmitCPassInterface {
/// Configure the conversion to EmitC at pass initialization.
LogicalResult initialize() final {
auto target = std::make_shared<ConversionTarget>(*context);
- auto typeConverter = std::make_shared<TypeConverter>();
-
- // Add fallback identity converison.
- typeConverter->addConversion([](Type type) -> std::optional<Type> {
- if (emitc::isSupportedEmitCType(type))
- return type;
- return std::nullopt;
- });
+ auto typeConverter = std::make_shared<EmitCTypeConverter>(context);
RewritePatternSet tempPatterns(context);
target->addLegalDialect<emitc::EmitCDialect>();
diff --git a/mlir/lib/Conversion/EmitCCommon/CMakeLists.txt b/mlir/lib/Conversion/EmitCCommon/CMakeLists.txt
new file mode 100644
index 0000000000000..a47f14bfda114
--- /dev/null
+++ b/mlir/lib/Conversion/EmitCCommon/CMakeLists.txt
@@ -0,0 +1,11 @@
+add_mlir_conversion_library(MLIREmitCCommonConversion
+ TypeConverter.cpp
+
+ ADDITIONAL_HEADER_DIRS
+ ${MLIR_MAIN_INCLUDE_DIR}/mlir/Conversion/EmitCCommon
+
+ LINK_LIBS PUBLIC
+ MLIREmitCDialect
+ MLIRIR
+ MLIRTransforms
+ )
diff --git a/mlir/lib/Conversion/EmitCCommon/TypeConverter.cpp b/mlir/lib/Conversion/EmitCCommon/TypeConverter.cpp
new file mode 100644
index 0000000000000..a65edcf8306b8
--- /dev/null
+++ b/mlir/lib/Conversion/EmitCCommon/TypeConverter.cpp
@@ -0,0 +1,58 @@
+//===- TypeConverter.cpp - Convert builtin to EmitC dialect types ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "mlir/Conversion/EmitCCommon/TypeConverter.h"
+
+#include "mlir/Dialect/EmitC/IR/EmitC.h"
+#include "mlir/IR/BuiltinTypes.h"
+#include "llvm/ADT/STLExtras.h"
+
+using namespace mlir;
+
+namespace {
+
+static bool isMemRefTypeLegalForEmitC(MemRefType memRefType) {
+ return memRefType.hasStaticShape() && memRefType.getLayout().isIdentity() &&
+ memRefType.getRank() != 0 &&
+ !llvm::is_contained(memRefType.getShape(), 0);
+}
+
+static Value materializeAsUnrealizedCast(OpBuilder &builder, Type resultType,
+ ValueRange inputs, Location loc) {
+ if (inputs.size() != 1)
+ return Value();
+
+ return UnrealizedConversionCastOp::create(builder, loc, resultType, inputs)
+ .getResult(0);
+}
+
+} // namespace
+
+EmitCTypeConverter::EmitCTypeConverter(MLIRContext *ctx) {
+ (void)ctx;
+
+ addConversion([](Type type) -> std::optional<Type> {
+ if (!emitc::isSupportedEmitCType(type))
+ return {};
+ return type;
+ });
+
+ addConversion([&](MemRefType memRefType) -> std::optional<Type> {
+ if (!isMemRefTypeLegalForEmitC(memRefType))
+ return {};
+
+ Type convertedElementType = convertType(memRefType.getElementType());
+ if (!convertedElementType)
+ return {};
+
+ return emitc::ArrayType::get(memRefType.getShape(), convertedElementType);
+ });
+
+ addSourceMaterialization(materializeAsUnrealizedCast);
+ addTargetMaterialization(materializeAsUnrealizedCast);
+}
diff --git a/mlir/lib/Conversion/FuncToEmitC/CMakeLists.txt b/mlir/lib/Conversion/FuncToEmitC/CMakeLists.txt
index 97752205bbcb4..c5d831f59379d 100644
--- a/mlir/lib/Conversion/FuncToEmitC/CMakeLists.txt
+++ b/mlir/lib/Conversion/FuncToEmitC/CMakeLists.txt
@@ -9,6 +9,7 @@ add_mlir_conversion_library(MLIRFuncToEmitC
MLIRConversionPassIncGen
LINK_LIBS PUBLIC
+ MLIREmitCCommonConversion
MLIREmitCDialect
MLIRFuncDialect
MLIRPass
diff --git a/mlir/lib/Conversion/FuncToEmitC/FuncToEmitCPass.cpp b/mlir/lib/Conversion/FuncToEmitC/FuncToEmitCPass.cpp
index 01129f3e4c5cd..d7052ad9837c1 100644
--- a/mlir/lib/Conversion/FuncToEmitC/FuncToEmitCPass.cpp
+++ b/mlir/lib/Conversion/FuncToEmitC/FuncToEmitCPass.cpp
@@ -12,6 +12,7 @@
#include "mlir/Conversion/FuncToEmitC/FuncToEmitCPass.h"
+#include "mlir/Conversion/EmitCCommon/TypeConverter.h"
#include "mlir/Conversion/FuncToEmitC/FuncToEmitC.h"
#include "mlir/Dialect/EmitC/IR/EmitC.h"
#include "mlir/Dialect/Func/IR/FuncOps.h"
@@ -41,13 +42,7 @@ void ConvertFuncToEmitC::runOnOperation() {
RewritePatternSet patterns(&getContext());
- TypeConverter typeConverter;
- // Fallback for other types.
- typeConverter.addConversion([](Type type) -> std::optional<Type> {
- if (!emitc::isSupportedEmitCType(type))
- return {};
- return type;
- });
+ EmitCTypeConverter typeConverter(&getContext());
populateFuncToEmitCPatterns(typeConverter, patterns, this->lowerToCpp);
diff --git a/mlir/lib/Conversion/MemRefToEmitC/CMakeLists.txt b/mlir/lib/Conversion/MemRefToEmitC/CMakeLists.txt
index 8a72e747d024a..23a40e7e48b8d 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/CMakeLists.txt
+++ b/mlir/lib/Conversion/MemRefToEmitC/CMakeLists.txt
@@ -12,6 +12,7 @@ add_mlir_conversion_library(MLIRMemRefToEmitC
Core
LINK_LIBS PUBLIC
+ MLIREmitCCommonConversion
MLIREmitCDialect
MLIRMemRefDialect
MLIRTransforms
diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
index 693ebc7bc3bd0..3e55f572d1418 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
@@ -45,7 +45,6 @@ struct MemRefToEmitCDialectInterface : public ConvertToEmitCPatternInterface {
void populateConvertToEmitCConversionPatterns(
ConversionTarget &target, TypeConverter &typeConverter,
RewritePatternSet &patterns, std::optional<bool> lowerToCpp) const final {
- populateMemRefToEmitCTypeConversion(typeConverter);
populateMemRefToEmitCConversionPatterns(patterns, typeConverter);
}
};
@@ -473,34 +472,6 @@ struct ConvertStore final : public OpConversionPattern<memref::StoreOp> {
} // namespace
-void mlir::populateMemRefToEmitCTypeConversion(TypeConverter &typeConverter) {
- typeConverter.addConversion(
- [&](MemRefType memRefType) -> std::optional<Type> {
- if (!isMemRefTypeLegalForEmitC(memRefType)) {
- return {};
- }
- Type convertedElementType =
- typeConverter.convertType(memRefType.getElementType());
- if (!convertedElementType)
- return {};
- return emitc::ArrayType::get(memRefType.getShape(),
- convertedElementType);
- });
-
- auto materializeAsUnrealizedCast = [](OpBuilder &builder, Type resultType,
- ValueRange inputs,
- Location loc) -> Value {
- if (inputs.size() != 1)
- return Value();
-
- return UnrealizedConversionCastOp::create(builder, loc, resultType, inputs)
- .getResult(0);
- };
-
- typeConverter.addSourceMaterialization(materializeAsUnrealizedCast);
- typeConverter.addTargetMaterialization(materializeAsUnrealizedCast);
-}
-
void mlir::populateMemRefToEmitCConversionPatterns(
RewritePatternSet &patterns, const TypeConverter &converter) {
patterns.add<ConvertAlloca, ConvertAlloc, ConvertCopy, ConvertDealloc,
diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp
index 29974c213fcfb..6a3e096ac5a18 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp
@@ -12,6 +12,7 @@
#include "mlir/Conversion/MemRefToEmitC/MemRefToEmitCPass.h"
+#include "mlir/Conversion/EmitCCommon/TypeConverter.h"
#include "mlir/Conversion/MemRefToEmitC/MemRefToEmitC.h"
#include "mlir/Dialect/EmitC/IR/EmitC.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
@@ -42,17 +43,9 @@ struct ConvertMemRefToEmitCPass
: public impl::ConvertMemRefToEmitCBase<ConvertMemRefToEmitCPass> {
using Base::Base;
void runOnOperation() override {
- TypeConverter converter;
+ EmitCTypeConverter converter(&getContext());
ConvertMemRefToEmitCOptions options;
options.lowerToCpp = this->lowerToCpp;
- // Fallback for other types.
- converter.addConversion([](Type type) -> std::optional<Type> {
- if (!emitc::isSupportedEmitCType(type))
- return {};
- return type;
- });
-
- populateMemRefToEmitCTypeConversion(converter);
RewritePatternSet patterns(&getContext());
populateMemRefToEmitCConversionPatterns(patterns, converter);
diff --git a/mlir/lib/Conversion/SCFToEmitC/CMakeLists.txt b/mlir/lib/Conversion/SCFToEmitC/CMakeLists.txt
index af5493be8a4b3..453aa6c44c467 100644
--- a/mlir/lib/Conversion/SCFToEmitC/CMakeLists.txt
+++ b/mlir/lib/Conversion/SCFToEmitC/CMakeLists.txt
@@ -12,6 +12,7 @@ add_mlir_conversion_library(MLIRSCFToEmitC
LINK_LIBS PUBLIC
MLIRArithDialect
+ MLIREmitCCommonConversion
MLIREmitCDialect
MLIREmitCTransforms
MLIRSCFDialect
diff --git a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
index b4616e23a7066..22afdf376bb70 100644
--- a/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
+++ b/mlir/lib/Conversion/SCFToEmitC/SCFToEmitC.cpp
@@ -13,6 +13,7 @@
#include "mlir/Conversion/SCFToEmitC/SCFToEmitC.h"
#include "mlir/Conversion/ConvertToEmitC/ToEmitCInterface.h"
+#include "mlir/Conversion/EmitCCommon/TypeConverter.h"
#include "mlir/Dialect/EmitC/IR/EmitC.h"
#include "mlir/Dialect/EmitC/Transforms/TypeConversions.h"
#include "mlir/Dialect/SCF/IR/SCF.h"
@@ -519,13 +520,7 @@ void mlir::populateSCFToEmitCConversionPatterns(RewritePatternSet &patterns,
void SCFToEmitCPass::runOnOperation() {
RewritePatternSet patterns(&getContext());
- TypeConverter typeConverter;
- // Fallback for other types.
- typeConverter.addConversion([](Type type) -> std::optional<Type> {
- if (!emitc::isSupportedEmitCType(type))
- return {};
- return type;
- });
+ EmitCTypeConverter typeConverter(&getContext());
populateEmitCSizeTTypeConversions(typeConverter);
populateSCFToEmitCConversionPatterns(patterns, typeConverter);
diff --git a/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir b/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
index 9ac863c4a8e9f..bedad2111dce1 100644
--- a/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
+++ b/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
@@ -166,3 +166,17 @@ func.func @first(%arg0: i32) -> (i32, i32) {
func.func @second(%arg0: i32) -> (i32, i32) {
return %arg0, %arg0 : i32, i32
}
+
+// -----
+
+// CHECK-LABEL: emitc.func private @memref_callee(!emitc.array<4x8xf32>)
+func.func private @memref_callee(%buff : memref<4x8xf32>)
+
+// CHECK-LABEL: emitc.func @memref_call(
+// CHECK-SAME: %[[ARG0:.*]]: !emitc.array<4x8xf32>)
+// CHECK-NEXT: call @memref_callee(%[[ARG0]]) : (!emitc.array<4x8xf32>) -> ()
+// CHECK-NEXT: return
+func.func @memref_call(%buff : memref<4x8xf32>) {
+ func.call @memref_callee(%buff) : (memref<4x8xf32>) -> ()
+ return
+}
More information about the Mlir-commits
mailing list