diff options
| author | Uday Bondhugula <bondhugula@google.com> | 2019-02-11 16:33:53 -0800 |
|---|---|---|
| committer | jpienaar <jpienaar@google.com> | 2019-03-29 16:24:08 -0700 |
| commit | 8b3f841daf3ad728eab81c73b8fafdc050627fa6 (patch) | |
| tree | 87ea816e56dd331f72ec4d9c2a7bc86cf5a36a11 /mlir/lib/Transforms/PipelineDataTransfer.cpp | |
| parent | f5eed89df06fbaf8c1dc7241bbbcfba8b5dea6ea (diff) | |
| download | bcm5719-llvm-8b3f841daf3ad728eab81c73b8fafdc050627fa6.tar.gz bcm5719-llvm-8b3f841daf3ad728eab81c73b8fafdc050627fa6.zip | |
Generate dealloc's for the alloc's of dma-generate.
- for the DMA buffers being allocated (and their tags), generate corresponding deallocs
- minor related update to replaceAllMemRefUsesWith and PipelineDataTransfer pass
Code generation for DMA transfers was being done with the initial simplifying
assumption that the alloc's would map to scoped allocations, and so no
deallocations would be necessary. Drop this assumption to generalize. Note that
even with scoped allocations, unrolling loops that have scoped allocations
could create a series of allocations and exhaustion of fast memory. Having a
end of lifetime marker like a dealloc in fact allows creating new scopes if
necessary when lowering to a backend and still utilize scoped allocation.
DMA buffers created by -dma-generate are guaranteed to have either
non-overlapping lifetimes or nested lifetimes.
PiperOrigin-RevId: 233502632
Diffstat (limited to 'mlir/lib/Transforms/PipelineDataTransfer.cpp')
| -rw-r--r-- | mlir/lib/Transforms/PipelineDataTransfer.cpp | 21 |
1 files changed, 16 insertions, 5 deletions
diff --git a/mlir/lib/Transforms/PipelineDataTransfer.cpp b/mlir/lib/Transforms/PipelineDataTransfer.cpp index cfa045f2279..5c2e38205e7 100644 --- a/mlir/lib/Transforms/PipelineDataTransfer.cpp +++ b/mlir/lib/Transforms/PipelineDataTransfer.cpp @@ -124,8 +124,9 @@ static bool doubleBuffer(Value *oldMemRef, OpPointer<AffineForOp> forOp) { // replaceAllMemRefUsesWith will always succeed unless the forOp body has // non-deferencing uses of the memref. - if (!replaceAllMemRefUsesWith(oldMemRef, newMemRef, {ivModTwoOp}, AffineMap(), - {}, &*forOp->getBody()->begin())) { + if (!replaceAllMemRefUsesWith( + oldMemRef, newMemRef, {ivModTwoOp}, AffineMap(), {}, + /*domInstFilter=*/&*forOp->getBody()->begin())) { LLVM_DEBUG(llvm::dbgs() << "memref replacement for double buffering failed\n";); ivModTwoOp->getInstruction()->erase(); @@ -284,10 +285,20 @@ PipelineDataTransfer::runOnAffineForOp(OpPointer<AffineForOp> forOp) { // If the old memref has no more uses, remove its 'dead' alloc if it was // alloc'ed. (note: DMA buffers are rarely function live-in; but a 'dim' // operation could have been used on it if it was dynamically shaped in - // order to create the double buffer above) - if (oldMemRef->use_empty()) - if (auto *allocInst = oldMemRef->getDefiningInst()) + // order to create the double buffer above.) + // '-canonicalize' does this in a more general way, but we'll anyway do the + // simple/common case so that the output / test cases looks clear. + if (auto *allocInst = oldMemRef->getDefiningInst()) { + if (oldMemRef->use_empty()) { allocInst->erase(); + } else if (oldMemRef->hasOneUse()) { + auto *singleUse = oldMemRef->use_begin()->getOwner(); + if (singleUse->isa<DeallocOp>()) { + singleUse->erase(); + oldMemRef->getDefiningInst()->erase(); + } + } + } } // Double the buffers for tag memrefs. |

