| //===-- Lower/OpenMP/Utils.h ------------------------------------*- C++ -*-===// |
| // |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| // See https://llvm.org/LICENSE.txt for license information. |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef FORTRAN_LOWER_OPENMPUTILS_H |
| #define FORTRAN_LOWER_OPENMPUTILS_H |
| |
| #include "flang/Lower/OpenMP/Clauses.h" |
| #include "flang/Optimizer/Builder/HLFIRTools.h" |
| #include "mlir/Dialect/LLVMIR/LLVMAttrs.h" |
| #include "mlir/Dialect/OpenMP/OpenMPDialect.h" |
| #include "mlir/IR/Location.h" |
| #include "mlir/IR/Value.h" |
| #include "llvm/Frontend/OpenMP/OMPContext.h" |
| #include "llvm/Support/CommandLine.h" |
| #include <cstdint> |
| #include <optional> |
| |
| extern llvm::cl::opt<bool> treatIndexAsSection; |
| |
| namespace fir { |
| class FirOpBuilder; |
| class RecordType; |
| } // namespace fir |
| namespace Fortran { |
| |
| namespace semantics { |
| class Symbol; |
| namespace omp { |
| class OmpVariantMatchContext; |
| } // namespace omp |
| } // namespace semantics |
| |
| namespace parser { |
| struct OmpObject; |
| struct OmpObjectList; |
| } // namespace parser |
| |
| namespace lower { |
| class StatementContext; |
| namespace pft { |
| struct Evaluation; |
| } |
| |
| class AbstractConverter; |
| |
| namespace omp { |
| |
| struct DeclareTargetCaptureInfo { |
| mlir::omp::DeclareTargetCaptureClause clause; |
| bool automap = false; |
| const semantics::Symbol &symbol; |
| |
| DeclareTargetCaptureInfo(mlir::omp::DeclareTargetCaptureClause c, |
| const semantics::Symbol &s, bool a = false) |
| : clause(c), automap(a), symbol(s) {} |
| }; |
| |
| // A small helper structure for keeping track of a component members MapInfoOp |
| // and index data when lowering OpenMP map clauses. Keeps track of the |
| // placement of the component in the derived type hierarchy it rests within, |
| // alongside the generated mlir::omp::MapInfoOp for the mapped component. |
| // |
| // As an example of what the contents of this data structure may be like, |
| // when provided the following derived type and map of that type: |
| // |
| // type :: bottom_layer |
| // real(8) :: i2 |
| // real(4) :: array_i2(10) |
| // real(4) :: array_j2(10) |
| // end type bottom_layer |
| // |
| // type :: top_layer |
| // real(4) :: i |
| // integer(4) :: array_i(10) |
| // real(4) :: j |
| // type(bottom_layer) :: nested |
| // integer, allocatable :: array_j(:) |
| // integer(4) :: k |
| // end type top_layer |
| // |
| // type(top_layer) :: top_dtype |
| // |
| // map(tofrom: top_dtype%nested%i2, top_dtype%k, top_dtype%nested%array_i2) |
| // |
| // We would end up with an OmpMapParentAndMemberData populated like below: |
| // |
| // memberPlacementIndices: |
| // Vector 1: 3, 0 |
| // Vector 2: 5 |
| // Vector 3: 3, 1 |
| // |
| // memberMap: |
| // Entry 1: omp.map.info for "top_dtype%nested%i2" |
| // Entry 2: omp.map.info for "top_dtype%k" |
| // Entry 3: omp.map.info for "top_dtype%nested%array_i2" |
| // |
| // And this OmpMapParentAndMemberData would be accessed via the parent |
| // symbol for top_dtype. Other parent derived type instances that have |
| // members mapped would have there own OmpMapParentAndMemberData entry |
| // accessed via their own symbol. |
| struct OmpMapParentAndMemberData { |
| // The indices representing the component members placement in its derived |
| // type parents hierarchy. |
| llvm::SmallVector<llvm::SmallVector<int64_t>> memberPlacementIndices; |
| |
| // Placement of the member in the member vector. |
| llvm::SmallVector<mlir::omp::MapInfoOp> memberMap; |
| |
| bool isDuplicateMemberMapInfo(llvm::SmallVectorImpl<int64_t> &memberIndices) { |
| return llvm::find_if(memberPlacementIndices, [&](auto &memberData) { |
| return llvm::equal(memberIndices, memberData); |
| }) != memberPlacementIndices.end(); |
| } |
| |
| void addChildIndexAndMapToParent(const omp::Object &object, |
| mlir::omp::MapInfoOp &mapOp, |
| semantics::SemanticsContext &semaCtx); |
| }; |
| |
| void insertChildMapInfoIntoParent( |
| Fortran::lower::AbstractConverter &converter, |
| Fortran::semantics::SemanticsContext &semaCtx, |
| Fortran::lower::StatementContext &stmtCtx, |
| std::map<Object, OmpMapParentAndMemberData> &parentMemberIndices, |
| llvm::SmallVectorImpl<mlir::Value> &mapOperands, |
| llvm::SmallVectorImpl<Object> &mapObjects); |
| |
| void generateMemberPlacementIndices( |
| const Object &object, llvm::SmallVectorImpl<int64_t> &indices, |
| Fortran::semantics::SemanticsContext &semaCtx); |
| |
| bool isMemberOrParentAllocatableOrPointer( |
| const Object &object, Fortran::semantics::SemanticsContext &semaCtx); |
| |
| mlir::Value createParentSymAndGenIntermediateMaps( |
| mlir::Location clauseLocation, Fortran::lower::AbstractConverter &converter, |
| semantics::SemanticsContext &semaCtx, lower::StatementContext &stmtCtx, |
| omp::ObjectList &objectList, llvm::SmallVectorImpl<int64_t> &indices, |
| OmpMapParentAndMemberData &parentMemberIndices, llvm::StringRef asFortran, |
| mlir::omp::ClauseMapFlags mapTypeBits); |
| |
| bool requiresImplicitDefaultDeclareMapper( |
| const semantics::DerivedTypeSpec &typeSpec); |
| |
| omp::ObjectList gatherObjectsOf(omp::Object derivedTypeMember, |
| semantics::SemanticsContext &semaCtx); |
| |
| mlir::Type getLoopVarType(lower::AbstractConverter &converter, |
| std::size_t loopVarTypeSize); |
| |
| semantics::Symbol * |
| getIterationVariableSymbol(const lower::pft::Evaluation &eval); |
| |
| void gatherFuncAndVarSyms( |
| const ObjectList &objects, mlir::omp::DeclareTargetCaptureClause clause, |
| llvm::SmallVectorImpl<DeclareTargetCaptureInfo> &symbolAndClause, |
| bool automap = false); |
| |
| int64_t getCollapseValue(const List<Clause> &clauses); |
| |
| void genObjectList(const ObjectList &objects, |
| lower::AbstractConverter &converter, |
| llvm::SmallVectorImpl<mlir::Value> &operands); |
| |
| void lastprivateModifierNotSupported(const omp::clause::Lastprivate &lastp, |
| mlir::Location loc); |
| |
| pft::Evaluation *getNestedDoConstruct(pft::Evaluation &eval); |
| |
| int64_t collectLoopRelatedInfo( |
| lower::AbstractConverter &converter, mlir::Location currentLocation, |
| lower::pft::Evaluation &eval, lower::pft::Evaluation *nestedEval, |
| const omp::List<omp::Clause> &clauses, |
| mlir::omp::LoopRelatedClauseOps &result, |
| llvm::SmallVectorImpl<const semantics::Symbol *> &iv); |
| |
| void collectLoopRelatedInfo( |
| lower::AbstractConverter &converter, mlir::Location currentLocation, |
| lower::pft::Evaluation &eval, lower::pft::Evaluation *nestedEval, |
| std::int64_t collapseValue, |
| // const omp::List<omp::Clause> &clauses, |
| mlir::omp::LoopRelatedClauseOps &result, |
| llvm::SmallVectorImpl<const semantics::Symbol *> &iv); |
| |
| void collectTileSizesFromOpenMPConstruct( |
| const parser::OpenMPConstruct *ompCons, |
| llvm::SmallVectorImpl<int64_t> &tileSizes, |
| Fortran::semantics::SemanticsContext &semaCtx); |
| |
| mlir::Value genElementSizeInBytes(fir::FirOpBuilder &builder, |
| mlir::Location loc, |
| const mlir::DataLayout &dl, |
| hlfir::Entity entity); |
| |
| mlir::Value genAffinityAddr(Fortran::lower::AbstractConverter &converter, |
| const omp::Object &object, |
| Fortran::lower::StatementContext &stmtCtx, |
| mlir::Location loc); |
| |
| mlir::Value genAffinityLen(fir::FirOpBuilder &builder, mlir::Location loc, |
| const mlir::DataLayout &dl, hlfir::Entity entity, |
| llvm::ArrayRef<mlir::Value> bounds); |
| |
| struct IteratorRange { |
| mlir::Value lb; |
| mlir::Value ub; |
| mlir::Value step; |
| Fortran::semantics::Symbol *ivSym = nullptr; |
| }; |
| |
| bool hasIteratorIVReference( |
| const omp::Object &object, |
| const llvm::SmallPtrSetImpl<const Fortran::semantics::Symbol *> &ivSyms); |
| |
| /// Default name mangler for implicit default mappers. |
| /// |
| /// \param converter The converter to use for name mangling. |
| /// \param mapperIdName The name of the mapper to mangle. |
| /// \param memberName The name of the member to mangle. |
| void defaultMangler(Fortran::lower::AbstractConverter &converter, |
| std::string &mapperIdName, llvm::StringRef memberName); |
| |
| mlir::Value genIteratorCoordinate(Fortran::lower::AbstractConverter &converter, |
| hlfir::Entity entity, |
| llvm::ArrayRef<mlir::Value> ivs, |
| mlir::Location loc); |
| |
| /// Resolve the declare mapper symbol to attach to a mapped object. |
| /// |
| /// The default mapper path first looks for a user-defined mapper. If none |
| /// exists, it may synthesize a compiler-generated mapper, except for mapped |
| /// members whose parent object is also mapped and for target enter data, |
| /// target exit data, and target update directives. |
| /// |
| /// \param converter The converter used to query and generate mapper symbols. |
| /// \param loc The location to use when generating an implicit mapper. |
| /// \param object The mapped object whose type controls mapper resolution. |
| /// \param mapperIdName An explicit mapper name, `__implicit_mapper`, or an |
| /// empty name. |
| /// \param mapTypeBits The map flags used when deciding whether an implicit |
| /// mapper should be generated. |
| /// \param directive The enclosing OpenMP directive. |
| /// \param hasParentObj True if a mapped parent object already owns this object. |
| /// \return A symbol reference to the resolved mapper, or a null attribute when |
| /// no mapper applies. |
| mlir::FlatSymbolRefAttr |
| resolveMapperId(Fortran::lower::AbstractConverter &converter, |
| mlir::Location loc, const omp::Object &object, |
| llvm::StringRef mapperIdName, |
| mlir::omp::ClauseMapFlags mapTypeBits, |
| llvm::omp::Directive directive, bool hasParentObj); |
| |
| std::optional<llvm::SmallVector<mlir::Value>> getIteratorElementIndices( |
| Fortran::lower::AbstractConverter &converter, const omp::Object &object, |
| Fortran::lower::StatementContext &stmtCtx, mlir::Location loc); |
| |
| /// Walk the already-emitted MLIR parent operations starting from \p op and |
| /// collect the implied OpenMP construct traits in outermost-to-innermost |
| /// order. Used by metadirective lowering and declare-variant call resolution |
| /// to build the `ConstructTraits` of an `OMPContext`. |
| void collectEnclosingConstructTraits( |
| mlir::Operation *op, |
| llvm::SmallVectorImpl<llvm::omp::TraitProperty> &constructTraits); |
| |
| /// Build the OpenMP variant-matching context for \p module. The device flag, |
| /// host triple, offload triple, and target features are read from the module; |
| /// \p constructTraits seeds the enclosing-construct traits. |
| semantics::omp::OmpVariantMatchContext makeVariantMatchContext( |
| mlir::ModuleOp module, |
| llvm::ArrayRef<llvm::omp::TraitProperty> constructTraits); |
| |
| } // namespace omp |
| } // namespace lower |
| } // namespace Fortran |
| |
| #endif // FORTRAN_LOWER_OPENMPUTILS_H |