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"
34class ElementalOpInterface;
36class EvaluateInMemoryOp;
41inline bool isFortranVariableWithAttributes(mlir::Value value) {
42 return value.getDefiningOp<fir::FortranVariableOpInterface>();
47inline bool isFortranEntityWithAttributes(mlir::Value value) {
48 return isFortranValue(value) || isFortranVariableWithAttributes(value);
53 explicit Entity(mlir::Value value) : mlir::Value(value) {
54 assert(isFortranEntity(value) &&
55 "must be a value representing a Fortran value or variable like");
57 Entity(fir::FortranVariableOpInterface variable)
58 : mlir::Value(variable.getBase()) {}
59 bool isValue()
const {
return isFortranValue(*
this); }
60 bool isVariable()
const {
return !isValue(); }
61 bool isMutableBox()
const {
return hlfir::isBoxAddressType(getType()); }
62 bool isProcedurePointer()
const {
65 bool isBoxAddressOrValue()
const {
66 return hlfir::isBoxAddressOrValueType(getType());
70 bool isProcedure()
const {
return isFortranProcedureValue(getType()); }
81 if (
auto seqTy = mlir::dyn_cast<fir::SequenceType>(type)) {
82 if (seqTy.hasUnknownShape())
84 return seqTy.getDimension();
86 if (
auto exprType = mlir::dyn_cast<hlfir::ExprType>(type))
87 return exprType.getRank();
90 bool isScalar()
const {
return !
isArray(); }
92 bool isPolymorphic()
const {
return hlfir::isPolymorphicType(getType()); }
94 mlir::Type getFortranElementType()
const {
95 return hlfir::getFortranElementType(getType());
97 mlir::Type getElementOrSequenceType()
const {
98 return hlfir::getFortranElementOrSequenceType(getType());
101 bool hasLengthParameters()
const {
102 mlir::Type eleTy = getFortranElementType();
103 return mlir::isa<fir::CharacterType>(eleTy) ||
107 bool isCharacter()
const {
108 return mlir::isa<fir::CharacterType>(getFortranElementType());
111 bool hasIntrinsicType()
const {
112 mlir::Type eleTy = getFortranElementType();
116 bool isDerivedWithLengthParameters()
const {
120 bool mayHaveNonDefaultLowerBounds()
const;
125 bool isSimplyContiguous()
const {
128 if (!hlfir::isBoxAddressOrValueType(getFirBase().getType()))
133 if (
auto varIface = getMaybeDereferencedVariableInterface())
134 return varIface.isAllocatable() || varIface.hasContiguousAttr();
138 fir::FortranVariableOpInterface getIfVariableInterface()
const {
139 return this->getDefiningOp<fir::FortranVariableOpInterface>();
145 fir::FortranVariableOpInterface
146 getMaybeDereferencedVariableInterface()
const {
147 mlir::Value base = *
this;
148 if (
auto loadOp = base.getDefiningOp<fir::LoadOp>())
149 base = loadOp.getMemref();
150 return base.getDefiningOp<fir::FortranVariableOpInterface>();
153 bool isOptional()
const {
154 auto varIface = getIfVariableInterface();
155 return varIface ? varIface.isOptional() :
false;
158 bool isParameter()
const {
159 auto varIface = getIfVariableInterface();
160 return varIface ? varIface.isParameter() :
false;
163 bool isAllocatable()
const {
164 auto varIface = getIfVariableInterface();
165 return varIface ? varIface.isAllocatable() :
false;
168 bool isPointer()
const {
169 auto varIface = getIfVariableInterface();
170 return varIface ? varIface.isPointer() :
false;
175 mlir::Value getBase()
const {
return *
this; }
184 mlir::Value getFirBase()
const;
195 assert(isFortranEntityWithAttributes(value) &&
196 "must be a value representing a Fortran value or variable");
200 fir::FortranVariableOpInterface getIfVariable()
const {
201 return getIfVariableInterface();
210using CleanupFunction = std::function<void()>;
211std::pair<fir::ExtendedValue, std::optional<CleanupFunction>>
213 Entity entity,
bool contiguousHint =
false);
220 fir::FortranVariableOpInterface fortranVariable,
221 bool forceHlfirBase =
false);
224fir::FortranVariableOpInterface
227 fir::FortranVariableFlagsAttr flags,
228 mlir::Value dummyScope =
nullptr,
229 cuf::DataAttributeAttr dataAttr = {});
237 llvm::StringRef name,
238 std::optional<mlir::NamedAttribute> attr = std::nullopt);
244mlir::Value genVariableRawAddress(mlir::Location loc,
266hlfir::Entity derefPointersAndAllocatables(mlir::Location loc,
274 Entity entity, mlir::ValueRange oneBasedIndices);
287 mlir::Value shape,
unsigned rank);
317 llvm::SmallVectorImpl<mlir::Value> &result);
325 Entity entity, mlir::Type resultType);
331std::pair<mlir::Value, mlir::Value> genVariableFirBaseShapeAndParams(
333 llvm::SmallVectorImpl<mlir::Value> &typeParams);
353hlfir::ElementalOp genElementalOp(
355 mlir::Value shape, mlir::ValueRange typeParams,
356 const ElementalKernelGenerator &genKernel,
bool isUnordered =
false,
357 mlir::Value polymorphicMold = {}, mlir::Type exprType = mlir::Type{});
361 mlir::Operation *outerOp =
nullptr;
362 mlir::Block *body =
nullptr;
374 mlir::ValueRange extents,
bool isUnordered =
false,
375 bool emitWorkshareLoop =
false);
377 mlir::Value shape,
bool isUnordered =
false,
378 bool emitWorkshareLoop =
false) {
379 return genLoopNest(loc, builder, getIndexExtents(loc, builder, shape),
380 isUnordered, emitWorkshareLoop);
389using ReductionLoopBodyGenerator = std::function<llvm::SmallVector<mlir::Value>(
411 mlir::ValueRange reductionInits,
const ReductionLoopBodyGenerator &genBody,
412 bool isUnordered =
false);
419hlfir::YieldElementOp inlineElementalOp(mlir::Location loc,
421 hlfir::ElementalOp elemental,
422 mlir::ValueRange oneBasedIndices);
431mlir::Value inlineElementalOp(
433 hlfir::ElementalOpInterface elemental, mlir::ValueRange oneBasedIndices,
434 mlir::IRMapping &mapper,
435 const std::function<
bool(hlfir::ElementalOp)> &mustRecursivelyInline);
441std::pair<hlfir::Entity, bool>
443 hlfir::EvaluateInMemoryOp evalInMem,
444 mlir::Value shape, mlir::ValueRange typeParams);
453 hlfir::EvaluateInMemoryOp, mlir::Value storage);
455std::pair<fir::ExtendedValue, std::optional<hlfir::CleanupFunction>>
459std::pair<fir::ExtendedValue, std::optional<hlfir::CleanupFunction>>
463std::pair<fir::ExtendedValue, std::optional<hlfir::CleanupFunction>>
468hlfir::ElementalOp cloneToElementalOp(mlir::Location loc,
470 hlfir::ElementalAddrOp elementalAddrOp);
477bool elementalOpMustProduceTemp(hlfir::ElementalOp elemental);
479std::pair<hlfir::Entity, mlir::Value>
506std::pair<hlfir::Entity, std::optional<hlfir::CleanupFunction>>
509 bool preserveLowerBounds);
514 Entity entity, mlir::ValueRange oneBasedIndices);
Definition: BoxValue.h:478
Definition: FIRBuilder.h:55
Definition: HLFIRTools.h:192
Definition: HLFIRTools.h:51
bool isAssumedRank() const
Is this an assumed ranked entity?
Definition: HLFIRTools.h:76
int getRank() const
Return the rank of this entity or -1 if it is an assumed rank.
Definition: HLFIRTools.h:79
bool isArray() const
Is this an array or an assumed ranked entity?
Definition: HLFIRTools.h:73
bool isProcedure() const
Is this entity a procedure designator?
Definition: HLFIRTools.h:70
Definition: AbstractConverter.h:31
mlir::Type unwrapPassByRefType(mlir::Type t)
Definition: FIRType.h:266
bool isBoxProcAddressType(mlir::Type t)
Is this a fir.boxproc address type?
Definition: FIRType.h:479
bool isRecordWithTypeParameters(mlir::Type ty)
Return true iff ty is a RecordType with type parameters.
Definition: FIRType.h:394
bool isa_trivial(mlir::Type t)
Definition: FIRType.h:195
Definition: AbstractConverter.h:27
Structure to describe a loop nest.
Definition: HLFIRTools.h:360