13#ifndef FORTRAN_OPTIMIZER_BUILDER_HLFIRTOOLS_H
14#define FORTRAN_OPTIMIZER_BUILDER_HLFIRTOOLS_H
16#include "flang/Optimizer/Builder/BoxValue.h"
17#include "flang/Optimizer/Dialect/FIROps.h"
18#include "flang/Optimizer/Dialect/FortranVariableInterface.h"
19#include "flang/Optimizer/HLFIR/HLFIRDialect.h"
20#include "flang/Optimizer/HLFIR/HLFIROps.h"
35class ElementalOpInterface;
37class EvaluateInMemoryOp;
42inline bool isFortranVariableWithAttributes(mlir::Value value) {
43 return value.getDefiningOp<fir::FortranVariableOpInterface>();
48inline bool isFortranEntityWithAttributes(mlir::Value value) {
49 return isFortranValue(value) || isFortranVariableWithAttributes(value);
52class Entity :
public mlir::Value {
54 explicit Entity(mlir::Value value) : mlir::Value(value) {
55 assert(isFortranEntity(value) &&
56 "must be a value representing a Fortran value or variable like");
58 Entity(fir::FortranVariableOpInterface variable)
59 : mlir::Value(variable.getBase()) {}
60 bool isValue()
const {
return isFortranValue(*
this); }
61 bool isVariable()
const {
return !isValue(); }
62 bool isMutableBox()
const {
return hlfir::isBoxAddressType(getType()); }
63 bool isProcedurePointer()
const {
64 return hlfir::isFortranProcedurePointerType(getType());
66 bool isBoxAddressOrValue()
const {
67 return hlfir::isBoxAddressOrValueType(getType());
71 bool isProcedure()
const {
return isFortranProcedureValue(getType()); }
82 if (
auto seqTy = mlir::dyn_cast<fir::SequenceType>(type)) {
83 if (seqTy.hasUnknownShape())
85 return seqTy.getDimension();
87 if (
auto exprType = mlir::dyn_cast<hlfir::ExprType>(type))
88 return exprType.getRank();
91 bool isScalar()
const {
return !
isArray(); }
93 bool isPolymorphic()
const {
return hlfir::isPolymorphicType(getType()); }
95 mlir::Type getFortranElementType()
const {
96 return hlfir::getFortranElementType(getType());
98 mlir::Type getElementOrSequenceType()
const {
99 return hlfir::getFortranElementOrSequenceType(getType());
103 if (isBoxAddressOrValue())
104 return llvm::cast<fir::BaseBoxType>(fir::unwrapRefType(getType()));
106 return fir::BoxType::get(getElementOrSequenceType(), isVolatile);
109 bool hasLengthParameters()
const {
110 mlir::Type eleTy = getFortranElementType();
111 return mlir::isa<fir::CharacterType>(eleTy) ||
115 bool isCharacter()
const {
116 return mlir::isa<fir::CharacterType>(getFortranElementType());
119 bool hasIntrinsicType()
const {
120 mlir::Type eleTy = getFortranElementType();
124 bool isDerivedWithLengthParameters()
const {
128 bool mayHaveNonDefaultLowerBounds()
const;
133 bool isSimplyContiguous()
const {
136 if (!hlfir::isBoxAddressOrValueType(getFirBase().getType()) || isScalar())
141 if (
auto varIface = getMaybeDereferencedVariableInterface())
142 return varIface.isAllocatable() || varIface.hasContiguousAttr();
146 fir::FortranVariableOpInterface getIfVariableInterface()
const {
147 return this->getDefiningOp<fir::FortranVariableOpInterface>();
153 fir::FortranVariableOpInterface
154 getMaybeDereferencedVariableInterface()
const {
155 mlir::Value base = *
this;
156 if (
auto loadOp = base.getDefiningOp<fir::LoadOp>())
157 base = loadOp.getMemref();
158 return base.getDefiningOp<fir::FortranVariableOpInterface>();
161 bool mayBeOptional()
const;
163 bool isParameter()
const {
164 auto varIface = getIfVariableInterface();
165 return varIface ? varIface.isParameter() :
false;
168 bool isAllocatable()
const {
169 auto varIface = getIfVariableInterface();
170 return varIface ? varIface.isAllocatable() :
false;
173 bool isPointer()
const {
174 auto varIface = getIfVariableInterface();
175 return varIface ? varIface.isPointer() :
false;
180 mlir::Value getBase()
const {
return *
this; }
189 mlir::Value getFirBase()
const;
197class EntityWithAttributes :
public Entity {
199 explicit EntityWithAttributes(mlir::Value value) : Entity(value) {
200 assert(isFortranEntityWithAttributes(value) &&
201 "must be a value representing a Fortran value or variable");
203 EntityWithAttributes(fir::FortranVariableOpInterface variable)
204 : Entity(variable) {}
205 fir::FortranVariableOpInterface getIfVariable()
const {
206 return getIfVariableInterface();
215using CleanupFunction = std::function<void()>;
216std::pair<fir::ExtendedValue, std::optional<CleanupFunction>>
218 Entity entity,
bool contiguousHint =
false,
219 bool keepScalarOptionalBoxed =
false);
226 fir::FortranVariableOpInterface fortranVariable,
227 bool forceHlfirBase =
false);
230fir::FortranVariableOpInterface
233 fir::FortranVariableFlagsAttr flags,
234 mlir::Value dummyScope =
nullptr, mlir::Value storage =
nullptr,
235 std::uint64_t storageOffset = 0,
236 cuf::DataAttributeAttr dataAttr = {});
244 llvm::StringRef name,
245 std::optional<mlir::NamedAttribute> attr = std::nullopt);
251mlir::Value genVariableRawAddress(mlir::Location loc,
271Entity loadTrivialScalar(mlir::Location loc, fir::FirOpBuilder &builder,
276hlfir::Entity derefPointersAndAllocatables(mlir::Location loc,
277 fir::FirOpBuilder &builder,
283hlfir::Entity getElementAt(mlir::Location loc, fir::FirOpBuilder &builder,
284 Entity entity, mlir::ValueRange oneBasedIndices);
286llvm::SmallVector<std::pair<mlir::Value, mlir::Value>>
287genBounds(mlir::Location loc, fir::FirOpBuilder &builder,
Entity entity);
290llvm::SmallVector<std::pair<mlir::Value, mlir::Value>>
291genBounds(mlir::Location loc, fir::FirOpBuilder &builder, mlir::Value shape);
295llvm::SmallVector<mlir::Value> genLowerbounds(mlir::Location loc,
296 fir::FirOpBuilder &builder,
297 mlir::Value shape,
unsigned rank);
300mlir::Value genShape(mlir::Location loc, fir::FirOpBuilder &builder,
305mlir::Value genExtent(mlir::Location loc, fir::FirOpBuilder &builder,
306 hlfir::Entity entity,
unsigned dim);
310mlir::Value genLBound(mlir::Location loc, fir::FirOpBuilder &builder,
311 hlfir::Entity entity,
unsigned dim);
315llvm::SmallVector<mlir::Value> getIndexExtents(mlir::Location loc,
316 fir::FirOpBuilder &builder,
321llvm::SmallVector<mlir::Value>
322getExplicitExtentsFromShape(mlir::Value shape, fir::FirOpBuilder &builder);
325void genLengthParameters(mlir::Location loc, fir::FirOpBuilder &builder,
327 llvm::SmallVectorImpl<mlir::Value> &result);
331mlir::Value genCharLength(mlir::Location loc, fir::FirOpBuilder &builder,
336std::optional<std::int64_t> getCharLengthIfConst(
Entity entity);
338mlir::Value genRank(mlir::Location loc, fir::FirOpBuilder &builder,
339 Entity entity, mlir::Type resultType);
345std::pair<mlir::Value, mlir::Value> genVariableFirBaseShapeAndParams(
346 mlir::Location loc, fir::FirOpBuilder &builder,
Entity entity,
347 llvm::SmallVectorImpl<mlir::Value> &typeParams);
352mlir::Type getVariableElementType(hlfir::Entity variable);
357mlir::Type getEntityElementType(hlfir::Entity entity);
359using ElementalKernelGenerator = std::function<hlfir::Entity(
360 mlir::Location, fir::FirOpBuilder &, mlir::ValueRange)>;
367hlfir::ElementalOp genElementalOp(
368 mlir::Location loc, fir::FirOpBuilder &builder, mlir::Type elementType,
369 mlir::Value shape, mlir::ValueRange typeParams,
370 const ElementalKernelGenerator &genKernel,
bool isUnordered =
false,
371 mlir::Value polymorphicMold = {}, mlir::Type exprType = mlir::Type{});
375 mlir::Operation *outerOp =
nullptr;
376 mlir::Block *body =
nullptr;
388 mlir::ValueRange extents,
bool isUnordered =
false,
389 bool emitWorkshareLoop =
false,
390 bool couldVectorize =
true);
392 mlir::Value shape,
bool isUnordered =
false,
393 bool emitWorkshareLoop =
false,
394 bool couldVectorize =
true) {
395 return genLoopNest(loc, builder, getIndexExtents(loc, builder, shape),
396 isUnordered, emitWorkshareLoop, couldVectorize);
405using ReductionLoopBodyGenerator = std::function<llvm::SmallVector<mlir::Value>(
427 mlir::ValueRange reductionInits,
const ReductionLoopBodyGenerator &genBody,
428 bool isUnordered =
false);
435hlfir::YieldElementOp inlineElementalOp(mlir::Location loc,
437 hlfir::ElementalOp elemental,
438 mlir::ValueRange oneBasedIndices);
447mlir::Value inlineElementalOp(
449 hlfir::ElementalOpInterface elemental, mlir::ValueRange oneBasedIndices,
450 mlir::IRMapping &mapper,
451 const std::function<
bool(hlfir::ElementalOp)> &mustRecursivelyInline);
457std::pair<hlfir::Entity, bool>
459 hlfir::EvaluateInMemoryOp evalInMem,
460 mlir::Value shape, mlir::ValueRange typeParams);
469 hlfir::EvaluateInMemoryOp, mlir::Value storage);
471std::pair<fir::ExtendedValue, std::optional<hlfir::CleanupFunction>>
475std::pair<fir::ExtendedValue, std::optional<hlfir::CleanupFunction>>
479std::pair<fir::ExtendedValue, std::optional<hlfir::CleanupFunction>>
484hlfir::ElementalOp cloneToElementalOp(mlir::Location loc,
486 hlfir::ElementalAddrOp elementalAddrOp);
493bool elementalOpMustProduceTemp(hlfir::ElementalOp elemental);
504std::pair<hlfir::Entity, bool> createTempFromMold(mlir::Location loc,
531std::pair<hlfir::Entity, std::optional<hlfir::CleanupFunction>>
534 bool preserveLowerBounds);
539 Entity entity, mlir::ValueRange oneBasedIndices);
555 Entity array, int64_t dim,
556 mlir::ArrayRef<mlir::Value> lbounds,
557 mlir::ArrayRef<mlir::Value> extents,
558 mlir::ValueRange oneBasedIndices,
559 mlir::ArrayRef<mlir::Value> typeParams);
564bool designatePreservesContinuity(hlfir::DesignateOp op);
572bool isSimplyContiguous(mlir::Value base,
bool checkWhole =
true);
This class provides a shared interface for box and class types.
Definition FIRType.h:40
Definition BoxValue.h:478
Definition FIRBuilder.h:55
Definition HLFIRTools.h:197
Definition HLFIRTools.h:52
bool isAssumedRank() const
Is this an assumed ranked entity?
Definition HLFIRTools.h:77
int getRank() const
Return the rank of this entity or -1 if it is an assumed rank.
Definition HLFIRTools.h:80
bool isArray() const
Is this an array or an assumed ranked entity?
Definition HLFIRTools.h:74
bool isProcedure() const
Is this entity a procedure designator?
Definition HLFIRTools.h:71
fir::BaseBoxType getBoxType() const
Return the fir.class or fir.box type needed to describe this entity.
Definition HLFIRTools.h:102
Definition AbstractConverter.h:34
bool isa_volatile_type(mlir::Type t)
Definition FIRType.cpp:748
mlir::Type unwrapPassByRefType(mlir::Type t)
Definition FIRType.h:292
bool isRecordWithTypeParameters(mlir::Type ty)
Return true iff ty is a RecordType with type parameters.
Definition FIRType.h:430
bool isa_trivial(mlir::Type t)
Definition FIRType.h:217
Definition AbstractConverter.h:29
Structure to describe a loop nest.
Definition HLFIRTools.h:374