[Mlir-commits] [mlir] 0ed130a - [mlir][memref] Fix mem2reg crash on zero-extent alloca (#216851)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Wed Aug 19 08:59:43 PDT 2026


Author: Alessandro Potenza
Date: 2026-08-19T17:59:37+02:00
New Revision: 0ed130af5b5fe60d8633d0b2c4226c7d86966db4

URL: https://github.com/llvm/llvm-project/commit/0ed130af5b5fe60d8633d0b2c4226c7d86966db4
DIFF: https://github.com/llvm/llvm-project/commit/0ed130af5b5fe60d8633d0b2c4226c7d86966db4.diff

LOG: [mlir][memref] Fix mem2reg crash on zero-extent alloca (#216851)

`memref` allows a zero extent, but vector types require strictly
positive ones.
Since #211880, `AllocaOp::getPromotableSlots` builds a `VectorType` from
the
memref shape, so `mlir-opt --mem2reg` asserts on

```mlir
func.func @z() { %a = memref.alloca() : memref<0xf32>  return }
```

Bail out of whole-buffer promotion when the shape contains a zero
extent. The
scalable path needs `*c > 0` rather than `!= 0`, since
`VectorType::verify`
rejects `<= 0`.

Assisted-by: Claude (Anthropic)

AI-assisted, disclosed per the LLVM AI Tool Use Policy.

Added: 
    

Modified: 
    mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp
    mlir/test/Dialect/MemRef/mem2reg.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp b/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp
index a832b0c47809b..cfcca90b2b969 100644
--- a/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp
+++ b/mlir/lib/Dialect/MemRef/IR/MemRefMemorySlot.cpp
@@ -103,18 +103,25 @@ SmallVector<MemorySlot> memref::AllocaOp::getPromotableSlots() {
   // is only ever accessed as a whole buffer (e.g. through whole-buffer
   // `vector.transfer_read`/`vector.transfer_write`).
   if (VectorType::isValidElementType(type.getElementType())) {
+    // Vector types require strictly positive extents, so a memref with a zero
+    // extent has nothing to promote.
+    if (llvm::is_contained(type.getShape(), 0))
+      return {};
+
     // Static shape: a fixed-size vector of the same extents.
     if (type.hasStaticShape())
       return {MemorySlot{getResult(), VectorType::get(type.getShape(),
                                                       type.getElementType())}};
 
-    // A 1-D memref whose single dynamic extent is `vector.vscale * C` maps to a
-    // scalable `vector<[C]x...>` slot.
+    // A 1-D memref whose single dynamic extent is `vector.vscale * N` maps to a
+    // scalable `vector<[N]x...>` slot, for a strictly positive multiple `N`.
     if (type.getRank() == 1 && type.isDynamicDim(0)) {
-      if (std::optional<int64_t> c = matchVScaleMultiple(getDynamicSizes()[0]))
-        return {
-            MemorySlot{getResult(), VectorType::get({*c}, type.getElementType(),
-                                                    /*scalableDims=*/{true})}};
+      if (std::optional<int64_t> multiple =
+              matchVScaleMultiple(getDynamicSizes()[0]);
+          multiple && *multiple > 0)
+        return {MemorySlot{getResult(),
+                           VectorType::get({*multiple}, type.getElementType(),
+                                           /*scalableDims=*/{true})}};
     }
   }
 

diff  --git a/mlir/test/Dialect/MemRef/mem2reg.mlir b/mlir/test/Dialect/MemRef/mem2reg.mlir
index 8f937c4efe75e..ba26b5f984a27 100644
--- a/mlir/test/Dialect/MemRef/mem2reg.mlir
+++ b/mlir/test/Dialect/MemRef/mem2reg.mlir
@@ -309,3 +309,37 @@ func.func @two_consecutive_merge_points(%cond1: i1, %cond2: i1) -> i32 {
   // CHECK: return %[[RESULT]] : i32
   return %result : i32
 }
+
+// -----
+
+// A memref with a zero extent holds no elements and cannot be promoted.
+
+// CHECK-LABEL: func.func @zero_extent_alloca
+func.func @zero_extent_alloca() {
+  // CHECK: memref.alloca() : memref<0xf32>
+  %alloca = memref.alloca() : memref<0xf32>
+  return
+}
+
+// -----
+
+// CHECK-LABEL: func.func @zero_extent_alloca_multi_dim
+func.func @zero_extent_alloca_multi_dim() {
+  // CHECK: memref.alloca() : memref<2x0x3xf32>
+  %alloca = memref.alloca() : memref<2x0x3xf32>
+  return
+}
+
+// -----
+
+// A memref with a `vector.vscale * 0` extent holds no elements and cannot be promoted.
+
+// CHECK-LABEL: func.func @scalable_zero_extent_alloca
+func.func @scalable_zero_extent_alloca() {
+  %vscale = vector.vscale
+  %c0 = arith.constant 0 : index
+  %size = arith.muli %vscale, %c0 : index
+  // CHECK: memref.alloca(%{{.*}}) : memref<?xf32>
+  %alloca = memref.alloca(%size) : memref<?xf32>
+  return
+}


        


More information about the Mlir-commits mailing list