FLANG
FIROpsSupport.h
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#include "llvm/ADT/APInt.h"
16
17namespace fir {
18
26 mlir::TypeRange type,
28 mlir::SideEffects::EffectInstance<mlir::MemoryEffects::Effect>>
29 &effects) {
30 for (mlir::Type t : type) {
32 effects.emplace_back(mlir::MemoryEffects::Read::get(),
33 fir::VolatileMemoryResource::get());
34 effects.emplace_back(mlir::MemoryEffects::Write::get(),
35 fir::VolatileMemoryResource::get());
36 break;
37 }
38 }
39}
40
42inline bool isaCall(mlir::Operation *op) {
43 return mlir::isa<fir::CallOp>(op) || mlir::isa<fir::DispatchOp>(op) ||
44 mlir::isa<mlir::func::CallOp>(op) ||
45 mlir::isa<mlir::func::CallIndirectOp>(op);
46}
47
51inline bool impureCall(mlir::Operation *op) {
52 // Should we also auto-detect that the called function is pure if its
53 // arguments are not references? For now, rely on a "pure" attribute.
54 return op && isaCall(op) && !op->getAttr("pure");
55}
56
60inline bool pureCall(mlir::Operation *op) {
61 // Should we also auto-detect that the called function is pure if its
62 // arguments are not references? For now, rely on a "pure" attribute.
63 return op && isaCall(op) && op->getAttr("pure");
64}
65
75mlir::func::FuncOp createFuncOp(mlir::Location loc, mlir::ModuleOp module,
76 llvm::StringRef name, mlir::FunctionType type,
78 mlir::SymbolTable *symbolTable = nullptr);
79
82fir::GlobalOp createGlobalOp(mlir::Location loc, mlir::ModuleOp module,
83 llvm::StringRef name, mlir::Type type,
84 llvm::ArrayRef<mlir::NamedAttribute> attrs = {},
85 mlir::SymbolTable *symbolTable = nullptr);
86
94void registerSymbol(mlir::SymbolTable *symbolTable, mlir::Operation *symbol);
95
97constexpr llvm::StringRef getContiguousAttrName() { return "fir.contiguous"; }
98
100constexpr llvm::StringRef getOptionalAttrName() { return "fir.optional"; }
101
103static constexpr llvm::StringRef getTargetAttrName() { return "fir.target"; }
104
106static constexpr llvm::StringRef getAsynchronousAttrName() {
107 return "fir.asynchronous";
108}
109
111static constexpr llvm::StringRef getVolatileAttrName() {
112 return "fir.volatile";
113}
114
121static constexpr llvm::StringRef getReadOnlyAttrName() {
122 return "fir.read_only";
123}
124
129static constexpr llvm::StringRef getFortranAttrsAttrName() {
130 return "fir.fortran_attrs";
131}
132
135static constexpr llvm::StringRef getCharacterProcedureDummyAttrName() {
136 return "fir.char_proc";
137}
138
140static constexpr llvm::StringRef getSymbolAttrName() {
141 return "fir.bindc_name";
142}
143
145static constexpr llvm::StringRef getHostAssocAttrName() {
146 return "fir.host_assoc";
147}
148
150static constexpr llvm::StringRef getHostSymbolAttrName() {
151 return "fir.host_symbol";
152}
153
158static constexpr llvm::StringRef getDefiningSubmoduleAttrName() {
159 return "fir.defining_submodule";
160}
161
164static constexpr llvm::StringRef getInternalFuncNameAttrName() {
165 return "fir.internal_name";
166}
167
170static constexpr llvm::StringRef getHasLifetimeMarkerAttrName() {
171 return "fir.has_lifetime";
172}
173
175static constexpr llvm::StringRef getAccessGroupsAttrName() {
176 return "access_groups";
177}
178
183static constexpr llvm::StringRef getUniqNameAttrName() { return "uniq_name"; }
184
189static constexpr llvm::StringRef getBindcNameAttrName() { return "bindc_name"; }
190
192constexpr llvm::StringRef getCorankAttrName() { return "fir.corank"; }
193
196bool hasHostAssociationArgument(mlir::func::FuncOp func);
197
201inline bool isInternalProcedure(mlir::func::FuncOp func) {
202 return func->hasAttr(fir::getHostSymbolAttrName());
203}
204
213bool valueHasFirAttribute(mlir::Value value, llvm::StringRef attributeName);
214
225bool valueMayHaveFirAttributes(mlir::Value value,
226 llvm::ArrayRef<llvm::StringRef> attributeNames);
227
231bool anyFuncArgsHaveAttr(mlir::func::FuncOp func, llvm::StringRef attr);
232
234std::optional<llvm::APInt> getIntIfConstant(mlir::Value value);
235
236static constexpr llvm::StringRef getAdaptToByRefAttrName() {
237 return "adapt.valuebyref";
238}
239
240static constexpr llvm::StringRef getFuncPureAttrName() {
241 return "fir.func_pure";
242}
243
244static constexpr llvm::StringRef getFuncElementalAttrName() {
245 return "fir.func_elemental";
246}
247
248static constexpr llvm::StringRef getFuncRecursiveAttrName() {
249 return "fir.func_recursive";
250}
251
252static constexpr llvm::StringRef getFortranProcedureFlagsAttrName() {
253 return "fir.proc_attrs";
254}
255
256// Attribute for an alloca that is a trivial adaptor for converting a value to
257// pass-by-ref semantics for a VALUE parameter. The optimizer may be able to
258// eliminate these.
259// Template is used to avoid compiler errors in places that don't include
260// FIRBuilder.h
261template <typename Builder>
262inline mlir::NamedAttribute getAdaptToByRefAttr(Builder &builder) {
263 return {mlir::StringAttr::get(builder.getContext(),
264 fir::getAdaptToByRefAttrName()),
265 builder.getUnitAttr()};
266}
267
268bool isDummyArgument(mlir::Value v);
269
271enum class FortranDummyIntent { In, Out, InOut };
272
277inline std::optional<FortranDummyIntent>
278getFortranDummyIntent(mlir::func::FuncOp callee, unsigned argIdx) {
279 if (!callee || argIdx >= callee.getNumArguments())
280 return std::nullopt;
281 auto attrs = callee.getArgAttrOfType<FortranVariableFlagsAttr>(
282 argIdx, getFortranAttrsAttrName());
283 if (!attrs)
284 return std::nullopt;
285 switch (attrs.getFlags()) {
286 case FortranVariableFlagsEnum::intent_in:
287 return FortranDummyIntent::In;
288 case FortranVariableFlagsEnum::intent_out:
289 return FortranDummyIntent::Out;
290 case FortranVariableFlagsEnum::intent_inout:
291 return FortranDummyIntent::InOut;
292 default:
293 return std::nullopt;
294 }
295}
296
297template <fir::FortranProcedureFlagsEnum Flag>
298inline bool hasProcedureAttr(fir::FortranProcedureFlagsEnumAttr flags) {
299 return flags && bitEnumContainsAny(flags.getValue(), Flag);
300}
301
302template <fir::FortranProcedureFlagsEnum Flag>
303inline bool hasProcedureAttr(mlir::Operation *op) {
304 if (auto firCallOp = mlir::dyn_cast<fir::CallOp>(op))
305 return hasProcedureAttr<Flag>(firCallOp.getProcedureAttrsAttr());
306 if (auto firCallOp = mlir::dyn_cast<fir::DispatchOp>(op))
307 return hasProcedureAttr<Flag>(firCallOp.getProcedureAttrsAttr());
308 return hasProcedureAttr<Flag>(
309 op->getAttrOfType<fir::FortranProcedureFlagsEnumAttr>(
310 getFortranProcedureFlagsAttrName()));
311}
312
313inline bool hasBindcAttr(mlir::Operation *op) {
314 return hasProcedureAttr<fir::FortranProcedureFlagsEnum::bind_c>(op);
315}
316
319std::optional<int64_t> getAllocaByteSize(fir::AllocaOp alloca,
320 const mlir::DataLayout &dl,
321 const fir::KindMapping &kindMap);
322
331bool reboxPreservesContinuity(fir::ReboxOp rebox,
332 bool mayHaveNonDefaultLowerBounds = true,
333 bool checkWhole = true);
334
340bool isContiguousEmbox(fir::EmboxOp embox, bool checkWhole = true);
341
346bool isInOffloadRegion(mlir::Operation *op);
347
348} // namespace fir
349
350#endif // FORTRAN_OPTIMIZER_DIALECT_FIROPSSUPPORT_H
Definition FIRType.h:106
Definition OpenACC.h:22
Definition AbstractConverter.h:37
constexpr llvm::StringRef getCorankAttrName()
Attribute to mark coarray Fortran entities with the CORANK attribute.
Definition FIROpsSupport.h:192
bool isContiguousEmbox(fir::EmboxOp embox, bool checkWhole=true)
Definition FIROps.cpp:2914
bool anyFuncArgsHaveAttr(mlir::func::FuncOp func, llvm::StringRef attr)
Definition FIROps.cpp:6249
bool isa_volatile_type(mlir::Type t)
Definition FIRType.cpp:768
constexpr llvm::StringRef getContiguousAttrName()
Attribute to mark Fortran entities with the CONTIGUOUS attribute.
Definition FIROpsSupport.h:97
bool reboxPreservesContinuity(fir::ReboxOp rebox, bool mayHaveNonDefaultLowerBounds=true, bool checkWhole=true)
Definition FIROps.cpp:6321
bool hasHostAssociationArgument(mlir::func::FuncOp func)
Definition FIROps.cpp:6122
std::optional< int64_t > getAllocaByteSize(fir::AllocaOp alloca, const mlir::DataLayout &dl, const fir::KindMapping &kindMap)
Definition FIROps.cpp:6338
bool isInternalProcedure(mlir::func::FuncOp func)
Definition FIROpsSupport.h:201
std::optional< llvm::APInt > getIntIfConstant(mlir::Value value)
Unwrap an integer constant from an mlir::Value as an APInt.
Definition FIROps.cpp:6256
fir::GlobalOp createGlobalOp(mlir::Location loc, mlir::ModuleOp module, llvm::StringRef name, mlir::Type type, llvm::ArrayRef< mlir::NamedAttribute > attrs={}, mlir::SymbolTable *symbolTable=nullptr)
Definition FIROps.cpp:6100
void registerSymbol(mlir::SymbolTableCollection *symbolTables, mlir::Operation *symbolTableOp, mlir::Operation *symbol)
Definition FIROpPatterns.cpp:37
constexpr llvm::StringRef getOptionalAttrName()
Attribute to mark Fortran entities with the OPTIONAL attribute.
Definition FIROpsSupport.h:100
bool pureCall(mlir::Operation *op)
Definition FIROpsSupport.h:60
void addVolatileMemoryEffects(mlir::TypeRange type, llvm::SmallVectorImpl< mlir::SideEffects::EffectInstance< mlir::MemoryEffects::Effect > > &effects)
Definition FIROpsSupport.h:25
bool isInOffloadRegion(mlir::Operation *op)
Definition FIROps.cpp:7140
bool valueHasFirAttribute(mlir::Value value, llvm::StringRef attributeName)
Definition FIROps.cpp:6242
mlir::func::FuncOp createFuncOp(mlir::Location loc, mlir::ModuleOp module, llvm::StringRef name, mlir::FunctionType type, llvm::ArrayRef< mlir::NamedAttribute > attrs={}, mlir::SymbolTable *symbolTable=nullptr)
Definition FIROps.cpp:6076
bool valueMayHaveFirAttributes(mlir::Value value, llvm::ArrayRef< llvm::StringRef > attributeNames)
Definition FIROps.cpp:6235
bool impureCall(mlir::Operation *op)
Definition FIROpsSupport.h:51
bool isaCall(mlir::Operation *op)
Return true iff the Operation is a call.
Definition FIROpsSupport.h:42
FortranDummyIntent
Intent of function argument argIdx.
Definition FIROpsSupport.h:271
std::optional< FortranDummyIntent > getFortranDummyIntent(mlir::func::FuncOp callee, unsigned argIdx)
Definition FIROpsSupport.h:278