-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[mlir][bufferization] Ownership-based deallocation: Allow manual (de)allocs #68648
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ | |
#include "mlir/Dialect/Bufferization/IR/BufferDeallocationOpInterface.h" | ||
#include "mlir/Dialect/Bufferization/IR/Bufferization.h" | ||
#include "mlir/Dialect/Bufferization/Transforms/Passes.h" | ||
#include "mlir/Dialect/ControlFlow/IR/ControlFlowOps.h" | ||
#include "mlir/Dialect/Func/IR/FuncOps.h" | ||
#include "mlir/Dialect/MemRef/IR/MemRef.h" | ||
#include "mlir/Dialect/SCF/IR/SCF.h" | ||
|
@@ -856,13 +857,32 @@ FailureOr<Operation *> BufferDeallocation::handleInterface(CallOpInterface op) { | |
FailureOr<Operation *> | ||
BufferDeallocation::handleInterface(MemoryEffectOpInterface op) { | ||
auto *block = op->getBlock(); | ||
OpBuilder builder = OpBuilder::atBlockBegin(block); | ||
|
||
for (auto operand : llvm::make_filter_range(op->getOperands(), isMemref)) | ||
if (op.getEffectOnValue<MemoryEffects::Free>(operand).has_value()) | ||
return op->emitError( | ||
"memory free side-effect on MemRef value not supported!"); | ||
for (auto operand : llvm::make_filter_range(op->getOperands(), isMemref)) { | ||
if (op.getEffectOnValue<MemoryEffects::Free>(operand).has_value()) { | ||
if (!op->hasAttr(BufferizationDialect::kManualDeallocation)) | ||
return op->emitError( | ||
"memory free side-effect on MemRef value not supported!"); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't quite get this message here? It does not seems to relate to the conditions that lead here, or am I missing something? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is one of the things that confused me in #72289. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The buffer deallocation pass fails if there are any "free" side effects (memory deallocations) in the input IR. We cannot handle such input programs at the moment. There is one exception: Existing buffer deallocation ops are allowed if they are annotated with In essence, The code here checks if the op has a free side effect. If that is the case and there is no |
||
|
||
// Buffers that were allocated under "manual deallocation" may be | ||
// manually deallocated. We insert a runtime assertion to cover certain | ||
// cases of invalid IR where an automatically managed buffer allocation | ||
// is manually deallocated. This is not a bulletproof check! | ||
OpBuilder::InsertionGuard g(builder); | ||
builder.setInsertionPoint(op); | ||
Ownership ownership = state.getOwnership(operand, block); | ||
if (ownership.isUnique()) { | ||
Value ownershipInverted = builder.create<arith::XOrIOp>( | ||
op.getLoc(), ownership.getIndicator(), | ||
buildBoolValue(builder, op.getLoc(), true)); | ||
builder.create<cf::AssertOp>( | ||
op.getLoc(), ownershipInverted, | ||
"expected that the block does not have ownership"); | ||
} | ||
} | ||
} | ||
|
||
OpBuilder builder = OpBuilder::atBlockBegin(block); | ||
for (auto res : llvm::make_filter_range(op->getResults(), isMemref)) { | ||
auto allocEffect = op.getEffectOnValue<MemoryEffects::Allocate>(res); | ||
if (allocEffect.has_value()) { | ||
|
@@ -880,6 +900,15 @@ BufferDeallocation::handleInterface(MemoryEffectOpInterface op) { | |
continue; | ||
} | ||
|
||
if (op->hasAttr(BufferizationDialect::kManualDeallocation)) { | ||
// This allocation will be deallocated manually. Assign an ownership of | ||
// "false", so that it will never be deallocated by the buffer | ||
// deallocation pass. | ||
state.resetOwnerships(res, block); | ||
state.updateOwnership(res, buildBoolValue(builder, op.getLoc(), false)); | ||
continue; | ||
} | ||
|
||
state.updateOwnership(res, buildBoolValue(builder, op.getLoc(), true)); | ||
state.addMemrefToDeallocate(res, block); | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do we want to repeat the doc in both td and cpp ?