xref: /llvm-project/flang/lib/Optimizer/CodeGen/PreCGRewrite.cpp (revision 0def9a923dadc2b2b3dd067eefcef541e475594c)
197d8972cSEric Schweitz //===-- PreCGRewrite.cpp --------------------------------------------------===//
297d8972cSEric Schweitz //
397d8972cSEric Schweitz // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
497d8972cSEric Schweitz // See https://llvm.org/LICENSE.txt for license information.
597d8972cSEric Schweitz // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
697d8972cSEric Schweitz //
797d8972cSEric Schweitz //===----------------------------------------------------------------------===//
897d8972cSEric Schweitz //
997d8972cSEric Schweitz // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
1097d8972cSEric Schweitz //
1197d8972cSEric Schweitz //===----------------------------------------------------------------------===//
1297d8972cSEric Schweitz 
13039b969bSMichele Scuttari #include "flang/Optimizer/CodeGen/CodeGen.h"
1467d0d7acSMichele Scuttari 
159d99b482SValentin Clement #include "flang/Optimizer/Builder/Todo.h" // remove when TODO's are done
16cd5ee271SAbid Qadeer #include "flang/Optimizer/CodeGen/CGOps.h"
1797d8972cSEric Schweitz #include "flang/Optimizer/Dialect/FIRDialect.h"
1897d8972cSEric Schweitz #include "flang/Optimizer/Dialect/FIROps.h"
1997d8972cSEric Schweitz #include "flang/Optimizer/Dialect/FIRType.h"
20b07ef9e7SRenaud-K #include "flang/Optimizer/Dialect/Support/FIRContext.h"
21bf08d0e1SjeanPerier #include "mlir/IR/Iterators.h"
2297d8972cSEric Schweitz #include "mlir/Transforms/DialectConversion.h"
2397d8972cSEric Schweitz #include "llvm/ADT/STLExtras.h"
24861eff24SNico Weber #include "llvm/Support/Debug.h"
2597d8972cSEric Schweitz 
2667d0d7acSMichele Scuttari namespace fir {
2767d0d7acSMichele Scuttari #define GEN_PASS_DEF_CODEGENREWRITE
2867d0d7acSMichele Scuttari #include "flang/Optimizer/CodeGen/CGPasses.h.inc"
2967d0d7acSMichele Scuttari } // namespace fir
3067d0d7acSMichele Scuttari 
3197d8972cSEric Schweitz //===----------------------------------------------------------------------===//
3297d8972cSEric Schweitz // Codegen rewrite: rewriting of subgraphs of ops
3397d8972cSEric Schweitz //===----------------------------------------------------------------------===//
3497d8972cSEric Schweitz 
3597d8972cSEric Schweitz #define DEBUG_TYPE "flang-codegen-rewrite"
3697d8972cSEric Schweitz 
3797d8972cSEric Schweitz static void populateShape(llvm::SmallVectorImpl<mlir::Value> &vec,
381f31795cSEric Schweitz                           fir::ShapeOp shape) {
39149ad3d5SShraiysh Vaishay   vec.append(shape.getExtents().begin(), shape.getExtents().end());
4097d8972cSEric Schweitz }
4197d8972cSEric Schweitz 
4297d8972cSEric Schweitz // Operands of fir.shape_shift split into two vectors.
4397d8972cSEric Schweitz static void populateShapeAndShift(llvm::SmallVectorImpl<mlir::Value> &shapeVec,
4497d8972cSEric Schweitz                                   llvm::SmallVectorImpl<mlir::Value> &shiftVec,
451f31795cSEric Schweitz                                   fir::ShapeShiftOp shift) {
461f31795cSEric Schweitz   for (auto i = shift.getPairs().begin(), endIter = shift.getPairs().end();
471f31795cSEric Schweitz        i != endIter;) {
4897d8972cSEric Schweitz     shiftVec.push_back(*i++);
4997d8972cSEric Schweitz     shapeVec.push_back(*i++);
5097d8972cSEric Schweitz   }
5197d8972cSEric Schweitz }
5297d8972cSEric Schweitz 
5397d8972cSEric Schweitz static void populateShift(llvm::SmallVectorImpl<mlir::Value> &vec,
541f31795cSEric Schweitz                           fir::ShiftOp shift) {
55149ad3d5SShraiysh Vaishay   vec.append(shift.getOrigins().begin(), shift.getOrigins().end());
5697d8972cSEric Schweitz }
5797d8972cSEric Schweitz 
5897d8972cSEric Schweitz namespace {
5997d8972cSEric Schweitz 
6097d8972cSEric Schweitz /// Convert fir.embox to the extended form where necessary.
6197d8972cSEric Schweitz ///
6297d8972cSEric Schweitz /// The embox operation can take arguments that specify multidimensional array
6397d8972cSEric Schweitz /// properties at runtime. These properties may be shared between distinct
6497d8972cSEric Schweitz /// objects that have the same properties. Before we lower these small DAGs to
6597d8972cSEric Schweitz /// LLVM-IR, we gather all the information into a single extended operation. For
6697d8972cSEric Schweitz /// example,
6797d8972cSEric Schweitz /// ```
6897d8972cSEric Schweitz /// %1 = fir.shape_shift %4, %5 : (index, index) -> !fir.shapeshift<1>
6997d8972cSEric Schweitz /// %2 = fir.slice %6, %7, %8 : (index, index, index) -> !fir.slice<1>
70a54f4eaeSMogball /// %3 = fir.embox %0 (%1) [%2] : (!fir.ref<!fir.array<?xi32>>,
71a54f4eaeSMogball /// !fir.shapeshift<1>, !fir.slice<1>) -> !fir.box<!fir.array<?xi32>>
7297d8972cSEric Schweitz /// ```
7397d8972cSEric Schweitz /// can be rewritten as
7497d8972cSEric Schweitz /// ```
75a54f4eaeSMogball /// %1 = fircg.ext_embox %0(%5) origin %4[%6, %7, %8] :
76a54f4eaeSMogball /// (!fir.ref<!fir.array<?xi32>>, index, index, index, index, index) ->
77a54f4eaeSMogball /// !fir.box<!fir.array<?xi32>>
7897d8972cSEric Schweitz /// ```
791f31795cSEric Schweitz class EmboxConversion : public mlir::OpRewritePattern<fir::EmboxOp> {
8097d8972cSEric Schweitz public:
8197d8972cSEric Schweitz   using OpRewritePattern::OpRewritePattern;
8297d8972cSEric Schweitz 
83db791b27SRamkumar Ramachandra   llvm::LogicalResult
841f31795cSEric Schweitz   matchAndRewrite(fir::EmboxOp embox,
8597d8972cSEric Schweitz                   mlir::PatternRewriter &rewriter) const override {
8697d8972cSEric Schweitz     // If the embox does not include a shape, then do not convert it
871f31795cSEric Schweitz     if (auto shapeVal = embox.getShape())
8897d8972cSEric Schweitz       return rewriteDynamicShape(embox, rewriter, shapeVal);
89fac349a1SChristian Sigg     if (mlir::isa<fir::ClassType>(embox.getType()))
909d99b482SValentin Clement       TODO(embox.getLoc(), "embox conversion for fir.class type");
91fac349a1SChristian Sigg     if (auto boxTy = mlir::dyn_cast<fir::BoxType>(embox.getType()))
92fac349a1SChristian Sigg       if (auto seqTy = mlir::dyn_cast<fir::SequenceType>(boxTy.getEleTy()))
937ae39114SMats Petersson         if (!seqTy.hasDynamicExtents())
9497d8972cSEric Schweitz           return rewriteStaticShape(embox, rewriter, seqTy);
9597d8972cSEric Schweitz     return mlir::failure();
9697d8972cSEric Schweitz   }
9797d8972cSEric Schweitz 
98db791b27SRamkumar Ramachandra   llvm::LogicalResult rewriteStaticShape(fir::EmboxOp embox,
9997d8972cSEric Schweitz                                          mlir::PatternRewriter &rewriter,
1001f31795cSEric Schweitz                                          fir::SequenceType seqTy) const {
10197d8972cSEric Schweitz     auto loc = embox.getLoc();
10297d8972cSEric Schweitz     llvm::SmallVector<mlir::Value> shapeOpers;
10397d8972cSEric Schweitz     auto idxTy = rewriter.getIndexType();
10497d8972cSEric Schweitz     for (auto ext : seqTy.getShape()) {
10597d8972cSEric Schweitz       auto iAttr = rewriter.getIndexAttr(ext);
106a54f4eaeSMogball       auto extVal = rewriter.create<mlir::arith::ConstantOp>(loc, idxTy, iAttr);
10797d8972cSEric Schweitz       shapeOpers.push_back(extVal);
10897d8972cSEric Schweitz     }
1091f31795cSEric Schweitz     auto xbox = rewriter.create<fir::cg::XEmboxOp>(
1109a417395SKazu Hirata         loc, embox.getType(), embox.getMemref(), shapeOpers, std::nullopt,
1119a417395SKazu Hirata         std::nullopt, std::nullopt, std::nullopt, embox.getTypeparams(),
112*0def9a92SValentin Clement (バレンタイン クレメン)         embox.getSourceBox(), embox.getAllocatorIdxAttr());
11397d8972cSEric Schweitz     LLVM_DEBUG(llvm::dbgs() << "rewriting " << embox << " to " << xbox << '\n');
11497d8972cSEric Schweitz     rewriter.replaceOp(embox, xbox.getOperation()->getResults());
11597d8972cSEric Schweitz     return mlir::success();
11697d8972cSEric Schweitz   }
11797d8972cSEric Schweitz 
118db791b27SRamkumar Ramachandra   llvm::LogicalResult rewriteDynamicShape(fir::EmboxOp embox,
11997d8972cSEric Schweitz                                           mlir::PatternRewriter &rewriter,
12097d8972cSEric Schweitz                                           mlir::Value shapeVal) const {
12197d8972cSEric Schweitz     auto loc = embox.getLoc();
12297d8972cSEric Schweitz     llvm::SmallVector<mlir::Value> shapeOpers;
12397d8972cSEric Schweitz     llvm::SmallVector<mlir::Value> shiftOpers;
1241f31795cSEric Schweitz     if (auto shapeOp = mlir::dyn_cast<fir::ShapeOp>(shapeVal.getDefiningOp())) {
12597d8972cSEric Schweitz       populateShape(shapeOpers, shapeOp);
12697d8972cSEric Schweitz     } else {
1271f31795cSEric Schweitz       auto shiftOp =
1281f31795cSEric Schweitz           mlir::dyn_cast<fir::ShapeShiftOp>(shapeVal.getDefiningOp());
12997d8972cSEric Schweitz       assert(shiftOp && "shape is neither fir.shape nor fir.shape_shift");
13097d8972cSEric Schweitz       populateShapeAndShift(shapeOpers, shiftOpers, shiftOp);
13197d8972cSEric Schweitz     }
13297d8972cSEric Schweitz     llvm::SmallVector<mlir::Value> sliceOpers;
13397d8972cSEric Schweitz     llvm::SmallVector<mlir::Value> subcompOpers;
1343c7ff45cSValentin Clement     llvm::SmallVector<mlir::Value> substrOpers;
13597d8972cSEric Schweitz     if (auto s = embox.getSlice())
1361f31795cSEric Schweitz       if (auto sliceOp =
1371f31795cSEric Schweitz               mlir::dyn_cast_or_null<fir::SliceOp>(s.getDefiningOp())) {
138149ad3d5SShraiysh Vaishay         sliceOpers.assign(sliceOp.getTriples().begin(),
139149ad3d5SShraiysh Vaishay                           sliceOp.getTriples().end());
140149ad3d5SShraiysh Vaishay         subcompOpers.assign(sliceOp.getFields().begin(),
141149ad3d5SShraiysh Vaishay                             sliceOp.getFields().end());
142149ad3d5SShraiysh Vaishay         substrOpers.assign(sliceOp.getSubstr().begin(),
143149ad3d5SShraiysh Vaishay                            sliceOp.getSubstr().end());
14497d8972cSEric Schweitz       }
1451f31795cSEric Schweitz     auto xbox = rewriter.create<fir::cg::XEmboxOp>(
146149ad3d5SShraiysh Vaishay         loc, embox.getType(), embox.getMemref(), shapeOpers, shiftOpers,
1472e978986SValentin Clement         sliceOpers, subcompOpers, substrOpers, embox.getTypeparams(),
148*0def9a92SValentin Clement (バレンタイン クレメン)         embox.getSourceBox(), embox.getAllocatorIdxAttr());
14997d8972cSEric Schweitz     LLVM_DEBUG(llvm::dbgs() << "rewriting " << embox << " to " << xbox << '\n');
15097d8972cSEric Schweitz     rewriter.replaceOp(embox, xbox.getOperation()->getResults());
15197d8972cSEric Schweitz     return mlir::success();
15297d8972cSEric Schweitz   }
15397d8972cSEric Schweitz };
15497d8972cSEric Schweitz 
15597d8972cSEric Schweitz /// Convert fir.rebox to the extended form where necessary.
15697d8972cSEric Schweitz ///
15797d8972cSEric Schweitz /// For example,
15897d8972cSEric Schweitz /// ```
159a54f4eaeSMogball /// %5 = fir.rebox %3(%1) : (!fir.box<!fir.array<?xi32>>, !fir.shapeshift<1>) ->
160a54f4eaeSMogball /// !fir.box<!fir.array<?xi32>>
16197d8972cSEric Schweitz /// ```
16297d8972cSEric Schweitz /// converted to
16397d8972cSEric Schweitz /// ```
164a54f4eaeSMogball /// %5 = fircg.ext_rebox %3(%13) origin %12 : (!fir.box<!fir.array<?xi32>>,
165a54f4eaeSMogball /// index, index) -> !fir.box<!fir.array<?xi32>>
16697d8972cSEric Schweitz /// ```
1671f31795cSEric Schweitz class ReboxConversion : public mlir::OpRewritePattern<fir::ReboxOp> {
16897d8972cSEric Schweitz public:
16997d8972cSEric Schweitz   using OpRewritePattern::OpRewritePattern;
17097d8972cSEric Schweitz 
171db791b27SRamkumar Ramachandra   llvm::LogicalResult
1721f31795cSEric Schweitz   matchAndRewrite(fir::ReboxOp rebox,
17397d8972cSEric Schweitz                   mlir::PatternRewriter &rewriter) const override {
17497d8972cSEric Schweitz     auto loc = rebox.getLoc();
17597d8972cSEric Schweitz     llvm::SmallVector<mlir::Value> shapeOpers;
17697d8972cSEric Schweitz     llvm::SmallVector<mlir::Value> shiftOpers;
177149ad3d5SShraiysh Vaishay     if (auto shapeVal = rebox.getShape()) {
1781f31795cSEric Schweitz       if (auto shapeOp = mlir::dyn_cast<fir::ShapeOp>(shapeVal.getDefiningOp()))
17997d8972cSEric Schweitz         populateShape(shapeOpers, shapeOp);
1801f31795cSEric Schweitz       else if (auto shiftOp =
1811f31795cSEric Schweitz                    mlir::dyn_cast<fir::ShapeShiftOp>(shapeVal.getDefiningOp()))
18297d8972cSEric Schweitz         populateShapeAndShift(shapeOpers, shiftOpers, shiftOp);
1831f31795cSEric Schweitz       else if (auto shiftOp =
1841f31795cSEric Schweitz                    mlir::dyn_cast<fir::ShiftOp>(shapeVal.getDefiningOp()))
18597d8972cSEric Schweitz         populateShift(shiftOpers, shiftOp);
18697d8972cSEric Schweitz       else
18797d8972cSEric Schweitz         return mlir::failure();
18897d8972cSEric Schweitz     }
18997d8972cSEric Schweitz     llvm::SmallVector<mlir::Value> sliceOpers;
19097d8972cSEric Schweitz     llvm::SmallVector<mlir::Value> subcompOpers;
1913c7ff45cSValentin Clement     llvm::SmallVector<mlir::Value> substrOpers;
192149ad3d5SShraiysh Vaishay     if (auto s = rebox.getSlice())
1931f31795cSEric Schweitz       if (auto sliceOp =
1941f31795cSEric Schweitz               mlir::dyn_cast_or_null<fir::SliceOp>(s.getDefiningOp())) {
195149ad3d5SShraiysh Vaishay         sliceOpers.append(sliceOp.getTriples().begin(),
196149ad3d5SShraiysh Vaishay                           sliceOp.getTriples().end());
197149ad3d5SShraiysh Vaishay         subcompOpers.append(sliceOp.getFields().begin(),
198149ad3d5SShraiysh Vaishay                             sliceOp.getFields().end());
199149ad3d5SShraiysh Vaishay         substrOpers.append(sliceOp.getSubstr().begin(),
200149ad3d5SShraiysh Vaishay                            sliceOp.getSubstr().end());
20197d8972cSEric Schweitz       }
20297d8972cSEric Schweitz 
2031f31795cSEric Schweitz     auto xRebox = rewriter.create<fir::cg::XReboxOp>(
204149ad3d5SShraiysh Vaishay         loc, rebox.getType(), rebox.getBox(), shapeOpers, shiftOpers,
205149ad3d5SShraiysh Vaishay         sliceOpers, subcompOpers, substrOpers);
20697d8972cSEric Schweitz     LLVM_DEBUG(llvm::dbgs()
20797d8972cSEric Schweitz                << "rewriting " << rebox << " to " << xRebox << '\n');
20897d8972cSEric Schweitz     rewriter.replaceOp(rebox, xRebox.getOperation()->getResults());
20997d8972cSEric Schweitz     return mlir::success();
21097d8972cSEric Schweitz   }
21197d8972cSEric Schweitz };
21297d8972cSEric Schweitz 
21397d8972cSEric Schweitz /// Convert all fir.array_coor to the extended form.
21497d8972cSEric Schweitz ///
21597d8972cSEric Schweitz /// For example,
21697d8972cSEric Schweitz /// ```
217a54f4eaeSMogball ///  %4 = fir.array_coor %addr (%1) [%2] %0 : (!fir.ref<!fir.array<?xi32>>,
218a54f4eaeSMogball ///  !fir.shapeshift<1>, !fir.slice<1>, index) -> !fir.ref<i32>
21997d8972cSEric Schweitz /// ```
22097d8972cSEric Schweitz /// converted to
22197d8972cSEric Schweitz /// ```
222a54f4eaeSMogball /// %40 = fircg.ext_array_coor %addr(%9) origin %8[%4, %5, %6<%39> :
223a54f4eaeSMogball /// (!fir.ref<!fir.array<?xi32>>, index, index, index, index, index, index) ->
224a54f4eaeSMogball /// !fir.ref<i32>
22597d8972cSEric Schweitz /// ```
2261f31795cSEric Schweitz class ArrayCoorConversion : public mlir::OpRewritePattern<fir::ArrayCoorOp> {
22797d8972cSEric Schweitz public:
22897d8972cSEric Schweitz   using OpRewritePattern::OpRewritePattern;
22997d8972cSEric Schweitz 
230db791b27SRamkumar Ramachandra   llvm::LogicalResult
2311f31795cSEric Schweitz   matchAndRewrite(fir::ArrayCoorOp arrCoor,
23297d8972cSEric Schweitz                   mlir::PatternRewriter &rewriter) const override {
23397d8972cSEric Schweitz     auto loc = arrCoor.getLoc();
23497d8972cSEric Schweitz     llvm::SmallVector<mlir::Value> shapeOpers;
23597d8972cSEric Schweitz     llvm::SmallVector<mlir::Value> shiftOpers;
236149ad3d5SShraiysh Vaishay     if (auto shapeVal = arrCoor.getShape()) {
2371f31795cSEric Schweitz       if (auto shapeOp = mlir::dyn_cast<fir::ShapeOp>(shapeVal.getDefiningOp()))
23897d8972cSEric Schweitz         populateShape(shapeOpers, shapeOp);
2391f31795cSEric Schweitz       else if (auto shiftOp =
2401f31795cSEric Schweitz                    mlir::dyn_cast<fir::ShapeShiftOp>(shapeVal.getDefiningOp()))
24197d8972cSEric Schweitz         populateShapeAndShift(shapeOpers, shiftOpers, shiftOp);
2421f31795cSEric Schweitz       else if (auto shiftOp =
2431f31795cSEric Schweitz                    mlir::dyn_cast<fir::ShiftOp>(shapeVal.getDefiningOp()))
24497d8972cSEric Schweitz         populateShift(shiftOpers, shiftOp);
24597d8972cSEric Schweitz       else
24697d8972cSEric Schweitz         return mlir::failure();
24797d8972cSEric Schweitz     }
24897d8972cSEric Schweitz     llvm::SmallVector<mlir::Value> sliceOpers;
24997d8972cSEric Schweitz     llvm::SmallVector<mlir::Value> subcompOpers;
250149ad3d5SShraiysh Vaishay     if (auto s = arrCoor.getSlice())
2511f31795cSEric Schweitz       if (auto sliceOp =
2521f31795cSEric Schweitz               mlir::dyn_cast_or_null<fir::SliceOp>(s.getDefiningOp())) {
253149ad3d5SShraiysh Vaishay         sliceOpers.append(sliceOp.getTriples().begin(),
254149ad3d5SShraiysh Vaishay                           sliceOp.getTriples().end());
255149ad3d5SShraiysh Vaishay         subcompOpers.append(sliceOp.getFields().begin(),
256149ad3d5SShraiysh Vaishay                             sliceOp.getFields().end());
257149ad3d5SShraiysh Vaishay         assert(sliceOp.getSubstr().empty() &&
2583c7ff45cSValentin Clement                "Don't allow substring operations on array_coor. This "
2593c7ff45cSValentin Clement                "restriction may be lifted in the future.");
26097d8972cSEric Schweitz       }
2611f31795cSEric Schweitz     auto xArrCoor = rewriter.create<fir::cg::XArrayCoorOp>(
262149ad3d5SShraiysh Vaishay         loc, arrCoor.getType(), arrCoor.getMemref(), shapeOpers, shiftOpers,
263149ad3d5SShraiysh Vaishay         sliceOpers, subcompOpers, arrCoor.getIndices(),
264149ad3d5SShraiysh Vaishay         arrCoor.getTypeparams());
26597d8972cSEric Schweitz     LLVM_DEBUG(llvm::dbgs()
26697d8972cSEric Schweitz                << "rewriting " << arrCoor << " to " << xArrCoor << '\n');
26797d8972cSEric Schweitz     rewriter.replaceOp(arrCoor, xArrCoor.getOperation()->getResults());
26897d8972cSEric Schweitz     return mlir::success();
26997d8972cSEric Schweitz   }
27097d8972cSEric Schweitz };
27197d8972cSEric Schweitz 
272c852174aSJean Perier class DeclareOpConversion : public mlir::OpRewritePattern<fir::DeclareOp> {
273cd5ee271SAbid Qadeer   bool preserveDeclare;
274cd5ee271SAbid Qadeer 
275c852174aSJean Perier public:
276c852174aSJean Perier   using OpRewritePattern::OpRewritePattern;
277cd5ee271SAbid Qadeer   DeclareOpConversion(mlir::MLIRContext *ctx, bool preserveDecl)
278cd5ee271SAbid Qadeer       : OpRewritePattern(ctx), preserveDeclare(preserveDecl) {}
279c852174aSJean Perier 
280db791b27SRamkumar Ramachandra   llvm::LogicalResult
281c852174aSJean Perier   matchAndRewrite(fir::DeclareOp declareOp,
282c852174aSJean Perier                   mlir::PatternRewriter &rewriter) const override {
283cd5ee271SAbid Qadeer     if (!preserveDeclare) {
284c852174aSJean Perier       rewriter.replaceOp(declareOp, declareOp.getMemref());
285c852174aSJean Perier       return mlir::success();
286c852174aSJean Perier     }
287cd5ee271SAbid Qadeer     auto loc = declareOp.getLoc();
288cd5ee271SAbid Qadeer     llvm::SmallVector<mlir::Value> shapeOpers;
289cd5ee271SAbid Qadeer     llvm::SmallVector<mlir::Value> shiftOpers;
290cd5ee271SAbid Qadeer     if (auto shapeVal = declareOp.getShape()) {
291cd5ee271SAbid Qadeer       if (auto shapeOp = mlir::dyn_cast<fir::ShapeOp>(shapeVal.getDefiningOp()))
292cd5ee271SAbid Qadeer         populateShape(shapeOpers, shapeOp);
293cd5ee271SAbid Qadeer       else if (auto shiftOp =
294cd5ee271SAbid Qadeer                    mlir::dyn_cast<fir::ShapeShiftOp>(shapeVal.getDefiningOp()))
295cd5ee271SAbid Qadeer         populateShapeAndShift(shapeOpers, shiftOpers, shiftOp);
296cd5ee271SAbid Qadeer       else if (auto shiftOp =
297cd5ee271SAbid Qadeer                    mlir::dyn_cast<fir::ShiftOp>(shapeVal.getDefiningOp()))
298cd5ee271SAbid Qadeer         populateShift(shiftOpers, shiftOp);
299cd5ee271SAbid Qadeer       else
300cd5ee271SAbid Qadeer         return mlir::failure();
301cd5ee271SAbid Qadeer     }
302cd5ee271SAbid Qadeer     // FIXME: Add FortranAttrs and CudaAttrs
303cd5ee271SAbid Qadeer     auto xDeclOp = rewriter.create<fir::cg::XDeclareOp>(
304cd5ee271SAbid Qadeer         loc, declareOp.getType(), declareOp.getMemref(), shapeOpers, shiftOpers,
305cd5ee271SAbid Qadeer         declareOp.getTypeparams(), declareOp.getDummyScope(),
306cd5ee271SAbid Qadeer         declareOp.getUniqName());
307cd5ee271SAbid Qadeer     LLVM_DEBUG(llvm::dbgs()
308cd5ee271SAbid Qadeer                << "rewriting " << declareOp << " to " << xDeclOp << '\n');
309cd5ee271SAbid Qadeer     rewriter.replaceOp(declareOp, xDeclOp.getOperation()->getResults());
310cd5ee271SAbid Qadeer     return mlir::success();
311cd5ee271SAbid Qadeer   }
312c852174aSJean Perier };
313c852174aSJean Perier 
314986f832cSSlava Zakharin class DummyScopeOpConversion
315986f832cSSlava Zakharin     : public mlir::OpRewritePattern<fir::DummyScopeOp> {
316986f832cSSlava Zakharin public:
317986f832cSSlava Zakharin   using OpRewritePattern::OpRewritePattern;
318986f832cSSlava Zakharin 
319db791b27SRamkumar Ramachandra   llvm::LogicalResult
320986f832cSSlava Zakharin   matchAndRewrite(fir::DummyScopeOp dummyScopeOp,
321986f832cSSlava Zakharin                   mlir::PatternRewriter &rewriter) const override {
322986f832cSSlava Zakharin     rewriter.replaceOpWithNewOp<fir::UndefOp>(dummyScopeOp,
323986f832cSSlava Zakharin                                               dummyScopeOp.getType());
324986f832cSSlava Zakharin     return mlir::success();
325986f832cSSlava Zakharin   }
326986f832cSSlava Zakharin };
327986f832cSSlava Zakharin 
328bf08d0e1SjeanPerier /// Simple DCE to erase fir.shape/shift/slice/unused shape operands after this
329bf08d0e1SjeanPerier /// pass (fir.shape and like have no codegen).
330bf08d0e1SjeanPerier /// mlir::RegionDCE is expensive and requires running
331bf08d0e1SjeanPerier /// mlir::eraseUnreachableBlocks. It does things that are not needed here, like
332bf08d0e1SjeanPerier /// removing unused block arguments. fir.shape/shift/slice cannot be block
333bf08d0e1SjeanPerier /// arguments.
334bf08d0e1SjeanPerier /// This helper does a naive backward walk of the IR. It is not even guaranteed
335bf08d0e1SjeanPerier /// to walk blocks according to backward dominance, but that is good enough for
336bf08d0e1SjeanPerier /// what is done here, fir.shape/shift/slice have no usages anymore. The
337bf08d0e1SjeanPerier /// backward walk allows getting rid of most of the unused operands, it is not a
338bf08d0e1SjeanPerier /// problem to leave some in the weird cases.
339bf08d0e1SjeanPerier static void simpleDCE(mlir::RewriterBase &rewriter, mlir::Operation *op) {
340bf08d0e1SjeanPerier   op->walk<mlir::WalkOrder::PostOrder, mlir::ReverseIterator>(
341bf08d0e1SjeanPerier       [&](mlir::Operation *subOp) {
342bf08d0e1SjeanPerier         if (mlir::isOpTriviallyDead(subOp))
343bf08d0e1SjeanPerier           rewriter.eraseOp(subOp);
344bf08d0e1SjeanPerier       });
345bf08d0e1SjeanPerier }
346bf08d0e1SjeanPerier 
34767d0d7acSMichele Scuttari class CodeGenRewrite : public fir::impl::CodeGenRewriteBase<CodeGenRewrite> {
34897d8972cSEric Schweitz public:
3497eaae4e6STom Eccles   using CodeGenRewriteBase<CodeGenRewrite>::CodeGenRewriteBase;
3507eaae4e6STom Eccles 
3511f63a56cSTom Eccles   void runOnOperation() override final {
3521f63a56cSTom Eccles     mlir::ModuleOp mod = getOperation();
3531f63a56cSTom Eccles 
35497d8972cSEric Schweitz     auto &context = getContext();
35597d8972cSEric Schweitz     mlir::ConversionTarget target(context);
3566c8d8d10SJakub Kuderski     target.addLegalDialect<mlir::arith::ArithDialect, fir::FIROpsDialect,
3571f31795cSEric Schweitz                            fir::FIRCodeGenDialect, mlir::func::FuncDialect>();
3581f31795cSEric Schweitz     target.addIllegalOp<fir::ArrayCoorOp>();
3591f31795cSEric Schweitz     target.addIllegalOp<fir::ReboxOp>();
360c852174aSJean Perier     target.addIllegalOp<fir::DeclareOp>();
361986f832cSSlava Zakharin     target.addIllegalOp<fir::DummyScopeOp>();
3621f31795cSEric Schweitz     target.addDynamicallyLegalOp<fir::EmboxOp>([](fir::EmboxOp embox) {
363fac349a1SChristian Sigg       return !(embox.getShape() ||
364fac349a1SChristian Sigg                mlir::isa<fir::SequenceType>(
365fac349a1SChristian Sigg                    mlir::cast<fir::BaseBoxType>(embox.getType()).getEleTy()));
36697d8972cSEric Schweitz     });
3679f85c198SRiver Riddle     mlir::RewritePatternSet patterns(&context);
368cd5ee271SAbid Qadeer     fir::populatePreCGRewritePatterns(patterns, preserveDeclare);
36997d8972cSEric Schweitz     if (mlir::failed(
3701f63a56cSTom Eccles             mlir::applyPartialConversion(mod, target, std::move(patterns)))) {
37197d8972cSEric Schweitz       mlir::emitError(mlir::UnknownLoc::get(&context),
37297d8972cSEric Schweitz                       "error in running the pre-codegen conversions");
37397d8972cSEric Schweitz       signalPassFailure();
3742adcf1b2SJean Perier       return;
37597d8972cSEric Schweitz     }
3762adcf1b2SJean Perier     // Erase any residual (fir.shape, fir.slice...).
3772adcf1b2SJean Perier     mlir::IRRewriter rewriter(&context);
378bf08d0e1SjeanPerier     simpleDCE(rewriter, mod.getOperation());
379b09426ffSValentin Clement   }
38097d8972cSEric Schweitz };
38197d8972cSEric Schweitz 
38297d8972cSEric Schweitz } // namespace
38397d8972cSEric Schweitz 
384cd5ee271SAbid Qadeer void fir::populatePreCGRewritePatterns(mlir::RewritePatternSet &patterns,
385cd5ee271SAbid Qadeer                                        bool preserveDeclare) {
38622eb8000SValentin Clement (バレンタイン クレメン)   patterns.insert<EmboxConversion, ArrayCoorConversion, ReboxConversion,
387cd5ee271SAbid Qadeer                   DummyScopeOpConversion>(patterns.getContext());
388cd5ee271SAbid Qadeer   patterns.add<DeclareOpConversion>(patterns.getContext(), preserveDeclare);
38922eb8000SValentin Clement (バレンタイン クレメン) }
390