[Mlir-commits] [mlir] [mlir][llvm] Fix SROA crash on empty LLVM struct types (PR #184596)

llvmlistbot at llvm.org llvmlistbot at llvm.org
Wed Mar 4 03:56:13 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-mlir

Author: Mehdi Amini (joker-eph)

<details>
<summary>Changes</summary>

When SROA runs on an alloca of an empty struct type (llvm.struct<()>), it crashes with:

  Assertion `\!subelementIndexMap->empty()' failed.

The root cause is in LLVMStructType::getSubelementIndexMap(): for an empty struct (no body fields), the loop doesn't execute and an empty DenseMap is returned as a non-null optional. Later, getTypeAtIndex() asserts the map is non-empty, triggering the crash.

Fix this by returning std::nullopt for empty structs, indicating they cannot be destructured. This is consistent with how LLVMArrayType handles the zero-element case.

Fixes #<!-- -->108366

---
Full diff: https://github.com/llvm/llvm-project/pull/184596.diff


2 Files Affected:

- (modified) mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp (+3) 
- (modified) mlir/test/Dialect/LLVMIR/sroa.mlir (+15) 


``````````diff
diff --git a/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp b/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp
index 7d9058c262562..8f3c0dac026a7 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp
@@ -1585,6 +1585,9 @@ DeletionKind LLVM::MemmoveOp::rewire(const DestructurableMemorySlot &slot,
 
 std::optional<DenseMap<Attribute, Type>>
 LLVM::LLVMStructType::getSubelementIndexMap() const {
+  // Empty structs have no sub-elements and cannot be destructured.
+  if (getBody().empty())
+    return std::nullopt;
   Type i32 = IntegerType::get(getContext(), 32);
   DenseMap<Attribute, Type> destructured;
   for (const auto &[index, elemType] : llvm::enumerate(getBody()))
diff --git a/mlir/test/Dialect/LLVMIR/sroa.mlir b/mlir/test/Dialect/LLVMIR/sroa.mlir
index 1674bbd8c796f..b019e66d5a430 100644
--- a/mlir/test/Dialect/LLVMIR/sroa.mlir
+++ b/mlir/test/Dialect/LLVMIR/sroa.mlir
@@ -448,3 +448,18 @@ llvm.func @out_of_bound_gep_array_access(%arg: i32) {
   llvm.store %arg, %2 : i32, !llvm.ptr
   llvm.return
 }
+
+// -----
+
+// Regression test: SROA must not crash when processing an alloca of an empty
+// struct type. Empty structs have no sub-elements and cannot be destructured,
+// so the alloca must be left unchanged.
+// https://github.com/llvm/llvm-project/issues/108366
+// CHECK-LABEL: llvm.func @empty_struct_not_destructured
+llvm.func @empty_struct_not_destructured() -> !llvm.struct<()> {
+  %0 = llvm.mlir.constant(1 : i32) : i32
+  // CHECK: llvm.alloca %{{.*}} x !llvm.struct<()>
+  %1 = llvm.alloca %0 x !llvm.struct<()> : (i32) -> !llvm.ptr
+  %2 = llvm.load %1 : !llvm.ptr -> !llvm.struct<()>
+  llvm.return %2 : !llvm.struct<()>
+}

``````````

</details>


https://github.com/llvm/llvm-project/pull/184596


More information about the Mlir-commits mailing list