Skip to content

[mlir][linalg] BufferizeToAllocationOp: fix side effects #72986

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

Conversation

matthias-springer
Copy link
Member

@matthias-springer matthias-springer commented Nov 21, 2023

bufferize_to_allocation does not bufferize/replace targeted ops if bufferize_destination_only is set.

Fixes #72931.

`bufferize_to_allocation` does not bufferize/replace ops if `bufferize_destination_only` is set.
@llvmbot
Copy link
Member

llvmbot commented Nov 21, 2023

@llvm/pr-subscribers-mlir-linalg

Author: Matthias Springer (matthias-springer)

Changes

bufferize_to_allocation does not bufferize/replace targeted ops if bufferize_destination_only is set.

Fixes #72931.


Full diff: https://github.com/llvm/llvm-project/pull/72986.diff

1 Files Affected:

  • (modified) mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp (+7-1)
diff --git a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
index de4965f937162ea..ef5d88d46dd28a0 100644
--- a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
+++ b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
@@ -289,7 +289,13 @@ DiagnosedSilenceableFailure transform::BufferizeToAllocationOp::apply(
 
 void transform::BufferizeToAllocationOp::getEffects(
     SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
-  consumesHandle(getTarget(), effects);
+  if (getBufferizeDestinationOnly()) {
+    // The destination is replaced with a newly allocated buffer, but the op
+    // itself remains in place.
+    onlyReadsHandle(getTarget(), effects);
+  } else {
+    consumesHandle(getTarget(), effects);
+  }
   producesHandle(getAllocatedBuffer(), effects);
   producesHandle(getNewOps(), effects);
   modifiesPayload(effects);

@llvmbot
Copy link
Member

llvmbot commented Nov 21, 2023

@llvm/pr-subscribers-mlir

Author: Matthias Springer (matthias-springer)

Changes

bufferize_to_allocation does not bufferize/replace targeted ops if bufferize_destination_only is set.

Fixes #72931.


Full diff: https://github.com/llvm/llvm-project/pull/72986.diff

1 Files Affected:

  • (modified) mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp (+7-1)
diff --git a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
index de4965f937162ea..ef5d88d46dd28a0 100644
--- a/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
+++ b/mlir/lib/Dialect/Linalg/TransformOps/LinalgTransformOps.cpp
@@ -289,7 +289,13 @@ DiagnosedSilenceableFailure transform::BufferizeToAllocationOp::apply(
 
 void transform::BufferizeToAllocationOp::getEffects(
     SmallVectorImpl<MemoryEffects::EffectInstance> &effects) {
-  consumesHandle(getTarget(), effects);
+  if (getBufferizeDestinationOnly()) {
+    // The destination is replaced with a newly allocated buffer, but the op
+    // itself remains in place.
+    onlyReadsHandle(getTarget(), effects);
+  } else {
+    consumesHandle(getTarget(), effects);
+  }
   producesHandle(getAllocatedBuffer(), effects);
   producesHandle(getNewOps(), effects);
   modifiesPayload(effects);

@matthias-springer matthias-springer merged commit 6367677 into llvm:main Nov 23, 2023
matthias-springer added a commit to matthias-springer/llvm-project that referenced this pull request Nov 28, 2023
When running with "expensive checks", the transform dialect interpreter
maintains a payload `Operation *` -> `OperationName` cache. This cache
is used to detect invalid API usage such as missing/incorrect handle
consumption/production side effects and/or payload IR modifications that
bypass the rewriter.

There was a bug in the check that can cause issues such as llvm#72931.
(llvm#72986 was just a workaround and did not really fix the underlying
issue.)

- Payload ops mapped to newly produced handles are now added to the
  cache. This is in addition to adding/checking all mapped payload ops
  at the beginning of each transform op, for extra safety.
- Remove consumed ops (and their children) before applying the transform
  op. This used to happen after applying the transform op, which is
  incorrect in cases such as: (1) transform op replaces a consumed
  payload op with another op, (2) the new op reuses the same memory
  pointer and (3) the new op is added to a newly produced handle. In
  such a case the previous implementation removed the newly created op
  from the cache.
- No assumptions can be made about whether an op should be in the cache
  or not. The code previously reported an error when an op was not found
  in the cache. E.g., this is problematic in cases such as: (1) the
  transform op consumes the handle mapped to a payload op A and (2) the
  implementation of the payload op removes/replaces a nested op with A,
  which is mapped to another handle. This triggers a listener
  notification, which removes the nested op from the cache. However,
  because consumed ops (and their children) are removed from the cache
  before applying the transform op, the nested op will not be in cache
  and making such an assumption would be incorrect.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Failing test case with transform dialect due to potentially mis-tracked operation.
3 participants