[Mlir-commits] [mlir] a02ad6c - [mlir][bufferization] Generalize getAliasingOpResults to getAliasingValues

Matthias Springer llvmlistbot at llvm.org
Tue Aug 15 06:03:14 PDT 2023


Author: Matthias Springer
Date: 2023-08-15T15:02:47+02:00
New Revision: a02ad6c1773368c9ce67d3a28578bf6284c6c1be

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

LOG: [mlir][bufferization] Generalize getAliasingOpResults to getAliasingValues

This revision is needed to support bufferization of `cf.br`/`cf.cond_br`. It will also be useful for better analysis of loop ops.

This revision generalizes `getAliasingOpResults` to `getAliasingValues`. An OpOperand can now not only alias with OpResults but also with BlockArguments. In the case of `cf.br` (will be added in a later revision): a `cf.br` operand will alias with the corresponding argument of the destination block.

If an op does not implement the `BufferizableOpInterface`, the analysis in conservative. It previously assumed that an OpOperand may alias with each OpResult. It now assumes that an OpOperand may alias with each OpResult and each BlockArgument of the entry block.

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

Added: 
    

Modified: 
    mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h
    mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.td
    mlir/include/mlir/Dialect/Bufferization/IR/BufferizationOps.td
    mlir/include/mlir/Dialect/Bufferization/IR/DstBufferizableOpInterfaceImpl.h
    mlir/lib/Dialect/Arith/Transforms/BufferizableOpInterfaceImpl.cpp
    mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp
    mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp
    mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp
    mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp
    mlir/lib/Dialect/MemRef/Transforms/BufferizableOpInterfaceImpl.cpp
    mlir/lib/Dialect/SCF/Transforms/BufferizableOpInterfaceImpl.cpp
    mlir/lib/Dialect/Shape/Transforms/BufferizableOpInterfaceImpl.cpp
    mlir/lib/Dialect/SparseTensor/Transforms/BufferizableOpInterfaceImpl.cpp
    mlir/lib/Dialect/Tensor/Transforms/BufferizableOpInterfaceImpl.cpp
    mlir/lib/Dialect/Vector/Transforms/BufferizableOpInterfaceImpl.cpp
    mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis.mlir

Removed: 
    


################################################################################
diff  --git a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h
index 9cde7740066e59..7f758e492d89eb 100644
--- a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h
+++ b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h
@@ -49,14 +49,13 @@ struct AliasingOpOperand {
   bool isDefinite;
 };
 
-/// A maybe aliasing OpResult. If `isDefinite` is `true`, the OpResult is
-/// guaranteed to alias at runtime.
-struct AliasingOpResult {
-  AliasingOpResult(OpResult opResult, BufferRelation relation,
-                   bool isDefinite = true)
-      : opResult(opResult), relation(relation), isDefinite(isDefinite) {}
+/// A maybe aliasing Value. If `isDefinite` is `true`, the Value is guaranteed
+/// to alias at runtime.
+struct AliasingValue {
+  AliasingValue(Value value, BufferRelation relation, bool isDefinite = true)
+      : value(value), relation(relation), isDefinite(isDefinite) {}
 
-  OpResult opResult;
+  Value value;
   BufferRelation relation;
   bool isDefinite;
 };
@@ -90,12 +89,12 @@ template <typename T> class AliasList {
 };
 
 /// A list of possible aliasing OpOperands. This list models the runtime
-/// aliasing relationship for an OpResult.
+/// aliasing relationship for a Value.
 using AliasingOpOperandList = AliasList<AliasingOpOperand>;
 
-/// A list of possible aliasing OpResults. This list models the runtime
-/// aliasing relationship for an OpOperand.
-using AliasingOpResultList = AliasList<AliasingOpResult>;
+/// A list of possible aliasing Values. This list models the runtime aliasing
+/// relationship for an OpOperand.
+using AliasingValueList = AliasList<AliasingValue>;
 
 class OpFilter {
 public:
@@ -418,15 +417,14 @@ struct TraversalConfig {
 /// tensor values.
 class AnalysisState {
 public:
-  /// Determine which OpOperand* will alias with `result` if the op is
+  /// Determine which OpOperand* will alias with `value` if the op is
   /// bufferized in place. Return all tensor OpOperand* if the op is not
   /// bufferizable.
-  AliasingOpOperandList getAliasingOpOperands(OpResult result) const;
+  AliasingOpOperandList getAliasingOpOperands(Value value) const;
 
-  /// Determine which OpResult will alias with `opOperand` if the op is
-  /// bufferized in place. Return all tensor OpResults if the op is not
-  /// bufferizable.
-  AliasingOpResultList getAliasingOpResults(OpOperand &opOperand) const;
+  /// Determine which Value will alias with `opOperand` if the op is bufferized
+  /// in place. Return all tensor Values if the op is not bufferizable.
+  AliasingValueList getAliasingValues(OpOperand &opOperand) const;
 
   /// Return true if `opOperand` bufferizes to a memory read. Return `true` if
   /// the op is not bufferizable.
@@ -685,7 +683,7 @@ namespace detail {
 /// This is the default implementation of
 /// BufferizableOpInterface::getAliasingOpOperands. Should not be called from
 /// other places.
-AliasingOpOperandList defaultGetAliasingOpOperands(OpResult opResult,
+AliasingOpOperandList defaultGetAliasingOpOperands(Value value,
                                                    const AnalysisState &state);
 
 /// This is the default implementation of
@@ -709,11 +707,11 @@ bool defaultIsRepetitiveRegion(BufferizableOpInterface bufferizableOp,
 
 /// This is the default implementation of getAliasingOpOperands in case the
 /// defining op does not implement the BufferizableOpInterface.
-AliasingOpOperandList unknownGetAliasingOpOperands(OpResult opResult);
+AliasingOpOperandList unknownGetAliasingOpOperands(Value value);
 
-/// This is the default implementation of getAliasingOpResults in case the
-/// owner op does not implement the BufferizableOpInterface.
-AliasingOpResultList unknownGetAliasingOpResults(OpOperand &opOperand);
+/// This is the default implementation of getAliasingValues in case the owner
+/// op does not implement the BufferizableOpInterface.
+AliasingValueList unknownGetAliasingValues(OpOperand &opOperand);
 } // namespace detail
 
 } // namespace bufferization

diff  --git a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.td b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.td
index df8c08c0031e24..6a349f34ef1fbd 100644
--- a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.td
+++ b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizableOpInterface.td
@@ -18,23 +18,23 @@ def BufferizableOpInterface : OpInterface<"BufferizableOpInterface"> {
 
     Note: All "bufferizesTo*" and "getAliasing*" interface methods must be
     implemented conservatively. If it is not statically known whether an
-    OpOperand/OpResult bufferizes in a certain way (e.g., to a memory write),
+    OpOperand/Value bufferizes in a certain way (e.g., to a memory write),
     the worst case must be assumed (e.g., that it does). Similarly,
     "getAliasing*" interface methods may always return additional OpOperands or
-    OpResults, but must not miss an OpOperand or OpResult that could potentially
+    Values, but must not miss an OpOperand or Value that could potentially
     alias at runtime.
   }];
   let cppNamespace = "::mlir::bufferization";
   let methods = [
       InterfaceMethod<
         /*desc=*/[{
-          Return `true` if the given OpResult may bufferize to a new buffer
-          allocation. If it is statically unknown if the given OpResult
+          Return `true` if the given Value may bufferize to a new buffer
+          allocation. If it is statically unknown that the given Value
           bufferizes to a buffer allocation, `true` should be returned.
         }],
         /*retType=*/"bool",
         /*methodName=*/"bufferizesToAllocation",
-        /*args=*/(ins "::mlir::OpResult":$opResult),
+        /*args=*/(ins "::mlir::Value":$value),
         /*methodBody=*/"",
         /*defaultImplementation=*/"return false;"
       >,
@@ -68,10 +68,9 @@ def BufferizableOpInterface : OpInterface<"BufferizableOpInterface"> {
           tensor type.
 
           This method will never be called on OpOperands that do not have an
-          aliasing OpResult. Intuitively, it does not make sense for an
-          OpOperand to bufferize to a memory write without returning an aliasing
-          tensor, because the write would have no visible effect outside of the
-          op.
+          aliasing Value. Intuitively, it does not make sense for an OpOperand
+          to bufferize to a memory write without returning an aliasing tensor,
+          because the write would have no visible effect outside of the op.
 
           Note: It is always safe to consider an OpOperand as a memory write,
           even if it does actually not write; however, this can introduce
@@ -87,7 +86,7 @@ def BufferizableOpInterface : OpInterface<"BufferizableOpInterface"> {
         /*defaultImplementation=*/[{
           // Does not have to be implemented for ops without tensor OpOperands.
           // Does not have to be implemented for OpOperands that do not have an
-          // aliasing OpResult.
+          // aliasing Value.
           llvm_unreachable("bufferizesToMemoryWrite not implemented");
          }]
       >,
@@ -221,21 +220,21 @@ def BufferizableOpInterface : OpInterface<"BufferizableOpInterface"> {
       >,
       InterfaceMethod<
         /*desc=*/[{
-          Return the OpResults that may alias with a given OpOperand when
+          Return the Values that may alias with a given OpOperand when
           bufferized in-place. This method will never be called on OpOperands
           that do not have a tensor type.
 
-          This method can return multiple OpResults, indicating that a given
+          This method can return multiple Values, indicating that a given
           OpOperand may at runtime alias with any (or multiple) of the returned
-          OpResults.
+          Values.
 
           Each alias is specified with a degree of certainty:
 
           * MAYBE (`isDefinite = false`): At runtime, buffer(opOperand) may
-            alias with the specified OpResult.
+            alias with the specified Value.
           * DEFINITE (`isDefinite = true`, default): At runtime,
             buffer(opOperand) is guaranteed to alias the buffer of the specified
-            OpResult. This is a stronger property than MAYBE and allows for more
+            Value. This is a stronger property than MAYBE and allows for more
             precise analyses. DEFINITE properties should be used when possible.
 
           Furthermore, each alias is specified with a buffer relation:
@@ -245,39 +244,39 @@ def BufferizableOpInterface : OpInterface<"BufferizableOpInterface"> {
           * `BufferRelation::Unknown`: There is no further information apart
             from the fact that both buffers alias.
 
-          False positives are allowed in the list of OpResults, but they can
+          False positives are allowed in the list of Values, but they can
           adversely affect the accuracy of the anlysis. On the contrary,
           omitting potential aliases is incorrect.
 
           One possible (conservative) implementation of this interface method,
-          that is always safe, is to return all tensor OpResults with
+          that is always safe, is to return all tensor Values with
           BufferRelation::Unknown and MAYBE.
 
           Examples:
 
           ```
-          // aliasingOpResults(%t) = DEFINITE {Equivalent %r}
+          // aliasingValues(%t) = DEFINITE {Equivalent %r}
           %r = tensor.insert_slice %f into %t : tensor<10xf32>
 
-          // aliasingOpResults(%t) = DEFINITE {Unknown %r}
+          // aliasingValues(%t) = DEFINITE {Unknown %r}
           // Note: "Buffer is subset of buffer" relationship are not yet
           // supported, so "Unknown" is the best we can do for now.
           %r = tensor.extract_slice %t[0]][5][1]
               : tensor<10xf32> to tensor<5xf32>
 
-          // aliasingOpResults(%t1) = MAYBE {Equivalent %r}
-          // aliasingOpResults(%t2) = MAYBE {Equivalent %r}
+          // aliasingValues(%t1) = MAYBE {Equivalent %r}
+          // aliasingValues(%t2) = MAYBE {Equivalent %r}
           %r = arith.select %c, %t1, %t2 : tensor<10xf32>
 
           // A hypothetical op that bufferizes to rolling a dice and based on
           // the result to either return buffer(%t) or a newly allocated copy
           // thereof.
-          // aliasingOpResults(%t) = MAYBE {Equivalent %r}
+          // aliasingValues(%t) = MAYBE {Equivalent %r}
           %r = "dummy.alias_or_copy(%t) : (tensor<10xf32>) -> (tensor<10xf32>)"
           ```
         }],
-        /*retType=*/"::mlir::bufferization::AliasingOpResultList",
-        /*methodName=*/"getAliasingOpResults",
+        /*retType=*/"::mlir::bufferization::AliasingValueList",
+        /*methodName=*/"getAliasingValues",
         /*args=*/(ins "::mlir::OpOperand &":$opOperand,
                       "const ::mlir::bufferization::AnalysisState &":$state),
         /*methodBody=*/"",
@@ -285,29 +284,29 @@ def BufferizableOpInterface : OpInterface<"BufferizableOpInterface"> {
           // Does not have to be implemented for ops without tensor OpOperands.
           assert(::llvm::isa<::mlir::TensorType>(opOperand.get().getType()) &&
                  "expected OpOperand with tensor type");
-          llvm_unreachable("getAliasingOpResults not implemented");
+          llvm_unreachable("getAliasingValues not implemented");
         }]
       >,
       InterfaceMethod<
         /*desc=*/[{
-          Return the OpOperands that alias with a given OpResult when
-          bufferized in-place. This method will never be called on OpResults
-          that do not have a tensor type.
+          Return the OpOperands that alias with a given Value when bufferized
+          in-place. This method will never be called on Values that do not
+          have a tensor type.
 
-          By default, this method is the inverse of `getAliasingOpResults`. Ops
+          By default, this method is the inverse of `getAliasingValues`. Ops
           with a region that yield values may want to override this method to
           return the OpOperands that are yielded by the terminator.
 
           This method can return multiple OpOperands, indicating that a given
-          OpResult may at runtime alias with any (or multiple) of the returned
+          Value may at runtime alias with any (or multiple) of the returned
           OpOperands.
 
           This property is specified with a degree of certainty:
 
-          * MAYBE (`isDefinite = false`): At runtime, buffer(opResult) may
-            alias with the specified OpOperand.
+          * MAYBE (`isDefinite = false`): At runtime, buffer(value) may alias
+            with the specified OpOperand.
           * DEFINITE (`isDefinite = true`, default): At runtime,
-            buffer(opResult) is guaranteed to alias the buffer of the specified
+            buffer(value) is guaranteed to alias the buffer of the specified
             OpOperand. This is a stronger property than MAYBE and allows for
             more precise analyses. DEFINITE properties should be used when
             possible.
@@ -350,14 +349,14 @@ def BufferizableOpInterface : OpInterface<"BufferizableOpInterface"> {
         }],
         /*retType=*/"::mlir::bufferization::AliasingOpOperandList",
         /*methodName=*/"getAliasingOpOperands",
-        /*args=*/(ins "::mlir::OpResult":$opResult,
+        /*args=*/(ins "::mlir::Value":$value,
                       "const ::mlir::bufferization::AnalysisState &":$state),
         /*methodBody=*/"",
         /*defaultImplementation=*/[{
-          assert(::llvm::isa<::mlir::TensorType>(opResult.getType()) &&
-                 "expected OpResult with tensor type");
+          assert(isa<::mlir::TensorType>(value.getType()) &&
+                 "expected tensor type");
           return ::mlir::bufferization::detail::defaultGetAliasingOpOperands(
-              opResult, state);
+              value, state);
         }]
       >,
       InterfaceMethod<
@@ -568,7 +567,7 @@ def BufferizableOpInterface : OpInterface<"BufferizableOpInterface"> {
           ::llvm::cast<::mlir::bufferization::BufferizableOpInterface>(getOperation());
       return !bufferizableOp.bufferizesToMemoryRead(opOperand, state)
           && !bufferizableOp.bufferizesToMemoryWrite(opOperand, state)
-          && bufferizableOp.getAliasingOpResults(opOperand, state)
+          && bufferizableOp.getAliasingValues(opOperand, state)
               .getNumAliases() != 0;
     }
   }];

diff  --git a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizationOps.td b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizationOps.td
index 8a4fea27a45629..d62f781a01b003 100644
--- a/mlir/include/mlir/Dialect/Bufferization/IR/BufferizationOps.td
+++ b/mlir/include/mlir/Dialect/Bufferization/IR/BufferizationOps.td
@@ -95,7 +95,7 @@ def Bufferization_AllocTensorOp : Bufferization_Op<"alloc_tensor",
     bool resultBufferizesToMemoryWrite(OpResult opResult,
                                        const AnalysisState &state);
 
-    bool bufferizesToAllocation(OpResult opResult) { return true; }
+    bool bufferizesToAllocation(Value value) { return true; }
 
     bool bufferizesToMemoryRead(OpOperand &opOperand,
                                 const AnalysisState &state);
@@ -103,7 +103,7 @@ def Bufferization_AllocTensorOp : Bufferization_Op<"alloc_tensor",
     bool bufferizesToMemoryWrite(OpOperand &opOperand,
                                  const AnalysisState &state);
 
-    AliasingOpResultList getAliasingOpResults(
+    AliasingValueList getAliasingValues(
         OpOperand &opOperand, const AnalysisState &state);
 
     FailureOr<BaseMemRefType> getBufferType(
@@ -237,7 +237,7 @@ def Bufferization_CopyTensorOp : Bufferization_Op<"copy_tensor",
     bool bufferizesToMemoryWrite(OpOperand &opOperand,
                                  const AnalysisState &state);
 
-    AliasingOpResultList getAliasingOpResults(
+    AliasingValueList getAliasingValues(
         OpOperand &opOperand, const AnalysisState &state);
 
     RankedTensorType getType() {
@@ -295,7 +295,7 @@ def Bufferization_DeallocTensorOp : Bufferization_Op<"dealloc_tensor",
       return false;
     }
 
-    AliasingOpResultList getAliasingOpResults(
+    AliasingValueList getAliasingValues(
         OpOperand &opOperand, const AnalysisState &state) const {
       return {};
     }
@@ -459,7 +459,7 @@ def Bufferization_ToMemrefOp : Bufferization_Op<"to_memref", [
       return !getReadOnly();
     }
 
-    AliasingOpResultList getAliasingOpResults(
+    AliasingValueList getAliasingValues(
         OpOperand &opOperand, const AnalysisState &state) const {
       return {};
     }

diff  --git a/mlir/include/mlir/Dialect/Bufferization/IR/DstBufferizableOpInterfaceImpl.h b/mlir/include/mlir/Dialect/Bufferization/IR/DstBufferizableOpInterfaceImpl.h
index 9652c2d6d4cd84..bd0d1c99397957 100644
--- a/mlir/include/mlir/Dialect/Bufferization/IR/DstBufferizableOpInterfaceImpl.h
+++ b/mlir/include/mlir/Dialect/Bufferization/IR/DstBufferizableOpInterfaceImpl.h
@@ -36,8 +36,8 @@ struct DstBufferizableOpInterfaceExternalModel
     return dstOp.isDpsInit(&opOperand);
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     // Output operands alias with their respective tied OpResults.
     auto dstOp = cast<DestinationStyleOpInterface>(op);
     if (dstOp.isDpsInit(&opOperand))

diff  --git a/mlir/lib/Dialect/Arith/Transforms/BufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/Arith/Transforms/BufferizableOpInterfaceImpl.cpp
index bda230bfaea640..ddc5ce54040f65 100644
--- a/mlir/lib/Dialect/Arith/Transforms/BufferizableOpInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/Arith/Transforms/BufferizableOpInterfaceImpl.cpp
@@ -76,8 +76,8 @@ struct IndexCastOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {{op->getResult(0), BufferRelation::Equivalent}};
   }
 
@@ -123,8 +123,8 @@ struct SelectOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {{op->getOpResult(0) /*result*/, BufferRelation::Equivalent,
              /*isDefinite=*/false}};
   }

diff  --git a/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp b/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp
index 701ac5cdc07d9f..1427037619e591 100644
--- a/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp
+++ b/mlir/lib/Dialect/Bufferization/IR/BufferizableOpInterface.cpp
@@ -209,9 +209,9 @@ LogicalResult BufferizableOpInterface::resolveTensorOpOperandConflicts(
   SmallVector<OpOperand *> outOfPlaceOpOperands;
   DenseSet<OpOperand *> copiedOpOperands;
   DenseSet<OpOperand *> escapingOpOperandCopies;
-  SmallVector<OpResult> outOfPlaceOpResults;
-  DenseSet<OpResult> copiedOpResults;
-  DenseSet<OpResult> escapingOpResultCopies;
+  SmallVector<Value> outOfPlaceValues;
+  DenseSet<Value> copiedOpValues;
+  DenseSet<Value> escapingValueCopies;
 
   // Find all out-of-place OpOperands.
   for (OpOperand &opOperand : op->getOpOperands()) {
@@ -223,34 +223,33 @@ LogicalResult BufferizableOpInterface::resolveTensorOpOperandConflicts(
     if (llvm::isa<UnrankedTensorType>(operandType))
       return op->emitError("copying of unranked tensors is not implemented");
 
-    AliasingOpResultList aliasingOpResults =
-        state.getAliasingOpResults(opOperand);
+    AliasingValueList aliasingValues = state.getAliasingValues(opOperand);
     // Is the result yielded from a block? Or are deallocations turned off
     // entirely? In either case, mark the allocation as "escaping", so that it
     // will not be deallocated.
     bool escape = !state.getOptions().createDeallocs ||
-                  llvm::any_of(aliasingOpResults, [&](AliasingOpResult a) {
-                    return state.isTensorYielded(a.opResult);
+                  llvm::any_of(aliasingValues, [&](AliasingValue a) {
+                    return state.isTensorYielded(a.value);
                   });
 
-    if (aliasingOpResults.getNumAliases() == 1 &&
+    if (aliasingValues.getNumAliases() == 1 &&
         !state.bufferizesToMemoryWrite(opOperand) &&
-        state.getAliasingOpOperands(aliasingOpResults.getAliases()[0].opResult)
+        state.getAliasingOpOperands(aliasingValues.getAliases()[0].value)
                 .getNumAliases() == 1 &&
-        !llvm::isa<UnrankedTensorType>(
-            aliasingOpResults.getAliases()[0].opResult.getType())) {
+        !isa<UnrankedTensorType>(
+            aliasingValues.getAliases()[0].value.getType())) {
       // The op itself does not write but may create exactly one alias. Instead
       // of copying the OpOperand, copy the OpResult. The OpResult can sometimes
       // be smaller than the OpOperand (e.g., in the case of an extract_slice,
       // where the result is usually a smaller part of the source). Do not apply
       // this optimization if the OpResult is an unranked tensor (because those
       // cannot be copied at the moment).
-      OpResult opResult = aliasingOpResults.getAliases()[0].opResult;
-      outOfPlaceOpResults.push_back(opResult);
+      Value value = aliasingValues.getAliases()[0].value;
+      outOfPlaceValues.push_back(value);
       if (!state.canOmitTensorCopy(opOperand))
-        copiedOpResults.insert(opResult);
+        copiedOpValues.insert(value);
       if (escape)
-        escapingOpResultCopies.insert(opResult);
+        escapingValueCopies.insert(value);
     } else {
       // In all other cases, make a copy of the OpOperand.
       outOfPlaceOpOperands.push_back(&opOperand);
@@ -273,17 +272,16 @@ LogicalResult BufferizableOpInterface::resolveTensorOpOperandConflicts(
     rewriter.updateRootInPlace(op, [&]() { opOperand->set(*copy); });
   }
 
-  // Insert copies of OpResults.
+  // Insert copies of Values.
   rewriter.setInsertionPointAfter(op);
-  for (OpResult opResult : outOfPlaceOpResults) {
+  for (Value value : outOfPlaceValues) {
     FailureOr<Value> copy = allocateTensorForShapedValue(
-        rewriter, op->getLoc(), opResult,
-        escapingOpResultCopies.contains(opResult), state.getOptions(),
-        copiedOpResults.count(opResult));
+        rewriter, op->getLoc(), value, escapingValueCopies.contains(value),
+        state.getOptions(), copiedOpValues.count(value));
     if (failed(copy))
       return failure();
-    SmallVector<OpOperand *> uses = llvm::to_vector(llvm::map_range(
-        opResult.getUses(), [](OpOperand &use) { return &use; }));
+    SmallVector<OpOperand *> uses = llvm::to_vector(
+        llvm::map_range(value.getUses(), [](OpOperand &use) { return &use; }));
     for (OpOperand *use : uses) {
       // Do not update the alloc_tensor op that we just created.
       if (use->getOwner() == copy->getDefiningOp())
@@ -425,29 +423,26 @@ static void setInsertionPointAfter(OpBuilder &b, Value value) {
   }
 }
 
-/// Determine which OpOperand* will alias with `opResult` if the op is
-/// bufferized in place. Return all tensor OpOperand* if the op is not
-/// bufferizable.
-AliasingOpOperandList
-AnalysisState::getAliasingOpOperands(OpResult opResult) const {
-  if (Operation *op = opResult.getDefiningOp())
+/// Determine which OpOperand* will alias with `value` if the op is bufferized
+/// in place. Return all tensor OpOperand* if the op is not bufferizable.
+AliasingOpOperandList AnalysisState::getAliasingOpOperands(Value value) const {
+  if (Operation *op = getOwnerOfValue(value))
     if (auto bufferizableOp = getOptions().dynCastBufferizableOp(op))
-      return bufferizableOp.getAliasingOpOperands(opResult, *this);
+      return bufferizableOp.getAliasingOpOperands(value, *this);
 
   // The op is not bufferizable.
-  return detail::unknownGetAliasingOpOperands(opResult);
+  return detail::unknownGetAliasingOpOperands(value);
 }
 
-/// Determine which OpResult will alias with `opOperand` if the op is bufferized
-/// in place. Return all tensor OpResults if the op is not bufferizable.
-AliasingOpResultList
-AnalysisState::getAliasingOpResults(OpOperand &opOperand) const {
+/// Determine which Values will alias with `opOperand` if the op is bufferized
+/// in place. Return all tensor Values if the op is not bufferizable.
+AliasingValueList AnalysisState::getAliasingValues(OpOperand &opOperand) const {
   if (auto bufferizableOp =
           getOptions().dynCastBufferizableOp(opOperand.getOwner()))
-    return bufferizableOp.getAliasingOpResults(opOperand, *this);
+    return bufferizableOp.getAliasingValues(opOperand, *this);
 
   // The op is not bufferizable.
-  return detail::unknownGetAliasingOpResults(opOperand);
+  return detail::unknownGetAliasingValues(opOperand);
 }
 
 /// Return true if `opOperand` bufferizes to a memory read. Return `true` if the
@@ -509,8 +504,8 @@ bool AnalysisState::isValueRead(Value value) const {
     OpOperand *uMaybeReading = workingSet.pop_back_val();
     // Skip over all ops that neither read nor write (but create an alias).
     if (bufferizesToAliasOnly(*uMaybeReading))
-      for (AliasingOpResult alias : getAliasingOpResults(*uMaybeReading))
-        for (OpOperand &use : alias.opResult.getUses())
+      for (AliasingValue alias : getAliasingValues(*uMaybeReading))
+        for (OpOperand &use : alias.value.getUses())
           workingSet.push_back(&use);
     if (bufferizesToMemoryRead(*uMaybeReading))
       return true;
@@ -536,16 +531,7 @@ llvm::SetVector<Value> AnalysisState::findValueInReverseUseDefChain(
       continue;
     }
 
-    if (llvm::isa<BlockArgument>(value)) {
-      if (config.alwaysIncludeLeaves)
-        result.insert(value);
-      continue;
-    }
-
-    OpResult opResult = llvm::cast<OpResult>(value);
-    BufferizableOpInterface bufferizableOp =
-        options.dynCastBufferizableOp(opResult.getDefiningOp());
-    if (!config.followUnknownOps && !bufferizableOp) {
+    if (!config.followUnknownOps && !options.dynCastBufferizableOp(value)) {
       // Stop iterating if `followUnknownOps` is unset and the op is either
       // not bufferizable or excluded in the OpFilter.
       if (config.alwaysIncludeLeaves)
@@ -553,7 +539,7 @@ llvm::SetVector<Value> AnalysisState::findValueInReverseUseDefChain(
       continue;
     }
 
-    AliasingOpOperandList aliases = getAliasingOpOperands(opResult);
+    AliasingOpOperandList aliases = getAliasingOpOperands(value);
     if (aliases.getNumAliases() == 0) {
       // The traversal ends naturally if there are no more OpOperands that
       // could be followed.
@@ -582,7 +568,7 @@ llvm::SetVector<Value> AnalysisState::findValueInReverseUseDefChain(
 
       if (config.followSameTypeOrCastsOnly &&
           a.opOperand->get().getType() != value.getType() &&
-          !opResult.getDefiningOp<CastOpInterface>()) {
+          !value.getDefiningOp<CastOpInterface>()) {
         // Stop iterating if `followSameTypeOrCastsOnly` is set but the alias is
         // has a 
diff erent type and the op is not a cast.
         if (config.alwaysIncludeLeaves)
@@ -626,10 +612,10 @@ bool AnalysisState::canOmitTensorCopy(OpOperand &opOperand) const {
     return true;
 
   // Do not copy if the tensor is never read.
-  AliasingOpResultList aliases = getAliasingOpResults(opOperand);
+  AliasingValueList aliases = getAliasingValues(opOperand);
   if (!bufferizesToMemoryRead(opOperand) &&
-      llvm::none_of(
-          aliases, [&](AliasingOpResult a) { return isValueRead(a.opResult); }))
+      llvm::none_of(aliases,
+                    [&](AliasingValue a) { return isValueRead(a.value); }))
     return true;
 
   // Default: Cannot omit the copy.
@@ -693,12 +679,12 @@ bool AnalysisState::isTensorYielded(Value tensor) const {
     if (isa<RegionBranchTerminatorOpInterface>(op))
       return true;
 
-    // Add all aliasing OpResults to the worklist.
+    // Add all aliasing Values to the worklist.
     // Note: In the absence of detailed analysis information (e.g., there may be
-    // no function call analysis information), this `getAliasingOpResult` is
-    // conservative and may report additional OpResults as potentially aliasing.
-    for (AliasingOpResult alias : getAliasingOpResults(*operand))
-      for (OpOperand &use : alias.opResult.getUses())
+    // no function call analysis information), this `getAliasingValues` is
+    // conservative and may report additional Values as potentially aliasing.
+    for (AliasingValue alias : getAliasingValues(*operand))
+      for (OpOperand &use : alias.value.getUses())
         worklist.push_back(&use);
   }
 
@@ -991,19 +977,18 @@ bool bufferization::detail::defaultResultBufferizesToMemoryWrite(
   return false;
 }
 
-// Compute the AliasingOpOperandList for a given OpResult based on
-// getAliasingOpResults.
+// Compute the AliasingOpOperandList for a given Value based on
+// getAliasingValues.
 AliasingOpOperandList bufferization::detail::defaultGetAliasingOpOperands(
-    OpResult opResult, const AnalysisState &state) {
-  Operation *op = opResult.getDefiningOp();
+    Value value, const AnalysisState &state) {
+  Operation *op = getOwnerOfValue(value);
   SmallVector<AliasingOpOperand> result;
   for (OpOperand &opOperand : op->getOpOperands()) {
     if (!llvm::isa<TensorType>(opOperand.get().getType()))
       continue;
-    AliasingOpResultList aliasingOpResults =
-        state.getAliasingOpResults(opOperand);
-    for (const auto &it : aliasingOpResults)
-      if (it.opResult == opResult)
+    AliasingValueList aliasingValues = state.getAliasingValues(opOperand);
+    for (const auto &it : aliasingValues)
+      if (it.value == value)
         result.emplace_back(&opOperand, it.relation, it.isDefinite);
   }
   return AliasingOpOperandList(std::move(result));
@@ -1051,21 +1036,37 @@ bool bufferization::detail::defaultIsRepetitiveRegion(
 }
 
 AliasingOpOperandList
-bufferization::detail::unknownGetAliasingOpOperands(OpResult opResult) {
-  // Conservatively assume that everything may be aliasing.
+bufferization::detail::unknownGetAliasingOpOperands(Value value) {
+  // TODO: Take into account successor blocks.
+  // No aliasing in case of non-entry blocks.
+  if (auto bbArg = dyn_cast<BlockArgument>(value))
+    if (bbArg.getOwner() != &bbArg.getOwner()->getParent()->getBlocks().front())
+      return {};
+
+  // Unknown op: Conservatively assume that each OpResult may alias with every
+  // OpOperand. In addition, each block argument of an entry block may alias
+  // with every OpOperand.
   AliasingOpOperandList r;
-  for (OpOperand &operand : opResult.getDefiningOp()->getOpOperands())
-    if (llvm::isa<TensorType>(operand.get().getType()))
+  for (OpOperand &operand : value.getDefiningOp()->getOpOperands())
+    if (isa<TensorType>(operand.get().getType()))
       r.addAlias({&operand, BufferRelation::Unknown, /*isDefinite=*/false});
   return r;
 }
 
-AliasingOpResultList
-bufferization::detail::unknownGetAliasingOpResults(OpOperand &opOperand) {
-  // Conservatively assume that everything may be aliasing.
-  AliasingOpResultList r;
+AliasingValueList
+bufferization::detail::unknownGetAliasingValues(OpOperand &opOperand) {
+  // TODO: Take into account successor blocks.
+  // Unknown op: Conservatively assume that each OpResult may alias with every
+  // OpOperand. In addition, each block argument of an entry block may alias
+  // with every OpOperand.
+  AliasingValueList r;
   for (OpResult result : opOperand.getOwner()->getOpResults())
     if (llvm::isa<TensorType>(result.getType()))
       r.addAlias({result, BufferRelation::Unknown, /*isDefinite=*/false});
+  for (Region &region : opOperand.getOwner()->getRegions())
+    if (!region.getBlocks().empty())
+      for (BlockArgument bbArg : region.getBlocks().front().getArguments())
+        if (bbArg.getType().isa<TensorType>())
+          r.addAlias({bbArg, BufferRelation::Unknown, /*isDefinite=*/false});
   return r;
 }

diff  --git a/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp b/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp
index bc6f2cd29523a3..e16cfcead1c37d 100644
--- a/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp
+++ b/mlir/lib/Dialect/Bufferization/IR/BufferizationOps.cpp
@@ -224,9 +224,8 @@ bool AllocTensorOp::bufferizesToMemoryWrite(OpOperand &opOperand,
   return false;
 }
 
-AliasingOpResultList
-AllocTensorOp::getAliasingOpResults(OpOperand &opOperand,
-                                    const AnalysisState &state) {
+AliasingValueList AllocTensorOp::getAliasingValues(OpOperand &opOperand,
+                                                   const AnalysisState &state) {
   // This is a new allocation. It does not alias with any other buffer.
   return {};
 }
@@ -460,9 +459,8 @@ bool CopyTensorOp::bufferizesToMemoryWrite(OpOperand &opOperand,
   return false;
 }
 
-AliasingOpResultList
-CopyTensorOp::getAliasingOpResults(OpOperand &opOperand,
-                                   const AnalysisState &state) {
+AliasingValueList CopyTensorOp::getAliasingValues(OpOperand &opOperand,
+                                                  const AnalysisState &state) {
   if (&opOperand == &getOperation()->getOpOperand(1) /*dest*/)
     return {{getOperation()->getResult(0), BufferRelation::Equivalent}};
   return {};

diff  --git a/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp
index fbefaf06e11737..b72c4f1999401b 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/FuncBufferizableOpInterfaceImpl.cpp
@@ -164,14 +164,14 @@ struct CallOpInterface
         opOperand.getOperandNumber());
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     func::CallOp callOp = cast<func::CallOp>(op);
     FuncOp funcOp = getCalledFunction(callOp);
     assert(funcOp && "expected CallOp to a FuncOp");
     if (getFuncOpAnalysisState(state, funcOp) != FuncOpAnalysisState::Analyzed)
       // FuncOp not analyzed yet. Any OpResult may be aliasing.
-      return detail::unknownGetAliasingOpResults(opOperand);
+      return detail::unknownGetAliasingValues(opOperand);
 
     // Get aliasing results from state.
     const FuncAnalysisState &funcState = getFuncAnalysisState(state);
@@ -188,7 +188,7 @@ struct CallOpInterface
               *equivalent == opOperand.getOperandNumber()) &&
              "inconsistent analysis state");
     }
-    AliasingOpResultList result;
+    AliasingValueList result;
     for (int64_t resultIdx : aliasingReturnVals)
       result.addAlias({callOp->getOpResult(resultIdx),
                        equivalent.has_value() ? BufferRelation::Equivalent
@@ -299,8 +299,8 @@ struct ReturnOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {};
   }
 

diff  --git a/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp b/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp
index 31ac218d32220f..7f7ab9c21041c5 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/OneShotAnalysis.cpp
@@ -79,7 +79,10 @@ static bool isaTensor(Type t) { return isa<TensorType>(t); }
 /// Attribute marker to specify op operands that bufferize in-place.
 constexpr StringLiteral kInPlaceOperandsAttrName = "__inplace_operands_attr__";
 
-constexpr StringLiteral kAliasSetAttrName = "__alias_set_attr__";
+constexpr StringLiteral kOpResultAliasSetAttrName =
+    "__opresult_alias_set_attr__";
+
+constexpr StringLiteral kBbArgAliasSetAttrName = "__bbarg_alias_set_attr__";
 
 /// Mark whether OpOperand will be bufferized inplace.
 static void setInPlaceOpOperand(OpOperand &opOperand, bool inPlace) {
@@ -161,8 +164,8 @@ void OneShotAnalysisState::bufferizeInPlace(OpOperand &operand) {
   if (inplaceBufferized.contains(&operand))
     return;
   inplaceBufferized.insert(&operand);
-  for (AliasingOpResult alias : getAliasingOpResults(operand))
-    aliasInfo.unionSets(alias.opResult, operand.get());
+  for (AliasingValue alias : getAliasingValues(operand))
+    aliasInfo.unionSets(alias.value, operand.get());
   ++statNumTensorInPlace;
 }
 
@@ -258,14 +261,10 @@ bool OneShotAnalysisState::isValueWritten(Value value) const {
 
 bool OneShotAnalysisState::isWritable(Value value) const {
   // TODO: Out-of-place bufferized value could be considered writable.
-  if (auto bufferizableOp = getOptions().dynCastBufferizableOp(value))
-    return bufferizableOp.isWritable(value, *this);
-
   // Query BufferizableOpInterface to see if the BlockArgument is writable.
-  if (auto bbArg = dyn_cast<BlockArgument>(value))
-    if (auto bufferizableOp =
-            getOptions().dynCastBufferizableOp(bbArg.getOwner()->getParentOp()))
-      return bufferizableOp.isWritable(bbArg, *this);
+  if (auto bufferizableOp =
+          getOptions().dynCastBufferizableOp(getOwnerOfValue(value)))
+    return bufferizableOp.isWritable(value, *this);
 
   // Not a bufferizable op: The conservative answer is "not writable".
   return false;
@@ -614,10 +613,9 @@ hasReadAfterWriteInterference(const DenseSet<OpOperand *> &usesRead,
 
         // No conflict if the conflicting write and the definition are the same
         // use.
-        AliasingOpResultList aliases =
-            state.getAliasingOpResults(*uConflictingWrite);
+        AliasingValueList aliases = state.getAliasingValues(*uConflictingWrite);
         if (aliases.getNumAliases() == 1 &&
-            aliases.getAliases()[0].opResult == definition) {
+            aliases.getAliases()[0].value == definition) {
           LLVM_DEBUG(llvm::dbgs()
                      << "    no conflict: definition and write are same\n");
           continue;
@@ -674,9 +672,9 @@ static void getAliasingReads(DenseSet<OpOperand *> &res, Value root,
       // there would then be no flow of data from the extract_slice operand to
       // its result's uses.)
       if (!state.bufferizesToMemoryWrite(use)) {
-        AliasingOpResultList aliases = state.getAliasingOpResults(use);
-        if (llvm::any_of(aliases, [&](AliasingOpResult a) {
-              return state.isValueRead(a.opResult);
+        AliasingValueList aliases = state.getAliasingValues(use);
+        if (llvm::any_of(aliases, [&](AliasingValue a) {
+              return state.isValueRead(a.value);
             }))
           res.insert(&use);
       }
@@ -720,9 +718,9 @@ static bool wouldCreateReadAfterWriteInterference(
   DenseSet<OpOperand *> usesRead, usesWrite;
   getAliasingReads(usesRead, operand.get(), state);
   getAliasingInplaceWrites(usesWrite, operand.get(), state);
-  for (AliasingOpResult alias : state.getAliasingOpResults(operand)) {
-    getAliasingReads(usesRead, alias.opResult, state);
-    getAliasingInplaceWrites(usesWrite, alias.opResult, state);
+  for (AliasingValue alias : state.getAliasingValues(operand)) {
+    getAliasingReads(usesRead, alias.value, state);
+    getAliasingInplaceWrites(usesWrite, alias.value, state);
   }
   if (!checkConsistencyOnly && state.bufferizesToMemoryWrite(operand))
     usesWrite.insert(&operand);
@@ -760,8 +758,8 @@ wouldCreateWriteToNonWritableBuffer(OpOperand &operand,
     // Collect writes of all aliases of OpOperand and OpResult.
     DenseSet<OpOperand *> usesWrite;
     getAliasingInplaceWrites(usesWrite, operand.get(), state);
-    for (AliasingOpResult alias : state.getAliasingOpResults(operand))
-      getAliasingInplaceWrites(usesWrite, alias.opResult, state);
+    for (AliasingValue alias : state.getAliasingValues(operand))
+      getAliasingInplaceWrites(usesWrite, alias.value, state);
     foundWrite = !usesWrite.empty();
   }
 
@@ -778,8 +776,8 @@ wouldCreateWriteToNonWritableBuffer(OpOperand &operand,
     }
   };
   state.applyOnAliases(operand.get(), checkReadOnly);
-  for (AliasingOpResult alias : state.getAliasingOpResults(operand))
-    state.applyOnAliases(alias.opResult, checkReadOnly);
+  for (AliasingValue alias : state.getAliasingValues(operand))
+    state.applyOnAliases(alias.value, checkReadOnly);
   if (foundReadOnly) {
     LLVM_DEBUG(llvm::dbgs() << "=> NOT WRITABLE\n");
     return true;
@@ -881,8 +879,8 @@ static void equivalenceAnalysis(SmallVector<Operation *> &ops,
         // allocation, it is a definite, equivalent alias. E.g.:
         //
         // aliasingOpOperands(%r) = {(%t0, EQUIV, MAYBE), (%t1, EQUIV, MAYBE)}
-        // aliasingOpResults(%t0) = {(%r, EQUIV, MAYBE)}
-        // aliasingOpResults(%t1) = {(%r, EQUIV, MAYBE)}
+        // aliasingValues(%t0) = {(%r, EQUIV, MAYBE)}
+        // aliasingValues(%t1) = {(%r, EQUIV, MAYBE)}
         // %r = arith.select %c, %t0, %t1 : tensor<?xf32>
         //
         // If %t0 and %t1 are equivalent, it is safe to union the equivalence
@@ -1032,22 +1030,48 @@ static void annotateOpsWithAliasSets(Operation *op,
                                      const OneShotAnalysisState &state) {
   AsmState asmState(op);
   Builder b(op->getContext());
+  // Helper function to build an array attribute of aliasing SSA value strings.
+  auto buildAliasesArray = [&](Value v) {
+    SmallVector<Attribute> aliases;
+    state.applyOnAliases(v, [&](Value alias) {
+      std::string buffer;
+      llvm::raw_string_ostream stream(buffer);
+      alias.printAsOperand(stream, asmState);
+      aliases.push_back(b.getStringAttr(stream.str()));
+    });
+    return b.getArrayAttr(aliases);
+  };
+
   op->walk([&](Operation *op) {
-    SmallVector<Attribute> aliasSets;
+    // Build alias set array for every OpResult.
+    SmallVector<Attribute> opResultAliasSets;
     for (OpResult opResult : op->getOpResults()) {
       if (llvm::isa<TensorType>(opResult.getType())) {
-        SmallVector<Attribute> aliases;
-        state.applyOnAliases(opResult, [&](Value alias) {
-          std::string buffer;
-          llvm::raw_string_ostream stream(buffer);
-          alias.printAsOperand(stream, asmState);
-          aliases.push_back(b.getStringAttr(stream.str()));
-        });
-        aliasSets.push_back(b.getArrayAttr(aliases));
+        opResultAliasSets.push_back(buildAliasesArray(opResult));
+      }
+    }
+    if (!opResultAliasSets.empty())
+      op->setAttr(kOpResultAliasSetAttrName, b.getArrayAttr(opResultAliasSets));
+
+    // Build alias set array for every BlockArgument.
+    SmallVector<Attribute> regionAliasSets;
+    bool hasTensorBbArg = false;
+    for (Region &r : op->getRegions()) {
+      SmallVector<Attribute> blockAliasSets;
+      for (Block &block : r.getBlocks()) {
+        SmallVector<Attribute> bbArgAliasSets;
+        for (BlockArgument bbArg : block.getArguments()) {
+          if (llvm::isa<TensorType>(bbArg.getType())) {
+            bbArgAliasSets.push_back(buildAliasesArray(bbArg));
+            hasTensorBbArg = true;
+          }
+        }
+        blockAliasSets.push_back(b.getArrayAttr(bbArgAliasSets));
       }
+      regionAliasSets.push_back(b.getArrayAttr(blockAliasSets));
     }
-    if (!aliasSets.empty())
-      op->setAttr(kAliasSetAttrName, b.getArrayAttr(aliasSets));
+    if (hasTensorBbArg)
+      op->setAttr(kBbArgAliasSetAttrName, b.getArrayAttr(regionAliasSets));
   });
 }
 

diff  --git a/mlir/lib/Dialect/MemRef/Transforms/BufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/MemRef/Transforms/BufferizableOpInterfaceImpl.cpp
index c11bce95b7eadf..9687a83a6172fe 100644
--- a/mlir/lib/Dialect/MemRef/Transforms/BufferizableOpInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/MemRef/Transforms/BufferizableOpInterfaceImpl.cpp
@@ -21,8 +21,8 @@ namespace {
 struct TensorStoreOpInterface
     : public BufferizableOpInterface::ExternalModel<TensorStoreOpInterface,
                                                     memref::TensorStoreOp> {
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {};
   }
 

diff  --git a/mlir/lib/Dialect/SCF/Transforms/BufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/SCF/Transforms/BufferizableOpInterfaceImpl.cpp
index 677cd04802d3d9..11ee5415bb4cbc 100644
--- a/mlir/lib/Dialect/SCF/Transforms/BufferizableOpInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/SCF/Transforms/BufferizableOpInterfaceImpl.cpp
@@ -57,8 +57,8 @@ struct ConditionOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {};
   }
 
@@ -105,7 +105,7 @@ struct ExecuteRegionOpInterface
     : public BufferizableOpInterface::ExternalModel<ExecuteRegionOpInterface,
                                                     scf::ExecuteRegionOp> {
   AliasingOpOperandList
-  getAliasingOpOperands(Operation *op, OpResult opResult,
+  getAliasingOpOperands(Operation *op, Value value,
                         const AnalysisState &state) const {
     // ExecuteRegionOps do not have tensor OpOperands. The yielded value can be
     // any SSA value that is in scope. To allow for use-def chain traversal
@@ -113,7 +113,7 @@ struct ExecuteRegionOpInterface
     // is considered to be aliasing with the result.
     auto executeRegionOp = cast<scf::ExecuteRegionOp>(op);
     size_t resultNum = std::distance(op->getOpResults().begin(),
-                                     llvm::find(op->getOpResults(), opResult));
+                                     llvm::find(op->getOpResults(), value));
     // TODO: Support multiple blocks.
     assert(executeRegionOp.getRegion().getBlocks().size() == 1 &&
            "expected exactly 1 block");
@@ -160,7 +160,7 @@ struct ExecuteRegionOpInterface
 struct IfOpInterface
     : public BufferizableOpInterface::ExternalModel<IfOpInterface, scf::IfOp> {
   AliasingOpOperandList
-  getAliasingOpOperands(Operation *op, OpResult opResult,
+  getAliasingOpOperands(Operation *op, Value value,
                         const AnalysisState &state) const {
     // IfOps do not have tensor OpOperands. The yielded value can be any SSA
     // value that is in scope. To allow for use-def chain traversal through
@@ -168,7 +168,7 @@ struct IfOpInterface
     // branches are considered to be aliasing with the result.
     auto ifOp = cast<scf::IfOp>(op);
     size_t resultNum = std::distance(op->getOpResults().begin(),
-                                     llvm::find(op->getOpResults(), opResult));
+                                     llvm::find(op->getOpResults(), value));
     OpOperand *thenOperand = &ifOp.thenYield()->getOpOperand(resultNum);
     OpOperand *elseOperand = &ifOp.elseYield()->getOpOperand(resultNum);
     return {{thenOperand, BufferRelation::Equivalent, /*isDefinite=*/false},
@@ -426,8 +426,8 @@ struct ForOpInterface
     return true;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     auto forOp = cast<scf::ForOp>(op);
     OpResult opResult = forOp.getResultForOpOperand(opOperand);
     BufferRelation relation = bufferRelation(op, opResult, state);
@@ -643,8 +643,8 @@ struct WhileOpInterface
     return true;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     auto whileOp = cast<scf::WhileOp>(op);
     unsigned int idx = opOperand.getOperandNumber();
 
@@ -938,8 +938,8 @@ struct YieldOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     if (auto ifOp = dyn_cast<scf::IfOp>(op->getParentOp())) {
       return {{op->getParentOp()->getResult(opOperand.getOperandNumber()),
                BufferRelation::Equivalent, /*isDefinite=*/false}};
@@ -1039,8 +1039,8 @@ struct ForallOpInterface
     return true;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     auto forallOp = cast<ForallOp>(op);
     return {
         {{forallOp.getTiedOpResult(&opOperand), BufferRelation::Equivalent}}};

diff  --git a/mlir/lib/Dialect/Shape/Transforms/BufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/Shape/Transforms/BufferizableOpInterfaceImpl.cpp
index 4a567f48aeb42c..66a2e450017817 100644
--- a/mlir/lib/Dialect/Shape/Transforms/BufferizableOpInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/Shape/Transforms/BufferizableOpInterfaceImpl.cpp
@@ -28,7 +28,7 @@ struct AssumingOpInterface
     : public BufferizableOpInterface::ExternalModel<AssumingOpInterface,
                                                     shape::AssumingOp> {
   AliasingOpOperandList
-  getAliasingOpOperands(Operation *op, OpResult opResult,
+  getAliasingOpOperands(Operation *op, Value value,
                         const AnalysisState &state) const {
     // AssumingOps do not have tensor OpOperands. The yielded value can be any
     // SSA value that is in scope. To allow for use-def chain traversal through
@@ -36,7 +36,7 @@ struct AssumingOpInterface
     // to be aliasing with the result.
     auto assumingOp = cast<shape::AssumingOp>(op);
     size_t resultNum = std::distance(op->getOpResults().begin(),
-                                     llvm::find(op->getOpResults(), opResult));
+                                     llvm::find(op->getOpResults(), value));
     // TODO: Support multiple blocks.
     assert(assumingOp.getDoRegion().getBlocks().size() == 1 &&
            "expected exactly 1 block");
@@ -94,8 +94,8 @@ struct AssumingYieldOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     assert(isa<shape::AssumingOp>(op->getParentOp()) &&
            "expected that parent is an AssumingOp");
     OpResult opResult =

diff  --git a/mlir/lib/Dialect/SparseTensor/Transforms/BufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/SparseTensor/Transforms/BufferizableOpInterfaceImpl.cpp
index cd49205627ea7c..e8467ee3087ae6 100644
--- a/mlir/lib/Dialect/SparseTensor/Transforms/BufferizableOpInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/SparseTensor/Transforms/BufferizableOpInterfaceImpl.cpp
@@ -29,9 +29,7 @@ namespace {
 struct ConcatenateOpInterface
     : public BufferizableOpInterface::ExternalModel<
           ConcatenateOpInterface, sparse_tensor::ConcatenateOp> {
-  bool bufferizesToAllocation(Operation *op, OpResult opResult) const {
-    return true;
-  }
+  bool bufferizesToAllocation(Operation *op, Value value) const { return true; }
 
   bool bufferizesToMemoryRead(Operation *op, OpOperand &opOperand,
                               const AnalysisState &state) const {
@@ -43,8 +41,8 @@ struct ConcatenateOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {};
   }
 
@@ -57,7 +55,7 @@ struct ConcatenateOpInterface
 struct ConvertOpInterface
     : public BufferizableOpInterface::ExternalModel<ConvertOpInterface,
                                                     sparse_tensor::ConvertOp> {
-  bool bufferizesToAllocation(Operation *op, OpResult opResult) const {
+  bool bufferizesToAllocation(Operation *op, Value value) const {
     // ConvertOps may allocate. (Unless they convert between two identical
     // types, then they fold away.)
     return true;
@@ -73,8 +71,8 @@ struct ConvertOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {};
   }
 
@@ -97,8 +95,8 @@ struct LoadOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {{op->getOpResult(0), BufferRelation::Equivalent}};
   }
 };
@@ -112,15 +110,13 @@ struct NewOpInterface
     return false;
   }
 
-  bool bufferizesToAllocation(Operation *op, OpResult opResult) const {
-    return true;
-  }
+  bool bufferizesToAllocation(Operation *op, Value value) const { return true; }
 };
 
 struct PackOpInterface
     : public BufferizableOpInterface::ExternalModel<PackOpInterface,
                                                     sparse_tensor::PackOp> {
-  bool bufferizesToAllocation(Operation *op, OpResult opResult) const {
+  bool bufferizesToAllocation(Operation *op, Value value) const {
     // PackOp reuses all the buffers instead of allocating new ones
     return false;
   }
@@ -135,8 +131,8 @@ struct PackOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     assert(op->getNumResults() == 1);
     // PackOp reuses the input tensors as values/coordinates instead of
     // creating new ones when packing into a COO format.
@@ -152,7 +148,7 @@ struct PackOpInterface
 struct UnpackOpInterface
     : public BufferizableOpInterface::ExternalModel<UnpackOpInterface,
                                                     sparse_tensor::UnpackOp> {
-  bool bufferizesToAllocation(Operation *op, OpResult opResult) const {
+  bool bufferizesToAllocation(Operation *op, Value value) const {
     // The output buffer is pre-allocated by the user.
     return false;
   }
@@ -170,8 +166,8 @@ struct UnpackOpInterface
     return opOperand.getOperandNumber() > 0;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     assert(2 * (op->getNumOperands() - 1) == op->getNumResults());
 
     if (opOperand.getOperandNumber() == 0)
@@ -196,8 +192,8 @@ struct InsertOpInterface
     return true;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     // InsertOp returns an alias of its operand.
     assert(op->getNumResults() == 1);
     return {{op->getOpResult(0), BufferRelation::Equivalent}};
@@ -217,8 +213,8 @@ struct NumberOfEntriesOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {};
   }
 };
@@ -239,8 +235,8 @@ struct ToCoordinatesBufferOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {};
   }
 };
@@ -260,8 +256,8 @@ struct ToCoordinatesOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {};
   }
 };
@@ -281,8 +277,8 @@ struct ToPositionsOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {};
   }
 };
@@ -302,8 +298,8 @@ struct ToValuesOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {};
   }
 };

diff  --git a/mlir/lib/Dialect/Tensor/Transforms/BufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/Tensor/Transforms/BufferizableOpInterfaceImpl.cpp
index a4f14ea1bf9e10..efcea2f6b45ca9 100644
--- a/mlir/lib/Dialect/Tensor/Transforms/BufferizableOpInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/Tensor/Transforms/BufferizableOpInterfaceImpl.cpp
@@ -41,8 +41,8 @@ struct CastOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {{op->getResult(0), BufferRelation::Equivalent}};
   }
 
@@ -125,8 +125,8 @@ struct CollapseShapeOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     // TODO: CollapseShapeOp may allocate at runtime.
     return {{op->getOpResult(0), BufferRelation::Equivalent}};
   }
@@ -235,8 +235,8 @@ struct DimOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {};
   }
 
@@ -295,8 +295,8 @@ struct ExpandShapeOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {{op->getOpResult(0), BufferRelation::Equivalent}};
   }
 
@@ -349,8 +349,8 @@ struct ExtractSliceOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {{op->getOpResult(0), BufferRelation::Unknown}};
   }
 
@@ -413,8 +413,8 @@ struct ExtractOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {};
   }
 
@@ -458,9 +458,7 @@ struct FromElementsOpInterface
     : public BufferizableOpInterface::ExternalModel<FromElementsOpInterface,
                                                     tensor::FromElementsOp> {
 
-  bool bufferizesToAllocation(Operation *op, OpResult opResult) const {
-    return true;
-  }
+  bool bufferizesToAllocation(Operation *op, Value value) const { return true; }
 
   LogicalResult bufferize(Operation *op, RewriterBase &rewriter,
                           const BufferizationOptions &options) const {
@@ -578,9 +576,7 @@ struct GenerateOpInterface
     : public BufferizableOpInterface::ExternalModel<GenerateOpInterface,
                                                     tensor::GenerateOp> {
 
-  bool bufferizesToAllocation(Operation *op, OpResult opResult) const {
-    return true;
-  }
+  bool bufferizesToAllocation(Operation *op, Value value) const { return true; }
 
   LogicalResult bufferize(Operation *op, RewriterBase &rewriter,
                           const BufferizationOptions &options) const {
@@ -838,9 +834,7 @@ struct InsertSliceOpInterface
 struct PadOpInterface
     : public BufferizableOpInterface::ExternalModel<PadOpInterface,
                                                     tensor::PadOp> {
-  bool bufferizesToAllocation(Operation *op, OpResult opResult) const {
-    return true;
-  }
+  bool bufferizesToAllocation(Operation *op, Value value) const { return true; }
 
   bool bufferizesToMemoryRead(Operation *op, OpOperand &opOperand,
                               const AnalysisState &state) const {
@@ -852,8 +846,8 @@ struct PadOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {};
   }
 
@@ -950,8 +944,8 @@ struct RankOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {};
   }
 
@@ -983,8 +977,8 @@ struct ReshapeOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {{op->getOpResult(0), BufferRelation::Equivalent}};
   }
 
@@ -1025,8 +1019,8 @@ struct ReshapeOpInterface
 struct ParallelInsertSliceOpInterface
     : public BufferizableOpInterface::ExternalModel<
           ParallelInsertSliceOpInterface, ParallelInsertSliceOp> {
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {};
   }
 
@@ -1113,9 +1107,7 @@ struct SplatOpInterface
     : public BufferizableOpInterface::ExternalModel<SplatOpInterface,
                                                     tensor::SplatOp> {
 
-  bool bufferizesToAllocation(Operation *op, OpResult opResult) const {
-    return true;
-  }
+  bool bufferizesToAllocation(Operation *op, Value value) const { return true; }
 
   LogicalResult bufferize(Operation *op, RewriterBase &rewriter,
                           const BufferizationOptions &options) const {

diff  --git a/mlir/lib/Dialect/Vector/Transforms/BufferizableOpInterfaceImpl.cpp b/mlir/lib/Dialect/Vector/Transforms/BufferizableOpInterfaceImpl.cpp
index a8ed4d305a3825..d050bf6f5ce141 100644
--- a/mlir/lib/Dialect/Vector/Transforms/BufferizableOpInterfaceImpl.cpp
+++ b/mlir/lib/Dialect/Vector/Transforms/BufferizableOpInterfaceImpl.cpp
@@ -42,8 +42,8 @@ struct TransferReadOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {};
   }
 
@@ -142,8 +142,8 @@ struct GatherOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {};
   }
 
@@ -169,13 +169,13 @@ struct MaskOpInterface
     : public BufferizableOpInterface::ExternalModel<MaskOpInterface,
                                                     vector::MaskOp> {
   AliasingOpOperandList
-  getAliasingOpOperands(Operation *op, OpResult opResult,
+  getAliasingOpOperands(Operation *op, Value value,
                         const AnalysisState &state) const {
     // MaskOps do not have tensor OpOperands. The yielded values are the result
     // of the wrapped op.
     auto maskOp = cast<vector::MaskOp>(op);
     size_t resultNum = std::distance(op->getOpResults().begin(),
-                                     llvm::find(op->getOpResults(), opResult));
+                                     llvm::find(op->getOpResults(), value));
     auto yieldOp =
         cast<vector::YieldOp>(maskOp.getMaskRegion().front().getTerminator());
     return {{&yieldOp->getOpOperand(resultNum), BufferRelation::Equivalent}};
@@ -265,8 +265,8 @@ struct YieldOpInterface
     return false;
   }
 
-  AliasingOpResultList getAliasingOpResults(Operation *op, OpOperand &opOperand,
-                                            const AnalysisState &state) const {
+  AliasingValueList getAliasingValues(Operation *op, OpOperand &opOperand,
+                                      const AnalysisState &state) const {
     return {{op->getParentOp()->getResult(opOperand.getOperandNumber()),
              BufferRelation::Equivalent}};
   }

diff  --git a/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis.mlir b/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis.mlir
index 0938f3d2dd17d4..5a505c66892f11 100644
--- a/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis.mlir
+++ b/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis.mlir
@@ -6,6 +6,7 @@
 // RUN: FileCheck %s --check-prefix=CHECK-ALIAS-SETS
 
 // CHECK-LABEL: func @unknown_op_aliasing(
+// CHECK-ALIAS-SETS-LABEL: func @unknown_op_aliasing(
 func.func @unknown_op_aliasing(%f: f32, %f2: f32, %pos: index) -> f32 {
   // CHECK-ALIAS-SETS: %[[empty:.*]] = tensor.empty
 
@@ -20,8 +21,8 @@ func.func @unknown_op_aliasing(%f: f32, %f2: f32, %pos: index) -> f32 {
   %alias = "dummy.dummy_op"(%1) : (tensor<10xf32>) -> (tensor<10xf32>)
 
   // CHECK: linalg.fill {__inplace_operands_attr__ = ["none", "true"]}
-  // CHECK-ALIAS-SETS: %[[fill2:.*]] = linalg.fill {__alias_set_attr__ = [
-  // CHECK-ALIAS-SETS-SAME: ["%[[fill2]]", "%[[fill1]]", "%[[empty]]"]]
+  // CHECK-ALIAS-SETS: %[[fill2:.*]] = linalg.fill
+  // CHECK-ALIAS-SETS-SAME: __opresult_alias_set_attr__ = [{{\[}}"%[[fill2]]", "%[[fill1]]", "%[[empty]]"]]
   %2 = linalg.fill ins(%f2 : f32) outs(%1 : tensor<10xf32>) -> tensor<10xf32>
   %3 = tensor.extract %alias[%pos] : tensor<10xf32>
   return %3 : f32
@@ -29,6 +30,23 @@ func.func @unknown_op_aliasing(%f: f32, %f2: f32, %pos: index) -> f32 {
 
 // -----
 
+// CHECK-LABEL: func @unknown_op_bbarg_aliasing(
+// CHECK-ALIAS-SETS-LABEL: func @unknown_op_bbarg_aliasing(
+func.func @unknown_op_bbarg_aliasing() {
+  %0 = tensor.empty() : tensor<7xf32>
+
+  // %arg0 is not aliasing with %0 because it bufferizes out-of-place.
+  // CHECK-ALIAS-SETS: "dummy.dummy_op"
+  // CHECK-ALIAS-SETS-NEXT: ^{{.*}}(%[[arg:.*]]: tensor<7xf32>):
+  // CHECK-ALIAS-SETS-NEXT: }) {__bbarg_alias_set_attr__ = [{{\[}}[{{\[}}"%[[arg]]"]]]], __inplace_operands_attr__ = ["false"]} : (tensor<7xf32>) -> ()
+  "dummy.dummy_op"(%0) ({
+  ^bb0(%arg1: tensor<7xf32>):
+  }) : (tensor<7xf32>) -> ()
+  return
+}
+
+// -----
+
 // CHECK-LABEL: func @unknown_op_writing(
 func.func @unknown_op_writing(%f: f32, %f2: f32, %pos: index) -> f32 {
   %0 = tensor.empty() : tensor<10xf32>
@@ -98,3 +116,45 @@ func.func @to_memref_read_only(%idx : index, %f: f32) -> f32 {
   %2 = tensor.extract %t[%idx] : tensor<5xf32>
   return %2 : f32
 }
+
+// -----
+
+// CHECK-LABEL: func @bbarg_of_unknown_op(
+func.func @bbarg_of_unknown_op(%f: f32) {
+  %0 = tensor.empty() : tensor<10xf32>
+  // CHECK: linalg.fill {__inplace_operands_attr__ = ["none", "true"]}
+  %1 = linalg.fill ins(%f : f32) outs(%0 : tensor<10xf32>) -> tensor<10xf32>
+
+  // The op is not bufferizable because %1 is assumed to alias with %arg1.
+  // BlockArguments are considered "not writable" by default. So %1 is also
+  // considered "not writable".
+
+  // CHECK: "dummy.dummy_op"
+  // CHECK: {__inplace_operands_attr__ = ["false"]} : (tensor<10xf32>) -> ()
+  "dummy.dummy_op"(%1) ({
+  ^bb0(%arg1: tensor<10xf32>):
+  }) : (tensor<10xf32>) -> ()
+  return
+}
+
+// -----
+
+// CHECK-LABEL: func @bbarg_of_unknown_op_2(
+func.func @bbarg_of_unknown_op_2(%f: f32) {
+  %0 = tensor.empty() : tensor<10xf32>
+  // CHECK: linalg.fill {__inplace_operands_attr__ = ["none", "true"]}
+  %1 = linalg.fill ins(%f : f32) outs(%0 : tensor<10xf32>) -> tensor<10xf32>
+
+  // The op is not bufferizable because %1 is assumed to alias with %arg1.
+  // BlockArguments are considered "not writable" by default. So %1 is also
+  // considered "not writable".
+
+  // CHECK: "dummy.dummy_op"
+  "dummy.dummy_op"(%1) ({
+  ^bb0(%arg1: tensor<10xf32>):
+    // CHECK: "dummy.another_op"(%{{.*}}) {__inplace_operands_attr__ = ["false"]}
+    "dummy.another_op"(%arg1) : (tensor<10xf32>) -> ()
+  }) : (tensor<10xf32>) -> ()
+  // CHECK: {__inplace_operands_attr__ = ["false"]} : (tensor<10xf32>) -> ()
+  return
+}


        


More information about the Mlir-commits mailing list