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