[Mlir-commits] [mlir] e62681e - [mlir][bufferize] Eliminate tensor.empty ops instead of bufferization.alloc_tensor ops

Matthias Springer llvmlistbot at llvm.org
Fri Nov 11 02:42:49 PST 2022


Author: Matthias Springer
Date: 2022-11-11T11:39:18+01:00
New Revision: e62681e70a4e0cef34d7310d42de7d425784264b

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

LOG: [mlir][bufferize] Eliminate tensor.empty ops instead of bufferization.alloc_tensor ops

tensor.empty op elimination is an optimization that brings IR in a more bufferization-friendly form. E.g.:

```
%0 = tensor.empty()
%1 = linalg.fill(%cst, %0) {inplace = [true]}
%2 = tensor.insert_slice %1 into %t[10][20][1]
```

Is rewritten to:

```
%0 = tensor.extract_slice %t[10][20][1]
%1 = linalg.fill(%cst, %0) {inplace = [true]}
%2 = tensor.insert_slice %1 into %t[10][20][1]
```

This optimization used to operate on bufferization.alloc_tensor ops. This is not correct because the documentation of bufferization.alloc_tensor says that it always bufferizes to an allocation. Instead, this optimization should operate on tensor.empty ops, which can then be lowered to bufferization.alloc_tensor ops (if they don't get eliminated).

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

Added: 
    mlir/include/mlir/Dialect/Bufferization/Transforms/EmptyTensorElimination.h
    mlir/lib/Dialect/Bufferization/Transforms/EmptyTensorElimination.cpp
    mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis-empty-tensor-elimination.mlir
    mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-empty-tensor-elimination.mlir

Modified: 
    mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h
    mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
    mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt

Removed: 
    mlir/include/mlir/Dialect/Bufferization/Transforms/AllocTensorElimination.h
    mlir/lib/Dialect/Bufferization/Transforms/AllocTensorElimination.cpp
    mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-alloc-tensor-elimination.mlir
    mlir/test/Dialect/Linalg/one-shot-bufferize-analysis-init-tensor-elimination.mlir


################################################################################
diff  --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/AllocTensorElimination.h b/mlir/include/mlir/Dialect/Bufferization/Transforms/EmptyTensorElimination.h
similarity index 66%
rename from mlir/include/mlir/Dialect/Bufferization/Transforms/AllocTensorElimination.h
rename to mlir/include/mlir/Dialect/Bufferization/Transforms/EmptyTensorElimination.h
index c74c7b75f37c5..59521d419c589 100644
--- a/mlir/include/mlir/Dialect/Bufferization/Transforms/AllocTensorElimination.h
+++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/EmptyTensorElimination.h
@@ -1,4 +1,4 @@
-//===- AllocTensorElimination.h - alloc_tensor op elimination -------------===//
+//===- EmptyTensorElimination.h - tensor.empty op elimination -------------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -6,15 +6,15 @@
 //
 //===----------------------------------------------------------------------===//
 
-#ifndef MLIR_DIALECT_BUFFERIZATION_TRANSFORMS_ALLOCTENSORELIMINATION_H
-#define MLIR_DIALECT_BUFFERIZATION_TRANSFORMS_ALLOCTENSORELIMINATION_H
+#ifndef MLIR_DIALECT_BUFFERIZATION_TRANSFORMS_EMPTYTENSORELIMINATION_H
+#define MLIR_DIALECT_BUFFERIZATION_TRANSFORMS_EMPTYTENSORELIMINATION_H
 
 #include "mlir/Dialect/Bufferization/Transforms/OneShotAnalysis.h"
 
 namespace mlir {
 namespace bufferization {
 
-/// A function that matches anchor OpOperands for AllocTensorOp elimination.
+/// A function that matches anchor OpOperands for tensor::EmptyOp elimination.
 /// If an OpOperand is matched, the function should populate the SmallVector
 /// with all values that are needed during `RewriteFn` to produce the
 /// replacement value.
@@ -23,26 +23,26 @@ using AnchorMatchFn = std::function<bool(OpOperand &, SmallVector<Value> &)>;
 /// A function that rewrites matched anchors.
 using RewriteFn = std::function<Value(OpBuilder &, Location, OpOperand &)>;
 
-/// Try to eliminate AllocTensorOps inside `op`.
+/// Try to eliminate tensor::EmptyOps inside `op`.
 ///
-/// * `rewriteFunc` generates the replacement for the AllocTensorOp.
-/// * Only AllocTensorOps that are anchored on a matching OpOperand as per
+/// * `rewriteFunc` generates the replacement for the tensor::EmptyOp.
+/// * Only tensor::EmptyOps that are anchored on a matching OpOperand as per
 ///   `anchorMatchFunc` are considered. "Anchored" means that there is a path
 ///   on the reverse SSA use-def chain, starting from the OpOperand and always
 ///   following the aliasing  OpOperand, that eventually ends at a single
-///   AllocTensorOp.
-LogicalResult eliminateAllocTensors(RewriterBase &rewriter, Operation *op,
+///   tensor::EmptyOp.
+LogicalResult eliminateEmptyTensors(RewriterBase &rewriter, Operation *op,
                                     bufferization::AnalysisState &state,
                                     AnchorMatchFn anchorMatchFunc,
                                     RewriteFn rewriteFunc);
 
-/// Try to eliminate AllocTensorOps inside `op` that are anchored on an
+/// Try to eliminate tensor::EmptyOps inside `op` that are anchored on an
 /// InsertSliceOp, i.e., if it is eventually inserted into another tensor
 /// (and some other conditions are met).
-LogicalResult insertSliceAnchoredAllocTensorEliminationStep(
+LogicalResult insertSliceAnchoredEmptyTensorEliminationStep(
     RewriterBase &rewriter, Operation *op, bufferization::AnalysisState &state);
 
 } // namespace bufferization
 } // namespace mlir
 
-#endif // MLIR_DIALECT_BUFFERIZATION_TRANSFORMS_ALLOCTENSORELIMINATION_H
+#endif // MLIR_DIALECT_BUFFERIZATION_TRANSFORMS_EMPTYTENSORELIMINATION_H

diff  --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h
index 445430ac21a00..52ba73b60181a 100644
--- a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h
+++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.h
@@ -90,9 +90,9 @@ createPromoteBuffersToStackPass(unsigned maxAllocSizeInBytes = 1024,
 std::unique_ptr<Pass>
 createPromoteBuffersToStackPass(std::function<bool(Value)> isSmallAlloc);
 
-/// Create a pass that tries to eliminate alloc_tensor ops that are anchored on
+/// Create a pass that tries to eliminate tensor.empty ops that are anchored on
 /// insert_slice ops.
-std::unique_ptr<Pass> createAllocTensorEliminationPass();
+std::unique_ptr<Pass> createEmptyTensorEliminationPass();
 
 /// Create a pass that bufferizes ops from the bufferization dialect.
 std::unique_ptr<Pass> createBufferizationBufferizePass();

diff  --git a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
index a4062c7f420e8..ebad5bb4772f1 100644
--- a/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
+++ b/mlir/include/mlir/Dialect/Bufferization/Transforms/Passes.td
@@ -371,16 +371,16 @@ def TensorCopyInsertion : Pass<"tensor-copy-insertion"> {
   let constructor = "mlir::bufferization::createTensorCopyInsertionPass()";
 }
 
-def AllocTensorElimination : Pass<"eliminate-alloc-tensors"> {
-  let summary = "Try to eliminate all alloc_tensor ops.";
+def EmptyTensorElimination : Pass<"eliminate-empty-tensors"> {
+  let summary = "Try to eliminate all tensor.empty ops.";
   let description = [{
-    This pass tries to eliminate all insert_slice op-anchored alloc_tensor ops.
-    I.e., when a value that is equivalent to an alloc_tensor op is inserted into
+    This pass tries to eliminate all insert_slice op-anchored tensor.empty ops.
+    I.e., when a value that is equivalent to an tensor.empty op is inserted into
     another tensor, this pass tries to rewrite the IR in such a way that the
     destination tensor of the insert_slice op is used directly instead of the
-    alloc_tensor result.
+    tensor.empty result.
   }];
-  let constructor = "mlir::bufferization::createAllocTensorEliminationPass()";
+  let constructor = "mlir::bufferization::createEmptyTensorEliminationPass()";
 }
 
 #endif // MLIR_DIALECT_BUFFERIZATION_TRANSFORMS_PASSES

diff  --git a/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt b/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt
index 3fc472c408c44..453d71f1d5b58 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt
+++ b/mlir/lib/Dialect/Bufferization/Transforms/CMakeLists.txt
@@ -1,5 +1,4 @@
 add_mlir_dialect_library(MLIRBufferizationTransforms
-  AllocTensorElimination.cpp
   Bufferize.cpp
   BufferDeallocation.cpp
   BufferOptimizations.cpp
@@ -7,6 +6,7 @@ add_mlir_dialect_library(MLIRBufferizationTransforms
   BufferUtils.cpp
   BufferViewFlowAnalysis.cpp
   DropEquivalentBufferResults.cpp
+  EmptyTensorElimination.cpp
   EmptyTensorToAllocTensor.cpp
   FuncBufferizableOpInterfaceImpl.cpp
   OneShotAnalysis.cpp

diff  --git a/mlir/lib/Dialect/Bufferization/Transforms/AllocTensorElimination.cpp b/mlir/lib/Dialect/Bufferization/Transforms/EmptyTensorElimination.cpp
similarity index 70%
rename from mlir/lib/Dialect/Bufferization/Transforms/AllocTensorElimination.cpp
rename to mlir/lib/Dialect/Bufferization/Transforms/EmptyTensorElimination.cpp
index 4a1d4122a66d3..c85980e599848 100644
--- a/mlir/lib/Dialect/Bufferization/Transforms/AllocTensorElimination.cpp
+++ b/mlir/lib/Dialect/Bufferization/Transforms/EmptyTensorElimination.cpp
@@ -1,4 +1,4 @@
-//===- AllocTensorElimination.cpp - alloc_tensor op elimination -----------===//
+//===- EmptyTensorElimination.cpp - tensor.empty op elimination -----------===//
 //
 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 // See https://llvm.org/LICENSE.txt for license information.
@@ -10,7 +10,7 @@
 
 #include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h"
 #include "mlir/Dialect/Bufferization/IR/Bufferization.h"
-#include "mlir/Dialect/Bufferization/Transforms/AllocTensorElimination.h"
+#include "mlir/Dialect/Bufferization/Transforms/EmptyTensorElimination.h"
 #include "mlir/Dialect/Bufferization/Transforms/OneShotAnalysis.h"
 #include "mlir/Dialect/Tensor/IR/Tensor.h"
 #include "mlir/IR/Dominance.h"
@@ -18,7 +18,7 @@
 
 namespace mlir {
 namespace bufferization {
-#define GEN_PASS_DEF_ALLOCTENSORELIMINATION
+#define GEN_PASS_DEF_EMPTYTENSORELIMINATION
 #include "mlir/Dialect/Bufferization/Transforms/Passes.h.inc"
 } // namespace bufferization
 } // namespace mlir
@@ -47,27 +47,27 @@ neededValuesDominateInsertionPoint(const DominanceInfo &domInfo,
 }
 
 /// Return true if the given `insertionPoint` dominates all uses of
-/// `allocTensorOp`.
+/// `emptyTensorOp`.
 static bool insertionPointDominatesUses(const DominanceInfo &domInfo,
                                         Operation *insertionPoint,
-                                        Operation *allocTensorOp) {
-  for (Operation *user : allocTensorOp->getUsers())
+                                        Operation *emptyTensorOp) {
+  for (Operation *user : emptyTensorOp->getUsers())
     if (!domInfo.dominates(insertionPoint, user))
       return false;
   return true;
 }
 
-/// Find a valid insertion point for a replacement of `allocTensorOp`, assuming
+/// Find a valid insertion point for a replacement of `emptyTensorOp`, assuming
 /// that the replacement may use any value from `neededValues`.
 static Operation *
-findValidInsertionPoint(Operation *allocTensorOp,
+findValidInsertionPoint(Operation *emptyTensorOp,
                         const SmallVector<Value> &neededValues) {
   DominanceInfo domInfo;
 
-  // Gather all possible insertion points: the location of `allocTensorOp` and
+  // Gather all possible insertion points: the location of `emptyTensorOp` and
   // right after the definition of each value in `neededValues`.
   SmallVector<Operation *> insertionPointCandidates;
-  insertionPointCandidates.push_back(allocTensorOp);
+  insertionPointCandidates.push_back(emptyTensorOp);
   for (Value val : neededValues) {
     // Note: The anchor op is using all of `neededValues`, so:
     // * in case of a block argument: There must be at least one op in the block
@@ -90,7 +90,7 @@ findValidInsertionPoint(Operation *allocTensorOp,
                                             neededValues))
       continue;
     // Check if the insertion point is before all uses.
-    if (!insertionPointDominatesUses(domInfo, insertionPoint, allocTensorOp))
+    if (!insertionPointDominatesUses(domInfo, insertionPoint, emptyTensorOp))
       continue;
     return insertionPoint;
   }
@@ -99,12 +99,12 @@ findValidInsertionPoint(Operation *allocTensorOp,
   return nullptr;
 }
 
-/// Try to eliminate AllocTensorOps inside `op`. An AllocTensorOp is replaced
+/// Try to eliminate tensor::EmptyOps inside `op`. A tensor::EmptyOp is replaced
 /// with the result of `rewriteFunc` if it is anchored on a matching
 /// OpOperand. "Anchored" means that there is a path on the reverse SSA use-def
 /// chain, starting from the OpOperand and always following the aliasing
-/// OpOperand, that eventually ends at a single AllocTensorOp.
-LogicalResult mlir::bufferization::eliminateAllocTensors(
+/// OpOperand, that eventually ends at a single tensor::EmptyOp.
+LogicalResult mlir::bufferization::eliminateEmptyTensors(
     RewriterBase &rewriter, Operation *op, AnalysisState &state,
     AnchorMatchFn anchorMatchFunc, RewriteFn rewriteFunc) {
   OpBuilder::InsertionGuard g(rewriter);
@@ -119,56 +119,40 @@ LogicalResult mlir::bufferization::eliminateAllocTensors(
       // Is this a matching OpOperand?
       if (!anchorMatchFunc(operand, neededValues))
         continue;
-      SetVector<Value> maybeAllocTensor =
-          state.findValueInReverseUseDefChain(operand.get(), [&](Value val) {
-            // Continue traversal until this function returns true.
-            OpResult opResult = val.dyn_cast<OpResult>();
-            if (!opResult)
-              return true;
-            SmallVector<OpOperand *> opOperands =
-                state.getAliasingOpOperand(opResult);
-            if (!llvm::all_of(opOperands, [&](OpOperand *operand) {
-                  return state.isInPlace(*operand);
-                }))
-              return true;
-            // Only equivalent tensors are supported at the moment.
-            // TODO: Support cases such as extract_slice(alloc_tensor)
-            return !llvm::all_of(opOperands, [&](OpOperand *operand) {
-              return state.areEquivalentBufferizedValues(operand->get(),
-                                                         opResult);
-            });
-          });
+      SetVector<Value> maybeEmptyTensor = state.findValueInReverseUseDefChain(
+          operand.get(), /*condition=*/[&](Value val) { return false; },
+          /*followEquivalentOnly=*/true);
 
       // Replace only if the reverse use-def chain ends at exactly one
-      // AllocTensorOp.
-      if (maybeAllocTensor.size() != 1 ||
-          !maybeAllocTensor.front().getDefiningOp<AllocTensorOp>())
+      // tensor::EmptyOp.
+      if (maybeEmptyTensor.size() != 1 ||
+          !maybeEmptyTensor.front().getDefiningOp<tensor::EmptyOp>())
         return WalkResult::skip();
-      Value allocTensor = maybeAllocTensor.front();
+      Value emptyTensor = maybeEmptyTensor.front();
 
       // Replace only if the types match.
       // TODO: This could be extended to support IR such as:
-      // %0 = bufferization.alloc_tensor : tensor<128xf32>
+      // %0 = tensor.empty() : tensor<128xf32>
       // %1 = "some_op"(%0) : (tensor<128xf32>) -> (tensor<128xf32>)
       // %2 = tensor.expand_shape %1 ...
       // %3 = tensor.insert_slice %2 into ...
-      if (allocTensor.getType() != operand.get().getType())
+      if (emptyTensor.getType() != operand.get().getType())
         return WalkResult::skip();
 
       // Find a suitable insertion point.
       Operation *insertionPoint =
-          findValidInsertionPoint(allocTensor.getDefiningOp(), neededValues);
+          findValidInsertionPoint(emptyTensor.getDefiningOp(), neededValues);
       if (!insertionPoint)
         continue;
 
-      // Create a replacement for the AllocTensorOp.
+      // Create a replacement for the tensor::EmptyOp.
       rewriter.setInsertionPoint(insertionPoint);
-      Value replacement = rewriteFunc(rewriter, allocTensor.getLoc(), operand);
+      Value replacement = rewriteFunc(rewriter, emptyTensor.getLoc(), operand);
       if (!replacement)
         continue;
 
-      // Replace the AllocTensorOp.
-      rewriter.replaceOp(allocTensor.getDefiningOp(), replacement);
+      // Replace the tensor::EmptyOp.
+      rewriter.replaceOp(emptyTensor.getDefiningOp(), replacement);
     }
 
     // Advance to the next operation.
@@ -178,34 +162,35 @@ LogicalResult mlir::bufferization::eliminateAllocTensors(
   return failure(status.wasInterrupted());
 }
 
-/// Try to eliminate AllocTensorOps inside `op`. An AllocTensorOp can be
+/// Try to eliminate tensor::EmptyOps inside `op`. An tensor::EmptyOp can be
 /// eliminated if it is eventually inserted into another tensor (and some other
 /// conditions are met).
 ///
 /// E.g.:
-/// %0 = linalg.alloc_tensor
+/// %0 = tensor.empty()
 /// %1 = linalg.fill(%cst, %0) {inplace = [true]}
 /// %2 = tensor.insert_slice %1 into %t[10][20][1]
 ///
-/// AllocTensorOp elimination will try to fill %t inplace instead of filling a
+/// tensor::EmptyOp elimination will try to fill %t inplace instead of filling a
 /// new allocation %0 and inserting it into %t. This is done by replacing the
-/// AllocTensorOp with:
+/// tensor::EmptyOp with:
 ///
 /// %0 = tensor.extract_slice %t[10][20][1]
 ///
 /// The analysis looks for matching ExtractSliceOp/InsertSliceOp pairs and lets
 /// those bufferize inplace in the absence of other conflicts.
 ///
-/// Starting from an InsertSliceOp, an AllocTensorOp at the end of the insert
+/// Starting from an InsertSliceOp, an tensor::EmptyOp at the end of the insert
 /// source's reverse use-def chain is eliminated if:
 /// * On the reverse use-def chain path from the InsertSliceOp to the
-///   AllocTensorOp, all ops were decided to bufferize inplace and the buffer
+///   tensor::EmptyOp, all ops were decided to bufferize inplace and the buffer
 ///   relation is "equivalent" (TODO: can be relaxed if needed).
-/// * The reverse use-def chain has exactly one end, which is the AllocTensorOp.
+/// * The reverse use-def chain has exactly one end, which is the
+///   tensor::EmptyOp.
 LogicalResult
-mlir::bufferization::insertSliceAnchoredAllocTensorEliminationStep(
+mlir::bufferization::insertSliceAnchoredEmptyTensorEliminationStep(
     RewriterBase &rewriter, Operation *op, AnalysisState &state) {
-  return eliminateAllocTensors(
+  return eliminateEmptyTensors(
       rewriter, op, state,
       /*anchorMatchFunc=*/
       [&](OpOperand &operand, SmallVector<Value> &neededValues) {
@@ -239,10 +224,10 @@ mlir::bufferization::insertSliceAnchoredAllocTensorEliminationStep(
 }
 
 namespace {
-struct AllocTensorElimination
-    : public bufferization::impl::AllocTensorEliminationBase<
-          AllocTensorElimination> {
-  AllocTensorElimination() = default;
+struct EmptyTensorElimination
+    : public bufferization::impl::EmptyTensorEliminationBase<
+          EmptyTensorElimination> {
+  EmptyTensorElimination() = default;
 
   void runOnOperation() override;
 
@@ -253,7 +238,7 @@ struct AllocTensorElimination
 };
 } // namespace
 
-void AllocTensorElimination::runOnOperation() {
+void EmptyTensorElimination::runOnOperation() {
   Operation *op = getOperation();
   OneShotBufferizationOptions options;
   OneShotAnalysisState state(op, options);
@@ -263,11 +248,11 @@ void AllocTensorElimination::runOnOperation() {
   }
 
   IRRewriter rewriter(op->getContext());
-  if (failed(bufferization::insertSliceAnchoredAllocTensorEliminationStep(
+  if (failed(bufferization::insertSliceAnchoredEmptyTensorEliminationStep(
           rewriter, op, state)))
     signalPassFailure();
 }
 
-std::unique_ptr<Pass> mlir::bufferization::createAllocTensorEliminationPass() {
-  return std::make_unique<AllocTensorElimination>();
+std::unique_ptr<Pass> mlir::bufferization::createEmptyTensorEliminationPass() {
+  return std::make_unique<EmptyTensorElimination>();
 }

diff  --git a/mlir/test/Dialect/Linalg/one-shot-bufferize-analysis-init-tensor-elimination.mlir b/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis-empty-tensor-elimination.mlir
similarity index 81%
rename from mlir/test/Dialect/Linalg/one-shot-bufferize-analysis-init-tensor-elimination.mlir
rename to mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis-empty-tensor-elimination.mlir
index 04911960933d4..d74455fdf914d 100644
--- a/mlir/test/Dialect/Linalg/one-shot-bufferize-analysis-init-tensor-elimination.mlir
+++ b/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-analysis-empty-tensor-elimination.mlir
@@ -1,8 +1,4 @@
-// RUN: mlir-opt %s -eliminate-alloc-tensors -one-shot-bufferize="bufferize-function-boundaries test-analysis-only allow-return-allocs" -split-input-file | FileCheck %s
-
-//===----------------------------------------------------------------------===//
-// AllocTensorOp elimination
-//===----------------------------------------------------------------------===//
+// RUN: mlir-opt %s -eliminate-empty-tensors -empty-tensor-to-alloc-tensor -one-shot-bufferize="bufferize-function-boundaries test-analysis-only allow-return-allocs" -split-input-file | FileCheck %s
 
 // CHECK-LABEL: func @buffer_forwarding_conflict
 func.func @buffer_forwarding_conflict(%arg0: tensor<?xf32> {bufferization.writable = true}, %arg1: index) -> (tensor<?xf32>, tensor<?xf32>) {
@@ -10,7 +6,7 @@ func.func @buffer_forwarding_conflict(%arg0: tensor<?xf32> {bufferization.writab
   //      CHECK: tensor.extract_slice
   // CHECK-SAME: {__inplace_operands_attr__ = ["false", "none"]
   // Instead of allocating, share buffer with some inplace bufferization?
-  %0 = bufferization.alloc_tensor(%arg1) : tensor<?xf32>
+  %0 = tensor.empty(%arg1) : tensor<?xf32>
 
   //      CHECK: linalg.fill
   // CHECK-SAME: {__inplace_operands_attr__ = ["none", "true"]
@@ -37,7 +33,7 @@ func.func @buffer_forwarding_no_conflict(%arg0: tensor<?xf32> {bufferization.wri
   //      CHECK: tensor.extract_slice
   // CHECK-SAME: {__inplace_operands_attr__ = ["true", "none"]
   // Instead of allocating, share buffer with some inplace bufferization?
-  %0 = bufferization.alloc_tensor(%arg1) : tensor<?xf32>
+  %0 = tensor.empty(%arg1) : tensor<?xf32>
 
   //      CHECK: linalg.fill
   // CHECK-SAME: {__inplace_operands_attr__ = ["none", "true"]

diff  --git a/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-alloc-tensor-elimination.mlir b/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-empty-tensor-elimination.mlir
similarity index 86%
rename from mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-alloc-tensor-elimination.mlir
rename to mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-empty-tensor-elimination.mlir
index c6454cf894194..73ac2e1f1f2f0 100644
--- a/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-alloc-tensor-elimination.mlir
+++ b/mlir/test/Dialect/Bufferization/Transforms/one-shot-bufferize-empty-tensor-elimination.mlir
@@ -1,4 +1,4 @@
-// RUN: mlir-opt %s -eliminate-alloc-tensors -one-shot-bufferize="bufferize-function-boundaries allow-return-allocs" -canonicalize -split-input-file | FileCheck %s
+// RUN: mlir-opt %s -eliminate-empty-tensors -empty-tensor-to-alloc-tensor -one-shot-bufferize="bufferize-function-boundaries allow-return-allocs" -canonicalize -split-input-file | FileCheck %s
 
 //      CHECK: func @buffer_forwarding_conflict(
 // CHECK-SAME:   %[[FUNC_ARG:[0-9a-zA-Z]*]]: memref<?xf32>
@@ -16,10 +16,10 @@ func.func @buffer_forwarding_conflict(
   //     CHECK: %[[DIM:.*]] = memref.dim %[[FUNC_ARG]]
   // This allocs the whole dim to allow for a full clone of t.
   //     CHECK: %[[ALLOC:.*]] = memref.alloc(%[[DIM]])
-  // alloc_tensor itself does not alloc but forwards to the **second**
-  // insert_slice. AllocTensorOp replaces the alloc_tensor with an out-of-place
+  // tensor.empty itself does not alloc but forwards to the **second**
+  // insert_slice. The pass replaces the tensor.empty with an out-of-place
   // extract_slice.
-  %a = bufferization.alloc_tensor(%sz) : tensor<?xf32>
+  %a = tensor.empty(%sz) : tensor<?xf32>
   %f = linalg.fill ins(%f0 : f32) outs(%a : tensor<?xf32>) -> tensor<?xf32>
 
   //     CHECK: memref.copy %[[FUNC_ARG]], %[[ALLOC]] : memref<?xf32> to memref<?xf32>
@@ -46,11 +46,11 @@ func.func @buffer_forwarding_no_conflict(
 {
   %f0 = arith.constant 0.0: f32
 
-  // alloc_tensor itself does not alloc but forwards to the insert_slice.
-  // AllocTensorOpElimination replaces the alloc_tensor with an inplace
+  // tensor.empty itself does not alloc but forwards to the insert_slice.
+  // EmptyTensorOpElimination replaces the tensor.empty with an inplace
   // extract_slice.
   // CHECK: %[[T_SUBVIEW:.*]] =  memref.subview %[[FUNC_ARG]][42] [%[[sz]]] [1]
-  %a = bufferization.alloc_tensor(%sz) : tensor<?xf32>
+  %a = tensor.empty(%sz) : tensor<?xf32>
 
   // CHECK: linalg.fill ins({{.*}} : f32) outs(%[[T_SUBVIEW]] : memref<?xf32
   %f = linalg.fill ins(%f0 : f32) outs(%a : tensor<?xf32>) -> tensor<?xf32>
@@ -71,7 +71,7 @@ func.func @insertion_point_inside_loop(%t : tensor<?xf32>, %sz : index) -> (tens
   %c5 = arith.constant 5 : index
 
   // CHECK-NOT: memref.alloc
-  %blank = bufferization.alloc_tensor() : tensor<5xf32>
+  %blank = tensor.empty() : tensor<5xf32>
 
   // CHECK: scf.for %[[iv:.*]] = %{{.*}} to %[[sz]] step %{{.*}} {
   %r = scf.for %iv = %c0 to %sz step %c5 iter_args(%bb = %t) -> (tensor<?xf32>) {
@@ -102,7 +102,7 @@ func.func @insertion_point_outside_loop(%t : tensor<?xf32>, %sz : index,
 
   // CHECK-NOT: memref.alloc
   // CHECK: %[[subview:.*]] = memref.subview %[[t]][%[[idx]]] [5] [1]
-  %blank = bufferization.alloc_tensor() : tensor<5xf32>
+  %blank = tensor.empty() : tensor<5xf32>
 
   // CHECK: scf.for %[[iv:.*]] = %{{.*}} to %[[sz]] step %{{.*}} {
   %r = scf.for %iv = %c0 to %sz step %c5 iter_args(%bb = %t) -> (tensor<?xf32>) {
@@ -122,14 +122,14 @@ func.func @insertion_point_outside_loop(%t : tensor<?xf32>, %sz : index,
 
 // -----
 
-// AllocTensorElimination does currently not apply to chains where the type is
+// EmptyTensorElimination does currently not apply to chains where the type is
 // changing. This test just ensures that we do not crash or generate IR that
 // does not verify.
 
 // CHECK-LABEL: func @shape_mismatch
 func.func @shape_mismatch(%t: tensor<5x6x128xf32>) -> tensor<5x6x128xf32> {
   %cst = arith.constant 8.0 : f32
-  %0 = bufferization.alloc_tensor() : tensor<128xf32>
+  %0 = tensor.empty() : tensor<128xf32>
   %1 = linalg.fill ins(%cst : f32) outs(%0 : tensor<128xf32>) -> tensor<128xf32>
   %2 = tensor.expand_shape %1 [[0, 1, 2]]
       : tensor<128xf32> into tensor<1x1x128xf32>


        


More information about the Mlir-commits mailing list