Return the OpResult that aliases with a given OpOperand when
bufferized in-place. This method will never be called on OpOperands
that do not have a tensor type.
+
+ Note: This method can return multiple OpResults, indicating that a
+ given OpOperand may at runtime alias with any (or multiple) of the
+ returned OpResults.
}],
/*retType=*/"SmallVector<OpResult>",
/*methodName=*/"getAliasingOpResult",
return the OpOperands that are yielded by the terminator.
Note: This method can return multiple OpOperands, indicating that the
- given OpResult may at runtime alias with any of the OpOperands. This
- is useful for branches and for ops such as `arith.select`.
+ given OpResult may at runtime alias with any (or multiple) of the
+ returned OpOperands. This can be useful for branches and for ops such
+ as `arith.select`.
}],
/*retType=*/"SmallVector<OpOperand *>",
/*methodName=*/"getAliasingOpOperand",
--- /dev/null
+//===- DstBufferizableOpInterfaceImpl.h - Dst Op Bufferization --*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef MLIR_DIALECT_BUFFERIZATION_IR_DSTBUFFERIZABLEOPINTERFACEIMPL_H_
+#define MLIR_DIALECT_BUFFERIZATION_IR_DSTBUFFERIZABLEOPINTERFACEIMPL_H_
+
+#include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h"
+#include "mlir/Interfaces/DestinationStyleOpInterface.h"
+
+namespace mlir {
+namespace bufferization {
+
+/// Bufferizable ops that implement the DestinationStyleOpInterface can use this
+/// external model base class. It provides default implementations for various
+/// required interface methods.
+template <typename ConcreteModel, typename ConcreteOp>
+struct DstBufferizableOpInterfaceExternalModel
+ : public BufferizableOpInterface::ExternalModel<ConcreteModel, ConcreteOp> {
+ bool bufferizesToMemoryRead(Operation *op, OpOperand &opOperand,
+ const AnalysisState &state) const {
+ // All inputs and outputs bufferize to a memory read.
+ assert(isa<DestinationStyleOpInterface>(op) &&
+ "expected that op implements DestinationStyleOpInterface");
+ return true;
+ }
+
+ bool bufferizesToMemoryWrite(Operation *op, OpOperand &opOperand,
+ const AnalysisState &state) const {
+ // Only outputs bufferize to a memory write.
+ auto dstOp = cast<DestinationStyleOpInterface>(op);
+ return dstOp.isOutput(&opOperand);
+ }
+
+ SmallVector<OpResult> getAliasingOpResult(Operation *op, OpOperand &opOperand,
+ const AnalysisState &state) const {
+ // Output operands alias with their respective tied OpResults.
+ auto dstOp = cast<DestinationStyleOpInterface>(op);
+ if (dstOp.isOutput(&opOperand))
+ return {dstOp.getTiedOpResult(&opOperand)};
+ return {};
+ }
+
+ BufferRelation bufferRelation(Operation *op, OpResult opResult,
+ const AnalysisState &state) const {
+ assert(isa<DestinationStyleOpInterface>(op) &&
+ "expected that op implements DestinationStyleOpInterface");
+ return BufferRelation::Equivalent;
+ }
+};
+
+} // namespace bufferization
+} // namespace mlir
+
+#endif // MLIR_DIALECT_BUFFERIZATION_IR_DSTBUFFERIZABLEOPINTERFACEIMPL_H_
#include "mlir/Dialect/Arith/IR/Arith.h"
#include "mlir/Dialect/Bufferization/IR/BufferizableOpInterface.h"
#include "mlir/Dialect/Bufferization/IR/Bufferization.h"
+#include "mlir/Dialect/Bufferization/IR/DstBufferizableOpInterfaceImpl.h"
#include "mlir/Dialect/MemRef/IR/MemRef.h"
#include "mlir/Dialect/SCF/IR/SCF.h"
#include "mlir/Dialect/Tensor/IR/Tensor.h"
};
/// Bufferization of tensor.insert. Replace with memref.store.
+///
+/// Note: DstBufferizableOpInterfaceExternalModel provides many default method
+/// implementations for DestinationStyle ops.
struct InsertOpInterface
- : public BufferizableOpInterface::ExternalModel<InsertOpInterface,
- tensor::InsertOp> {
- bool bufferizesToMemoryRead(Operation *op, OpOperand &opOperand,
- const AnalysisState &state) const {
- return true;
- }
-
- bool bufferizesToMemoryWrite(Operation *op, OpOperand &opOperand,
- const AnalysisState &state) const {
- return true;
- }
-
- SmallVector<OpResult> getAliasingOpResult(Operation *op, OpOperand &opOperand,
- const AnalysisState &state) const {
- assert(&opOperand == &op->getOpOperand(1) /*dest*/ &&
- "expected dest OpOperand");
- return {op->getOpResult(0)};
- }
-
- SmallVector<OpOperand *>
- getAliasingOpOperand(Operation *op, OpResult opResult,
- const AnalysisState &state) const {
- return {&op->getOpOperand(1) /*dest*/};
- }
-
+ : public DstBufferizableOpInterfaceExternalModel<InsertOpInterface,
+ tensor::InsertOp> {
LogicalResult bufferize(Operation *op, RewriterBase &rewriter,
const BufferizationOptions &options) const {
auto insertOp = cast<tensor::InsertOp>(op);
replaceOpWithBufferizedValues(rewriter, op, *destMemref);
return success();
}
-
- BufferRelation bufferRelation(Operation *op, OpResult opResult,
- const AnalysisState &state) const {
- return BufferRelation::Equivalent;
- }
};
/// Return true if the (ExtractSliceOp, InsertSliceOp) pair match (i.e.
/// Bufferization of tensor.insert_slice. Replace with a memory copy. Under
/// certain circumstances, this op can also be a no-op.
+///
+/// Note: DstBufferizableOpInterfaceExternalModel provides many default method
+/// implementations for DestinationStyle ops.
struct InsertSliceOpInterface
- : public BufferizableOpInterface::ExternalModel<InsertSliceOpInterface,
- tensor::InsertSliceOp> {
- bool bufferizesToMemoryRead(Operation *op, OpOperand &opOperand,
- const AnalysisState &state) const {
- return true;
- }
-
- bool bufferizesToMemoryWrite(Operation *op, OpOperand &opOperand,
- const AnalysisState &state) const {
- return &opOperand == &op->getOpOperand(1) /*dest*/;
- }
-
- SmallVector<OpResult> getAliasingOpResult(Operation *op, OpOperand &opOperand,
- const AnalysisState &state) const {
- if (&opOperand == &op->getOpOperand(1) /*dest*/)
- return {op->getResult(0)};
- return {};
- }
-
- BufferRelation bufferRelation(Operation *op, OpResult opResult,
- const AnalysisState &state) const {
- return BufferRelation::Equivalent;
- }
-
+ : public DstBufferizableOpInterfaceExternalModel<InsertSliceOpInterface,
+ tensor::InsertSliceOp> {
bool isNotConflicting(Operation *op, OpOperand *uRead,
OpOperand *uConflictingWrite,
const AnalysisState &state) const {