[Mlir-commits] [mlir] [MLIR][MemRef] Add `alloca` support for `erase_dead_alloc_and_stores` (PR #142131)

Vitalii Shutov llvmlistbot at llvm.org
Mon Jun 2 09:39:41 PDT 2025


https://github.com/Lallapallooza updated https://github.com/llvm/llvm-project/pull/142131

>From 3e9990df0093f569332a5eb9a1ab28353fc2bd10 Mon Sep 17 00:00:00 2001
From: Vitalii Shutov <vitalii.shutov at arm.com>
Date: Fri, 30 May 2025 13:05:55 +0100
Subject: [PATCH 1/2] [MLIR][MemRef] Add `alloca` support for
 `erase_dead_alloc_and_stores`

Previously, `erase_dead_alloc_and_stores` didn't support `memref.alloca`.
This patch introduces support for it.

Signed-off-by: Vitalii Shutov <vitalii.shutov at arm.com>
---
 .../MemRef/TransformOps/MemRefTransformOps.td |  2 +-
 mlir/lib/Dialect/MemRef/Utils/MemRefUtils.cpp | 10 +++++---
 mlir/test/Dialect/MemRef/transform-ops.mlir   | 24 +++++++++++++++++++
 3 files changed, 32 insertions(+), 4 deletions(-)

diff --git a/mlir/include/mlir/Dialect/MemRef/TransformOps/MemRefTransformOps.td b/mlir/include/mlir/Dialect/MemRef/TransformOps/MemRefTransformOps.td
index 2d060f3c2da64..f4694a30a8a12 100644
--- a/mlir/include/mlir/Dialect/MemRef/TransformOps/MemRefTransformOps.td
+++ b/mlir/include/mlir/Dialect/MemRef/TransformOps/MemRefTransformOps.td
@@ -245,7 +245,7 @@ def MemRefEraseDeadAllocAndStoresOp
     ]> {
   let description = [{
     This applies memory optimization on memref. In particular it does store to
-    load forwarding, dead store elimination and dead alloc elimination.
+    load forwarding, dead store elimination and dead alloc/alloca elimination.
 
     #### Return modes
 
diff --git a/mlir/lib/Dialect/MemRef/Utils/MemRefUtils.cpp b/mlir/lib/Dialect/MemRef/Utils/MemRefUtils.cpp
index 3f9fb071e0ba8..bd30276339812 100644
--- a/mlir/lib/Dialect/MemRef/Utils/MemRefUtils.cpp
+++ b/mlir/lib/Dialect/MemRef/Utils/MemRefUtils.cpp
@@ -156,13 +156,17 @@ static bool resultIsNotRead(Operation *op, std::vector<Operation *> &uses) {
 
 void eraseDeadAllocAndStores(RewriterBase &rewriter, Operation *parentOp) {
   std::vector<Operation *> opToErase;
-  parentOp->walk([&](memref::AllocOp op) {
+  auto collectOpsToErase = [&](Operation *op) {
     std::vector<Operation *> candidates;
     if (resultIsNotRead(op, candidates)) {
       llvm::append_range(opToErase, candidates);
-      opToErase.push_back(op.getOperation());
+      opToErase.push_back(op);
     }
-  });
+  };
+
+  parentOp->walk([&](memref::AllocOp op) { collectOpsToErase(op); });
+  parentOp->walk([&](memref::AllocaOp op) { collectOpsToErase(op); });
+
   for (Operation *op : opToErase)
     rewriter.eraseOp(op);
 }
diff --git a/mlir/test/Dialect/MemRef/transform-ops.mlir b/mlir/test/Dialect/MemRef/transform-ops.mlir
index acab37e482cfe..3b37c62fcb28e 100644
--- a/mlir/test/Dialect/MemRef/transform-ops.mlir
+++ b/mlir/test/Dialect/MemRef/transform-ops.mlir
@@ -327,6 +327,30 @@ module attributes {transform.with_named_sequence} {
   }
 }
 
+// -----
+
+// CHECK-LABEL: func.func @dead_alloca
+func.func @dead_alloca() {
+  // CHECK-NOT: %{{.+}} = memref.alloca
+  %0 = memref.alloca() : memref<8x64xf32, 3>
+  %1 = memref.subview %0[0, 0] [8, 4] [1, 1] : memref<8x64xf32, 3> to
+    memref<8x4xf32, affine_map<(d0, d1) -> (d0 * 64 + d1)>, 3>
+  %c0 = arith.constant 0 : index
+  %cst_0 = arith.constant dense<0.000000e+00> : vector<1x4xf32>
+  vector.transfer_write %cst_0, %1[%c0, %c0] {in_bounds = [true, true]} :
+    vector<1x4xf32>, memref<8x4xf32, affine_map<(d0, d1) -> (d0 * 64 + d1)>, 3>
+  return
+}
+
+module attributes {transform.with_named_sequence} {
+  transform.named_sequence @__transform_main(%arg1: !transform.any_op {transform.readonly}) {
+    %0 = transform.structured.match ops{["func.func"]} in %arg1 : (!transform.any_op) -> !transform.any_op
+    transform.memref.erase_dead_alloc_and_stores %0 : (!transform.any_op) -> ()
+    transform.yield
+  }
+}
+
+
 // -----
 
 // CHECK-LABEL: @store_to_load

>From ecb4559bff6ea6c01d250280865240771443819e Mon Sep 17 00:00:00 2001
From: Vitalii Shutov <vitalii.shutov at arm.com>
Date: Fri, 30 May 2025 13:05:55 +0100
Subject: [PATCH 2/2] [MLIR][MemRef] Add `alloca` support for
 `erase_dead_alloc_and_stores`

Previously, `erase_dead_alloc_and_stores` didn't support `memref.alloca`.
This patch introduces support for it.

Signed-off-by: Vitalii Shutov <vitalii.shutov at arm.com>
---
 mlir/lib/Dialect/MemRef/Utils/MemRefUtils.cpp | 10 ++++------
 1 file changed, 4 insertions(+), 6 deletions(-)

diff --git a/mlir/lib/Dialect/MemRef/Utils/MemRefUtils.cpp b/mlir/lib/Dialect/MemRef/Utils/MemRefUtils.cpp
index bd30276339812..8735b10255ae3 100644
--- a/mlir/lib/Dialect/MemRef/Utils/MemRefUtils.cpp
+++ b/mlir/lib/Dialect/MemRef/Utils/MemRefUtils.cpp
@@ -156,16 +156,14 @@ static bool resultIsNotRead(Operation *op, std::vector<Operation *> &uses) {
 
 void eraseDeadAllocAndStores(RewriterBase &rewriter, Operation *parentOp) {
   std::vector<Operation *> opToErase;
-  auto collectOpsToErase = [&](Operation *op) {
+  parentOp->walk([&](Operation *op) {
     std::vector<Operation *> candidates;
-    if (resultIsNotRead(op, candidates)) {
+    if (isa<memref::AllocOp, memref::AllocaOp>(op) &&
+        resultIsNotRead(op, candidates)) {
       llvm::append_range(opToErase, candidates);
       opToErase.push_back(op);
     }
-  };
-
-  parentOp->walk([&](memref::AllocOp op) { collectOpsToErase(op); });
-  parentOp->walk([&](memref::AllocaOp op) { collectOpsToErase(op); });
+  });
 
   for (Operation *op : opToErase)
     rewriter.eraseOp(op);



More information about the Mlir-commits mailing list