//===- MemRefToEmitC.cpp - MemRef to EmitC conversion ---------------------===// // // 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 // //===----------------------------------------------------------------------===// // // This file implements patterns to convert memref ops into emitc ops. // //===----------------------------------------------------------------------===// #include "mlir/Conversion/MemRefToEmitC/MemRefToEmitC.h" #include "mlir/Dialect/EmitC/IR/EmitC.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" #include "mlir/IR/Builders.h" #include "mlir/IR/PatternMatch.h" #include "mlir/Transforms/DialectConversion.h" using namespace mlir; namespace { struct ConvertAlloca final : public OpConversionPattern { using OpConversionPattern::OpConversionPattern; LogicalResult matchAndRewrite(memref::AllocaOp op, OpAdaptor operands, ConversionPatternRewriter &rewriter) const override { if (!op.getType().hasStaticShape()) { return rewriter.notifyMatchFailure( op.getLoc(), "cannot transform alloca with dynamic shape"); } if (op.getAlignment().value_or(1) > 1) { // TODO: Allow alignment if it is not more than the natural alignment // of the C array. return rewriter.notifyMatchFailure( op.getLoc(), "cannot transform alloca with alignment requirement"); } auto resultTy = getTypeConverter()->convertType(op.getType()); if (!resultTy) { return rewriter.notifyMatchFailure(op.getLoc(), "cannot convert type"); } auto noInit = emitc::OpaqueAttr::get(getContext(), ""); rewriter.replaceOpWithNewOp(op, resultTy, noInit); return success(); } }; struct ConvertLoad final : public OpConversionPattern { using OpConversionPattern::OpConversionPattern; LogicalResult matchAndRewrite(memref::LoadOp op, OpAdaptor operands, ConversionPatternRewriter &rewriter) const override { auto resultTy = getTypeConverter()->convertType(op.getType()); if (!resultTy) { return rewriter.notifyMatchFailure(op.getLoc(), "cannot convert type"); } auto arrayValue = dyn_cast>(operands.getMemref()); if (!arrayValue) { return rewriter.notifyMatchFailure(op.getLoc(), "expected array type"); } auto subscript = rewriter.create( op.getLoc(), arrayValue, operands.getIndices()); auto noInit = emitc::OpaqueAttr::get(getContext(), ""); auto var = rewriter.create(op.getLoc(), resultTy, noInit); rewriter.create(op.getLoc(), var, subscript); rewriter.replaceOp(op, var); return success(); } }; struct ConvertStore final : public OpConversionPattern { using OpConversionPattern::OpConversionPattern; LogicalResult matchAndRewrite(memref::StoreOp op, OpAdaptor operands, ConversionPatternRewriter &rewriter) const override { auto arrayValue = dyn_cast>(operands.getMemref()); if (!arrayValue) { return rewriter.notifyMatchFailure(op.getLoc(), "expected array type"); } auto subscript = rewriter.create( op.getLoc(), arrayValue, operands.getIndices()); rewriter.replaceOpWithNewOp(op, subscript, operands.getValue()); return success(); } }; } // namespace void mlir::populateMemRefToEmitCTypeConversion(TypeConverter &typeConverter) { typeConverter.addConversion( [&](MemRefType memRefType) -> std::optional { if (!memRefType.hasStaticShape() || !memRefType.getLayout().isIdentity() || memRefType.getRank() == 0) { return {}; } Type convertedElementType = typeConverter.convertType(memRefType.getElementType()); if (!convertedElementType) return {}; return emitc::ArrayType::get(memRefType.getShape(), convertedElementType); }); } void mlir::populateMemRefToEmitCConversionPatterns(RewritePatternSet &patterns, TypeConverter &converter) { patterns.add(converter, patterns.getContext()); }