[Mlir-commits] [mlir] 9fbb941 - [mlir][Func][EmitC] Bail-out to avoid errors from MemRef array conversions (#198583)
llvmlistbot at llvm.org
llvmlistbot at llvm.org
Thu Jun 4 07:26:26 PDT 2026
Author: ioana ghiban
Date: 2026-06-04T16:26:19+02:00
New Revision: 9fbb941b9defce93fb98099b91653db063b0ecba
URL: https://github.com/llvm/llvm-project/commit/9fbb941b9defce93fb98099b91653db063b0ecba
DIFF: https://github.com/llvm/llvm-project/commit/9fbb941b9defce93fb98099b91653db063b0ecba.diff
LOG: [mlir][Func][EmitC] Bail-out to avoid errors from MemRef array conversions (#198583)
Update FuncToEmitC to bail-out before creating invalid EmitC ops for
unsupported cases.
FuncToEmitC now rejects functions, calls, and returns whose converted
result type is `emitc.array`, instead of relying on later `emitc.func`,
`emitc.call`, or `emitc.return` verifier failures.
This does not add support for returning memrefs from functions. It only
makes the existing limitation explicit at the conversion boundary.
## Tests
Added negative tests for the standalone conversion pass. This pass marks
their source ops illegal, so when a pattern bails-out the pass reports a
legalization failure. This is the expected behavior and documents the
unsupported cases directly.
`convert-to-emitc` is more permissive because it allows partial
conversion and does not mark the same source ops illegal, so it can
leave unsupported ops unconverted without reporting the same failures.
Assisted-by: Codex (refine description). I reviewed all text before
submission.
Added:
Modified:
mlir/lib/Conversion/FuncToEmitC/FuncToEmitC.cpp
mlir/test/Conversion/FuncToEmitC/func-to-emitc-failed.mlir
Removed:
################################################################################
diff --git a/mlir/lib/Conversion/FuncToEmitC/FuncToEmitC.cpp b/mlir/lib/Conversion/FuncToEmitC/FuncToEmitC.cpp
index d2fb359c9aabe..4801f07d82c9f 100644
--- a/mlir/lib/Conversion/FuncToEmitC/FuncToEmitC.cpp
+++ b/mlir/lib/Conversion/FuncToEmitC/FuncToEmitC.cpp
@@ -60,6 +60,17 @@ class CallOpConversion final : public OpConversionPattern<func::CallOp> {
return rewriter.notifyMatchFailure(
callOp, "only functions with zero or one result can be converted");
+ if (callOp.getNumResults() == 1) {
+ Type resultType =
+ getTypeConverter()->convertType(callOp.getResult(0).getType());
+ if (!resultType)
+ return rewriter.notifyMatchFailure(callOp,
+ "result type conversion failed");
+ if (isa<emitc::ArrayType>(resultType))
+ return rewriter.notifyMatchFailure(
+ callOp, "function calls returning arrays are not supported");
+ }
+
rewriter.replaceOpWithNewOp<emitc::CallOp>(callOp, callOp.getResultTypes(),
adaptor.getOperands(),
callOp->getAttrs());
@@ -97,6 +108,9 @@ class FuncOpConversion final : public OpConversionPattern<func::FuncOp> {
if (!resultType)
return rewriter.notifyMatchFailure(funcOp,
"result type conversion failed");
+ if (isa<emitc::ArrayType>(resultType))
+ return rewriter.notifyMatchFailure(
+ funcOp, "functions returning arrays are not supported");
}
// Create the converted `emitc.func` op.
@@ -149,6 +163,10 @@ class ReturnOpConversion final : public OpConversionPattern<func::ReturnOp> {
if (returnOp.getNumOperands() > 1)
return rewriter.notifyMatchFailure(
returnOp, "only zero or one operand is supported");
+ if (returnOp.getNumOperands() == 1 &&
+ isa<emitc::ArrayType>(adaptor.getOperands()[0].getType()))
+ return rewriter.notifyMatchFailure(returnOp,
+ "returning arrays is not supported");
rewriter.replaceOpWithNewOp<emitc::ReturnOp>(
returnOp,
diff --git a/mlir/test/Conversion/FuncToEmitC/func-to-emitc-failed.mlir b/mlir/test/Conversion/FuncToEmitC/func-to-emitc-failed.mlir
index 73b3adeedaecd..d85069371e691 100644
--- a/mlir/test/Conversion/FuncToEmitC/func-to-emitc-failed.mlir
+++ b/mlir/test/Conversion/FuncToEmitC/func-to-emitc-failed.mlir
@@ -4,3 +4,96 @@
func.func @unsuppoted_emitc_type(%arg0: i4) -> i4 {
return %arg0 : i4
}
+
+// -----
+
+// expected-error at +1 {{failed to legalize operation 'func.func'}}
+func.func private @return_rank0_alloc() -> memref<i32> {
+ %alloc = memref.alloc() : memref<i32>
+ return %alloc : memref<i32>
+}
+
+// -----
+
+// expected-error at +1 {{failed to legalize operation 'func.func'}}
+func.func private @return_rank0_arg(%arg0: memref<i32>) -> memref<i32> {
+ return %arg0 : memref<i32>
+}
+
+// -----
+
+// expected-error at +1 {{failed to legalize operation 'func.func'}}
+func.func private @return_rank1_alloc() -> memref<1xi32> {
+ %alloc = memref.alloc() : memref<1xi32>
+ return %alloc : memref<1xi32>
+}
+
+// -----
+
+// expected-error at +1 {{failed to legalize operation 'func.func'}}
+func.func private @return_rank1_arg(%arg0: memref<1xi32>) -> memref<1xi32> {
+ return %arg0 : memref<1xi32>
+}
+
+// -----
+
+// expected-error at +1 {{failed to legalize operation 'func.func'}}
+func.func private @return_rank2_arg(%arg0: memref<1x1xi32>) -> memref<1x1xi32> {
+ return %arg0 : memref<1x1xi32>
+}
+
+// -----
+
+// expected-error at +1 {{failed to legalize operation 'func.func'}}
+func.func private @return_rank1_two_elements(%arg0: memref<2xi64>) -> memref<2xi64> {
+ return %arg0 : memref<2xi64>
+}
+
+// -----
+
+// expected-error at +1 {{failed to legalize operation 'func.func'}}
+func.func private @return_multiple_values(%arg0: memref<1xi32>) -> (memref<1xi32>, i32) {
+ %1 = arith.constant 7 : i32
+ return %arg0, %1 : memref<1xi32>, i32
+}
+
+// -----
+
+// expected-error at +1 {{failed to legalize operation 'func.func'}}
+func.func private @return_dynamic_shape(%arg0: memref<?xi32>) -> memref<?xi32> {
+ return %arg0 : memref<?xi32>
+}
+
+// -----
+
+// expected-error at +1 {{failed to legalize operation 'func.func'}}
+func.func private @return_non_identity_layout(%arg0: memref<1x1xi32, strided<[2, 1], offset: 0>>)
+ -> memref<1x1xi32, strided<[2, 1], offset: 0>> {
+ return %arg0 : memref<1x1xi32, strided<[2, 1], offset: 0>>
+}
+
+// -----
+
+// expected-error at +1 {{failed to legalize operation 'func.func'}}
+func.func private @return_unranked(%arg0: memref<*xi32>) -> memref<*xi32> {
+ return %arg0 : memref<*xi32>
+}
+
+// -----
+
+// expected-error at +1 {{failed to legalize operation 'func.func'}}
+func.func @public_function(%arg0: memref<1xi64>) -> memref<1xi64> {
+ return %arg0 : memref<1xi64>
+}
+
+// -----
+
+func.func private @callee(%arg0: i64) -> i64 {
+ return %arg0 : i64
+}
+
+// expected-error at +1 {{failed to legalize operation 'func.func'}}
+func.func private @caller(%arg0: memref<1xi64>, %arg1: i64) -> memref<1xi64> {
+ %0 = call @callee(%arg1) : (i64) -> i64
+ return %arg0 : memref<1xi64>
+}
More information about the Mlir-commits
mailing list