[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