[Mlir-commits] [mlir] [mlir][EmitC] Add rank-0 MemRef conversion (PR #205774)

ioana ghiban llvmlistbot at llvm.org
Tue Jul 14 04:21:52 PDT 2026


https://github.com/ioghiban updated https://github.com/llvm/llvm-project/pull/205774

>From f741504ef4239958e3b7d1af170d3bc9af6d809c Mon Sep 17 00:00:00 2001
From: Ioana Ghiban <ioana.ghiban at arm.com>
Date: Mon, 22 Jun 2026 14:05:19 +0200
Subject: [PATCH 1/5] [mlir][EmitC] Add rank-0 MemRef conversion

---
 .../Conversion/EmitCCommon/TypeConverter.cpp  |  3 +-
 .../MemRefToEmitC/MemRefToEmitC.cpp           | 72 ++++++++++++++-----
 .../FuncToEmitC/func-to-emitc-failed.mlir     | 15 ----
 .../memref-to-emitc-alloc-dealloc.mlir        | 26 +++++++
 .../memref-to-emitc-alloc-load-store.mlir     | 48 +++++++++++++
 .../MemRefToEmitC/memref-to-emitc-copy.mlir   | 21 +++++-
 6 files changed, 150 insertions(+), 35 deletions(-)

diff --git a/mlir/lib/Conversion/EmitCCommon/TypeConverter.cpp b/mlir/lib/Conversion/EmitCCommon/TypeConverter.cpp
index a65edcf8306b8..1722fb95524d5 100644
--- a/mlir/lib/Conversion/EmitCCommon/TypeConverter.cpp
+++ b/mlir/lib/Conversion/EmitCCommon/TypeConverter.cpp
@@ -18,7 +18,6 @@ namespace {
 
 static bool isMemRefTypeLegalForEmitC(MemRefType memRefType) {
   return memRefType.hasStaticShape() && memRefType.getLayout().isIdentity() &&
-         memRefType.getRank() != 0 &&
          !llvm::is_contained(memRefType.getShape(), 0);
 }
 
@@ -50,6 +49,8 @@ EmitCTypeConverter::EmitCTypeConverter(MLIRContext *ctx) {
     if (!convertedElementType)
       return {};
 
+    if (memRefType.getRank() == 0)
+      return emitc::PointerType::get(convertedElementType);
     return emitc::ArrayType::get(memRefType.getShape(), convertedElementType);
   });
 
diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
index 8acb737f0e9b8..3af48fe23d140 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
@@ -30,7 +30,6 @@ using namespace mlir;
 
 static bool isMemRefTypeLegalForEmitC(MemRefType memRefType) {
   return memRefType.hasStaticShape() && memRefType.getLayout().isIdentity() &&
-         memRefType.getRank() != 0 &&
          !llvm::is_contained(memRefType.getShape(), 0);
 }
 
@@ -73,6 +72,11 @@ struct ConvertAlloca final : public OpConversionPattern<memref::AllocaOp> {
           op.getLoc(), "cannot transform alloca with dynamic shape");
     }
 
+    if (op.getType().getRank() == 0) {
+      return rewriter.notifyMatchFailure(
+          op.getLoc(), "cannot transform alloca with zero rank");
+    }
+
     if (op.getAlignment().value_or(1) > 1) {
       // TODO: Allow alignment if it is not more than the natural alignment
       // of the C array.
@@ -142,9 +146,12 @@ createPointerFromEmitcArray(Location loc, OpBuilder &builder,
   return ptr;
 }
 
-// If `v` is defined through an unrealized cast and the source of that cast
-// is `emitc.ptr`, return the pointer.
-static Value stripPointerUnrealizedCast(Value v) {
+static Value getPointerOrStripUnrealizedCast(Value v) {
+  if (isa<emitc::PointerType>(v.getType()))
+    return v;
+
+  // If `v` is defined through an unrealized cast and the source of that cast
+  // is `emitc.ptr`, return the pointer.
   if (auto cast = v.getDefiningOp<UnrealizedConversionCastOp>())
     if (cast.getNumOperands() == 1 &&
         isa<emitc::PointerType>(cast.getOperand(0).getType()))
@@ -165,6 +172,9 @@ static Value computeRowMajorLinearIndex(ImplicitLocOpBuilder &builder,
           ? emitc::ConstantOp::create(builder, idxType, builder.getIndexAttr(0))
           : indices[0];
 
+  if (shape.empty())
+    return linearIndex;
+
   for (auto [dim, idx] : llvm::zip(shape.drop_front(), indices.drop_front())) {
     Value dimSize =
         emitc::ConstantOp::create(builder, idxType, builder.getIndexAttr(dim));
@@ -238,10 +248,9 @@ struct ConvertDealloc final : public OpConversionPattern<memref::DeallocOp> {
                   ConversionPatternRewriter &rewriter) const override {
     Location loc = deallocOp.getLoc();
     // `free` can only be emitted when the dealloc operand is recoverable as an
-    // `emitc.ptr<T>`. In the current conversion, that happens via an
-    // unrealized_conversion_cast from the pointer-backed EmitC form.
-    Value strippedPtr = stripPointerUnrealizedCast(operands.getMemref());
-    if (!strippedPtr) {
+    // `emitc.ptr<T>`.
+    Value ptr = getPointerOrStripUnrealizedCast(operands.getMemref());
+    if (!ptr) {
       return rewriter.notifyMatchFailure(
           loc, "expected pointer-backed memref for EmitC deallocation");
     }
@@ -252,7 +261,7 @@ struct ConvertDealloc final : public OpConversionPattern<memref::DeallocOp> {
     Type opaqueVoidPtrType = emitc::PointerType::get(
         emitc::OpaqueType::get(rewriter.getContext(), "void"));
     Value freeArg =
-        emitc::CastOp::create(rewriter, loc, opaqueVoidPtrType, strippedPtr);
+        emitc::CastOp::create(rewriter, loc, opaqueVoidPtrType, ptr);
     emitc::CallOpaqueOp freeCall = emitc::CallOpaqueOp::create(
         rewriter, loc, TypeRange{}, rewriter.getStringAttr(freeFunctionName),
         ValueRange{freeArg});
@@ -280,6 +289,35 @@ struct ConvertCopy final : public OpConversionPattern<memref::CopyOp> {
       return rewriter.notifyMatchFailure(
           loc, "incompatible target memref type for EmitC conversion");
 
+    if (srcMemrefType.getRank() == 0) {
+      assert(targetMemrefType.getRank() == 0 &&
+             "target must have same rank as source");
+      Type elementType =
+          getTypeConverter()->convertType(srcMemrefType.getElementType());
+      if (!elementType)
+        return rewriter.notifyMatchFailure(loc, "cannot convert element type");
+
+      Value srcPtr = getPointerOrStripUnrealizedCast(operands.getSource());
+      Value targetPtr = getPointerOrStripUnrealizedCast(operands.getTarget());
+      if (!srcPtr || !targetPtr)
+        return rewriter.notifyMatchFailure(loc, "expected pointer operands");
+
+      Value zeroIndex = emitc::ConstantOp::create(
+          rewriter, loc, rewriter.getIndexType(), rewriter.getIndexAttr(0));
+      auto srcLValue = emitc::SubscriptOp::create(
+          rewriter, loc, cast<TypedValue<emitc::PointerType>>(srcPtr),
+          zeroIndex);
+      auto value = emitc::LoadOp::create(rewriter, loc, elementType,
+                                         srcLValue.getResult());
+
+      auto targetLValue = emitc::SubscriptOp::create(
+          rewriter, loc, cast<TypedValue<emitc::PointerType>>(targetPtr),
+          zeroIndex);
+      rewriter.replaceOpWithNewOp<emitc::AssignOp>(
+          copyOp, targetLValue.getResult(), value.getResult());
+      return success();
+    }
+
     auto srcArrayValue =
         cast<TypedValue<emitc::ArrayType>>(operands.getSource());
     emitc::AddressOfOp srcPtr =
@@ -414,8 +452,8 @@ struct ConvertLoad final : public OpConversionPattern<memref::LoadOp> {
 
     auto arrayValue =
         dyn_cast<TypedValue<emitc::ArrayType>>(operands.getMemref());
-    Value strippedPtr = stripPointerUnrealizedCast(operands.getMemref());
-    if (!strippedPtr && arrayValue) {
+    Value ptr = getPointerOrStripUnrealizedCast(operands.getMemref());
+    if (!ptr && arrayValue) {
       auto subscript = emitc::SubscriptOp::create(rewriter, loc, arrayValue,
                                                   operands.getIndices());
 
@@ -423,14 +461,14 @@ struct ConvertLoad final : public OpConversionPattern<memref::LoadOp> {
       return success();
     }
 
-    if (!strippedPtr)
+    if (!ptr)
       return rewriter.notifyMatchFailure(loc, "expected array or pointer type");
     MemRefType opMemrefType = cast<MemRefType>(op.getMemref().getType());
     ValueRange indices = operands.getIndices();
 
     ImplicitLocOpBuilder b(loc, rewriter);
     Value linearIndex = computeRowMajorLinearIndex(b, opMemrefType, indices);
-    auto typedPtr = cast<TypedValue<emitc::PointerType>>(strippedPtr);
+    auto typedPtr = cast<TypedValue<emitc::PointerType>>(ptr);
     auto subscript =
         emitc::SubscriptOp::create(rewriter, loc, typedPtr, linearIndex);
 
@@ -448,8 +486,8 @@ struct ConvertStore final : public OpConversionPattern<memref::StoreOp> {
     Location loc = op.getLoc();
     auto arrayValue =
         dyn_cast<TypedValue<emitc::ArrayType>>(operands.getMemref());
-    Value strippedPtr = stripPointerUnrealizedCast(operands.getMemref());
-    if (!strippedPtr && arrayValue) {
+    Value ptr = getPointerOrStripUnrealizedCast(operands.getMemref());
+    if (!ptr && arrayValue) {
       auto subscript = emitc::SubscriptOp::create(rewriter, loc, arrayValue,
                                                   operands.getIndices());
       rewriter.replaceOpWithNewOp<emitc::AssignOp>(op, subscript,
@@ -457,14 +495,14 @@ struct ConvertStore final : public OpConversionPattern<memref::StoreOp> {
       return success();
     }
 
-    if (!strippedPtr)
+    if (!ptr)
       return rewriter.notifyMatchFailure(loc, "expected array or pointer type");
     MemRefType opMemrefType = cast<MemRefType>(op.getMemref().getType());
     ValueRange indices = operands.getIndices();
 
     ImplicitLocOpBuilder b(loc, rewriter);
     Value linearIndex = computeRowMajorLinearIndex(b, opMemrefType, indices);
-    auto typedPtr = cast<TypedValue<emitc::PointerType>>(strippedPtr);
+    auto typedPtr = cast<TypedValue<emitc::PointerType>>(ptr);
     auto subscript =
         emitc::SubscriptOp::create(rewriter, loc, typedPtr, linearIndex);
 
diff --git a/mlir/test/Conversion/FuncToEmitC/func-to-emitc-failed.mlir b/mlir/test/Conversion/FuncToEmitC/func-to-emitc-failed.mlir
index 46e5319d7d17c..85410ec0134e6 100644
--- a/mlir/test/Conversion/FuncToEmitC/func-to-emitc-failed.mlir
+++ b/mlir/test/Conversion/FuncToEmitC/func-to-emitc-failed.mlir
@@ -7,21 +7,6 @@ func.func @unsuppoted_emitc_type(%arg0: i4) -> 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>
diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc-dealloc.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc-dealloc.mlir
index 9d20667a6490c..3194a40c16eeb 100644
--- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc-dealloc.mlir
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc-dealloc.mlir
@@ -89,3 +89,29 @@ func.func @allocating_and_deallocating_multi() {
 // NOCPP-NEXT: %[[FREE_PTR:.*]] = emitc.cast %[[ALLOC_CAST]] : !emitc.ptr<i32> to !emitc.ptr<!emitc.opaque<"void">>
 // NOCPP-NEXT: emitc.call_opaque "free"(%[[FREE_PTR]]) : (!emitc.ptr<!emitc.opaque<"void">>) -> ()
 // NOCPP-NEXT: return
+
+func.func @alloc_and_dealloc_rank0() {
+  %alloc = memref.alloc() : memref<i32>
+  memref.dealloc %alloc : memref<i32>
+  return
+}
+
+// CPP-LABEL: alloc_and_dealloc_rank0
+// CPP-NEXT: %[[ALLOC:.*]] = emitc.call_opaque "sizeof"() <{args = [i32]}> : () -> !emitc.size_t
+// CPP-NEXT: %[[ALLOC_SIZE:.*]] = "emitc.constant"() <{value = 1 : index}> : () -> index
+// CPP-NEXT: %[[ALLOC_TOTAL_SIZE:.*]] = emitc.mul %[[ALLOC]], %[[ALLOC_SIZE]] : (!emitc.size_t, index) -> !emitc.size_t
+// CPP-NEXT: %[[ALLOC_PTR:.*]] = emitc.call_opaque "malloc"(%[[ALLOC_TOTAL_SIZE]]) : (!emitc.size_t) -> !emitc.ptr<!emitc.opaque<"void">>
+// CPP-NEXT: %[[ALLOC_CAST:.*]] = emitc.cast %[[ALLOC_PTR]] : !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<i32>
+// CPP-NEXT: %[[FREE_PTR:.*]] = emitc.cast %[[ALLOC_CAST]] : !emitc.ptr<i32> to !emitc.ptr<!emitc.opaque<"void">>
+// CPP-NEXT: emitc.call_opaque "free"(%[[FREE_PTR]]) : (!emitc.ptr<!emitc.opaque<"void">>) -> ()
+// CPP-NEXT: return
+
+// NOCPP-LABEL: alloc_and_dealloc_rank0
+// NOCPP-NEXT: %[[ALLOC:.*]] = emitc.call_opaque "sizeof"() <{args = [i32]}> : () -> !emitc.size_t
+// NOCPP-NEXT: %[[ALLOC_SIZE:.*]] = "emitc.constant"() <{value = 1 : index}> : () -> index
+// NOCPP-NEXT: %[[ALLOC_TOTAL_SIZE:.*]] = emitc.mul %[[ALLOC]], %[[ALLOC_SIZE]] : (!emitc.size_t, index) -> !emitc.size_t
+// NOCPP-NEXT: %[[ALLOC_PTR:.*]] = emitc.call_opaque "malloc"(%[[ALLOC_TOTAL_SIZE]]) : (!emitc.size_t) -> !emitc.ptr<!emitc.opaque<"void">>
+// NOCPP-NEXT: %[[ALLOC_CAST:.*]] = emitc.cast %[[ALLOC_PTR]] : !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<i32>
+// NOCPP-NEXT: %[[FREE_PTR:.*]] = emitc.cast %[[ALLOC_CAST]] : !emitc.ptr<i32> to !emitc.ptr<!emitc.opaque<"void">>
+// NOCPP-NEXT: emitc.call_opaque "free"(%[[FREE_PTR]]) : (!emitc.ptr<!emitc.opaque<"void">>) -> ()
+// NOCPP-NEXT: return
diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc-load-store.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc-load-store.mlir
index 07cad3b0c4dc2..5e466630a66a0 100644
--- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc-load-store.mlir
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc-load-store.mlir
@@ -72,3 +72,51 @@ func.func @memref_load_store(%buff0: memref<2xf32>,
   memref.store %v, %buff1[%i, %j] : memref<4x8xf32>
   return
 }
+
+/// Rank-0 alloc-backed load/store lower through pointer subscript at index 0.
+// CHECK-LABEL: emitc.func private @memref_rank0_alloc_store(
+// CHECK-SAME:  %[[VAL:.*]]: i32)
+func.func private @memref_rank0_alloc_store(%v : i32) {
+  // CHECK:     %[[SIZEOF_I32:.*]] = call_opaque "sizeof"() <{args = [i32]}> : () -> !emitc.size_t
+  // CHECK:     %[[NUM_ELEMS:.*]] = "emitc.constant"() <{value = 1 : index}> : () -> index
+  // CHECK:     %[[TOTAL_BYTES:.*]] = mul %[[SIZEOF_I32]], %[[NUM_ELEMS]] : (!emitc.size_t, index) -> !emitc.size_t
+  // CHECK:     %[[MALLOC_PTR:.*]] = call_opaque "malloc"(%[[TOTAL_BYTES]]) : (!emitc.size_t) -> !emitc.ptr<!emitc.opaque<"void">>
+  // CHECK:     %[[ELEM_PTR:.*]] = cast %[[MALLOC_PTR]] : !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<i32>
+  %alloc = memref.alloc() : memref<i32>
+  // CHECK:     %[[ZERO:.*]] = "emitc.constant"() <{value = 0 : index}> : () -> index
+  // CHECK:     %[[ELEM_LVALUE:.*]] = subscript %[[ELEM_PTR]]{{\[}}%[[ZERO]]] : (!emitc.ptr<i32>, index) -> !emitc.lvalue<i32>
+  // CHECK:     assign %[[VAL]] : i32 to %[[ELEM_LVALUE]] : <i32>
+  memref.store %v, %alloc[] : memref<i32>
+  return
+}
+
+// CHECK-LABEL: emitc.func private @memref_rank0_alloc_load() -> i32
+func.func private @memref_rank0_alloc_load() -> i32 {
+  // CHECK:     %[[SIZEOF_I32:.*]] = call_opaque "sizeof"() <{args = [i32]}> : () -> !emitc.size_t
+  // CHECK:     %[[NUM_ELEMS:.*]] = "emitc.constant"() <{value = 1 : index}> : () -> index
+  // CHECK:     %[[TOTAL_BYTES:.*]] = mul %[[SIZEOF_I32]], %[[NUM_ELEMS]] : (!emitc.size_t, index) -> !emitc.size_t
+  // CHECK:     %[[MALLOC_PTR:.*]] = call_opaque "malloc"(%[[TOTAL_BYTES]]) : (!emitc.size_t) -> !emitc.ptr<!emitc.opaque<"void">>
+  // CHECK:     %[[ELEM_PTR:.*]] = cast %[[MALLOC_PTR]] : !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<i32>
+  %alloc = memref.alloc() : memref<i32>
+  // CHECK:     %[[ZERO:.*]] = "emitc.constant"() <{value = 0 : index}> : () -> index
+  // CHECK:     %[[ELEM_LVALUE:.*]] = subscript %[[ELEM_PTR]]{{\[}}%[[ZERO]]] : (!emitc.ptr<i32>, index) -> !emitc.lvalue<i32>
+  // CHECK:     %[[LOADED_VAL:.*]] = load %[[ELEM_LVALUE]] : <i32>
+  %v = memref.load %alloc[] : memref<i32>
+  // CHECK:     return %[[LOADED_VAL]] : i32
+  return %v : i32
+}
+
+// CHECK-LABEL: emitc.func @memref_rank0_load_store(
+// CHECK-SAME:  %[[SRC:.*]]: !emitc.ptr<i32>,
+// CHECK-SAME:  %[[DST:.*]]: !emitc.ptr<i32>)
+func.func @memref_rank0_load_store(%src: memref<i32>, %dst: memref<i32>) {
+  // CHECK:     %[[LOAD_ZERO:.*]] = "emitc.constant"() <{value = 0 : index}> : () -> index
+  // CHECK:     %[[SRC_LVALUE:.*]] = subscript %[[SRC]]{{\[}}%[[LOAD_ZERO]]] : (!emitc.ptr<i32>, index) -> !emitc.lvalue<i32>
+  // CHECK:     %[[VAL:.*]] = load %[[SRC_LVALUE]] : <i32>
+  %v = memref.load %src[] : memref<i32>
+  // CHECK:     %[[STORE_ZERO:.*]] = "emitc.constant"() <{value = 0 : index}> : () -> index
+  // CHECK:     %[[DST_LVALUE:.*]] = subscript %[[DST]]{{\[}}%[[STORE_ZERO]]] : (!emitc.ptr<i32>, index) -> !emitc.lvalue<i32>
+  // CHECK:     assign %[[VAL]] : i32 to %[[DST_LVALUE]] : <i32>
+  memref.store %v, %dst[] : memref<i32>
+  return
+}
diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-copy.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-copy.mlir
index 04e6edd5b6981..de3741e83c01c 100644
--- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-copy.mlir
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-copy.mlir
@@ -1,5 +1,5 @@
-// RUN: mlir-opt -convert-memref-to-emitc="lower-to-cpp=true" %s -split-input-file | FileCheck %s --check-prefixes=CPP,CHECK
-// RUN: mlir-opt -convert-memref-to-emitc="lower-to-cpp=false" %s -split-input-file | FileCheck %s --check-prefixes=NOCPP,CHECK
+// RUN: mlir-opt -convert-memref-to-emitc="lower-to-cpp=true" %s | FileCheck %s --check-prefixes=CPP,CHECK
+// RUN: mlir-opt -convert-memref-to-emitc="lower-to-cpp=false" %s | FileCheck %s --check-prefixes=NOCPP,CHECK
 
 func.func @copying(%arg0 : memref<9x4x5x7xf32>, %arg1 : memref<9x4x5x7xf32>) {
   memref.copy %arg0, %arg1 : memref<9x4x5x7xf32> to memref<9x4x5x7xf32>
@@ -28,3 +28,20 @@ func.func @copying(%arg0 : memref<9x4x5x7xf32>, %arg1 : memref<9x4x5x7xf32>) {
 // CHECK:           return
 // CHECK:         }
 
+func.func @copying_rank0(%arg0 : memref<i32>, %arg1 : memref<i32>) {
+  memref.copy %arg0, %arg1 : memref<i32> to memref<i32>
+  return
+}
+
+// CHECK-LABEL:   func.func @copying_rank0(
+// CHECK-SAME:      %[[ARG0:.*]]: memref<i32>,
+// CHECK-SAME:      %[[ARG1:.*]]: memref<i32>) {
+// CHECK:           %[[TARGET_CAST:.*]] = builtin.unrealized_conversion_cast %[[ARG1]] : memref<i32> to !emitc.ptr<i32>
+// CHECK:           %[[SOURCE_CAST:.*]] = builtin.unrealized_conversion_cast %[[ARG0]] : memref<i32> to !emitc.ptr<i32>
+// CHECK:           %[[ZERO:.*]] = "emitc.constant"() <{value = 0 : index}> : () -> index
+// CHECK:           %[[SOURCE_LVALUE:.*]] = emitc.subscript %[[SOURCE_CAST]]{{\[}}%[[ZERO]]] : (!emitc.ptr<i32>, index) -> !emitc.lvalue<i32>
+// CHECK:           %[[VALUE:.*]] = emitc.load %[[SOURCE_LVALUE]] : <i32>
+// CHECK:           %[[TARGET_LVALUE:.*]] = emitc.subscript %[[TARGET_CAST]]{{\[}}%[[ZERO]]] : (!emitc.ptr<i32>, index) -> !emitc.lvalue<i32>
+// CHECK:           emitc.assign %[[VALUE]] : i32 to %[[TARGET_LVALUE]] : <i32>
+// CHECK:           return
+// CHECK:         }

>From 83fcab31a7bc8d1e28498da25bcd3fe338032436 Mon Sep 17 00:00:00 2001
From: Ioana Ghiban <ioana.ghiban at arm.com>
Date: Mon, 29 Jun 2026 17:31:08 +0200
Subject: [PATCH 2/5] Support lowering rank-0 AllocaOp

---
 .../MemRefToEmitC/MemRefToEmitC.cpp           | 44 +++++++++++--------
 .../MemRefToEmitC/memref-to-emitc-failed.mlir |  8 ----
 .../MemRefToEmitC/memref-to-emitc.mlir        |  9 ++++
 3 files changed, 35 insertions(+), 26 deletions(-)

diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
index 3af48fe23d140..6a76ddddd4eeb 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
@@ -59,6 +59,16 @@ void mlir::registerConvertMemRefToEmitCInterface(DialectRegistry &registry) {
 // Conversion Patterns
 //===----------------------------------------------------------------------===//
 
+Type convertMemRefType(MemRefType opTy, const TypeConverter *typeConverter) {
+  Type resultTy;
+  if (opTy.getRank() == 0) {
+    resultTy = typeConverter->convertType(mlir::getElementTypeOrSelf(opTy));
+  } else {
+    resultTy = typeConverter->convertType(opTy);
+  }
+  return resultTy;
+}
+
 namespace {
 struct ConvertAlloca final : public OpConversionPattern<memref::AllocaOp> {
   using OpConversionPattern::OpConversionPattern;
@@ -72,11 +82,6 @@ struct ConvertAlloca final : public OpConversionPattern<memref::AllocaOp> {
           op.getLoc(), "cannot transform alloca with dynamic shape");
     }
 
-    if (op.getType().getRank() == 0) {
-      return rewriter.notifyMatchFailure(
-          op.getLoc(), "cannot transform alloca with zero rank");
-    }
-
     if (op.getAlignment().value_or(1) > 1) {
       // TODO: Allow alignment if it is not more than the natural alignment
       // of the C array.
@@ -84,26 +89,29 @@ struct ConvertAlloca final : public OpConversionPattern<memref::AllocaOp> {
           op.getLoc(), "cannot transform alloca with alignment requirement");
     }
 
-    auto resultTy = getTypeConverter()->convertType(op.getType());
-    if (!resultTy) {
+    auto resultTy = convertMemRefType(op.getType(), getTypeConverter());
+    if (!resultTy)
       return rewriter.notifyMatchFailure(op.getLoc(), "cannot convert type");
-    }
+
     auto noInit = emitc::OpaqueAttr::get(getContext(), "");
+    // Rank-0 path
+    if (op.getType().getRank() == 0) {
+      auto var = emitc::VariableOp::create(
+          rewriter, op.getLoc(), emitc::LValueType::get(resultTy), noInit);
+
+      auto ptr = emitc::AddressOfOp::create(rewriter, op.getLoc(),
+                                            emitc::PointerType::get(resultTy),
+                                            var.getResult());
+
+      rewriter.replaceOp(op, ptr.getResult());
+      return success();
+    }
+    // Rank > 0 path
     rewriter.replaceOpWithNewOp<emitc::VariableOp>(op, resultTy, noInit);
     return success();
   }
 };
 
-Type convertMemRefType(MemRefType opTy, const TypeConverter *typeConverter) {
-  Type resultTy;
-  if (opTy.getRank() == 0) {
-    resultTy = typeConverter->convertType(mlir::getElementTypeOrSelf(opTy));
-  } else {
-    resultTy = typeConverter->convertType(opTy);
-  }
-  return resultTy;
-}
-
 static Value calculateMemrefTotalSizeBytes(Location loc, MemRefType memrefType,
                                            OpBuilder &builder,
                                            Type convertedElementType) {
diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-failed.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-failed.mlir
index 753f749fabbd6..f2d0e9a5eee66 100644
--- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-failed.mlir
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-failed.mlir
@@ -72,14 +72,6 @@ func.func @non_identity_layout() {
 
 // -----
 
-func.func @zero_rank() {
-  // expected-error at +1 {{failed to legalize operation 'memref.alloca'}}
-  %0 = memref.alloca() : memref<f32>
-  return
-}
-
-// -----
-
 func.func @zero_dim_rank_1() {
   // expected-error at +1 {{failed to legalize operation 'memref.alloca'}}
   %0 = memref.alloca() : memref<0xf32>
diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
index 5ae22490ff05e..9749906e0c98a 100644
--- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
@@ -10,6 +10,15 @@ func.func @alloca() {
 
 // -----
 
+func.func @alloca_zero_rank() {
+  // CHECK: %[[LVALUE:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<f32>
+  // CHECK: %[[PTR:.*]] = emitc.address_of %[[LVALUE]] : !emitc.lvalue<f32>
+  %0 = memref.alloca() : memref<f32>
+  return
+}
+
+// -----
+
 // 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) {

>From 917305f0abe40582faebffa6cbc93e8cc90213d9 Mon Sep 17 00:00:00 2001
From: Ioana Ghiban <ioana.ghiban at arm.com>
Date: Wed, 1 Jul 2026 15:00:58 +0200
Subject: [PATCH 3/5] Address first round of comments

---
 mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp       | 7 +++----
 .../Conversion/MemRefToEmitC/memref-to-emitc-copy.mlir    | 8 ++++++--
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
index 6a76ddddd4eeb..b87bcd5476596 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
@@ -61,11 +61,10 @@ void mlir::registerConvertMemRefToEmitCInterface(DialectRegistry &registry) {
 
 Type convertMemRefType(MemRefType opTy, const TypeConverter *typeConverter) {
   Type resultTy;
-  if (opTy.getRank() == 0) {
+  if (opTy.getRank() == 0)
     resultTy = typeConverter->convertType(mlir::getElementTypeOrSelf(opTy));
-  } else {
+  else
     resultTy = typeConverter->convertType(opTy);
-  }
   return resultTy;
 }
 
@@ -180,7 +179,7 @@ static Value computeRowMajorLinearIndex(ImplicitLocOpBuilder &builder,
           ? emitc::ConstantOp::create(builder, idxType, builder.getIndexAttr(0))
           : indices[0];
 
-  if (shape.empty())
+  if (indices.empty())
     return linearIndex;
 
   for (auto [dim, idx] : llvm::zip(shape.drop_front(), indices.drop_front())) {
diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-copy.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-copy.mlir
index de3741e83c01c..6105521d9326d 100644
--- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-copy.mlir
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-copy.mlir
@@ -1,5 +1,5 @@
-// RUN: mlir-opt -convert-memref-to-emitc="lower-to-cpp=true" %s | FileCheck %s --check-prefixes=CPP,CHECK
-// RUN: mlir-opt -convert-memref-to-emitc="lower-to-cpp=false" %s | FileCheck %s --check-prefixes=NOCPP,CHECK
+// RUN: mlir-opt -convert-memref-to-emitc="lower-to-cpp=true" %s -split-input-file | FileCheck %s --check-prefixes=CPP,CHECK
+// RUN: mlir-opt -convert-memref-to-emitc="lower-to-cpp=false" %s -split-input-file | FileCheck %s --check-prefixes=NOCPP,CHECK
 
 func.func @copying(%arg0 : memref<9x4x5x7xf32>, %arg1 : memref<9x4x5x7xf32>) {
   memref.copy %arg0, %arg1 : memref<9x4x5x7xf32> to memref<9x4x5x7xf32>
@@ -28,11 +28,15 @@ func.func @copying(%arg0 : memref<9x4x5x7xf32>, %arg1 : memref<9x4x5x7xf32>) {
 // CHECK:           return
 // CHECK:         }
 
+// -----
+
 func.func @copying_rank0(%arg0 : memref<i32>, %arg1 : memref<i32>) {
   memref.copy %arg0, %arg1 : memref<i32> to memref<i32>
   return
 }
 
+// CHECK: module {
+
 // CHECK-LABEL:   func.func @copying_rank0(
 // CHECK-SAME:      %[[ARG0:.*]]: memref<i32>,
 // CHECK-SAME:      %[[ARG1:.*]]: memref<i32>) {

>From db8b6c19b2437acf68da60388363450c6a42a049 Mon Sep 17 00:00:00 2001
From: Ioana Ghiban <ioana.ghiban at arm.com>
Date: Wed, 8 Jul 2026 13:11:58 +0200
Subject: [PATCH 4/5] Remove wrapper for rank-0 conversion

---
 .../MemRefToEmitC/MemRefToEmitC.cpp           | 46 +++++++++----------
 1 file changed, 22 insertions(+), 24 deletions(-)

diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
index b87bcd5476596..8275749144f8d 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
@@ -59,15 +59,6 @@ void mlir::registerConvertMemRefToEmitCInterface(DialectRegistry &registry) {
 // Conversion Patterns
 //===----------------------------------------------------------------------===//
 
-Type convertMemRefType(MemRefType opTy, const TypeConverter *typeConverter) {
-  Type resultTy;
-  if (opTy.getRank() == 0)
-    resultTy = typeConverter->convertType(mlir::getElementTypeOrSelf(opTy));
-  else
-    resultTy = typeConverter->convertType(opTy);
-  return resultTy;
-}
-
 namespace {
 struct ConvertAlloca final : public OpConversionPattern<memref::AllocaOp> {
   using OpConversionPattern::OpConversionPattern;
@@ -88,18 +79,20 @@ struct ConvertAlloca final : public OpConversionPattern<memref::AllocaOp> {
           op.getLoc(), "cannot transform alloca with alignment requirement");
     }
 
-    auto resultTy = convertMemRefType(op.getType(), getTypeConverter());
+    Type resultTy = getTypeConverter()->convertType(op.getType());
     if (!resultTy)
       return rewriter.notifyMatchFailure(op.getLoc(), "cannot convert type");
 
     auto noInit = emitc::OpaqueAttr::get(getContext(), "");
     // Rank-0 path
     if (op.getType().getRank() == 0) {
+      auto pointerTy = dyn_cast<emitc::PointerType>(resultTy);
+      assert(pointerTy && "expected rank-0 MemRef to convert to pointer");
+      Type elemTy = pointerTy.getPointee();
       auto var = emitc::VariableOp::create(
-          rewriter, op.getLoc(), emitc::LValueType::get(resultTy), noInit);
+          rewriter, op.getLoc(), emitc::LValueType::get(elemTy), noInit);
 
-      auto ptr = emitc::AddressOfOp::create(rewriter, op.getLoc(),
-                                            emitc::PointerType::get(resultTy),
+      auto ptr = emitc::AddressOfOp::create(rewriter, op.getLoc(), resultTy,
                                             var.getResult());
 
       rewriter.replaceOp(op, ptr.getResult());
@@ -153,7 +146,7 @@ createPointerFromEmitcArray(Location loc, OpBuilder &builder,
   return ptr;
 }
 
-static Value getPointerOrStripUnrealizedCast(Value v) {
+static Value getMemRefPointer(Value v) {
   if (isa<emitc::PointerType>(v.getType()))
     return v;
 
@@ -256,7 +249,7 @@ struct ConvertDealloc final : public OpConversionPattern<memref::DeallocOp> {
     Location loc = deallocOp.getLoc();
     // `free` can only be emitted when the dealloc operand is recoverable as an
     // `emitc.ptr<T>`.
-    Value ptr = getPointerOrStripUnrealizedCast(operands.getMemref());
+    Value ptr = getMemRefPointer(operands.getMemref());
     if (!ptr) {
       return rewriter.notifyMatchFailure(
           loc, "expected pointer-backed memref for EmitC deallocation");
@@ -304,8 +297,8 @@ struct ConvertCopy final : public OpConversionPattern<memref::CopyOp> {
       if (!elementType)
         return rewriter.notifyMatchFailure(loc, "cannot convert element type");
 
-      Value srcPtr = getPointerOrStripUnrealizedCast(operands.getSource());
-      Value targetPtr = getPointerOrStripUnrealizedCast(operands.getTarget());
+      Value srcPtr = getMemRefPointer(operands.getSource());
+      Value targetPtr = getMemRefPointer(operands.getTarget());
       if (!srcPtr || !targetPtr)
         return rewriter.notifyMatchFailure(loc, "expected pointer operands");
 
@@ -376,7 +369,7 @@ struct ConvertGlobal final : public OpConversionPattern<memref::GlobalOp> {
                        "currently not supported");
     }
 
-    Type resultTy = convertMemRefType(opTy, getTypeConverter());
+    Type resultTy = getTypeConverter()->convertType(opTy);
 
     if (!resultTy) {
       return rewriter.notifyMatchFailure(op.getLoc(),
@@ -397,6 +390,9 @@ struct ConvertGlobal final : public OpConversionPattern<memref::GlobalOp> {
 
     Attribute initialValue = operands.getInitialValueAttr();
     if (opTy.getRank() == 0) {
+      auto pointerTy = dyn_cast<emitc::PointerType>(resultTy);
+      assert(pointerTy && "expected rank-0 MemRef to convert to pointer");
+      resultTy = pointerTy.getPointee();
       // special case for `variable : memref<i32> = dense<-1>`
       if (std::optional<Attribute> initValueAttr = op.getInitialValue()) {
         if (auto elementsAttr = llvm::dyn_cast<ElementsAttr>(*initValueAttr)) {
@@ -423,7 +419,7 @@ struct ConvertGetGlobal final
                   ConversionPatternRewriter &rewriter) const override {
 
     MemRefType opTy = op.getType();
-    Type resultTy = convertMemRefType(opTy, getTypeConverter());
+    Type resultTy = getTypeConverter()->convertType(opTy);
 
     if (!resultTy) {
       return rewriter.notifyMatchFailure(op.getLoc(),
@@ -431,11 +427,13 @@ struct ConvertGetGlobal final
     }
 
     if (opTy.getRank() == 0) {
-      emitc::LValueType lvalueType = emitc::LValueType::get(resultTy);
+      auto pointerTy = dyn_cast<emitc::PointerType>(resultTy);
+      assert(pointerTy && "expected rank-0 MemRef to convert to pointer");
+      Type elemTy = pointerTy.getPointee();
+      emitc::LValueType lvalueType = emitc::LValueType::get(elemTy);
       emitc::GetGlobalOp globalLValue = emitc::GetGlobalOp::create(
           rewriter, op.getLoc(), lvalueType, operands.getNameAttr());
-      emitc::PointerType pointerType = emitc::PointerType::get(resultTy);
-      rewriter.replaceOpWithNewOp<emitc::AddressOfOp>(op, pointerType,
+      rewriter.replaceOpWithNewOp<emitc::AddressOfOp>(op, resultTy,
                                                       globalLValue);
       return success();
     }
@@ -459,7 +457,7 @@ struct ConvertLoad final : public OpConversionPattern<memref::LoadOp> {
 
     auto arrayValue =
         dyn_cast<TypedValue<emitc::ArrayType>>(operands.getMemref());
-    Value ptr = getPointerOrStripUnrealizedCast(operands.getMemref());
+    Value ptr = getMemRefPointer(operands.getMemref());
     if (!ptr && arrayValue) {
       auto subscript = emitc::SubscriptOp::create(rewriter, loc, arrayValue,
                                                   operands.getIndices());
@@ -493,7 +491,7 @@ struct ConvertStore final : public OpConversionPattern<memref::StoreOp> {
     Location loc = op.getLoc();
     auto arrayValue =
         dyn_cast<TypedValue<emitc::ArrayType>>(operands.getMemref());
-    Value ptr = getPointerOrStripUnrealizedCast(operands.getMemref());
+    Value ptr = getMemRefPointer(operands.getMemref());
     if (!ptr && arrayValue) {
       auto subscript = emitc::SubscriptOp::create(rewriter, loc, arrayValue,
                                                   operands.getIndices());

>From cfea80626a09901047301b07cdbf687cdbaa0709 Mon Sep 17 00:00:00 2001
From: Ioana Ghiban <ioana.ghiban at arm.com>
Date: Mon, 13 Jul 2026 15:19:38 +0200
Subject: [PATCH 5/5] Address final comments

---
 mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp  | 11 +++++------
 .../memref-to-emitc-alloc-load-store.mlir            | 12 ++++++------
 .../Conversion/MemRefToEmitC/memref-to-emitc.mlir    |  2 +-
 3 files changed, 12 insertions(+), 13 deletions(-)

diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
index 8275749144f8d..9ac49e2eb1a14 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
@@ -304,17 +304,16 @@ struct ConvertCopy final : public OpConversionPattern<memref::CopyOp> {
 
       Value zeroIndex = emitc::ConstantOp::create(
           rewriter, loc, rewriter.getIndexType(), rewriter.getIndexAttr(0));
-      auto srcLValue = emitc::SubscriptOp::create(
+      Value srcLValue = emitc::SubscriptOp::create(
           rewriter, loc, cast<TypedValue<emitc::PointerType>>(srcPtr),
           zeroIndex);
-      auto value = emitc::LoadOp::create(rewriter, loc, elementType,
-                                         srcLValue.getResult());
+      Value value =
+          emitc::LoadOp::create(rewriter, loc, elementType, srcLValue);
 
-      auto targetLValue = emitc::SubscriptOp::create(
+      Value targetLValue = emitc::SubscriptOp::create(
           rewriter, loc, cast<TypedValue<emitc::PointerType>>(targetPtr),
           zeroIndex);
-      rewriter.replaceOpWithNewOp<emitc::AssignOp>(
-          copyOp, targetLValue.getResult(), value.getResult());
+      rewriter.replaceOpWithNewOp<emitc::AssignOp>(copyOp, targetLValue, value);
       return success();
     }
 
diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc-load-store.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc-load-store.mlir
index 5e466630a66a0..653220470bb5a 100644
--- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc-load-store.mlir
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc-load-store.mlir
@@ -74,9 +74,9 @@ func.func @memref_load_store(%buff0: memref<2xf32>,
 }
 
 /// Rank-0 alloc-backed load/store lower through pointer subscript at index 0.
-// CHECK-LABEL: emitc.func private @memref_rank0_alloc_store(
+// CHECK-LABEL: emitc.func private @memref_alloc_store_rank0(
 // CHECK-SAME:  %[[VAL:.*]]: i32)
-func.func private @memref_rank0_alloc_store(%v : i32) {
+func.func private @memref_alloc_store_rank0(%v : i32) {
   // CHECK:     %[[SIZEOF_I32:.*]] = call_opaque "sizeof"() <{args = [i32]}> : () -> !emitc.size_t
   // CHECK:     %[[NUM_ELEMS:.*]] = "emitc.constant"() <{value = 1 : index}> : () -> index
   // CHECK:     %[[TOTAL_BYTES:.*]] = mul %[[SIZEOF_I32]], %[[NUM_ELEMS]] : (!emitc.size_t, index) -> !emitc.size_t
@@ -90,8 +90,8 @@ func.func private @memref_rank0_alloc_store(%v : i32) {
   return
 }
 
-// CHECK-LABEL: emitc.func private @memref_rank0_alloc_load() -> i32
-func.func private @memref_rank0_alloc_load() -> i32 {
+// CHECK-LABEL: emitc.func private @memref_alloc_load_rank0() -> i32
+func.func private @memref_alloc_load_rank0() -> i32 {
   // CHECK:     %[[SIZEOF_I32:.*]] = call_opaque "sizeof"() <{args = [i32]}> : () -> !emitc.size_t
   // CHECK:     %[[NUM_ELEMS:.*]] = "emitc.constant"() <{value = 1 : index}> : () -> index
   // CHECK:     %[[TOTAL_BYTES:.*]] = mul %[[SIZEOF_I32]], %[[NUM_ELEMS]] : (!emitc.size_t, index) -> !emitc.size_t
@@ -106,10 +106,10 @@ func.func private @memref_rank0_alloc_load() -> i32 {
   return %v : i32
 }
 
-// CHECK-LABEL: emitc.func @memref_rank0_load_store(
+// CHECK-LABEL: emitc.func @memref_load_store_rank0(
 // CHECK-SAME:  %[[SRC:.*]]: !emitc.ptr<i32>,
 // CHECK-SAME:  %[[DST:.*]]: !emitc.ptr<i32>)
-func.func @memref_rank0_load_store(%src: memref<i32>, %dst: memref<i32>) {
+func.func @memref_load_store_rank0(%src: memref<i32>, %dst: memref<i32>) {
   // CHECK:     %[[LOAD_ZERO:.*]] = "emitc.constant"() <{value = 0 : index}> : () -> index
   // CHECK:     %[[SRC_LVALUE:.*]] = subscript %[[SRC]]{{\[}}%[[LOAD_ZERO]]] : (!emitc.ptr<i32>, index) -> !emitc.lvalue<i32>
   // CHECK:     %[[VAL:.*]] = load %[[SRC_LVALUE]] : <i32>
diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
index 9749906e0c98a..1c832b3fba6ec 100644
--- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
@@ -10,7 +10,7 @@ func.func @alloca() {
 
 // -----
 
-func.func @alloca_zero_rank() {
+func.func @alloca_rank0() {
   // CHECK: %[[LVALUE:.*]] = "emitc.variable"() <{value = #emitc.opaque<"">}> : () -> !emitc.lvalue<f32>
   // CHECK: %[[PTR:.*]] = emitc.address_of %[[LVALUE]] : !emitc.lvalue<f32>
   %0 = memref.alloca() : memref<f32>



More information about the Mlir-commits mailing list