xref: /llvm-project/flang/lib/Optimizer/Dialect/FIRDialect.cpp (revision 45daa4fdc68f5faa5bd5c33da052d2415cd88540)
1 //===-- FIRDialect.cpp ----------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "flang/Optimizer/Dialect/FIRDialect.h"
14 #include "flang/Optimizer/Dialect/CUF/Attributes/CUFAttr.h"
15 #include "flang/Optimizer/Dialect/FIRAttr.h"
16 #include "flang/Optimizer/Dialect/FIROps.h"
17 #include "flang/Optimizer/Dialect/FIRType.h"
18 #include "mlir/Dialect/LLVMIR/LLVMDialect.h"
19 #include "mlir/Target/LLVMIR/ModuleTranslation.h"
20 #include "mlir/Transforms/InliningUtils.h"
21 
22 #include "flang/Optimizer/Dialect/FIRDialect.cpp.inc"
23 
24 using namespace fir;
25 
26 namespace {
27 /// This class defines the interface for handling inlining of FIR calls.
28 struct FIRInlinerInterface : public mlir::DialectInlinerInterface {
29   using DialectInlinerInterface::DialectInlinerInterface;
30 
isLegalToInline__anon85a0a6fe0111::FIRInlinerInterface31   bool isLegalToInline(mlir::Operation *call, mlir::Operation *callable,
32                        bool wouldBeCloned) const final {
33     return fir::canLegallyInline(call, callable, wouldBeCloned);
34   }
35 
36   /// This hook checks to see if the operation `op` is legal to inline into the
37   /// given region `reg`.
isLegalToInline__anon85a0a6fe0111::FIRInlinerInterface38   bool isLegalToInline(mlir::Operation *op, mlir::Region *reg,
39                        bool wouldBeCloned, mlir::IRMapping &map) const final {
40     return fir::canLegallyInline(op, reg, wouldBeCloned, map);
41   }
42 
43   /// This hook is called when a terminator operation has been inlined.
44   /// We handle the return (a Fortran FUNCTION) by replacing the values
45   /// previously returned by the call operation with the operands of the
46   /// return.
handleTerminator__anon85a0a6fe0111::FIRInlinerInterface47   void handleTerminator(mlir::Operation *op,
48                         mlir::ValueRange valuesToRepl) const final {
49     auto returnOp = llvm::cast<mlir::func::ReturnOp>(op);
50     assert(returnOp.getNumOperands() == valuesToRepl.size());
51     for (const auto &it : llvm::enumerate(returnOp.getOperands()))
52       valuesToRepl[it.index()].replaceAllUsesWith(it.value());
53   }
54 
materializeCallConversion__anon85a0a6fe0111::FIRInlinerInterface55   mlir::Operation *materializeCallConversion(mlir::OpBuilder &builder,
56                                              mlir::Value input,
57                                              mlir::Type resultType,
58                                              mlir::Location loc) const final {
59     return builder.create<fir::ConvertOp>(loc, resultType, input);
60   }
61 };
62 } // namespace
63 
initialize()64 void fir::FIROpsDialect::initialize() {
65   registerTypes();
66   registerAttributes();
67   addOperations<
68 #define GET_OP_LIST
69 #include "flang/Optimizer/Dialect/FIROps.cpp.inc"
70       >();
71   registerOpExternalInterfaces();
72 }
73 
74 // Register the FIRInlinerInterface to FIROpsDialect
addFIRInlinerExtension(mlir::DialectRegistry & registry)75 void fir::addFIRInlinerExtension(mlir::DialectRegistry &registry) {
76   registry.addExtension(
77       +[](mlir::MLIRContext *ctx, fir::FIROpsDialect *dialect) {
78         dialect->addInterface<FIRInlinerInterface>();
79       });
80 }
81 
82 // We do not provide LLVMTranslationDialectInterface implementation
83 // for FIR dialect, since at the point of translation to LLVM IR
84 // there should not be any FIR operations (the CodeGen converts
85 // them to LLVMIR dialect operations).
86 // Here we register the default implementation of
87 // LLVMTranslationDialectInterface that will drop all FIR dialect
88 // attributes - this helps to avoid warnings about unhandled attributes.
89 // We can provide our own implementation of the interface,
90 // when more sophisticated translation is required.
addFIRToLLVMIRExtension(mlir::DialectRegistry & registry)91 void fir::addFIRToLLVMIRExtension(mlir::DialectRegistry &registry) {
92   registry.addExtension(
93       +[](mlir::MLIRContext *ctx, fir::FIROpsDialect *dialect) {
94         dialect->addInterface<mlir::LLVMTranslationDialectInterface>();
95       });
96 }
97 
parseType(mlir::DialectAsmParser & parser) const98 mlir::Type fir::FIROpsDialect::parseType(mlir::DialectAsmParser &parser) const {
99   return parseFirType(const_cast<FIROpsDialect *>(this), parser);
100 }
101 
printType(mlir::Type ty,mlir::DialectAsmPrinter & p) const102 void fir::FIROpsDialect::printType(mlir::Type ty,
103                                    mlir::DialectAsmPrinter &p) const {
104   return printFirType(const_cast<FIROpsDialect *>(this), ty, p);
105 }
106 
107 mlir::Attribute
parseAttribute(mlir::DialectAsmParser & parser,mlir::Type type) const108 fir::FIROpsDialect::parseAttribute(mlir::DialectAsmParser &parser,
109                                    mlir::Type type) const {
110   return parseFirAttribute(const_cast<FIROpsDialect *>(this), parser, type);
111 }
112 
printAttribute(mlir::Attribute attr,mlir::DialectAsmPrinter & p) const113 void fir::FIROpsDialect::printAttribute(mlir::Attribute attr,
114                                         mlir::DialectAsmPrinter &p) const {
115   printFirAttribute(const_cast<FIROpsDialect *>(this), attr, p);
116 }
117