[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