Skip to content

Commit 4a77110

Browse files
author
Stephan Herhut
committed
[mlir][bufferize] Fix buffer promotion to stack for index types
The index type does not have a bitsize and hence the size of corresponding allocations cannot be computed. Instead, the promotion pass now has an explicit option to specify the size of index. Differential Revision: https://reviews.llvm.org/D91360
1 parent 5da2423 commit 4a77110

File tree

4 files changed

+46
-14
lines changed

4 files changed

+46
-14
lines changed

mlir/include/mlir/Transforms/Passes.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,10 @@ std::unique_ptr<Pass> createBufferHoistingPass();
4141
std::unique_ptr<Pass> createBufferLoopHoistingPass();
4242

4343
/// Creates a pass that promotes heap-based allocations to stack-based ones.
44+
/// Only buffers smaller than the provided size are promoted.
4445
std::unique_ptr<Pass>
45-
createPromoteBuffersToStackPass(unsigned maxAllocSizeInBytes = 1024);
46+
createPromoteBuffersToStackPass(unsigned maxAllocSizeInBytes = 1024,
47+
unsigned bitwidthOfIndexType = 64);
4648

4749
/// Creates a pass that converts memref function results to out-params.
4850
std::unique_ptr<Pass> createBufferResultsToOutParamsPass();

mlir/include/mlir/Transforms/Passes.td

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,10 @@ def PromoteBuffersToStack : FunctionPass<"promote-buffers-to-stack"> {
214214
Option<"maxAllocSizeInBytes", "max-alloc-size-in-bytes", "unsigned",
215215
/*default=*/"1024",
216216
"Define the maximum size in bytes to promote allocations to stack.">,
217+
Option<"bitwidthOfIndexType", "bitwidth-of-index-type", "unsigned",
218+
/*default=*/"64",
219+
"Define the bitwidth of the index type. Used for size estimation.">,
220+
217221
];
218222
}
219223

mlir/lib/Transforms/BufferOptimizations.cpp

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,16 @@ static bool isKnownControlFlowInterface(Operation *op) {
2929
/// Check if the size of the allocation is less than the given size. The
3030
/// transformation is only applied to small buffers since large buffers could
3131
/// exceed the stack space.
32-
static bool isSmallAlloc(Value alloc, unsigned maximumSizeInBytes) {
32+
static bool isSmallAlloc(Value alloc, unsigned maximumSizeInBytes,
33+
unsigned bitwidthOfIndexType) {
3334
auto type = alloc.getType().dyn_cast<ShapedType>();
3435
if (!type || !type.hasStaticShape())
3536
return false;
36-
return type.getSizeInBits() < maximumSizeInBytes * 8;
37+
// For index types, use the provided size, as the type does not know.
38+
unsigned int bitwidth = type.getElementType().isIndex()
39+
? bitwidthOfIndexType
40+
: type.getElementTypeBitWidth();
41+
return type.getNumElements() * bitwidth <= maximumSizeInBytes * 8;
3742
}
3843

3944
/// Checks whether the given aliases leave the allocation scope.
@@ -281,14 +286,15 @@ class BufferPlacementPromotion : BufferPlacementTransformationBase {
281286
: BufferPlacementTransformationBase(op) {}
282287

283288
/// Promote buffers to stack-based allocations.
284-
void promote(unsigned maximumSize) {
289+
void promote(unsigned maximumSize, unsigned bitwidthOfIndexType) {
285290
for (BufferPlacementAllocs::AllocEntry &entry : allocs) {
286291
Value alloc = std::get<0>(entry);
292+
Operation *dealloc = std::get<1>(entry);
287293
// Checking several requirements to transform an AllocOp into an AllocaOp.
288294
// The transformation is done if the allocation is limited to a given
289295
// size. Furthermore, a deallocation must not be defined for this
290296
// allocation entry and a parent allocation scope must exist.
291-
if (!isSmallAlloc(alloc, maximumSize) || std::get<1>(entry) ||
297+
if (!isSmallAlloc(alloc, maximumSize, bitwidthOfIndexType) || dealloc ||
292298
!hasAllocationScope(alloc, aliases))
293299
continue;
294300

@@ -340,17 +346,17 @@ struct BufferLoopHoistingPass : BufferLoopHoistingBase<BufferLoopHoistingPass> {
340346
struct PromoteBuffersToStackPass
341347
: PromoteBuffersToStackBase<PromoteBuffersToStackPass> {
342348

343-
PromoteBuffersToStackPass(unsigned maxAllocSizeInBytes)
344-
: maximumSize(maxAllocSizeInBytes) {}
349+
PromoteBuffersToStackPass(unsigned maxAllocSizeInBytes,
350+
unsigned bitwidthOfIndexType) {
351+
this->maxAllocSizeInBytes = maxAllocSizeInBytes;
352+
this->bitwidthOfIndexType = bitwidthOfIndexType;
353+
}
345354

346355
void runOnFunction() override {
347356
// Move all allocation nodes and convert candidates into allocas.
348357
BufferPlacementPromotion optimizer(getFunction());
349-
optimizer.promote(maximumSize);
358+
optimizer.promote(this->maxAllocSizeInBytes, this->bitwidthOfIndexType);
350359
}
351-
352-
private:
353-
const unsigned maximumSize;
354360
};
355361

356362
} // end anonymous namespace
@@ -364,6 +370,8 @@ std::unique_ptr<Pass> mlir::createBufferLoopHoistingPass() {
364370
}
365371

366372
std::unique_ptr<Pass>
367-
mlir::createPromoteBuffersToStackPass(unsigned maxAllocSizeInBytes) {
368-
return std::make_unique<PromoteBuffersToStackPass>(maxAllocSizeInBytes);
373+
mlir::createPromoteBuffersToStackPass(unsigned maxAllocSizeInBytes,
374+
unsigned bitwidthOfIndexType) {
375+
return std::make_unique<PromoteBuffersToStackPass>(maxAllocSizeInBytes,
376+
bitwidthOfIndexType);
369377
}

mlir/test/Transforms/promote-buffers-to-stack.mlir

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
// RUN: mlir-opt -promote-buffers-to-stack -split-input-file %s | FileCheck %s
1+
// RUN: mlir-opt -promote-buffers-to-stack -split-input-file %s | FileCheck %s --check-prefix=CHECK --check-prefix DEFINDEX
2+
// RUN: mlir-opt -promote-buffers-to-stack="bitwidth-of-index-type=256 max-alloc-size-in-bytes=128" -split-input-file %s | FileCheck %s --check-prefix=CHECK --check-prefix BIGINDEX
3+
// RUN: mlir-opt -promote-buffers-to-stack="bitwidth-of-index-type=256 max-alloc-size-in-bytes=64" -split-input-file %s | FileCheck %s --check-prefix=CHECK --check-prefix LOWLIMIT
24

35
// This file checks the behavior of PromoteBuffersToStack pass for converting
46
// AllocOps into AllocaOps, if possible.
@@ -566,3 +568,19 @@ func @large_buffer_allocation(%arg0: memref<2048xf32>) {
566568

567569
// CHECK-NEXT: %[[ALLOC:.*]] = alloc()
568570
// CHECK-NEXT: test.copy
571+
572+
// -----
573+
574+
// Test Case: AllocOp with element type index.
575+
// PromoteBuffersToStack expected behavior: It should convert it to an
576+
// AllocaOp.
577+
578+
// CHECK-LABEL: func @indexElementType
579+
func @indexElementType() {
580+
%0 = alloc() : memref<4xindex>
581+
return
582+
}
583+
// DEFINDEX-NEXT: alloca()
584+
// BIGINDEX-NEXT: alloca()
585+
// LOWLIMIT-NEXT: alloc()
586+
// CHECK-NEXT: return

0 commit comments

Comments
 (0)