1 //===-- Optimizer/Dialect/FIROpsSupport.h -- FIR op support -----*- C++ -*-===//
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 #ifndef FORTRAN_OPTIMIZER_DIALECT_FIROPSSUPPORT_H
10 #define FORTRAN_OPTIMIZER_DIALECT_FIROPSSUPPORT_H
11 
12 #include "flang/Optimizer/Dialect/FIROps.h"
13 #include "mlir/Dialect/Func/IR/FuncOps.h"
14 #include "mlir/IR/BuiltinOps.h"
15 
16 namespace fir {
17 
18 /// Return true iff the Operation is a non-volatile LoadOp or ArrayLoadOp.
nonVolatileLoad(mlir::Operation * op)19 inline bool nonVolatileLoad(mlir::Operation *op) {
20   if (auto load = mlir::dyn_cast<fir::LoadOp>(op))
21     return !load->getAttr("volatile");
22   if (auto arrLoad = mlir::dyn_cast<fir::ArrayLoadOp>(op))
23     return !arrLoad->getAttr("volatile");
24   return false;
25 }
26 
27 /// Return true iff the Operation is a call.
isaCall(mlir::Operation * op)28 inline bool isaCall(mlir::Operation *op) {
29   return mlir::isa<fir::CallOp>(op) || mlir::isa<fir::DispatchOp>(op) ||
30          mlir::isa<mlir::func::CallOp>(op) ||
31          mlir::isa<mlir::func::CallIndirectOp>(op);
32 }
33 
34 /// Return true iff the Operation is a fir::CallOp, fir::DispatchOp,
35 /// mlir::CallOp, or mlir::CallIndirectOp and not pure
36 /// NB: This is not the same as `!pureCall(op)`.
impureCall(mlir::Operation * op)37 inline bool impureCall(mlir::Operation *op) {
38   // Should we also auto-detect that the called function is pure if its
39   // arguments are not references?  For now, rely on a "pure" attribute.
40   return op && isaCall(op) && !op->getAttr("pure");
41 }
42 
43 /// Return true iff the Operation is a fir::CallOp, fir::DispatchOp,
44 /// mlir::CallOp, or mlir::CallIndirectOp and is also pure.
45 /// NB: This is not the same as `!impureCall(op)`.
pureCall(mlir::Operation * op)46 inline bool pureCall(mlir::Operation *op) {
47   // Should we also auto-detect that the called function is pure if its
48   // arguments are not references?  For now, rely on a "pure" attribute.
49   return op && isaCall(op) && op->getAttr("pure");
50 }
51 
52 /// Get or create a FuncOp in a module.
53 ///
54 /// If `module` already contains FuncOp `name`, it is returned. Otherwise, a new
55 /// FuncOp is created, and that new FuncOp is returned.
56 mlir::func::FuncOp
57 createFuncOp(mlir::Location loc, mlir::ModuleOp module, llvm::StringRef name,
58              mlir::FunctionType type,
59              llvm::ArrayRef<mlir::NamedAttribute> attrs = {});
60 
61 /// Get or create a GlobalOp in a module.
62 fir::GlobalOp createGlobalOp(mlir::Location loc, mlir::ModuleOp module,
63                              llvm::StringRef name, mlir::Type type,
64                              llvm::ArrayRef<mlir::NamedAttribute> attrs = {});
65 
66 /// Attribute to mark Fortran entities with the CONTIGUOUS attribute.
getContiguousAttrName()67 constexpr llvm::StringRef getContiguousAttrName() { return "fir.contiguous"; }
68 
69 /// Attribute to mark Fortran entities with the OPTIONAL attribute.
getOptionalAttrName()70 constexpr llvm::StringRef getOptionalAttrName() { return "fir.optional"; }
71 
72 /// Attribute to mark Fortran entities with the TARGET attribute.
getTargetAttrName()73 static constexpr llvm::StringRef getTargetAttrName() { return "fir.target"; }
74 
75 /// Attribute to mark that a function argument is a character dummy procedure.
76 /// Character dummy procedure have special ABI constraints.
getCharacterProcedureDummyAttrName()77 static constexpr llvm::StringRef getCharacterProcedureDummyAttrName() {
78   return "fir.char_proc";
79 }
80 
81 /// Attribute to keep track of Fortran scoping information for a symbol.
getSymbolAttrName()82 static constexpr llvm::StringRef getSymbolAttrName() {
83   return "fir.bindc_name";
84 }
85 
86 /// Attribute to mark a function that takes a host associations argument.
getHostAssocAttrName()87 static constexpr llvm::StringRef getHostAssocAttrName() {
88   return "fir.host_assoc";
89 }
90 
91 /// Does the function, \p func, have a host-associations tuple argument?
92 /// Some internal procedures may have access to host procedure variables.
93 bool hasHostAssociationArgument(mlir::func::FuncOp func);
94 
95 /// Tell if \p value is:
96 ///   - a function argument that has attribute \p attributeName
97 ///   - or, the result of fir.alloca/fir.allocamem op that has attribute \p
98 ///     attributeName
99 ///   - or, the result of a fir.address_of of a fir.global that has attribute \p
100 ///     attributeName
101 ///   - or, a fir.box loaded from a fir.ref<fir.box> that matches one of the
102 ///     previous cases.
103 bool valueHasFirAttribute(mlir::Value value, llvm::StringRef attributeName);
104 
105 /// Scan the arguments of a FuncOp to determine if any arguments have the
106 /// attribute `attr` placed on them. This can be used to determine if the
107 /// function has any host associations, for example.
108 bool anyFuncArgsHaveAttr(mlir::func::FuncOp func, llvm::StringRef attr);
109 
110 } // namespace fir
111 
112 #endif // FORTRAN_OPTIMIZER_DIALECT_FIROPSSUPPORT_H
113