1*ae1ea0beSJulian Gross //===- BufferizationToMemRef.cpp - Bufferization to MemRef conversion -----===// 2*ae1ea0beSJulian Gross // 3*ae1ea0beSJulian Gross // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*ae1ea0beSJulian Gross // See https://llvm.org/LICENSE.txt for license information. 5*ae1ea0beSJulian Gross // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*ae1ea0beSJulian Gross // 7*ae1ea0beSJulian Gross //===----------------------------------------------------------------------===// 8*ae1ea0beSJulian Gross // 9*ae1ea0beSJulian Gross // This file implements patterns to convert Bufferization dialect to MemRef 10*ae1ea0beSJulian Gross // dialect. 11*ae1ea0beSJulian Gross // 12*ae1ea0beSJulian Gross //===----------------------------------------------------------------------===// 13*ae1ea0beSJulian Gross 14*ae1ea0beSJulian Gross #include "../PassDetail.h" 15*ae1ea0beSJulian Gross #include "mlir/Conversion/BufferizationToMemRef/BufferizationToMemRef.h" 16*ae1ea0beSJulian Gross #include "mlir/Dialect/Arithmetic/IR/Arithmetic.h" 17*ae1ea0beSJulian Gross #include "mlir/Dialect/Bufferization/IR/Bufferization.h" 18*ae1ea0beSJulian Gross #include "mlir/Dialect/MemRef/IR/MemRef.h" 19*ae1ea0beSJulian Gross #include "mlir/IR/BuiltinTypes.h" 20*ae1ea0beSJulian Gross #include "mlir/Support/LogicalResult.h" 21*ae1ea0beSJulian Gross #include "mlir/Transforms/DialectConversion.h" 22*ae1ea0beSJulian Gross 23*ae1ea0beSJulian Gross using namespace mlir; 24*ae1ea0beSJulian Gross 25*ae1ea0beSJulian Gross namespace { 26*ae1ea0beSJulian Gross /// The CloneOpConversion transforms all bufferization clone operations into 27*ae1ea0beSJulian Gross /// memref alloc and memref copy operations. In the dynamic-shape case, it also 28*ae1ea0beSJulian Gross /// emits additional dim and constant operations to determine the shape. This 29*ae1ea0beSJulian Gross /// conversion does not resolve memory leaks if it is used alone. 30*ae1ea0beSJulian Gross struct CloneOpConversion : public OpConversionPattern<bufferization::CloneOp> { 31*ae1ea0beSJulian Gross using OpConversionPattern<bufferization::CloneOp>::OpConversionPattern; 32*ae1ea0beSJulian Gross 33*ae1ea0beSJulian Gross LogicalResult 34*ae1ea0beSJulian Gross matchAndRewrite(bufferization::CloneOp op, OpAdaptor adaptor, 35*ae1ea0beSJulian Gross ConversionPatternRewriter &rewriter) const override { 36*ae1ea0beSJulian Gross // Check for unranked memref types which are currently not supported. 37*ae1ea0beSJulian Gross Type type = op.getType(); 38*ae1ea0beSJulian Gross if (type.isa<UnrankedMemRefType>()) { 39*ae1ea0beSJulian Gross return rewriter.notifyMatchFailure( 40*ae1ea0beSJulian Gross op, "UnrankedMemRefType is not supported."); 41*ae1ea0beSJulian Gross } 42*ae1ea0beSJulian Gross 43*ae1ea0beSJulian Gross // Transform a clone operation into alloc + copy operation and pay 44*ae1ea0beSJulian Gross // attention to the shape dimensions. 45*ae1ea0beSJulian Gross MemRefType memrefType = type.cast<MemRefType>(); 46*ae1ea0beSJulian Gross Location loc = op->getLoc(); 47*ae1ea0beSJulian Gross SmallVector<Value, 4> dynamicOperands; 48*ae1ea0beSJulian Gross for (int i = 0; i < memrefType.getRank(); ++i) { 49*ae1ea0beSJulian Gross if (!memrefType.isDynamicDim(i)) 50*ae1ea0beSJulian Gross continue; 51*ae1ea0beSJulian Gross Value size = rewriter.createOrFold<arith::ConstantIndexOp>(loc, i); 52*ae1ea0beSJulian Gross Value dim = rewriter.createOrFold<memref::DimOp>(loc, op.input(), size); 53*ae1ea0beSJulian Gross dynamicOperands.push_back(dim); 54*ae1ea0beSJulian Gross } 55*ae1ea0beSJulian Gross Value alloc = rewriter.replaceOpWithNewOp<memref::AllocOp>(op, memrefType, 56*ae1ea0beSJulian Gross dynamicOperands); 57*ae1ea0beSJulian Gross rewriter.create<memref::CopyOp>(loc, op.input(), alloc); 58*ae1ea0beSJulian Gross return success(); 59*ae1ea0beSJulian Gross } 60*ae1ea0beSJulian Gross }; 61*ae1ea0beSJulian Gross } // namespace 62*ae1ea0beSJulian Gross 63*ae1ea0beSJulian Gross void mlir::populateBufferizationToMemRefConversionPatterns( 64*ae1ea0beSJulian Gross RewritePatternSet &patterns) { 65*ae1ea0beSJulian Gross patterns.add<CloneOpConversion>(patterns.getContext()); 66*ae1ea0beSJulian Gross } 67*ae1ea0beSJulian Gross 68*ae1ea0beSJulian Gross namespace { 69*ae1ea0beSJulian Gross struct BufferizationToMemRefPass 70*ae1ea0beSJulian Gross : public ConvertBufferizationToMemRefBase<BufferizationToMemRefPass> { 71*ae1ea0beSJulian Gross BufferizationToMemRefPass() = default; 72*ae1ea0beSJulian Gross 73*ae1ea0beSJulian Gross void runOnOperation() override { 74*ae1ea0beSJulian Gross RewritePatternSet patterns(&getContext()); 75*ae1ea0beSJulian Gross populateBufferizationToMemRefConversionPatterns(patterns); 76*ae1ea0beSJulian Gross 77*ae1ea0beSJulian Gross ConversionTarget target(getContext()); 78*ae1ea0beSJulian Gross target.addLegalDialect<memref::MemRefDialect>(); 79*ae1ea0beSJulian Gross target.addLegalOp<arith::ConstantOp>(); 80*ae1ea0beSJulian Gross target.addIllegalDialect<bufferization::BufferizationDialect>(); 81*ae1ea0beSJulian Gross 82*ae1ea0beSJulian Gross if (failed(applyPartialConversion(getOperation(), target, 83*ae1ea0beSJulian Gross std::move(patterns)))) 84*ae1ea0beSJulian Gross signalPassFailure(); 85*ae1ea0beSJulian Gross } 86*ae1ea0beSJulian Gross }; 87*ae1ea0beSJulian Gross } // namespace 88*ae1ea0beSJulian Gross 89*ae1ea0beSJulian Gross std::unique_ptr<Pass> mlir::createBufferizationToMemRefPass() { 90*ae1ea0beSJulian Gross return std::make_unique<BufferizationToMemRefPass>(); 91*ae1ea0beSJulian Gross } 92