[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