[Mlir-commits] [mlir] f8453ea - [mlir][linalg][bufferize] Rewrite "write into non-writable memory" detection

Matthias Springer llvmlistbot at llvm.org
Fri Oct 8 05:28:52 PDT 2021


Author: Matthias Springer
Date: 2021-10-08T21:27:49+09:00
New Revision: f8453ea75fe3d8777357f1075ca28bc1ffc60503

URL: https://github.com/llvm/llvm-project/commit/f8453ea75fe3d8777357f1075ca28bc1ffc60503
DIFF: https://github.com/llvm/llvm-project/commit/f8453ea75fe3d8777357f1075ca28bc1ffc60503.diff

LOG: [mlir][linalg][bufferize] Rewrite "write into non-writable memory" detection

The purpose of this revision is to make "write into non-writable memory" conflict detection easier to understand.

The main idea is that there is a conflict in the case of inplace bufferization if:

1. Someone writes to (an alias of) opOperand, opResult or the to-be-bufferized op writes itself.
2. And, opOperand or opResult aliases a non-writable buffer.

Differential Revision: https://reviews.llvm.org/D111379

Added: 
    

Modified: 
    mlir/include/mlir/Dialect/Linalg/Transforms/ComprehensiveBufferize.h
    mlir/lib/Dialect/Linalg/Transforms/ComprehensiveBufferize.cpp
    mlir/test/Dialect/Linalg/comprehensive-module-bufferize-analysis.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/Linalg/Transforms/ComprehensiveBufferize.h b/mlir/include/mlir/Dialect/Linalg/Transforms/ComprehensiveBufferize.h
index c10dfdeff126..078c84998ff3 100644
--- a/mlir/include/mlir/Dialect/Linalg/Transforms/ComprehensiveBufferize.h
+++ b/mlir/include/mlir/Dialect/Linalg/Transforms/ComprehensiveBufferize.h
@@ -84,6 +84,10 @@ class BufferizationAliasInfo {
       Operation *opToBufferize, DenseSet<OpOperand *> &usesRead,
       DenseSet<OpOperand *> &usesWrite, const DominanceInfo &domInfo) const;
 
+  /// Return true if bufferizing `opResult` inplace would create a write to a
+  /// non-writable buffer.
+  bool wouldCreateWriteToNonWritableBuffer(OpResult opResult) const;
+
   /// Assume that result bufferizes in-place with one of the operation's
   /// operands. Return true if it is possible to find an inplace write W (resp.
   /// a read R) among the uses of `aliasInfo[result]`, and a read R (resp. an

diff  --git a/mlir/lib/Dialect/Linalg/Transforms/ComprehensiveBufferize.cpp b/mlir/lib/Dialect/Linalg/Transforms/ComprehensiveBufferize.cpp
index 0d735825cf70..7acff2607be8 100644
--- a/mlir/lib/Dialect/Linalg/Transforms/ComprehensiveBufferize.cpp
+++ b/mlir/lib/Dialect/Linalg/Transforms/ComprehensiveBufferize.cpp
@@ -972,6 +972,34 @@ bool BufferizationAliasInfo::wouldCreateReadAfterWriteInterference(
                                                usesWrite, domInfo);
 }
 
+/// Return true if bufferizing `opResult` inplace would create a write to a
+/// non-writable buffer.
+bool BufferizationAliasInfo::wouldCreateWriteToNonWritableBuffer(
+    OpResult opResult) const {
+  Optional<OpOperand *> maybeAliasingOperand = getAliasingOpOperand(opResult);
+  if (!maybeAliasingOperand || !*maybeAliasingOperand)
+    return false;
+
+  // Certain buffers are not writeable:
+  //   1. A function bbArg that is not inplaceable or
+  //   2. A constant op.
+  assert(!aliasesNonWritableBuffer(opResult) &&
+         "expected that opResult does not alias non-writable buffer");
+  bool nonWritable = aliasesNonWritableBuffer((*maybeAliasingOperand)->get());
+  if (!nonWritable)
+    return false;
+
+  // This is a problem only if the buffer is written to via some alias.
+  bool hasWrite = aliasesInPlaceWrite(opResult) ||
+                  aliasesInPlaceWrite((*maybeAliasingOperand)->get()) ||
+                  bufferizesToMemoryWrite(**maybeAliasingOperand);
+  if (!hasWrite)
+    return false;
+
+  LDBG("->the corresponding buffer is not writeable\n");
+  return true;
+}
+
 /// Return true if the source of a `insertSliceOp` bufferizes to an
 /// equivalent ExtractSliceOp that bufferizes inplace.
 bool BufferizationAliasInfo::isSourceEquivalentToAMatchingInplaceExtractSliceOp(
@@ -2231,23 +2259,14 @@ bufferizableInPlaceAnalysis(ExtractSliceOp extractSliceOp,
   LDBG("Inplace analysis for extract_slice: "
        << printOperationInfo(extractSliceOp) << '\n');
 
-  // If `extractSliceOp` were to be bufferized inplace, it cannot end up
-  // aliasing a write into a non-writable buffer.
-  bool wouldCreateAliasingWriteToNonWritableBuffer =
-      aliasInfo.aliasesInPlaceWrite(extractSliceOp.result()) &&
-      aliasInfo.aliasesNonWritableBuffer(extractSliceOp.source());
-
-  if (wouldCreateAliasingWriteToNonWritableBuffer)
-    LDBG("->the corresponding buffer is not writable\n");
-  else
-    LDBG("->bufferizes to writable inplace buffer\n");
-
-  // In any of extractSliceOp.result's aliases, can we find 2 such that we hit
-  // an interfering write?
   OpResult r = extractSliceOp->getResult(0);
   OpOperand &s = extractSliceOp->getOpOperand(0);
   bool foundInterference =
-      wouldCreateAliasingWriteToNonWritableBuffer ||
+      /* If `extractSliceOp` were to be bufferized inplace, it cannot end up
+         aliasing a write into a non-writable buffer.*/
+      aliasInfo.wouldCreateWriteToNonWritableBuffer(r) ||
+      /* In any of extractSliceOp.result's aliases, can we find 2 such that we
+         hit an interfering write? */
       aliasInfo.wouldCreateReadAfterWriteInterference(r, domInfo);
   if (foundInterference)
     aliasInfo.bufferizeOutOfPlace(r);
@@ -2282,20 +2301,8 @@ bufferizableInPlaceAnalysis(OpOperand &operand,
                                    << operand.getOperandNumber() << " in "
                                    << printValueInfo(result) << '\n');
 
-  // `result` must bufferize to a writable buffer to be a candidate.
-  // This means the operand  must not alias either:
-  //   1. a function bbArg that is not inplaceable or
-  //   2. a constant op.
-  // to be considered for inplace bufferization
-  bool wouldCreateAliasingWriteToNonWritableBuffer =
-      aliasInfo.aliasesNonWritableBuffer(operand.get());
-  if (wouldCreateAliasingWriteToNonWritableBuffer)
-    LDBG("->the corresponding buffer is not writable\n");
-  else
-    LDBG("->bufferizes to writable inplace buffer\n");
-
   bool foundInterference =
-      wouldCreateAliasingWriteToNonWritableBuffer ||
+      aliasInfo.wouldCreateWriteToNonWritableBuffer(result) ||
       aliasInfo.wouldCreateReadAfterWriteInterference(result, domInfo);
 
   if (foundInterference)

diff  --git a/mlir/test/Dialect/Linalg/comprehensive-module-bufferize-analysis.mlir b/mlir/test/Dialect/Linalg/comprehensive-module-bufferize-analysis.mlir
index effb510a49b6..2a406acfeef8 100644
--- a/mlir/test/Dialect/Linalg/comprehensive-module-bufferize-analysis.mlir
+++ b/mlir/test/Dialect/Linalg/comprehensive-module-bufferize-analysis.mlir
@@ -620,10 +620,28 @@ func @read_dependence_through_scf_and_call(
   return
 }
 
+// -----
+
 //===----------------------------------------------------------------------===//
 // Transitive cases through extract_slice.
 //===----------------------------------------------------------------------===//
 
+// CHECK-LABEL: func @write_into_constant_via_alias
+func @write_into_constant_via_alias(%v : vector<5xi32>,
+                                    %s1 : index, %s2 : index,
+                                    %s3 : index) -> tensor<?xi32> {
+  %A = constant dense<[1, 2, 3, 4]> : tensor<4xi32>
+  //      CHECK: tensor.extract_slice
+  // CHECK-SAME: {__inplace_results_attr__ = ["false"]}
+  %b = tensor.extract_slice %A[%s1][%s2][1] : tensor<4xi32> to tensor<?xi32>
+  //      CHECK: vector.transfer_write
+  // CHECK-SAME: {__inplace_results_attr__ = ["true"]}
+  %r = vector.transfer_write %v, %b[%s3] : vector<5xi32>, tensor<?xi32>
+  return %r : tensor<?xi32>
+}
+
+// -----
+
 builtin.func @matmul_on_tensors(
     %arg0: tensor<518x518xf32> {linalg.buffer_layout = affine_map<(d0, d1) -> (d0, d1)>, linalg.inplaceable = false},
     %arg1: tensor<518x518xf32> {linalg.buffer_layout = affine_map<(d0, d1) -> (d0, d1)>, linalg.inplaceable = false},


        


More information about the Mlir-commits mailing list