//===- VectorInterfaceImpl.cpp - Vector Impl. of BufferizableOpInterface --===// // // 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 // //===----------------------------------------------------------------------===// #include "mlir/Dialect/Linalg/ComprehensiveBufferize/VectorInterfaceImpl.h" #include "mlir/Dialect/Linalg/ComprehensiveBufferize/BufferizableOpInterface.h" #include "mlir/Dialect/Vector/VectorOps.h" #include "mlir/IR/Dialect.h" #include "mlir/IR/Operation.h" namespace mlir { namespace linalg { namespace comprehensive_bufferize { namespace vector_ext { /// Bufferization of vector.transfer_read. Replaced with a new /// vector.transfer_read that operates on a memref. struct TransferReadOpInterface : public BufferizableOpInterface::ExternalModel { bool bufferizesToMemoryRead(Operation *op, OpOperand &opOperand, const BufferizationState &state) const { assert(opOperand.get().getType().isa() && "only tensor types expected"); return true; } bool bufferizesToMemoryWrite(Operation *op, OpOperand &opOperand, const BufferizationState &state) const { assert(opOperand.get().getType().isa() && "only tensor types expected"); return false; } OpResult getAliasingOpResult(Operation *op, OpOperand &opOperand, const BufferizationState &state) const { return OpResult(); } LogicalResult bufferize(Operation *op, RewriterBase &rewriter, const BufferizationState &state) const { auto readOp = cast(op); assert(readOp.getShapedType().isa() && "only tensor types expected"); // TransferReadOp always reads from the bufferized op.source(). Value buffer = state.lookupBuffer(rewriter, readOp.source()); replaceOpWithNewBufferizedOp( rewriter, readOp, readOp.getVectorType(), buffer, readOp.indices(), readOp.permutation_map(), readOp.padding(), readOp.mask(), readOp.in_boundsAttr()); return success(); } }; /// Bufferization of vector.transfer_write. Replace with a new /// vector.transfer_write that operates on a memref. struct TransferWriteOpInterface : public BufferizableOpInterface::ExternalModel { bool bufferizesToMemoryRead(Operation *op, OpOperand &opOperand, const BufferizationState &state) const { assert(opOperand.get().getType().isa() && "only tensor types expected"); return true; } bool bufferizesToMemoryWrite(Operation *op, OpOperand &opOperand, const BufferizationState &state) const { assert(opOperand.get().getType().isa() && "only tensor types expected"); return true; } OpResult getAliasingOpResult(Operation *op, OpOperand &opOperand, const BufferizationState &state) const { assert(opOperand.get().getType().isa() && "only tensor types expected"); return op->getOpResult(0); } BufferRelation bufferRelation(Operation *op, OpResult opResult, const BufferizationAliasInfo &aliasInfo, const BufferizationState &state) const { return BufferRelation::Equivalent; } LogicalResult bufferize(Operation *op, RewriterBase &rewriter, const BufferizationState &state) const { auto writeOp = cast(op); assert(writeOp.getShapedType().isa() && "only tensor types expected"); // Create a new transfer_write on buffer that doesn't have a return value. // Leave the previous transfer_write to dead code as it still has uses at // this point. FailureOr resultBuffer = state.getResultBuffer(rewriter, op->getResult(0)); if (failed(resultBuffer)) return failure(); rewriter.create( writeOp.getLoc(), writeOp.vector(), *resultBuffer, writeOp.indices(), writeOp.permutation_mapAttr(), writeOp.in_boundsAttr()); replaceOpWithBufferizedValues(rewriter, op, *resultBuffer); return success(); } }; } // namespace vector_ext } // namespace comprehensive_bufferize } // namespace linalg } // namespace mlir void mlir::linalg::comprehensive_bufferize::vector_ext:: registerBufferizableOpInterfaceExternalModels(DialectRegistry ®istry) { registry.addOpInterface(); registry.addOpInterface(); }