Skip to content

Commit 252e255

Browse files
authored
[MLIR][LLVM][SROA] Avoid splitting dynamically indexed allocas (#85758)
This commit ensures that SROA does no longer attempt to split allocas that are indexed into dynamically. Dynamic indices into arrays are allowed to be negative or out-of-bounds, when the alloca containing the array has memory backing these produced indices.
1 parent 081a66f commit 252e255

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

mlir/lib/Dialect/LLVMIR/IR/LLVMMemorySlot.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,10 @@ LogicalResult LLVM::GEPOp::ensureOnlySafeAccesses(
344344
return failure();
345345
if (!isFirstIndexZero(*this))
346346
return failure();
347+
// Dynamic indices can be out-of-bounds (even negative), so an access with
348+
// dynamic indices can never be considered safe.
349+
if (!getDynamicIndices().empty())
350+
return failure();
347351
Type reachedType = getResultPtrElementType();
348352
if (!reachedType)
349353
return failure();
@@ -362,6 +366,10 @@ bool LLVM::GEPOp::canRewire(const DestructurableMemorySlot &slot,
362366
return false;
363367
if (!isFirstIndexZero(*this))
364368
return false;
369+
// Dynamic indices can be out-of-bounds (even negative), so an access with
370+
// dynamic indices can never be properly rewired.
371+
if (!getDynamicIndices().empty())
372+
return false;
365373
Type reachedType = getResultPtrElementType();
366374
if (!reachedType || getIndices().size() < 2)
367375
return false;

mlir/test/Dialect/LLVMIR/sroa.mlir

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,3 +197,21 @@ llvm.func @no_dynamic_indexing(%arg: i32) -> i32 {
197197
// CHECK: llvm.return %[[RES]] : i32
198198
llvm.return %3 : i32
199199
}
200+
201+
// -----
202+
203+
// CHECK-LABEL: llvm.func @no_nested_dynamic_indexing
204+
// CHECK-SAME: (%[[ARG:.*]]: i32)
205+
llvm.func @no_nested_dynamic_indexing(%arg: i32) -> i32 {
206+
// CHECK: %[[SIZE:.*]] = llvm.mlir.constant(1 : i32)
207+
%0 = llvm.mlir.constant(1 : i32) : i32
208+
// CHECK: %[[ALLOCA:.*]] = llvm.alloca %[[SIZE]] x !llvm.struct<(array<10 x i32>, i32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr
209+
%1 = llvm.alloca %0 x !llvm.struct<(array<10 x i32>, i32)> {alignment = 8 : i64} : (i32) -> !llvm.ptr
210+
// CHECK-NOT: = llvm.alloca
211+
// CHECK: %[[GEP:.*]] = llvm.getelementptr %[[ALLOCA]][0, 0, %[[ARG]]]
212+
%2 = llvm.getelementptr %1[0, 0, %arg] : (!llvm.ptr, i32) -> !llvm.ptr, !llvm.struct<(array<10 x i32>, i32)>
213+
// CHECK: %[[RES:.*]] = llvm.load %[[GEP]]
214+
%3 = llvm.load %2 : !llvm.ptr -> i32
215+
// CHECK: llvm.return %[[RES]] : i32
216+
llvm.return %3 : i32
217+
}

0 commit comments

Comments
 (0)