[Mlir-commits] [mlir] [mlir][emitc] Add type conversions to EmitC types to FuncToEmitC, MemRefToEmitC (PR #134096)

Corentin Ferry llvmlistbot at llvm.org
Wed Apr 2 08:19:01 PDT 2025


https://github.com/cferry-AMD created https://github.com/llvm/llvm-project/pull/134096

PR #93155 introduced EmitC `size_t`, `ptrdiff_t`, `ssize_t` types. Conversion passes `ArithToEmitC` and `SCFToEmitC` already make use of these types, but `FuncToEmitC` and `MemRefToEmitC` do not yet. This PR introduces EmitC type conversion into the latter two passes.

While `MemRefToEmitC` is pretty straightforward, `FuncToEmitC` required changes to:
* the call op lowering: the results of the op need to be converted,
* the function op lowering: the function signature (arguments and results) needs to be converted.


>From fd5a3a3e3ac9924a9a4213d13558ac6aafcad305 Mon Sep 17 00:00:00 2001
From: Corentin Ferry <corentin.ferry at amd.com>
Date: Tue, 21 May 2024 16:14:17 +0200
Subject: [PATCH 1/5] Use EmitC index types in all passes creating EmitC

---
 .../mlir/Conversion/FuncToEmitC/FuncToEmitC.h |  4 +-
 .../Conversion/FuncToEmitC/FuncToEmitC.cpp    | 45 ++++++++++++++++---
 .../FuncToEmitC/FuncToEmitCPass.cpp           | 10 ++++-
 .../MemRefToEmitC/MemRefToEmitCPass.cpp       |  2 +
 .../Conversion/FuncToEmitC/func-to-emitc.mlir | 30 +++++++++++++
 .../MemRefToEmitC/memref-to-emitc.mlir        | 22 +++++++++
 .../Conversion/SCFToEmitC/nest-for-if.mlir    | 33 ++++++++++++++
 7 files changed, 137 insertions(+), 9 deletions(-)
 create mode 100644 mlir/test/Conversion/SCFToEmitC/nest-for-if.mlir

diff --git a/mlir/include/mlir/Conversion/FuncToEmitC/FuncToEmitC.h b/mlir/include/mlir/Conversion/FuncToEmitC/FuncToEmitC.h
index 5c7f87e470306..ac6fe2da7d42f 100644
--- a/mlir/include/mlir/Conversion/FuncToEmitC/FuncToEmitC.h
+++ b/mlir/include/mlir/Conversion/FuncToEmitC/FuncToEmitC.h
@@ -9,10 +9,12 @@
 #ifndef MLIR_CONVERSION_FUNCTOEMITC_FUNCTOEMITC_H
 #define MLIR_CONVERSION_FUNCTOEMITC_FUNCTOEMITC_H
 
+#include "mlir/Transforms/DialectConversion.h"
 namespace mlir {
 class RewritePatternSet;
 
-void populateFuncToEmitCPatterns(RewritePatternSet &patterns);
+void populateFuncToEmitCPatterns(RewritePatternSet &patterns,
+                                 TypeConverter &typeConverter);
 } // namespace mlir
 
 #endif // MLIR_CONVERSION_FUNCTOEMITC_FUNCTOEMITC_H
diff --git a/mlir/lib/Conversion/FuncToEmitC/FuncToEmitC.cpp b/mlir/lib/Conversion/FuncToEmitC/FuncToEmitC.cpp
index 53b79839da04c..f2ea9add77d87 100644
--- a/mlir/lib/Conversion/FuncToEmitC/FuncToEmitC.cpp
+++ b/mlir/lib/Conversion/FuncToEmitC/FuncToEmitC.cpp
@@ -36,9 +36,17 @@ class CallOpConversion final : public OpConversionPattern<func::CallOp> {
       return rewriter.notifyMatchFailure(
           callOp, "only functions with zero or one result can be converted");
 
-    rewriter.replaceOpWithNewOp<emitc::CallOp>(callOp, callOp.getResultTypes(),
-                                               adaptor.getOperands(),
-                                               callOp->getAttrs());
+    // Convert the original function results.
+    Type resultTy = nullptr;
+    if (callOp.getNumResults()) {
+      resultTy = typeConverter->convertType(callOp.getResult(0).getType());
+      if (!resultTy)
+        return rewriter.notifyMatchFailure(
+            callOp, "function return type conversion failed");
+    }
+
+    rewriter.replaceOpWithNewOp<emitc::CallOp>(
+        callOp, resultTy, adaptor.getOperands(), callOp->getAttrs());
 
     return success();
   }
@@ -52,13 +60,34 @@ class FuncOpConversion final : public OpConversionPattern<func::FuncOp> {
   matchAndRewrite(func::FuncOp funcOp, OpAdaptor adaptor,
                   ConversionPatternRewriter &rewriter) const override {
 
-    if (funcOp.getFunctionType().getNumResults() > 1)
+    FunctionType type = funcOp.getFunctionType();
+    if (!type)
+      return failure();
+
+    if (type.getNumResults() > 1)
       return rewriter.notifyMatchFailure(
           funcOp, "only functions with zero or one result can be converted");
 
+    const TypeConverter *converter = getTypeConverter();
+
+    // Convert function signature
+    TypeConverter::SignatureConversion signatureConversion(type.getNumInputs());
+    SmallVector<Type, 1> convertedResults;
+    if (failed(converter->convertSignatureArgs(type.getInputs(),
+                                               signatureConversion)) ||
+        failed(converter->convertTypes(type.getResults(), convertedResults)) ||
+        failed(rewriter.convertRegionTypes(&funcOp.getFunctionBody(),
+                                           *converter, &signatureConversion)))
+      return rewriter.notifyMatchFailure(funcOp, "signature conversion failed");
+
+    // Convert the function type
+    auto convertedFunctionType = FunctionType::get(
+        rewriter.getContext(), signatureConversion.getConvertedTypes(),
+        convertedResults);
+
     // Create the converted `emitc.func` op.
     emitc::FuncOp newFuncOp = rewriter.create<emitc::FuncOp>(
-        funcOp.getLoc(), funcOp.getName(), funcOp.getFunctionType());
+        funcOp.getLoc(), funcOp.getName(), convertedFunctionType);
 
     // Copy over all attributes other than the function name and type.
     for (const auto &namedAttr : funcOp->getAttrs()) {
@@ -112,8 +141,10 @@ class ReturnOpConversion final : public OpConversionPattern<func::ReturnOp> {
 // Pattern population
 //===----------------------------------------------------------------------===//
 
-void mlir::populateFuncToEmitCPatterns(RewritePatternSet &patterns) {
+void mlir::populateFuncToEmitCPatterns(RewritePatternSet &patterns,
+                                       TypeConverter &typeConverter) {
   MLIRContext *ctx = patterns.getContext();
 
-  patterns.add<CallOpConversion, FuncOpConversion, ReturnOpConversion>(ctx);
+  patterns.add<CallOpConversion, FuncOpConversion, ReturnOpConversion>(
+      typeConverter, ctx);
 }
diff --git a/mlir/lib/Conversion/FuncToEmitC/FuncToEmitCPass.cpp b/mlir/lib/Conversion/FuncToEmitC/FuncToEmitCPass.cpp
index 0b97f2641ad08..94e324adfc466 100644
--- a/mlir/lib/Conversion/FuncToEmitC/FuncToEmitCPass.cpp
+++ b/mlir/lib/Conversion/FuncToEmitC/FuncToEmitCPass.cpp
@@ -14,6 +14,7 @@
 
 #include "mlir/Conversion/FuncToEmitC/FuncToEmitC.h"
 #include "mlir/Dialect/EmitC/IR/EmitC.h"
+#include "mlir/Dialect/EmitC/Transforms/TypeConversions.h"
 #include "mlir/Dialect/Func/IR/FuncOps.h"
 #include "mlir/Pass/Pass.h"
 #include "mlir/Transforms/DialectConversion.h"
@@ -33,13 +34,20 @@ struct ConvertFuncToEmitC
 } // namespace
 
 void ConvertFuncToEmitC::runOnOperation() {
+  TypeConverter typeConverter;
+  // Fallback converter
+  // See note https://mlir.llvm.org/docs/DialectConversion/#type-converter
+  // Type converters are called most to least recently inserted
+  typeConverter.addConversion([](Type t) { return t; });
+  populateEmitCSizeTTypeConversions(typeConverter);
+
   ConversionTarget target(getContext());
 
   target.addLegalDialect<emitc::EmitCDialect>();
   target.addIllegalOp<func::CallOp, func::FuncOp, func::ReturnOp>();
 
   RewritePatternSet patterns(&getContext());
-  populateFuncToEmitCPatterns(patterns);
+  populateFuncToEmitCPatterns(patterns, typeConverter);
 
   if (failed(
           applyPartialConversion(getOperation(), target, std::move(patterns))))
diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp
index 33097c71e70b1..95b7765129085 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp
@@ -14,6 +14,7 @@
 
 #include "mlir/Conversion/MemRefToEmitC/MemRefToEmitC.h"
 #include "mlir/Dialect/EmitC/IR/EmitC.h"
+#include "mlir/Dialect/EmitC/Transforms/TypeConversions.h"
 #include "mlir/Dialect/MemRef/IR/MemRef.h"
 #include "mlir/Pass/Pass.h"
 #include "mlir/Transforms/DialectConversion.h"
@@ -39,6 +40,7 @@ struct ConvertMemRefToEmitCPass
     });
 
     populateMemRefToEmitCTypeConversion(converter);
+    populateEmitCSizeTTypeConversions(converter);
 
     auto materializeAsUnrealizedCast = [](OpBuilder &builder, Type resultType,
                                           ValueRange inputs,
diff --git a/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir b/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
index bd48886ed739e..046073eb30306 100644
--- a/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
+++ b/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
@@ -74,3 +74,33 @@ func.func @call() {
   call @return_void() : () -> ()
   return
 }
+
+// -----
+
+// CHECK-LABEL: emitc.func @use_index
+// CHECK-SAME: (%[[Arg0:.*]]: !emitc.size_t) -> !emitc.size_t
+// CHECK: emitc.return %[[Arg0]] : !emitc.size_t
+func.func @use_index(%arg0: index) -> index {
+  return %arg0 : index
+}
+
+// -----
+
+// CHECK-LABEL: emitc.func private @prototype_index(!emitc.size_t) -> !emitc.size_t attributes {specifiers = ["extern"]}
+func.func private @prototype_index(%arg0: index) -> index
+
+// CHECK-LABEL: emitc.func @call(%arg0: !emitc.size_t) -> !emitc.size_t
+// CHECK-NEXT: %0 = emitc.call @prototype_index(%arg0) : (!emitc.size_t) -> !emitc.size_t
+// CHECK-NEXT: emitc.return %0 : !emitc.size_t
+func.func @call(%arg0: index) -> index {
+  %0 = call @prototype_index(%arg0) : (index) -> (index)
+  return %0 : index
+}
+
+// -----
+
+// CHECK-LABEL: emitc.func @index_args_only(%arg0: !emitc.size_t) -> f32
+func.func @index_args_only(%i: index) -> f32 {
+  %0 = arith.constant 0.0 : f32
+  return %0 : f32
+}
diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
index f5ef821cc9c05..26e1286e87ead 100644
--- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
@@ -52,3 +52,25 @@ module @globals {
     return
   }
 }
+
+// -----
+
+// CHECK-LABEL: memref_index_values
+// CHECK-SAME:  %[[argi:.*]]: index, %[[argj:.*]]: index
+// CHECK-SAME: -> index
+func.func @memref_index_values(%i: index, %j: index) -> index {
+  // CHECK: %[[i:.*]] = builtin.unrealized_conversion_cast %[[argi]] : index to !emitc.size_t
+  // CHECK: %[[j:.*]] = builtin.unrealized_conversion_cast %[[argj]] : index to !emitc.size_t
+
+  // CHECK: %[[ALLOCA:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.array<4x8x!emitc.size_t>
+  %0 = memref.alloca() : memref<4x8xindex>
+
+  // CHECK: %[[LOAD:.*]] = emitc.subscript %[[ALLOCA]][%[[i]], %[[j]]] : (!emitc.array<4x8x!emitc.size_t>, !emitc.size_t, !emitc.size_t) -> !emitc.size_t
+  // CHECK: %[[VAR:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.size_t
+  // CHECK: emitc.assign %[[LOAD]] : !emitc.size_t to %[[VAR]] : !emitc.size_t
+  %1 = memref.load %0[%i, %j] : memref<4x8xindex>
+
+  // CHECK: %[[CAST_RET:.*]] = builtin.unrealized_conversion_cast %[[VAR]] : !emitc.size_t to index
+  // CHECK: return %[[CAST_RET]] : index
+  return %1 : index
+}
diff --git a/mlir/test/Conversion/SCFToEmitC/nest-for-if.mlir b/mlir/test/Conversion/SCFToEmitC/nest-for-if.mlir
new file mode 100644
index 0000000000000..572ec657483ab
--- /dev/null
+++ b/mlir/test/Conversion/SCFToEmitC/nest-for-if.mlir
@@ -0,0 +1,33 @@
+// RUN: mlir-opt -allow-unregistered-dialect -convert-scf-to-emitc %s | FileCheck %s
+
+// CHECK-LABEL: func.func @nest_for_in_if
+// CHECK-SAME: %[[ARG_0:.*]]: i1, %[[ARG_1:.*]]: index, %[[ARG_2:.*]]: index, %[[ARG_3:.*]]: index, %[[ARG_4:.*]]: f32
+// CHECK-NEXT:    %[[CAST_0:.*]] = builtin.unrealized_conversion_cast %[[ARG_1]] : index to !emitc.size_t
+// CHECK-NEXT:    %[[CAST_1:.*]] = builtin.unrealized_conversion_cast %[[ARG_2]] : index to !emitc.size_t
+// CHECK-NEXT:    %[[CAST_2:.*]] = builtin.unrealized_conversion_cast %[[ARG_3]] : index to !emitc.size_t
+// CHECK-NEXT:    emitc.if %[[ARG_0]] {
+// CHECK-NEXT:      emitc.for %[[ARG_5:.*]] = %[[CAST_0]] to %[[CAST_1]] step %[[CAST_2]] {
+// CHECK-NEXT:        %[[CST_1:.*]] = arith.constant 1 : index
+// CHECK-NEXT:        %[[CAST_3:.*]] = builtin.unrealized_conversion_cast %[[CST_1]] : index to !emitc.size_t
+// CHECK-NEXT:        emitc.for %[[ARG_6:.*]] = %[[CAST_0]] to %[[CAST_1]] step %[[CAST_3]] {
+// CHECK-NEXT:          %[[CST_2:.*]] = arith.constant 1 : index
+// CHECK-NEXT:        }
+// CHECK-NEXT:      }
+// CHECK-NEXT:    } else {
+// CHECK-NEXT:      %3 = emitc.call_opaque "func_false"(%[[ARG_4]]) : (f32) -> i32
+// CHECK-NEXT:    }
+// CHECK-NEXT:    return
+// CHECK-NEXT:  }
+func.func @nest_for_in_if(%arg0: i1, %arg1: index, %arg2: index, %arg3: index, %arg4: f32) {
+  scf.if %arg0 {
+    scf.for %i0 = %arg1 to %arg2 step %arg3 {
+      %c1 = arith.constant 1 : index
+      scf.for %i1 = %arg1 to %arg2 step %c1 {
+        %c1_0 = arith.constant 1 : index
+      }
+    }
+  } else {
+    %0 = emitc.call_opaque "func_false"(%arg4) : (f32) -> i32
+  }
+  return
+}

>From b44fe89008ac12b51e65b82af02bc6a0855f7e83 Mon Sep 17 00:00:00 2001
From: Matthias Gehre <matthias.gehre at amd.com>
Date: Wed, 10 Jul 2024 15:57:34 +0200
Subject: [PATCH 2/5] Merge pull request #213 from Xilinx/matthias.emitc_func

[mlir][EmitC] Fix call ops with zero arguments in func to emitc conversion (llvm#94936)
---
 mlir/lib/Conversion/FuncToEmitC/FuncToEmitC.cpp  | 13 +++++--------
 .../Conversion/FuncToEmitC/func-to-emitc.mlir    | 16 ++++++++++++++++
 2 files changed, 21 insertions(+), 8 deletions(-)

diff --git a/mlir/lib/Conversion/FuncToEmitC/FuncToEmitC.cpp b/mlir/lib/Conversion/FuncToEmitC/FuncToEmitC.cpp
index f2ea9add77d87..8dbf15e4174d3 100644
--- a/mlir/lib/Conversion/FuncToEmitC/FuncToEmitC.cpp
+++ b/mlir/lib/Conversion/FuncToEmitC/FuncToEmitC.cpp
@@ -37,16 +37,13 @@ class CallOpConversion final : public OpConversionPattern<func::CallOp> {
           callOp, "only functions with zero or one result can be converted");
 
     // Convert the original function results.
-    Type resultTy = nullptr;
-    if (callOp.getNumResults()) {
-      resultTy = typeConverter->convertType(callOp.getResult(0).getType());
-      if (!resultTy)
-        return rewriter.notifyMatchFailure(
-            callOp, "function return type conversion failed");
+    SmallVector<Type> types;
+    if (failed(typeConverter->convertTypes(callOp.getResultTypes(), types))) {
+      return rewriter.notifyMatchFailure(
+          callOp, "function return type conversion failed");
     }
-
     rewriter.replaceOpWithNewOp<emitc::CallOp>(
-        callOp, resultTy, adaptor.getOperands(), callOp->getAttrs());
+        callOp, types, adaptor.getOperands(), callOp->getAttrs());
 
     return success();
   }
diff --git a/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir b/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
index 046073eb30306..611ac44e8ad1e 100644
--- a/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
+++ b/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
@@ -104,3 +104,19 @@ func.func @index_args_only(%i: index) -> f32 {
   %0 = arith.constant 0.0 : f32
   return %0 : f32
 }
+
+// -----
+
+// CHECK-LABEL: emitc.func private @return_void() attributes {specifiers = ["static"]}
+// CHECK-NEXT: emitc.return
+func.func private @return_void() {
+  return
+}
+
+// CHECK-LABEL: emitc.func @call()
+// CHECK-NEXT: emitc.call @return_void() : () -> ()
+// CHECK-NEXT: emitc.return
+func.func @call() {
+  call @return_void() : () -> ()
+  return
+}

>From 5b65859fa8adb828ff095c5520fe85f884ca0dbe Mon Sep 17 00:00:00 2001
From: Corentin Ferry <corentin.ferry at amd.com>
Date: Wed, 2 Apr 2025 08:51:55 -0600
Subject: [PATCH 3/5] Fix tests wrt upstream changes

---
 .../Conversion/FuncToEmitC/func-to-emitc.mlir | 12 +++++-----
 .../MemRefToEmitC/memref-to-emitc.mlir        | 23 +++++++++++--------
 .../Conversion/SCFToEmitC/nest-for-if.mlir    | 10 ++++----
 3 files changed, 24 insertions(+), 21 deletions(-)

diff --git a/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir b/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
index 611ac44e8ad1e..241b0dad5755f 100644
--- a/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
+++ b/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
@@ -79,7 +79,7 @@ func.func @call() {
 
 // CHECK-LABEL: emitc.func @use_index
 // CHECK-SAME: (%[[Arg0:.*]]: !emitc.size_t) -> !emitc.size_t
-// CHECK: emitc.return %[[Arg0]] : !emitc.size_t
+// CHECK: return %[[Arg0]] : !emitc.size_t
 func.func @use_index(%arg0: index) -> index {
   return %arg0 : index
 }
@@ -90,8 +90,8 @@ func.func @use_index(%arg0: index) -> index {
 func.func private @prototype_index(%arg0: index) -> index
 
 // CHECK-LABEL: emitc.func @call(%arg0: !emitc.size_t) -> !emitc.size_t
-// CHECK-NEXT: %0 = emitc.call @prototype_index(%arg0) : (!emitc.size_t) -> !emitc.size_t
-// CHECK-NEXT: emitc.return %0 : !emitc.size_t
+// CHECK-NEXT: %0 = call @prototype_index(%arg0) : (!emitc.size_t) -> !emitc.size_t
+// CHECK-NEXT: return %0 : !emitc.size_t
 func.func @call(%arg0: index) -> index {
   %0 = call @prototype_index(%arg0) : (index) -> (index)
   return %0 : index
@@ -108,14 +108,14 @@ func.func @index_args_only(%i: index) -> f32 {
 // -----
 
 // CHECK-LABEL: emitc.func private @return_void() attributes {specifiers = ["static"]}
-// CHECK-NEXT: emitc.return
+// CHECK-NEXT: return
 func.func private @return_void() {
   return
 }
 
 // CHECK-LABEL: emitc.func @call()
-// CHECK-NEXT: emitc.call @return_void() : () -> ()
-// CHECK-NEXT: emitc.return
+// CHECK-NEXT: call @return_void() : () -> ()
+// CHECK-NEXT: return
 func.func @call() {
   call @return_void() : () -> ()
   return
diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
index 26e1286e87ead..738e2dd09bc38 100644
--- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
@@ -12,9 +12,11 @@ func.func @alloca() {
 // CHECK-LABEL: memref_store
 // CHECK-SAME:  %[[buff:.*]]: memref<4x8xf32>, %[[v:.*]]: f32, %[[i:.*]]: index, %[[j:.*]]: index
 func.func @memref_store(%buff : memref<4x8xf32>, %v : f32, %i: index, %j: index) {
-  // CHECK-NEXT: %[[BUFFER:.*]] = builtin.unrealized_conversion_cast %[[buff]] : memref<4x8xf32> to !emitc.array<4x8xf32>
+  // CHECK-DAG: %[[IDX_I:.*]] = builtin.unrealized_conversion_cast %[[i]] : index to !emitc.size_t
+  // CHECK-DAG: %[[IDX_J:.*]] = builtin.unrealized_conversion_cast %[[j]] : index to !emitc.size_t
+  // CHECK-DAG: %[[BUFFER:.*]] = builtin.unrealized_conversion_cast %[[buff]] : memref<4x8xf32> to !emitc.array<4x8xf32>
   
-  // CHECK-NEXT: %[[SUBSCRIPT:.*]] = emitc.subscript %[[BUFFER]][%[[i]], %[[j]]] : (!emitc.array<4x8xf32>, index, index) -> !emitc.lvalue<f32>
+  // CHECK-NEXT: %[[SUBSCRIPT:.*]] = emitc.subscript %[[BUFFER]][%[[IDX_I]], %[[IDX_J]]] : (!emitc.array<4x8xf32>, !emitc.size_t, !emitc.size_t) -> !emitc.lvalue<f32>
   // CHECK-NEXT: emitc.assign %[[v]] : f32 to %[[SUBSCRIPT]] : <f32>
   memref.store %v, %buff[%i, %j] : memref<4x8xf32>
   return
@@ -25,9 +27,11 @@ func.func @memref_store(%buff : memref<4x8xf32>, %v : f32, %i: index, %j: index)
 // CHECK-LABEL: memref_load
 // CHECK-SAME:  %[[buff:.*]]: memref<4x8xf32>, %[[i:.*]]: index, %[[j:.*]]: index
 func.func @memref_load(%buff : memref<4x8xf32>, %i: index, %j: index) -> f32 {
-  // CHECK-NEXT: %[[BUFFER:.*]] = builtin.unrealized_conversion_cast %[[buff]] : memref<4x8xf32> to !emitc.array<4x8xf32>
+  // CHECK-DAG: %[[IDX_I:.*]] = builtin.unrealized_conversion_cast %[[i]] : index to !emitc.size_t
+  // CHECK-DAG: %[[IDX_J:.*]] = builtin.unrealized_conversion_cast %[[j]] : index to !emitc.size_t
+  // CHECK-DAG: %[[BUFFER:.*]] = builtin.unrealized_conversion_cast %[[buff]] : memref<4x8xf32> to !emitc.array<4x8xf32>
   
-  // CHECK-NEXT: %[[SUBSCRIPT:.*]] = emitc.subscript %[[BUFFER]][%[[i]], %[[j]]] : (!emitc.array<4x8xf32>, index, index) -> !emitc.lvalue<f32>
+  // CHECK-NEXT: %[[SUBSCRIPT:.*]] = emitc.subscript %[[BUFFER]][%[[IDX_I]], %[[IDX_J]]] : (!emitc.array<4x8xf32>, !emitc.size_t, !emitc.size_t) -> !emitc.lvalue<f32>
   // CHECK-NEXT: %[[LOAD:.*]] = emitc.load %[[SUBSCRIPT]] : <f32>
   %1 = memref.load %buff[%i, %j] : memref<4x8xf32>
   // CHECK-NEXT: return %[[LOAD]] : f32
@@ -59,18 +63,17 @@ module @globals {
 // CHECK-SAME:  %[[argi:.*]]: index, %[[argj:.*]]: index
 // CHECK-SAME: -> index
 func.func @memref_index_values(%i: index, %j: index) -> index {
-  // CHECK: %[[i:.*]] = builtin.unrealized_conversion_cast %[[argi]] : index to !emitc.size_t
-  // CHECK: %[[j:.*]] = builtin.unrealized_conversion_cast %[[argj]] : index to !emitc.size_t
+  // CHECK-DAG: %[[i:.*]] = builtin.unrealized_conversion_cast %[[argi]] : index to !emitc.size_t
+  // CHECK-DAG: %[[j:.*]] = builtin.unrealized_conversion_cast %[[argj]] : index to !emitc.size_t
 
   // CHECK: %[[ALLOCA:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.array<4x8x!emitc.size_t>
   %0 = memref.alloca() : memref<4x8xindex>
 
-  // CHECK: %[[LOAD:.*]] = emitc.subscript %[[ALLOCA]][%[[i]], %[[j]]] : (!emitc.array<4x8x!emitc.size_t>, !emitc.size_t, !emitc.size_t) -> !emitc.size_t
-  // CHECK: %[[VAR:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.size_t
-  // CHECK: emitc.assign %[[LOAD]] : !emitc.size_t to %[[VAR]] : !emitc.size_t
+  // CHECK: %[[SUBSCRIPT:.*]] = emitc.subscript %[[ALLOCA]][%[[i]], %[[j]]] : (!emitc.array<4x8x!emitc.size_t>, !emitc.size_t, !emitc.size_t) -> !emitc.lvalue<!emitc.size_t>
+  // CHECK: %[[LOAD:.*]] = emitc.load %[[SUBSCRIPT]] : <!emitc.size_t>
   %1 = memref.load %0[%i, %j] : memref<4x8xindex>
 
-  // CHECK: %[[CAST_RET:.*]] = builtin.unrealized_conversion_cast %[[VAR]] : !emitc.size_t to index
+  // CHECK: %[[CAST_RET:.*]] = builtin.unrealized_conversion_cast %[[LOAD]] : !emitc.size_t to index
   // CHECK: return %[[CAST_RET]] : index
   return %1 : index
 }
diff --git a/mlir/test/Conversion/SCFToEmitC/nest-for-if.mlir b/mlir/test/Conversion/SCFToEmitC/nest-for-if.mlir
index 572ec657483ab..bd3aa8acfcc0e 100644
--- a/mlir/test/Conversion/SCFToEmitC/nest-for-if.mlir
+++ b/mlir/test/Conversion/SCFToEmitC/nest-for-if.mlir
@@ -2,19 +2,19 @@
 
 // CHECK-LABEL: func.func @nest_for_in_if
 // CHECK-SAME: %[[ARG_0:.*]]: i1, %[[ARG_1:.*]]: index, %[[ARG_2:.*]]: index, %[[ARG_3:.*]]: index, %[[ARG_4:.*]]: f32
-// CHECK-NEXT:    %[[CAST_0:.*]] = builtin.unrealized_conversion_cast %[[ARG_1]] : index to !emitc.size_t
-// CHECK-NEXT:    %[[CAST_1:.*]] = builtin.unrealized_conversion_cast %[[ARG_2]] : index to !emitc.size_t
 // CHECK-NEXT:    %[[CAST_2:.*]] = builtin.unrealized_conversion_cast %[[ARG_3]] : index to !emitc.size_t
+// CHECK-NEXT:    %[[CAST_1:.*]] = builtin.unrealized_conversion_cast %[[ARG_2]] : index to !emitc.size_t
+// CHECK-NEXT:    %[[CAST_0:.*]] = builtin.unrealized_conversion_cast %[[ARG_1]] : index to !emitc.size_t
 // CHECK-NEXT:    emitc.if %[[ARG_0]] {
-// CHECK-NEXT:      emitc.for %[[ARG_5:.*]] = %[[CAST_0]] to %[[CAST_1]] step %[[CAST_2]] {
+// CHECK-NEXT:      for %[[ARG_5:.*]] = %[[CAST_0]] to %[[CAST_1]] step %[[CAST_2]] : !emitc.size_t {
 // CHECK-NEXT:        %[[CST_1:.*]] = arith.constant 1 : index
 // CHECK-NEXT:        %[[CAST_3:.*]] = builtin.unrealized_conversion_cast %[[CST_1]] : index to !emitc.size_t
-// CHECK-NEXT:        emitc.for %[[ARG_6:.*]] = %[[CAST_0]] to %[[CAST_1]] step %[[CAST_3]] {
+// CHECK-NEXT:        for %[[ARG_6:.*]] = %[[CAST_0]] to %[[CAST_1]] step %[[CAST_3]] : !emitc.size_t {
 // CHECK-NEXT:          %[[CST_2:.*]] = arith.constant 1 : index
 // CHECK-NEXT:        }
 // CHECK-NEXT:      }
 // CHECK-NEXT:    } else {
-// CHECK-NEXT:      %3 = emitc.call_opaque "func_false"(%[[ARG_4]]) : (f32) -> i32
+// CHECK-NEXT:      %3 = call_opaque "func_false"(%[[ARG_4]]) : (f32) -> i32
 // CHECK-NEXT:    }
 // CHECK-NEXT:    return
 // CHECK-NEXT:  }

>From 589065920f3f3673470b62a3405e42c0a8ec7b6d Mon Sep 17 00:00:00 2001
From: Corentin Ferry <corentin.ferry at amd.com>
Date: Wed, 2 Apr 2025 09:00:07 -0600
Subject: [PATCH 4/5] Remove duplicate test

---
 .../Conversion/FuncToEmitC/func-to-emitc.mlir    | 16 ----------------
 1 file changed, 16 deletions(-)

diff --git a/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir b/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
index 241b0dad5755f..4c151a244d2d0 100644
--- a/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
+++ b/mlir/test/Conversion/FuncToEmitC/func-to-emitc.mlir
@@ -104,19 +104,3 @@ func.func @index_args_only(%i: index) -> f32 {
   %0 = arith.constant 0.0 : f32
   return %0 : f32
 }
-
-// -----
-
-// CHECK-LABEL: emitc.func private @return_void() attributes {specifiers = ["static"]}
-// CHECK-NEXT: return
-func.func private @return_void() {
-  return
-}
-
-// CHECK-LABEL: emitc.func @call()
-// CHECK-NEXT: call @return_void() : () -> ()
-// CHECK-NEXT: return
-func.func @call() {
-  call @return_void() : () -> ()
-  return
-}

>From 3f85d554e92eaba474dad76db3cea50c3a448156 Mon Sep 17 00:00:00 2001
From: Corentin Ferry <corentin.ferry at amd.com>
Date: Wed, 2 Apr 2025 09:12:18 -0600
Subject: [PATCH 5/5] Test not part of the PR

---
 .../Conversion/SCFToEmitC/nest-for-if.mlir    | 33 -------------------
 1 file changed, 33 deletions(-)
 delete mode 100644 mlir/test/Conversion/SCFToEmitC/nest-for-if.mlir

diff --git a/mlir/test/Conversion/SCFToEmitC/nest-for-if.mlir b/mlir/test/Conversion/SCFToEmitC/nest-for-if.mlir
deleted file mode 100644
index bd3aa8acfcc0e..0000000000000
--- a/mlir/test/Conversion/SCFToEmitC/nest-for-if.mlir
+++ /dev/null
@@ -1,33 +0,0 @@
-// RUN: mlir-opt -allow-unregistered-dialect -convert-scf-to-emitc %s | FileCheck %s
-
-// CHECK-LABEL: func.func @nest_for_in_if
-// CHECK-SAME: %[[ARG_0:.*]]: i1, %[[ARG_1:.*]]: index, %[[ARG_2:.*]]: index, %[[ARG_3:.*]]: index, %[[ARG_4:.*]]: f32
-// CHECK-NEXT:    %[[CAST_2:.*]] = builtin.unrealized_conversion_cast %[[ARG_3]] : index to !emitc.size_t
-// CHECK-NEXT:    %[[CAST_1:.*]] = builtin.unrealized_conversion_cast %[[ARG_2]] : index to !emitc.size_t
-// CHECK-NEXT:    %[[CAST_0:.*]] = builtin.unrealized_conversion_cast %[[ARG_1]] : index to !emitc.size_t
-// CHECK-NEXT:    emitc.if %[[ARG_0]] {
-// CHECK-NEXT:      for %[[ARG_5:.*]] = %[[CAST_0]] to %[[CAST_1]] step %[[CAST_2]] : !emitc.size_t {
-// CHECK-NEXT:        %[[CST_1:.*]] = arith.constant 1 : index
-// CHECK-NEXT:        %[[CAST_3:.*]] = builtin.unrealized_conversion_cast %[[CST_1]] : index to !emitc.size_t
-// CHECK-NEXT:        for %[[ARG_6:.*]] = %[[CAST_0]] to %[[CAST_1]] step %[[CAST_3]] : !emitc.size_t {
-// CHECK-NEXT:          %[[CST_2:.*]] = arith.constant 1 : index
-// CHECK-NEXT:        }
-// CHECK-NEXT:      }
-// CHECK-NEXT:    } else {
-// CHECK-NEXT:      %3 = call_opaque "func_false"(%[[ARG_4]]) : (f32) -> i32
-// CHECK-NEXT:    }
-// CHECK-NEXT:    return
-// CHECK-NEXT:  }
-func.func @nest_for_in_if(%arg0: i1, %arg1: index, %arg2: index, %arg3: index, %arg4: f32) {
-  scf.if %arg0 {
-    scf.for %i0 = %arg1 to %arg2 step %arg3 {
-      %c1 = arith.constant 1 : index
-      scf.for %i1 = %arg1 to %arg2 step %c1 {
-        %c1_0 = arith.constant 1 : index
-      }
-    }
-  } else {
-    %0 = emitc.call_opaque "func_false"(%arg4) : (f32) -> i32
-  }
-  return
-}



More information about the Mlir-commits mailing list