1250dcf61SAlexander Belyaev //===- ShapeToShapeLowering.cpp - Prepare for lowering to Standard --------===//
2250dcf61SAlexander Belyaev //
3250dcf61SAlexander Belyaev // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4250dcf61SAlexander Belyaev // See https://llvm.org/LICENSE.txt for license information.
5250dcf61SAlexander Belyaev // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6250dcf61SAlexander Belyaev //
7250dcf61SAlexander Belyaev //===----------------------------------------------------------------------===//
8250dcf61SAlexander Belyaev 
9250dcf61SAlexander Belyaev #include "PassDetail.h"
10*a54f4eaeSMogball #include "mlir/Dialect/Arithmetic/IR/Arithmetic.h"
11250dcf61SAlexander Belyaev #include "mlir/Dialect/Shape/IR/Shape.h"
12250dcf61SAlexander Belyaev #include "mlir/Dialect/Shape/Transforms/Passes.h"
136d10d317SStephan Herhut #include "mlir/Dialect/StandardOps/IR/Ops.h"
14250dcf61SAlexander Belyaev #include "mlir/IR/Builders.h"
15250dcf61SAlexander Belyaev #include "mlir/IR/PatternMatch.h"
16250dcf61SAlexander Belyaev #include "mlir/Pass/Pass.h"
17250dcf61SAlexander Belyaev #include "mlir/Transforms/DialectConversion.h"
18250dcf61SAlexander Belyaev 
19250dcf61SAlexander Belyaev using namespace mlir;
20250dcf61SAlexander Belyaev using namespace mlir::shape;
21250dcf61SAlexander Belyaev 
22250dcf61SAlexander Belyaev namespace {
23250dcf61SAlexander Belyaev /// Converts `shape.num_elements` to `shape.reduce`.
24250dcf61SAlexander Belyaev struct NumElementsOpConverter : public OpRewritePattern<NumElementsOp> {
25250dcf61SAlexander Belyaev public:
26250dcf61SAlexander Belyaev   using OpRewritePattern::OpRewritePattern;
27250dcf61SAlexander Belyaev 
28250dcf61SAlexander Belyaev   LogicalResult matchAndRewrite(NumElementsOp op,
29250dcf61SAlexander Belyaev                                 PatternRewriter &rewriter) const final;
30250dcf61SAlexander Belyaev };
31250dcf61SAlexander Belyaev } // namespace
32250dcf61SAlexander Belyaev 
33250dcf61SAlexander Belyaev LogicalResult
34250dcf61SAlexander Belyaev NumElementsOpConverter::matchAndRewrite(NumElementsOp op,
35250dcf61SAlexander Belyaev                                         PatternRewriter &rewriter) const {
36250dcf61SAlexander Belyaev   auto loc = op.getLoc();
376d10d317SStephan Herhut   Type valueType = op.getResult().getType();
380bf4a82aSChristian Sigg   Value init = op->getDialect()
396d10d317SStephan Herhut                    ->materializeConstant(rewriter, rewriter.getIndexAttr(1),
406d10d317SStephan Herhut                                          valueType, loc)
416d10d317SStephan Herhut                    ->getResult(0);
42250dcf61SAlexander Belyaev   ReduceOp reduce = rewriter.create<ReduceOp>(loc, op.shape(), init);
43250dcf61SAlexander Belyaev 
44250dcf61SAlexander Belyaev   // Generate reduce operator.
45250dcf61SAlexander Belyaev   Block *body = reduce.getBody();
46250dcf61SAlexander Belyaev   OpBuilder b = OpBuilder::atBlockEnd(body);
476d10d317SStephan Herhut   Value product = b.create<MulOp>(loc, valueType, body->getArgument(1),
486d10d317SStephan Herhut                                   body->getArgument(2));
49136eb79aSFrederik Gossen   b.create<shape::YieldOp>(loc, product);
50250dcf61SAlexander Belyaev 
51250dcf61SAlexander Belyaev   rewriter.replaceOp(op, reduce.result());
52250dcf61SAlexander Belyaev   return success();
53250dcf61SAlexander Belyaev }
54250dcf61SAlexander Belyaev 
55250dcf61SAlexander Belyaev namespace {
56250dcf61SAlexander Belyaev struct ShapeToShapeLowering
57250dcf61SAlexander Belyaev     : public ShapeToShapeLoweringBase<ShapeToShapeLowering> {
58250dcf61SAlexander Belyaev   void runOnFunction() override;
59250dcf61SAlexander Belyaev };
60250dcf61SAlexander Belyaev } // namespace
61250dcf61SAlexander Belyaev 
62250dcf61SAlexander Belyaev void ShapeToShapeLowering::runOnFunction() {
637a9258e9SAlexander Belyaev   MLIRContext &ctx = getContext();
647a9258e9SAlexander Belyaev 
65dc4e913bSChris Lattner   RewritePatternSet patterns(&ctx);
663a506b31SChris Lattner   populateShapeRewritePatterns(patterns);
67250dcf61SAlexander Belyaev 
68250dcf61SAlexander Belyaev   ConversionTarget target(getContext());
69*a54f4eaeSMogball   target.addLegalDialect<arith::ArithmeticDialect, ShapeDialect,
70*a54f4eaeSMogball                          StandardOpsDialect>();
71250dcf61SAlexander Belyaev   target.addIllegalOp<NumElementsOp>();
723fffffa8SRiver Riddle   if (failed(mlir::applyPartialConversion(getFunction(), target,
733fffffa8SRiver Riddle                                           std::move(patterns))))
74250dcf61SAlexander Belyaev     signalPassFailure();
75250dcf61SAlexander Belyaev }
76250dcf61SAlexander Belyaev 
77dc4e913bSChris Lattner void mlir::populateShapeRewritePatterns(RewritePatternSet &patterns) {
78dc4e913bSChris Lattner   patterns.add<NumElementsOpConverter>(patterns.getContext());
797a9258e9SAlexander Belyaev }
807a9258e9SAlexander Belyaev 
81250dcf61SAlexander Belyaev std::unique_ptr<Pass> mlir::createShapeToShapeLowering() {
82250dcf61SAlexander Belyaev   return std::make_unique<ShapeToShapeLowering>();
83250dcf61SAlexander Belyaev }
84