Skip to content
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

[mlir][bufferization] Add deallocation option to remove existing dealloc operations, add option to specify the kind of alloc operations to consider #67556

Open
wants to merge 2 commits into
base: main
Choose a base branch
from

Conversation

maerhart
Copy link
Member

Depends on #66626
Only review top commit.

@llvmbot llvmbot added mlir:core MLIR Core Infrastructure mlir:linalg mlir mlir:bufferization Bufferization infrastructure mlir:arith labels Sep 27, 2023
…ction boundary ABI

Inserting clones requires a lot of assumptions to hold on the input IR, e.g.,
all writes to a buffer need to dominate all reads. This is not guaranteed by
one-shot bufferization and isn't easy to verify, thus it could quickly lead to
incorrect results that are hard to debug. This commit changes the mechanism of
how an ownership indicator is materialized when there is not already a unique
ownership present. Additionally, we don't create copies of returned memrefs
anymore when we don't have ownership. Instead, we insert assert operations to
make sure we have ownership at runtime, or otherwise report to the user that
correctness could not be guaranteed.
…loc operations, add option to specify the kind of alloc operations to consider
/// ownership will be set to 'false', i.e., it will be leaked. This is useful
/// to support deallocation of multiple different kinds of allocation ops.
DetectionFn isRelevantAllocOp = [](Operation *op) {
return isa<memref::MemRefDialect, bufferization::BufferizationDialect>(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the bufferization dialect in here? Can we just check for memref.alloc/memref.alloca in here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

BufferizationDialect is here because of bufferization.clone which has an allocation side-effect as well.

@@ -106,6 +111,48 @@ struct DeallocationOptions {
/// to, an error will already be emitted at compile time. This cannot be
/// changed with this option.
bool verifyFunctionBoundaryABI = true;

/// Given an allocation side-effect on the passed operation, determine whether
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given an operation with an allocation side effect

op->getDialect());
};

/// Given a free side-effect on the passed operation, determine whether this
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given an operation with a free side effect

PassOptions::Option<bool> removeExistingDeallocations{
*this, "remove-existing-deallocations",
llvm::cl::desc("Removes all pre-existing memref.dealloc operations and "
"insert all deallocations according to the buffer "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think just Removes pre-existing memref.dealloc operations should be enough.

@@ -233,6 +233,11 @@ def OwnershipBasedBufferDeallocation : Pass<
"If it can be determined statically that the ABI is not adhered "
"to, an error will already be emitted at compile time. This cannot "
"be changed with this option.">,
Option<"removeExistingDeallocations", "remove-existing-deallocations",
"bool", /*default=*/"false",
"Remove already existing MemRef deallocation operations and let the "
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

}

// Alloc operations from other dialects are expected to have matching
// deallocation operations inserted by another pass.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

inserted by a separate run of this pass


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()) {
// Assuming that an alloc effect is interpreted as MUST and not MAY.
state.resetOwnerships(res, block);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this doing?


WalkResult result = getOperation()->walk([&](FunctionOpInterface funcOp) {
// Deallocate the `memref.alloc` operations.
bufferization::DeallocationOptions options;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comment that by default the deallocation options are configured to look for memref.alloc/memref.dealloc only.

}
return ValueRange{};
}
return failure();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can be llvm_unreachable("expected gpu.dealloc op")? Then you could also make the gpuDealloc a cast<DeallocOp> and you won't need the "if" check.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mlir:arith mlir:bufferization Bufferization infrastructure mlir:core MLIR Core Infrastructure mlir:linalg mlir
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants