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());
72 bool isProcedure()
const {
return isFortranProcedureValue(getType()); }
83 if (
auto seqTy = mlir::dyn_cast<fir::SequenceType>(type)) {
84 if (seqTy.hasUnknownShape())
86 return seqTy.getDimension();
88 if (
auto exprType = mlir::dyn_cast<hlfir::ExprType>(type))
89 return exprType.getRank();
92 bool isScalar()
const {
return !
isArray(); }
94 bool isPolymorphic()
const {
return hlfir::isPolymorphicType(getType()); }
96 mlir::Type getFortranElementType()
const {
97 return hlfir::getFortranElementType(getType());
99 mlir::Type getElementOrSequenceType()
const {
100 return hlfir::getFortranElementOrSequenceType(getType());
104 if (isBoxAddressOrValue())
105 return llvm::cast<fir::BaseBoxType>(fir::unwrapRefType(getType()));
107 return fir::BoxType::get(getElementOrSequenceType(), isVolatile);
110 bool hasLengthParameters()
const {
111 mlir::Type eleTy = getFortranElementType();
112 return mlir::isa<fir::CharacterType>(eleTy) ||
116 bool isCharacter()
const {
117 return mlir::isa<fir::CharacterType>(getFortranElementType());
120 bool hasIntrinsicType()
const {
121 mlir::Type eleTy = getFortranElementType();
125 bool isDerivedWithLengthParameters()
const {
129 bool mayHaveNonDefaultLowerBounds()
const;
134 bool isSimplyContiguous()
const {
137 if (!hlfir::isBoxAddressOrValueType(getFirBase().getType()) || isScalar())
142 if (
auto varIface = getMaybeDereferencedVariableInterface())
143 return varIface.isAllocatable() || varIface.hasContiguousAttr();
147 fir::FortranVariableOpInterface getIfVariableInterface()
const {
148 return this->getDefiningOp<fir::FortranVariableOpInterface>();
154 fir::FortranVariableOpInterface
155 getMaybeDereferencedVariableInterface()
const {
156 mlir::Value base = *
this;
157 if (
auto loadOp = base.getDefiningOp<fir::LoadOp>())
158 base = loadOp.getMemref();
159 return base.getDefiningOp<fir::FortranVariableOpInterface>();
162 bool mayBeOptional()
const;
164 bool isParameter()
const {
165 auto varIface = getIfVariableInterface();
166 return varIface ? varIface.isParameter() :
false;
169 bool isAllocatable()
const {
170 auto varIface = getIfVariableInterface();
171 return varIface ? varIface.isAllocatable() :
false;
174 bool isPointer()
const {
175 auto varIface = getIfVariableInterface();
176 return varIface ? varIface.isPointer() :
false;
181 mlir::Value getBase()
const {
return *
this; }
190 mlir::Value getFirBase()
const;
198class EntityWithAttributes :
public Entity {
200 explicit EntityWithAttributes(mlir::Value value) : Entity(value) {
201 assert(isFortranEntityWithAttributes(value) &&
202 "must be a value representing a Fortran value or variable");
204 EntityWithAttributes(fir::FortranVariableOpInterface variable)
205 : Entity(variable) {}
206 fir::FortranVariableOpInterface getIfVariable()
const {
207 return getIfVariableInterface();
216using CleanupFunction = std::function<void()>;
217std::pair<fir::ExtendedValue, std::optional<CleanupFunction>>
219 Entity entity,
bool contiguousHint =
false,
220 bool keepScalarOptionalBoxed =
false);
227 fir::FortranVariableOpInterface fortranVariable,
228 bool forceHlfirBase =
false);
231fir::FortranVariableOpInterface
234 fir::FortranVariableFlagsAttr flags,
235 mlir::Value dummyScope =
nullptr, mlir::Value storage =
nullptr,
236 std::uint64_t storageOffset = 0,
237 cuf::DataAttributeAttr dataAttr = {},
unsigned dummyArgNo = 0);
245 llvm::StringRef name,
246 std::optional<mlir::NamedAttribute> attr = std::nullopt);
252mlir::Value genVariableRawAddress(mlir::Location loc,
272Entity loadTrivialScalar(mlir::Location loc, fir::FirOpBuilder &builder,
277hlfir::Entity derefPointersAndAllocatables(mlir::Location loc,
278 fir::FirOpBuilder &builder,
284hlfir::Entity getElementAt(mlir::Location loc, fir::FirOpBuilder &builder,
285 Entity entity, mlir::ValueRange oneBasedIndices);
287llvm::SmallVector<std::pair<mlir::Value, mlir::Value>>
288genBounds(mlir::Location loc, fir::FirOpBuilder &builder,
Entity entity);
291llvm::SmallVector<std::pair<mlir::Value, mlir::Value>>
292genBounds(mlir::Location loc, fir::FirOpBuilder &builder, mlir::Value shape);
296llvm::SmallVector<mlir::Value> genLowerbounds(mlir::Location loc,
297 fir::FirOpBuilder &builder,
298 mlir::Value shape,
unsigned rank);
301mlir::Value genShape(mlir::Location loc, fir::FirOpBuilder &builder,
306mlir::Value genExtent(mlir::Location loc, fir::FirOpBuilder &builder,
307 hlfir::Entity entity,
unsigned dim);
311mlir::Value genLBound(mlir::Location loc, fir::FirOpBuilder &builder,
312 hlfir::Entity entity,
unsigned dim);
316llvm::SmallVector<mlir::Value> getIndexExtents(mlir::Location loc,
317 fir::FirOpBuilder &builder,
322llvm::SmallVector<mlir::Value>
323getExplicitExtentsFromShape(mlir::Value shape, fir::FirOpBuilder &builder);
326void genLengthParameters(mlir::Location loc, fir::FirOpBuilder &builder,
328 llvm::SmallVectorImpl<mlir::Value> &result);
332mlir::Value genCharLength(mlir::Location loc, fir::FirOpBuilder &builder,
337std::optional<std::int64_t> getCharLengthIfConst(
Entity entity);
339mlir::Value genRank(mlir::Location loc, fir::FirOpBuilder &builder,
340 Entity entity, mlir::Type resultType);
346std::pair<mlir::Value, mlir::Value> genVariableFirBaseShapeAndParams(
347 mlir::Location loc, fir::FirOpBuilder &builder,
Entity entity,
348 llvm::SmallVectorImpl<mlir::Value> &typeParams);
353mlir::Type getVariableElementType(hlfir::Entity variable);
358mlir::Type getEntityElementType(hlfir::Entity entity);
360using ElementalKernelGenerator = std::function<hlfir::Entity(
361 mlir::Location, fir::FirOpBuilder &, mlir::ValueRange)>;
368hlfir::ElementalOp genElementalOp(
369 mlir::Location loc, fir::FirOpBuilder &builder, mlir::Type elementType,
370 mlir::Value shape, mlir::ValueRange typeParams,
371 const ElementalKernelGenerator &genKernel,
bool isUnordered =
false,
372 mlir::Value polymorphicMold = {}, mlir::Type exprType = mlir::Type{});
376 mlir::Operation *outerOp =
nullptr;
377 mlir::Block *body =
nullptr;
389 mlir::ValueRange extents,
bool isUnordered =
false,
390 bool emitWorkshareLoop =
false,
391 bool couldVectorize =
true);
393 mlir::Value shape,
bool isUnordered =
false,
394 bool emitWorkshareLoop =
false,
395 bool couldVectorize =
true) {
396 return genLoopNest(loc, builder, getIndexExtents(loc, builder, shape),
397 isUnordered, emitWorkshareLoop, couldVectorize);
406using ReductionLoopBodyGenerator = std::function<llvm::SmallVector<mlir::Value>(
428 mlir::ValueRange reductionInits,
const ReductionLoopBodyGenerator &genBody,
429 bool isUnordered =
false);
436hlfir::YieldElementOp inlineElementalOp(mlir::Location loc,
438 hlfir::ElementalOp elemental,
439 mlir::ValueRange oneBasedIndices);
448mlir::Value inlineElementalOp(
450 hlfir::ElementalOpInterface elemental, mlir::ValueRange oneBasedIndices,
451 mlir::IRMapping &mapper,
452 const std::function<
bool(hlfir::ElementalOp)> &mustRecursivelyInline);
464void genNoAliasArrayAssignment(
467 bool temporaryLHS =
false,
470 *scalarCombineAndAssign =
nullptr,
471 mlir::ArrayAttr accessGroups = {});
478void genNoAliasAssignment(
479 mlir::Location loc, fir::FirOpBuilder &builder, hlfir::Entity rhs,
480 hlfir::Entity lhs,
bool emitWorkshareLoop =
false,
481 bool temporaryLHS =
false,
482 std::function<
void(mlir::Location, fir::FirOpBuilder &, hlfir::Entity,
483 hlfir::Entity, mlir::ArrayAttr accessGroups)>
484 *scalarCombineAndAssign =
nullptr,
485 mlir::ArrayAttr accessGroups = {});
486inline void genNoAliasAssignment(
487 mlir::Location loc, fir::FirOpBuilder &builder, hlfir::Entity rhs,
488 hlfir::Entity lhs,
bool emitWorkshareLoop,
bool temporaryLHS,
489 std::function<
void(mlir::Location, fir::FirOpBuilder &, hlfir::Entity,
490 hlfir::Entity, mlir::ArrayAttr)>
491 scalarCombineAndAssign,
492 mlir::ArrayAttr accessGroups = {}) {
493 genNoAliasAssignment(loc, builder, rhs, lhs, emitWorkshareLoop, temporaryLHS,
494 &scalarCombineAndAssign, accessGroups);
501std::pair<hlfir::Entity, bool>
502computeEvaluateOpInNewTemp(mlir::Location, fir::FirOpBuilder &,
503 hlfir::EvaluateInMemoryOp evalInMem,
504 mlir::Value shape, mlir::ValueRange typeParams);
512void computeEvaluateOpIn(mlir::Location, fir::FirOpBuilder &,
513 hlfir::EvaluateInMemoryOp, mlir::Value storage);
515std::pair<fir::ExtendedValue, std::optional<hlfir::CleanupFunction>>
516convertToValue(mlir::Location loc, fir::FirOpBuilder &builder,
517 hlfir::Entity entity);
519std::pair<fir::ExtendedValue, std::optional<hlfir::CleanupFunction>>
520convertToAddress(mlir::Location loc, fir::FirOpBuilder &builder,
521 hlfir::Entity entity, mlir::Type targetType);
523std::pair<fir::ExtendedValue, std::optional<hlfir::CleanupFunction>>
524convertToBox(mlir::Location loc, fir::FirOpBuilder &builder,
525 hlfir::Entity entity, mlir::Type targetType);
528hlfir::ElementalOp cloneToElementalOp(mlir::Location loc,
529 fir::FirOpBuilder &builder,
530 hlfir::ElementalAddrOp elementalAddrOp);
537bool elementalOpMustProduceTemp(hlfir::ElementalOp elemental);
548std::pair<hlfir::Entity, bool> createTempFromMold(mlir::Location loc,
549 fir::FirOpBuilder &builder,
553hlfir::Entity createStackTempFromMold(mlir::Location loc,
554 fir::FirOpBuilder &builder,
557hlfir::EntityWithAttributes convertCharacterKind(mlir::Location loc,
558 fir::FirOpBuilder &builder,
559 hlfir::Entity scalarChar,
575std::pair<hlfir::Entity, std::optional<hlfir::CleanupFunction>>
576genTypeAndKindConvert(mlir::Location loc, fir::FirOpBuilder &builder,
577 hlfir::Entity source, mlir::Type toType,
578 bool preserveLowerBounds);
582Entity loadElementAt(mlir::Location loc, fir::FirOpBuilder &builder,
583 Entity entity, mlir::ValueRange oneBasedIndices);
588llvm::SmallVector<mlir::Value, Fortran::common::maxRank>
589genExtentsVector(mlir::Location loc, fir::FirOpBuilder &builder,
Entity entity);
598Entity gen1DSection(mlir::Location loc, fir::FirOpBuilder &builder,
599 Entity array, int64_t dim,
600 mlir::ArrayRef<mlir::Value> extents,
601 mlir::ValueRange oneBasedIndices,
602 mlir::ArrayRef<mlir::Value> typeParams);
607bool designatePreservesContinuity(hlfir::DesignateOp op);
615bool 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:52
bool isAssumedRank() const
Is this an assumed ranked entity?
Definition HLFIRTools.h:78
int getRank() const
Return the rank of this entity or -1 if it is an assumed rank.
Definition HLFIRTools.h:81
bool isArray() const
Is this an array or an assumed ranked entity?
Definition HLFIRTools.h:75
bool isProcedure() const
Is this entity a procedure designator?
Definition HLFIRTools.h:72
fir::BaseBoxType getBoxType() const
Return the fir.class or fir.box type needed to describe this entity.
Definition HLFIRTools.h:103
Definition AbstractConverter.h:37
bool isa_volatile_type(mlir::Type t)
Definition FIRType.cpp:750
mlir::Type unwrapPassByRefType(mlir::Type t)
Definition FIRType.h:292
bool isBoxAddress(mlir::Type t)
Is t an address to fir.box or class type?
Definition FIRType.h:512
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:32
Structure to describe a loop nest.
Definition HLFIRTools.h:375