[Mlir-commits] [mlir] [mlir][EmitC]Expand the MemRefToEmitC pass - Lowering `AllocOp` (PR #148257)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Wed Jul 23 10:22:47 PDT 2025


https://github.com/ajaden-codes updated https://github.com/llvm/llvm-project/pull/148257

>From b62e8f9ac11a7e4d2dd70ab32258e58ac58e37bf Mon Sep 17 00:00:00 2001
From: Jaddyen <ajaden at google.com>
Date: Fri, 11 Jul 2025 00:23:11 +0000
Subject: [PATCH 1/8] allocop to emitc malloc

---
 .../MemRefToEmitC/MemRefToEmitC.cpp           | 36 +++++++++++++++++--
 .../MemRefToEmitC/memref-to-emitc.mlir        |  8 +++++
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
index db244d1d1cac8..382affaff429f 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
@@ -77,6 +77,38 @@ struct ConvertAlloca final : public OpConversionPattern<memref::AllocaOp> {
   }
 };
 
+struct ConvertAlloc final : public OpConversionPattern<memref::AllocOp> {
+  using OpConversionPattern::OpConversionPattern;
+  LogicalResult
+  matchAndRewrite(memref::AllocOp allocOp, OpAdaptor operands,
+                  ConversionPatternRewriter &rewriter) const override {
+    mlir::Location loc = allocOp.getLoc();
+    auto memrefType = allocOp.getType();
+    if (!memrefType.hasStaticShape())
+      return rewriter.notifyMatchFailure(
+          allocOp.getLoc(), "cannot transform alloc op with dynamic shape");
+
+    int64_t totalSize =
+        memrefType.getNumElements() * memrefType.getElementTypeBitWidth() / 8;
+    auto alignment = allocOp.getAlignment();
+    if (alignment) {
+      int64_t alignVal = alignment.value();
+      totalSize = (totalSize + alignVal - 1) / alignVal * alignVal;
+    }
+    mlir::Value sizeBytes = rewriter.create<emitc::ConstantOp>(
+        loc, rewriter.getIndexType(),
+        rewriter.getIntegerAttr(rewriter.getIndexType(), totalSize));
+    auto mallocPtrType = emitc::PointerType::get(rewriter.getContext(),
+                                                 memrefType.getElementType());
+    auto mallocCall = rewriter.create<emitc::CallOpaqueOp>(
+        loc, mallocPtrType, rewriter.getStringAttr("malloc"),
+        mlir::ValueRange{sizeBytes});
+
+    rewriter.replaceOp(allocOp, mallocCall);
+    return success();
+  }
+};
+
 struct ConvertGlobal final : public OpConversionPattern<memref::GlobalOp> {
   using OpConversionPattern::OpConversionPattern;
 
@@ -222,6 +254,6 @@ void mlir::populateMemRefToEmitCTypeConversion(TypeConverter &typeConverter) {
 
 void mlir::populateMemRefToEmitCConversionPatterns(
     RewritePatternSet &patterns, const TypeConverter &converter) {
-  patterns.add<ConvertAlloca, ConvertGlobal, ConvertGetGlobal, ConvertLoad,
-               ConvertStore>(converter, patterns.getContext());
+  patterns.add<ConvertAlloca, ConvertAlloc, ConvertGlobal, ConvertGetGlobal,
+               ConvertLoad, ConvertStore>(converter, patterns.getContext());
 }
diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
index d37fd1de90add..23e1c20670f8c 100644
--- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
@@ -8,6 +8,14 @@ func.func @alloca() {
   return
 }
 
+// CHECK-LABEL: alloc()
+func.func @alloc() {
+  // CHECK-NEXT:  %0 = "emitc.constant"() <{value = 3996 : index}> : () -> index
+  // CHECK-NEXT:  %1 = emitc.call_opaque "malloc"(%0) : (index) -> !emitc.ptr<i32>
+  %alloc = memref.alloc() : memref<999xi32>
+  return
+}
+
 // -----
 
 // CHECK-LABEL: memref_store

>From a36e0a3e1dbc4d746073d82d1bf868b1e3403284 Mon Sep 17 00:00:00 2001
From: Jaddyen <ajaden at google.com>
Date: Mon, 14 Jul 2025 20:24:46 +0000
Subject: [PATCH 2/8] Specific TODOs

---
 mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
index 382affaff429f..ee6b7d89a76a6 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
@@ -85,13 +85,18 @@ struct ConvertAlloc final : public OpConversionPattern<memref::AllocOp> {
     mlir::Location loc = allocOp.getLoc();
     auto memrefType = allocOp.getType();
     if (!memrefType.hasStaticShape())
+      // TODO: Handle Dynamic shapes in the future. If the size
+      // of the allocation is the result of some function, we could
+      // potentially evaluate the function and use the result in the call to
+      // allocate.
       return rewriter.notifyMatchFailure(
           allocOp.getLoc(), "cannot transform alloc op with dynamic shape");
 
-    int64_t totalSize =
-        memrefType.getNumElements() * memrefType.getElementTypeBitWidth() / 8;
-    auto alignment = allocOp.getAlignment();
-    if (alignment) {
+    // TODO: Is there a better API to determine the number of bits in a byte in
+    // MLIR?
+    int64_t totalSize = memrefType.getNumElements() *
+                        memrefType.getElementTypeBitWidth() / CHAR_BIT;
+    if (auto alignment = allocOp.getAlignment()) {
       int64_t alignVal = alignment.value();
       totalSize = (totalSize + alignVal - 1) / alignVal * alignVal;
     }

>From 69e5a982e826af1eb7dc12a49d0ff7902d3ea732 Mon Sep 17 00:00:00 2001
From: Jaddyen <ajaden at google.com>
Date: Fri, 18 Jul 2025 05:14:35 +0000
Subject: [PATCH 3/8] Add the size computations to emitc output

---
 mlir/include/mlir/Conversion/Passes.td        |  2 +-
 .../MemRefToEmitC/MemRefToEmitC.cpp           | 74 ++++++++++++++-----
 .../MemRefToEmitC/MemRefToEmitCPass.cpp       | 10 +++
 .../MemRefToEmitC/memref-to-emitc.mlir        |  8 +-
 4 files changed, 72 insertions(+), 22 deletions(-)

diff --git a/mlir/include/mlir/Conversion/Passes.td b/mlir/include/mlir/Conversion/Passes.td
index 76e751243a12c..4660758f35b04 100644
--- a/mlir/include/mlir/Conversion/Passes.td
+++ b/mlir/include/mlir/Conversion/Passes.td
@@ -841,7 +841,7 @@ def ConvertMathToFuncs : Pass<"convert-math-to-funcs", "ModuleOp"> {
 // MemRefToEmitC
 //===----------------------------------------------------------------------===//
 
-def ConvertMemRefToEmitC : Pass<"convert-memref-to-emitc"> {
+def ConvertMemRefToEmitC : Pass<"convert-memref-to-emitc", "ModuleOp"> {
   let summary = "Convert MemRef dialect to EmitC dialect";
   let dependentDialects = ["emitc::EmitCDialect"];
 }
diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
index ee6b7d89a76a6..d8ceb4b205a55 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
@@ -16,6 +16,7 @@
 #include "mlir/Dialect/EmitC/IR/EmitC.h"
 #include "mlir/Dialect/MemRef/IR/MemRef.h"
 #include "mlir/IR/Builders.h"
+#include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/PatternMatch.h"
 #include "mlir/Transforms/DialectConversion.h"
 
@@ -84,34 +85,69 @@ struct ConvertAlloc final : public OpConversionPattern<memref::AllocOp> {
                   ConversionPatternRewriter &rewriter) const override {
     mlir::Location loc = allocOp.getLoc();
     auto memrefType = allocOp.getType();
-    if (!memrefType.hasStaticShape())
+    if (!memrefType.hasStaticShape()) {
       // TODO: Handle Dynamic shapes in the future. If the size
       // of the allocation is the result of some function, we could
       // potentially evaluate the function and use the result in the call to
       // allocate.
       return rewriter.notifyMatchFailure(
-          allocOp.getLoc(), "cannot transform alloc op with dynamic shape");
-
-    // TODO: Is there a better API to determine the number of bits in a byte in
-    // MLIR?
-    int64_t totalSize = memrefType.getNumElements() *
-                        memrefType.getElementTypeBitWidth() / CHAR_BIT;
-    if (auto alignment = allocOp.getAlignment()) {
-      int64_t alignVal = alignment.value();
-      totalSize = (totalSize + alignVal - 1) / alignVal * alignVal;
+          loc, "cannot transform alloc with dynamic shape");
     }
-    mlir::Value sizeBytes = rewriter.create<emitc::ConstantOp>(
-        loc, rewriter.getIndexType(),
-        rewriter.getIntegerAttr(rewriter.getIndexType(), totalSize));
-    auto mallocPtrType = emitc::PointerType::get(rewriter.getContext(),
-                                                 memrefType.getElementType());
-    auto mallocCall = rewriter.create<emitc::CallOpaqueOp>(
-        loc, mallocPtrType, rewriter.getStringAttr("malloc"),
-        mlir::ValueRange{sizeBytes});
 
-    rewriter.replaceOp(allocOp, mallocCall);
+    Type elementType = memrefType.getElementType();
+    mlir::Value elementTypeLiteral = rewriter.create<emitc::LiteralOp>(
+        loc, mlir::emitc::OpaqueType::get(rewriter.getContext(), "type"),
+        rewriter.getStringAttr(getCTypeName(elementType)));
+    emitc::CallOpaqueOp sizeofElementOp = rewriter.create<emitc::CallOpaqueOp>(
+        loc, mlir::emitc::SizeTType::get(rewriter.getContext()),
+        rewriter.getStringAttr("sizeof"), mlir::ValueRange{elementTypeLiteral});
+    mlir::Value sizeofElement = sizeofElementOp.getResult(0);
+
+    unsigned int elementWidth = elementType.getIntOrFloatBitWidth();
+    mlir::Value numElements;
+    if (elementType.isF32())
+      numElements = rewriter.create<emitc::ConstantOp>(
+          loc, elementType, rewriter.getFloatAttr(elementType, elementWidth));
+    else
+      numElements = rewriter.create<emitc::ConstantOp>(
+          loc, elementType, rewriter.getIntegerAttr(elementType, elementWidth));
+    mlir::Value totalSizeBytes = rewriter.create<emitc::MulOp>(
+        loc, mlir::emitc::SizeTType::get(rewriter.getContext()), sizeofElement,
+        numElements);
+
+    auto mallocCall = rewriter.create<emitc::CallOpaqueOp>(
+        loc,
+        emitc::PointerType::get(
+            rewriter.getContext(),
+            mlir::emitc::OpaqueType::get(rewriter.getContext(), "void")),
+        rewriter.getStringAttr("malloc"), mlir::ValueRange{totalSizeBytes});
+    auto targetPointerType =
+        emitc::PointerType::get(rewriter.getContext(), elementType);
+    auto castOp = rewriter.create<emitc::CastOp>(loc, targetPointerType,
+                                                 mallocCall.getResult(0));
+
+    rewriter.replaceOp(allocOp, castOp);
     return success();
   }
+
+private:
+  std::string getCTypeName(mlir::Type type) const {
+    if (type.isF32())
+      return "float";
+    if (type.isF64())
+      return "double";
+    if (type.isInteger(8))
+      return "int8_t";
+    if (type.isInteger(16))
+      return "int16_t";
+    if (type.isInteger(32))
+      return "int32_t";
+    if (type.isInteger(64))
+      return "int64_t";
+    if (type.isIndex())
+      return "size_t";
+    return "void";
+  }
 };
 
 struct ConvertGlobal final : public OpConversionPattern<memref::GlobalOp> {
diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp
index cf25c09a2c2f3..d7544007718eb 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp
@@ -30,6 +30,16 @@ struct ConvertMemRefToEmitCPass
     : public impl::ConvertMemRefToEmitCBase<ConvertMemRefToEmitCPass> {
   void runOnOperation() override {
     TypeConverter converter;
+    mlir::ModuleOp module = getOperation();
+    module.walk([&](mlir::Operation *op) {
+      if (llvm::isa<mlir::memref::AllocOp, mlir::memref::CopyOp>(op)) {
+        OpBuilder builder(module.getBody(), module.getBody()->begin());
+        builder.create<emitc::IncludeOp>(module.getLoc(),
+                                         builder.getStringAttr("stdlib.h"));
+        return mlir::WalkResult::interrupt();
+      }
+      return mlir::WalkResult::advance();
+    });
 
     // Fallback for other types.
     converter.addConversion([](Type type) -> std::optional<Type> {
diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
index 23e1c20670f8c..ad401c1a604ef 100644
--- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
@@ -10,8 +10,12 @@ func.func @alloca() {
 
 // CHECK-LABEL: alloc()
 func.func @alloc() {
-  // CHECK-NEXT:  %0 = "emitc.constant"() <{value = 3996 : index}> : () -> index
-  // CHECK-NEXT:  %1 = emitc.call_opaque "malloc"(%0) : (index) -> !emitc.ptr<i32>
+  // CHECK-NEXT:  %0 = emitc.literal "int32_t" : !emitc.opaque<"type">
+  // CHECK-NEXT:  %1 = emitc.call_opaque "sizeof"(%0) : (!emitc.opaque<"type">) -> !emitc.size_t
+  // CHECK-NEXT:  %2 = "emitc.constant"() <{value = 32 : i32}> : () -> i32
+  // CHECK-NEXT:  %3 = emitc.mul %1, %2 : (!emitc.size_t, i32) -> !emitc.size_t
+  // CHECK-NEXT:  %4 = emitc.call_opaque "malloc"(%3) : (!emitc.size_t) -> !emitc.ptr<!emitc.opaque<"void">>
+  // CHECK-NEXT:  %5 = emitc.cast %4 : !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<i32>
   %alloc = memref.alloc() : memref<999xi32>
   return
 }

>From f9d450e8d8c0bc0d376a942eab5d66c0376fdfac Mon Sep 17 00:00:00 2001
From: Jaddyen <ajaden at google.com>
Date: Mon, 21 Jul 2025 23:06:43 +0000
Subject: [PATCH 4/8] Remove unneeded context

---
 .../MemRefToEmitC/MemRefToEmitC.cpp           | 70 +++++++++++++------
 .../MemRefToEmitC/memref-to-emitc.mlir        | 11 ++-
 2 files changed, 52 insertions(+), 29 deletions(-)

diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
index d8ceb4b205a55..14e13f22f072f 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
@@ -18,6 +18,7 @@
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/BuiltinAttributes.h"
 #include "mlir/IR/PatternMatch.h"
+#include "mlir/IR/Value.h"
 #include "mlir/Transforms/DialectConversion.h"
 
 using namespace mlir;
@@ -95,22 +96,20 @@ struct ConvertAlloc final : public OpConversionPattern<memref::AllocOp> {
     }
 
     Type elementType = memrefType.getElementType();
-    mlir::Value elementTypeLiteral = rewriter.create<emitc::LiteralOp>(
-        loc, mlir::emitc::OpaqueType::get(rewriter.getContext(), "type"),
-        rewriter.getStringAttr(getCTypeName(elementType)));
-    emitc::CallOpaqueOp sizeofElementOp = rewriter.create<emitc::CallOpaqueOp>(
-        loc, mlir::emitc::SizeTType::get(rewriter.getContext()),
-        rewriter.getStringAttr("sizeof"), mlir::ValueRange{elementTypeLiteral});
+    mlir::emitc::CallOpaqueOp sizeofElementOp =
+        rewriter.create<mlir::emitc::CallOpaqueOp>(
+            loc, mlir::emitc::SizeTType::get(rewriter.getContext()),
+            rewriter.getStringAttr("sizeof"), mlir::ValueRange{},
+            mlir::ArrayAttr::get(rewriter.getContext(),
+                                 {mlir::TypeAttr::get(elementType)}));
     mlir::Value sizeofElement = sizeofElementOp.getResult(0);
 
     unsigned int elementWidth = elementType.getIntOrFloatBitWidth();
+    auto indexAttr = rewriter.getIndexAttr(elementWidth);
+
     mlir::Value numElements;
-    if (elementType.isF32())
-      numElements = rewriter.create<emitc::ConstantOp>(
-          loc, elementType, rewriter.getFloatAttr(elementType, elementWidth));
-    else
-      numElements = rewriter.create<emitc::ConstantOp>(
-          loc, elementType, rewriter.getIntegerAttr(elementType, elementWidth));
+    numElements = rewriter.create<emitc::ConstantOp>(
+        loc, rewriter.getIndexType(), indexAttr);
     mlir::Value totalSizeBytes = rewriter.create<emitc::MulOp>(
         loc, mlir::emitc::SizeTType::get(rewriter.getContext()), sizeofElement,
         numElements);
@@ -118,11 +117,9 @@ struct ConvertAlloc final : public OpConversionPattern<memref::AllocOp> {
     auto mallocCall = rewriter.create<emitc::CallOpaqueOp>(
         loc,
         emitc::PointerType::get(
-            rewriter.getContext(),
             mlir::emitc::OpaqueType::get(rewriter.getContext(), "void")),
         rewriter.getStringAttr("malloc"), mlir::ValueRange{totalSizeBytes});
-    auto targetPointerType =
-        emitc::PointerType::get(rewriter.getContext(), elementType);
+    auto targetPointerType = emitc::PointerType::get(elementType);
     auto castOp = rewriter.create<emitc::CastOp>(loc, targetPointerType,
                                                  mallocCall.getResult(0));
 
@@ -136,14 +133,41 @@ struct ConvertAlloc final : public OpConversionPattern<memref::AllocOp> {
       return "float";
     if (type.isF64())
       return "double";
-    if (type.isInteger(8))
-      return "int8_t";
-    if (type.isInteger(16))
-      return "int16_t";
-    if (type.isInteger(32))
-      return "int32_t";
-    if (type.isInteger(64))
-      return "int64_t";
+    if (auto integerType = mlir::dyn_cast<mlir::IntegerType>(type)) {
+      unsigned width = integerType.getWidth();
+      bool isSigned = integerType.isSigned();
+      if (isSigned) {
+        switch (width) {
+        case 8:
+          return "int8_t";
+        case 16:
+          return "int16_t";
+        case 32:
+          return "int32_t";
+        case 64:
+          return "int64_t";
+        case 128:
+          return "int128_t";
+        default:
+          return "unsupported_signed_integer_type";
+        }
+      } else {
+        switch (width) {
+        case 8:
+          return "uint8_t";
+        case 16:
+          return "uint16_t";
+        case 32:
+          return "uint32_t";
+        case 64:
+          return "uint64_t";
+        case 128:
+          return "uint128_t";
+        default:
+          return "unsupported_unsigned_integer_type";
+        }
+      }
+    }
     if (type.isIndex())
       return "size_t";
     return "void";
diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
index ad401c1a604ef..60cf47330169d 100644
--- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
@@ -10,12 +10,11 @@ func.func @alloca() {
 
 // CHECK-LABEL: alloc()
 func.func @alloc() {
-  // CHECK-NEXT:  %0 = emitc.literal "int32_t" : !emitc.opaque<"type">
-  // CHECK-NEXT:  %1 = emitc.call_opaque "sizeof"(%0) : (!emitc.opaque<"type">) -> !emitc.size_t
-  // CHECK-NEXT:  %2 = "emitc.constant"() <{value = 32 : i32}> : () -> i32
-  // CHECK-NEXT:  %3 = emitc.mul %1, %2 : (!emitc.size_t, i32) -> !emitc.size_t
-  // CHECK-NEXT:  %4 = emitc.call_opaque "malloc"(%3) : (!emitc.size_t) -> !emitc.ptr<!emitc.opaque<"void">>
-  // CHECK-NEXT:  %5 = emitc.cast %4 : !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<i32>
+  // CHECK-NEXT: %0 = emitc.call_opaque "sizeof"() {args = [i32]} : () -> !emitc.size_t
+  // CHECK-NEXT: %1 = "emitc.constant"() <{value = 32 : index}> : () -> index
+  // CHECK-NEXT: %2 = emitc.mul %0, %1 : (!emitc.size_t, index) -> !emitc.size_t
+  // CHECK-NEXT: %3 = emitc.call_opaque "malloc"(%2) : (!emitc.size_t) -> !emitc.ptr<!emitc.opaque<"void">>
+  // CHECK-NEXT: %4 = emitc.cast %3 : !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<i32>
   %alloc = memref.alloc() : memref<999xi32>
   return
 }

>From 13d5375ec072e1d134aee3d9f87cc62a255b5954 Mon Sep 17 00:00:00 2001
From: Jaddyen <ajaden at google.com>
Date: Tue, 22 Jul 2025 21:53:28 +0000
Subject: [PATCH 5/8] Check for alignment

---
 mlir/include/mlir/Conversion/Passes.td        |  4 +
 .../MemRefToEmitC/MemRefToEmitC.cpp           | 92 ++++++++-----------
 .../MemRefToEmitC/MemRefToEmitCPass.cpp       | 44 ++++++---
 .../MemRefToEmitC/memref-to-emitc-alloc.mlir  | 17 ++++
 .../MemRefToEmitC/memref-to-emitc.mlir        | 11 ---
 5 files changed, 91 insertions(+), 77 deletions(-)
 create mode 100644 mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc.mlir

diff --git a/mlir/include/mlir/Conversion/Passes.td b/mlir/include/mlir/Conversion/Passes.td
index 4660758f35b04..36567c62808dc 100644
--- a/mlir/include/mlir/Conversion/Passes.td
+++ b/mlir/include/mlir/Conversion/Passes.td
@@ -844,6 +844,10 @@ def ConvertMathToFuncs : Pass<"convert-math-to-funcs", "ModuleOp"> {
 def ConvertMemRefToEmitC : Pass<"convert-memref-to-emitc", "ModuleOp"> {
   let summary = "Convert MemRef dialect to EmitC dialect";
   let dependentDialects = ["emitc::EmitCDialect"];
+  let options = [Option<
+      "lowerToCpp", "lower-to-cpp", "bool",
+      /*default=*/"false",
+      /*description=*/"Target C++ (true) instead of C (false)">];
 }
 
 //===----------------------------------------------------------------------===//
diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
index 14e13f22f072f..ffb456f743618 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
@@ -17,9 +17,11 @@
 #include "mlir/Dialect/MemRef/IR/MemRef.h"
 #include "mlir/IR/Builders.h"
 #include "mlir/IR/BuiltinAttributes.h"
+#include "mlir/IR/BuiltinTypes.h"
 #include "mlir/IR/PatternMatch.h"
 #include "mlir/IR/Value.h"
 #include "mlir/Transforms/DialectConversion.h"
+#include <cstdint>
 
 using namespace mlir;
 
@@ -85,7 +87,7 @@ struct ConvertAlloc final : public OpConversionPattern<memref::AllocOp> {
   matchAndRewrite(memref::AllocOp allocOp, OpAdaptor operands,
                   ConversionPatternRewriter &rewriter) const override {
     mlir::Location loc = allocOp.getLoc();
-    auto memrefType = allocOp.getType();
+    MemRefType memrefType = allocOp.getType();
     if (!memrefType.hasStaticShape()) {
       // TODO: Handle Dynamic shapes in the future. If the size
       // of the allocation is the result of some function, we could
@@ -95,82 +97,62 @@ struct ConvertAlloc final : public OpConversionPattern<memref::AllocOp> {
           loc, "cannot transform alloc with dynamic shape");
     }
 
+    mlir::Type sizeTType = mlir::emitc::SizeTType::get(rewriter.getContext());
     Type elementType = memrefType.getElementType();
     mlir::emitc::CallOpaqueOp sizeofElementOp =
         rewriter.create<mlir::emitc::CallOpaqueOp>(
-            loc, mlir::emitc::SizeTType::get(rewriter.getContext()),
-            rewriter.getStringAttr("sizeof"), mlir::ValueRange{},
+            loc, sizeTType, rewriter.getStringAttr("sizeof"),
+            mlir::ValueRange{},
             mlir::ArrayAttr::get(rewriter.getContext(),
                                  {mlir::TypeAttr::get(elementType)}));
     mlir::Value sizeofElement = sizeofElementOp.getResult(0);
 
     unsigned int elementWidth = elementType.getIntOrFloatBitWidth();
-    auto indexAttr = rewriter.getIndexAttr(elementWidth);
+    IntegerAttr indexAttr = rewriter.getIndexAttr(elementWidth);
 
     mlir::Value numElements;
     numElements = rewriter.create<emitc::ConstantOp>(
         loc, rewriter.getIndexType(), indexAttr);
     mlir::Value totalSizeBytes = rewriter.create<emitc::MulOp>(
-        loc, mlir::emitc::SizeTType::get(rewriter.getContext()), sizeofElement,
-        numElements);
+        loc, sizeTType, sizeofElement, numElements);
 
-    auto mallocCall = rewriter.create<emitc::CallOpaqueOp>(
+    int64_t alignment = alignedAllocationGetAlignment(allocOp, elementWidth);
+    mlir::Value alignmentValue = rewriter.create<emitc::ConstantOp>(
+        loc, sizeTType,
+        rewriter.getIntegerAttr(rewriter.getIndexType(), alignment));
+
+    emitc::CallOpaqueOp alignedAllocCall = rewriter.create<emitc::CallOpaqueOp>(
         loc,
         emitc::PointerType::get(
             mlir::emitc::OpaqueType::get(rewriter.getContext(), "void")),
-        rewriter.getStringAttr("malloc"), mlir::ValueRange{totalSizeBytes});
-    auto targetPointerType = emitc::PointerType::get(elementType);
-    auto castOp = rewriter.create<emitc::CastOp>(loc, targetPointerType,
-                                                 mallocCall.getResult(0));
+        rewriter.getStringAttr("aligned_alloc"),
+        mlir::ValueRange{alignmentValue, totalSizeBytes});
+    emitc::PointerType targetPointerType = emitc::PointerType::get(elementType);
+    emitc::CastOp castOp = rewriter.create<emitc::CastOp>(
+        loc, targetPointerType, alignedAllocCall.getResult(0));
 
     rewriter.replaceOp(allocOp, castOp);
     return success();
   }
 
-private:
-  std::string getCTypeName(mlir::Type type) const {
-    if (type.isF32())
-      return "float";
-    if (type.isF64())
-      return "double";
-    if (auto integerType = mlir::dyn_cast<mlir::IntegerType>(type)) {
-      unsigned width = integerType.getWidth();
-      bool isSigned = integerType.isSigned();
-      if (isSigned) {
-        switch (width) {
-        case 8:
-          return "int8_t";
-        case 16:
-          return "int16_t";
-        case 32:
-          return "int32_t";
-        case 64:
-          return "int64_t";
-        case 128:
-          return "int128_t";
-        default:
-          return "unsupported_signed_integer_type";
-        }
-      } else {
-        switch (width) {
-        case 8:
-          return "uint8_t";
-        case 16:
-          return "uint16_t";
-        case 32:
-          return "uint32_t";
-        case 64:
-          return "uint64_t";
-        case 128:
-          return "uint128_t";
-        default:
-          return "unsupported_unsigned_integer_type";
-        }
-      }
-    }
-    if (type.isIndex())
-      return "size_t";
-    return "void";
+  /// The minimum alignment to use with aligned_alloc (has to be a power of 2).
+  static constexpr uint64_t kMinAlignedAllocAlignment = 16UL;
+
+  /// Computes the alignment for aligned_alloc used to allocate the buffer for
+  /// the memory allocation op.
+  ///
+  /// Aligned_alloc requires the allocation size to be a power of two, and the
+  /// allocation size to be a multiple of the alignment.
+  int64_t alignedAllocationGetAlignment(memref::AllocOp op,
+                                        unsigned int elementWidth) const {
+    if (std::optional<uint64_t> alignment = op.getAlignment())
+      return *alignment;
+
+    // Whenever we don't have alignment set, we will use an alignment
+    // consistent with the element type; since the allocation size has to be a
+    // power of two, we will bump to the next power of two if it isn't.
+    return std::max(kMinAlignedAllocAlignment,
+                    llvm::PowerOf2Ceil(elementWidth));
   }
 };
 
diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp
index d7544007718eb..d2fb448fe38ff 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp
@@ -15,6 +15,7 @@
 #include "mlir/Conversion/MemRefToEmitC/MemRefToEmitC.h"
 #include "mlir/Dialect/EmitC/IR/EmitC.h"
 #include "mlir/Dialect/MemRef/IR/MemRef.h"
+#include "mlir/IR/Attributes.h"
 #include "mlir/Pass/Pass.h"
 #include "mlir/Transforms/DialectConversion.h"
 
@@ -28,19 +29,15 @@ using namespace mlir;
 namespace {
 struct ConvertMemRefToEmitCPass
     : public impl::ConvertMemRefToEmitCBase<ConvertMemRefToEmitCPass> {
+  using Base = impl::ConvertMemRefToEmitCBase<ConvertMemRefToEmitCPass>;
+  ConvertMemRefToEmitCPass() = default;
+  ConvertMemRefToEmitCPass(ConvertMemRefToEmitCOptions options) {
+    this->lowerToCpp = options.lowerToCpp;
+  }
   void runOnOperation() override {
     TypeConverter converter;
-    mlir::ModuleOp module = getOperation();
-    module.walk([&](mlir::Operation *op) {
-      if (llvm::isa<mlir::memref::AllocOp, mlir::memref::CopyOp>(op)) {
-        OpBuilder builder(module.getBody(), module.getBody()->begin());
-        builder.create<emitc::IncludeOp>(module.getLoc(),
-                                         builder.getStringAttr("stdlib.h"));
-        return mlir::WalkResult::interrupt();
-      }
-      return mlir::WalkResult::advance();
-    });
-
+    ConvertMemRefToEmitCOptions options;
+    options.lowerToCpp = this->lowerToCpp;
     // Fallback for other types.
     converter.addConversion([](Type type) -> std::optional<Type> {
       if (!emitc::isSupportedEmitCType(type))
@@ -60,6 +57,31 @@ struct ConvertMemRefToEmitCPass
     if (failed(applyPartialConversion(getOperation(), target,
                                       std::move(patterns))))
       return signalPassFailure();
+
+    mlir::ModuleOp module = getOperation();
+    module.walk([&](mlir::emitc::CallOpaqueOp callOp) {
+      if (callOp.getCallee() != "aligned_alloc") {
+        return mlir::WalkResult::advance();
+      }
+
+      for (auto &op : *module.getBody()) {
+        if (auto includeOp = llvm::dyn_cast<mlir::emitc::IncludeOp>(op)) {
+          if (includeOp.getIsStandardInclude() &&
+              ((options.lowerToCpp && includeOp.getInclude() == "cstdlib") ||
+               (!options.lowerToCpp && includeOp.getInclude() == "stdlib.h"))) {
+            return mlir::WalkResult::interrupt();
+          }
+        }
+      }
+
+      mlir::OpBuilder builder(module.getBody(), module.getBody()->begin());
+      StringAttr includeAttr =
+          builder.getStringAttr(options.lowerToCpp ? "cstdlib" : "stdlib.h");
+      builder.create<mlir::emitc::IncludeOp>(
+          module.getLoc(), includeAttr,
+          /*is_standard_include=*/builder.getUnitAttr());
+      return mlir::WalkResult::interrupt();
+    });
   }
 };
 } // namespace
diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc.mlir
new file mode 100644
index 0000000000000..98a87158daf02
--- /dev/null
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc.mlir
@@ -0,0 +1,17 @@
+// RUN: mlir-opt -convert-memref-to-emitc="lower-to-cpp=true" %s -split-input-file | FileCheck %s
+
+func.func @alloc() {
+  %alloc = memref.alloc() : memref<999xi32>
+  return
+}
+
+// CHECK:module {
+// CHECK-NEXT: emitc.include <"cstdlib">
+// CHECK-LABEL: alloc()
+// CHECK-NEXT: %[[ALLOC:.*]] = emitc.call_opaque "sizeof"() {args = [i32]} : () -> !emitc.size_t 
+// CHECK-NEXT: %[[ALLOC:.*]] = "emitc.constant"() <{value = 32 : index}> : () -> index
+// CHECK-NEXT: %[[ALLOC:.*]] = emitc.mul %0, %1 : (!emitc.size_t, index) -> !emitc.size_t
+// CHECK-NEXT: %[[ALLOC:.*]] = "emitc.constant"() <{value = 32 : index}> : () -> !emitc.size_t 
+// CHECK-NEXT: %[[ALLOC:.*]] = emitc.call_opaque "aligned_alloc"(%3, %2) : (!emitc.size_t, !emitc.size_t) -> !emitc.ptr<!emitc.opaque<"void">>
+// CHECK-NEXT: %[[ALLOC:.*]] = emitc.cast %4 : !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<i32>
+// CHECK-NEXT: return 
\ No newline at end of file
diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
index 60cf47330169d..d37fd1de90add 100644
--- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc.mlir
@@ -8,17 +8,6 @@ func.func @alloca() {
   return
 }
 
-// CHECK-LABEL: alloc()
-func.func @alloc() {
-  // CHECK-NEXT: %0 = emitc.call_opaque "sizeof"() {args = [i32]} : () -> !emitc.size_t
-  // CHECK-NEXT: %1 = "emitc.constant"() <{value = 32 : index}> : () -> index
-  // CHECK-NEXT: %2 = emitc.mul %0, %1 : (!emitc.size_t, index) -> !emitc.size_t
-  // CHECK-NEXT: %3 = emitc.call_opaque "malloc"(%2) : (!emitc.size_t) -> !emitc.ptr<!emitc.opaque<"void">>
-  // CHECK-NEXT: %4 = emitc.cast %3 : !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<i32>
-  %alloc = memref.alloc() : memref<999xi32>
-  return
-}
-
 // -----
 
 // CHECK-LABEL: memref_store

>From 15a01f2948e3d3000e621779b95a9782304908b2 Mon Sep 17 00:00:00 2001
From: Jaddyen <ajaden at google.com>
Date: Tue, 22 Jul 2025 22:01:11 +0000
Subject: [PATCH 6/8] Correct end of line

---
 mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc.mlir | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc.mlir
index 98a87158daf02..e5d6566f2ed05 100644
--- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc.mlir
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc.mlir
@@ -14,4 +14,4 @@ func.func @alloc() {
 // CHECK-NEXT: %[[ALLOC:.*]] = "emitc.constant"() <{value = 32 : index}> : () -> !emitc.size_t 
 // CHECK-NEXT: %[[ALLOC:.*]] = emitc.call_opaque "aligned_alloc"(%3, %2) : (!emitc.size_t, !emitc.size_t) -> !emitc.ptr<!emitc.opaque<"void">>
 // CHECK-NEXT: %[[ALLOC:.*]] = emitc.cast %4 : !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<i32>
-// CHECK-NEXT: return 
\ No newline at end of file
+// CHECK-NEXT: return 

>From a6dde301fd9161b9a28a50af2b3cac1e1d1aad73 Mon Sep 17 00:00:00 2001
From: Jaddyen <ajaden at google.com>
Date: Wed, 23 Jul 2025 17:20:05 +0000
Subject: [PATCH 7/8] Allow for both malloc and alloc_aligned

---
 .../MemRefToEmitC/MemRefToEmitC.cpp           | 30 ++++++++++++++-----
 .../MemRefToEmitC/MemRefToEmitCPass.cpp       | 21 ++++++-------
 .../MemRefToEmitC/memref-to-emitc-alloc.mlir  | 20 +++++++++++--
 3 files changed, 50 insertions(+), 21 deletions(-)

diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
index ffb456f743618..349718d4eec3a 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitC.cpp
@@ -116,20 +116,34 @@ struct ConvertAlloc final : public OpConversionPattern<memref::AllocOp> {
     mlir::Value totalSizeBytes = rewriter.create<emitc::MulOp>(
         loc, sizeTType, sizeofElement, numElements);
 
-    int64_t alignment = alignedAllocationGetAlignment(allocOp, elementWidth);
-    mlir::Value alignmentValue = rewriter.create<emitc::ConstantOp>(
-        loc, sizeTType,
-        rewriter.getIntegerAttr(rewriter.getIndexType(), alignment));
+    emitc::CallOpaqueOp allocCall;
+    StringAttr allocFunctionName = allocOp.getAlignment()
+                                       ? rewriter.getStringAttr("aligned_alloc")
+                                       : rewriter.getStringAttr("malloc");
+    mlir::Value alignmentValue;
+    if (allocOp.getAlignment()) {
+      alignmentValue = rewriter.create<emitc::ConstantOp>(
+          loc, sizeTType,
+          rewriter.getIntegerAttr(
+              rewriter.getIndexType(),
+              alignedAllocationGetAlignment(allocOp, elementWidth)));
+    }
+
+    SmallVector<mlir::Value, 2> argsVec;
+    if (allocOp.getAlignment())
+      argsVec.push_back(alignmentValue);
+    argsVec.push_back(totalSizeBytes);
+    mlir::ValueRange args(argsVec);
 
-    emitc::CallOpaqueOp alignedAllocCall = rewriter.create<emitc::CallOpaqueOp>(
+    allocCall = rewriter.create<emitc::CallOpaqueOp>(
         loc,
         emitc::PointerType::get(
             mlir::emitc::OpaqueType::get(rewriter.getContext(), "void")),
-        rewriter.getStringAttr("aligned_alloc"),
-        mlir::ValueRange{alignmentValue, totalSizeBytes});
+        allocFunctionName, args);
+
     emitc::PointerType targetPointerType = emitc::PointerType::get(elementType);
     emitc::CastOp castOp = rewriter.create<emitc::CastOp>(
-        loc, targetPointerType, alignedAllocCall.getResult(0));
+        loc, targetPointerType, allocCall.getResult(0));
 
     rewriter.replaceOp(allocOp, castOp);
     return success();
diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp
index d2fb448fe38ff..8e2d3d906abc3 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp
@@ -31,9 +31,7 @@ struct ConvertMemRefToEmitCPass
     : public impl::ConvertMemRefToEmitCBase<ConvertMemRefToEmitCPass> {
   using Base = impl::ConvertMemRefToEmitCBase<ConvertMemRefToEmitCPass>;
   ConvertMemRefToEmitCPass() = default;
-  ConvertMemRefToEmitCPass(ConvertMemRefToEmitCOptions options) {
-    this->lowerToCpp = options.lowerToCpp;
-  }
+  ConvertMemRefToEmitCPass(ConvertMemRefToEmitCOptions options) {}
   void runOnOperation() override {
     TypeConverter converter;
     ConvertMemRefToEmitCOptions options;
@@ -60,17 +58,20 @@ struct ConvertMemRefToEmitCPass
 
     mlir::ModuleOp module = getOperation();
     module.walk([&](mlir::emitc::CallOpaqueOp callOp) {
-      if (callOp.getCallee() != "aligned_alloc") {
+      if (callOp.getCallee() != "aligned_alloc" &&
+          callOp.getCallee() != "malloc") {
         return mlir::WalkResult::advance();
       }
 
       for (auto &op : *module.getBody()) {
-        if (auto includeOp = llvm::dyn_cast<mlir::emitc::IncludeOp>(op)) {
-          if (includeOp.getIsStandardInclude() &&
-              ((options.lowerToCpp && includeOp.getInclude() == "cstdlib") ||
-               (!options.lowerToCpp && includeOp.getInclude() == "stdlib.h"))) {
-            return mlir::WalkResult::interrupt();
-          }
+        auto includeOp = llvm::dyn_cast<mlir::emitc::IncludeOp>(op);
+        if (!includeOp) {
+          continue;
+        }
+        if (includeOp.getIsStandardInclude() &&
+            ((options.lowerToCpp && includeOp.getInclude() == "cstdlib") ||
+             (!options.lowerToCpp && includeOp.getInclude() == "stdlib.h"))) {
+          return mlir::WalkResult::interrupt();
         }
       }
 
diff --git a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc.mlir b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc.mlir
index e5d6566f2ed05..6a9327aedd082 100644
--- a/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc.mlir
+++ b/mlir/test/Conversion/MemRefToEmitC/memref-to-emitc-alloc.mlir
@@ -11,7 +11,21 @@ func.func @alloc() {
 // CHECK-NEXT: %[[ALLOC:.*]] = emitc.call_opaque "sizeof"() {args = [i32]} : () -> !emitc.size_t 
 // CHECK-NEXT: %[[ALLOC:.*]] = "emitc.constant"() <{value = 32 : index}> : () -> index
 // CHECK-NEXT: %[[ALLOC:.*]] = emitc.mul %0, %1 : (!emitc.size_t, index) -> !emitc.size_t
-// CHECK-NEXT: %[[ALLOC:.*]] = "emitc.constant"() <{value = 32 : index}> : () -> !emitc.size_t 
-// CHECK-NEXT: %[[ALLOC:.*]] = emitc.call_opaque "aligned_alloc"(%3, %2) : (!emitc.size_t, !emitc.size_t) -> !emitc.ptr<!emitc.opaque<"void">>
-// CHECK-NEXT: %[[ALLOC:.*]] = emitc.cast %4 : !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<i32>
+// CHECK-NEXT: %[[ALLOC:.*]] = emitc.call_opaque "malloc"(%2) : (!emitc.size_t) -> !emitc.ptr<!emitc.opaque<"void">>
+// CHECK-NEXT: %[[ALLOC:.*]] = emitc.cast %3 : !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<i32>
 // CHECK-NEXT: return 
+
+func.func @alloc_aligned() {
+  %alloc = memref.alloc() {alignment = 64 : i64} : memref<999xf32>
+  return
+}
+
+// CHECK-LABEL: alloc_aligned
+// CHECK-NEXT: %[[ALLOC:.*]] = emitc.call_opaque "sizeof"() {args = [f32]} : () -> !emitc.size_t 
+// CHECK-NEXT: %[[ALLOC:.*]] = "emitc.constant"() <{value = 32 : index}> : () -> index
+// CHECK-NEXT: %[[ALLOC:.*]] = emitc.mul %0, %1 : (!emitc.size_t, index) -> !emitc.size_t
+// CHECK-NEXT: %[[ALIGNMENT:.*]] = "emitc.constant"() <{value = 64 : index}> : () -> !emitc.size_t 
+// CHECK-NEXT: %[[ALLOC:.*]] = emitc.call_opaque "aligned_alloc"(%3, %2) : (!emitc.size_t, !emitc.size_t) -> !emitc.ptr<!emitc.opaque<"void">>
+// CHECK-NEXT: %[[ALLOC:.*]] = emitc.cast %4 : !emitc.ptr<!emitc.opaque<"void">> to !emitc.ptr<f32>
+// CHECK-NEXT: return
+

>From feb651e246bfb7e26ce57e4fe83d0f01ca65fb86 Mon Sep 17 00:00:00 2001
From: Jaddyen <ajaden at google.com>
Date: Wed, 23 Jul 2025 17:22:24 +0000
Subject: [PATCH 8/8] Remove unnecessary auto

---
 mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp
index 8e2d3d906abc3..f6af461dc93f4 100644
--- a/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp
+++ b/mlir/lib/Conversion/MemRefToEmitC/MemRefToEmitCPass.cpp
@@ -64,7 +64,7 @@ struct ConvertMemRefToEmitCPass
       }
 
       for (auto &op : *module.getBody()) {
-        auto includeOp = llvm::dyn_cast<mlir::emitc::IncludeOp>(op);
+        emitc::IncludeOp includeOp = llvm::dyn_cast<mlir::emitc::IncludeOp>(op);
         if (!includeOp) {
           continue;
         }



More information about the Mlir-commits mailing list