| 1 | //===-- Lower/OpenMP/Utils.h ------------------------------------*- 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_LOWER_OPENMPUTILS_H |
| 10 | #define FORTRAN_LOWER_OPENMPUTILS_H |
| 11 | |
| 12 | #include "Clauses.h" |
| 13 | #include "mlir/Dialect/OpenMP/OpenMPDialect.h" |
| 14 | #include "mlir/IR/Location.h" |
| 15 | #include "mlir/IR/Value.h" |
| 16 | #include "llvm/Support/CommandLine.h" |
| 17 | #include <cstdint> |
| 18 | |
| 19 | extern llvm::cl::opt<bool> treatIndexAsSection; |
| 20 | |
| 21 | namespace fir { |
| 22 | class FirOpBuilder; |
| 23 | } // namespace fir |
| 24 | namespace Fortran { |
| 25 | |
| 26 | namespace semantics { |
| 27 | class Symbol; |
| 28 | } // namespace semantics |
| 29 | |
| 30 | namespace parser { |
| 31 | struct OmpObject; |
| 32 | struct OmpObjectList; |
| 33 | } // namespace parser |
| 34 | |
| 35 | namespace lower { |
| 36 | class StatementContext; |
| 37 | namespace pft { |
| 38 | struct Evaluation; |
| 39 | } |
| 40 | |
| 41 | class AbstractConverter; |
| 42 | |
| 43 | namespace omp { |
| 44 | |
| 45 | using DeclareTargetCapturePair = |
| 46 | std::pair<mlir::omp::DeclareTargetCaptureClause, const semantics::Symbol &>; |
| 47 | |
| 48 | // A small helper structure for keeping track of a component members MapInfoOp |
| 49 | // and index data when lowering OpenMP map clauses. Keeps track of the |
| 50 | // placement of the component in the derived type hierarchy it rests within, |
| 51 | // alongside the generated mlir::omp::MapInfoOp for the mapped component. |
| 52 | // |
| 53 | // As an example of what the contents of this data structure may be like, |
| 54 | // when provided the following derived type and map of that type: |
| 55 | // |
| 56 | // type :: bottom_layer |
| 57 | // real(8) :: i2 |
| 58 | // real(4) :: array_i2(10) |
| 59 | // real(4) :: array_j2(10) |
| 60 | // end type bottom_layer |
| 61 | // |
| 62 | // type :: top_layer |
| 63 | // real(4) :: i |
| 64 | // integer(4) :: array_i(10) |
| 65 | // real(4) :: j |
| 66 | // type(bottom_layer) :: nested |
| 67 | // integer, allocatable :: array_j(:) |
| 68 | // integer(4) :: k |
| 69 | // end type top_layer |
| 70 | // |
| 71 | // type(top_layer) :: top_dtype |
| 72 | // |
| 73 | // map(tofrom: top_dtype%nested%i2, top_dtype%k, top_dtype%nested%array_i2) |
| 74 | // |
| 75 | // We would end up with an OmpMapParentAndMemberData populated like below: |
| 76 | // |
| 77 | // memberPlacementIndices: |
| 78 | // Vector 1: 3, 0 |
| 79 | // Vector 2: 5 |
| 80 | // Vector 3: 3, 1 |
| 81 | // |
| 82 | // memberMap: |
| 83 | // Entry 1: omp.map.info for "top_dtype%nested%i2" |
| 84 | // Entry 2: omp.map.info for "top_dtype%k" |
| 85 | // Entry 3: omp.map.info for "top_dtype%nested%array_i2" |
| 86 | // |
| 87 | // And this OmpMapParentAndMemberData would be accessed via the parent |
| 88 | // symbol for top_dtype. Other parent derived type instances that have |
| 89 | // members mapped would have there own OmpMapParentAndMemberData entry |
| 90 | // accessed via their own symbol. |
| 91 | struct OmpMapParentAndMemberData { |
| 92 | // The indices representing the component members placement in its derived |
| 93 | // type parents hierarchy. |
| 94 | llvm::SmallVector<llvm::SmallVector<int64_t>> memberPlacementIndices; |
| 95 | |
| 96 | // Placement of the member in the member vector. |
| 97 | llvm::SmallVector<mlir::omp::MapInfoOp> memberMap; |
| 98 | |
| 99 | bool isDuplicateMemberMapInfo(llvm::SmallVectorImpl<int64_t> &memberIndices) { |
| 100 | return llvm::find_if(Range&: memberPlacementIndices, P: [&](auto &memberData) { |
| 101 | return llvm::equal(memberIndices, memberData); |
| 102 | }) != memberPlacementIndices.end(); |
| 103 | } |
| 104 | |
| 105 | void addChildIndexAndMapToParent(const omp::Object &object, |
| 106 | mlir::omp::MapInfoOp &mapOp, |
| 107 | semantics::SemanticsContext &semaCtx); |
| 108 | }; |
| 109 | |
| 110 | mlir::omp::MapInfoOp |
| 111 | createMapInfoOp(fir::FirOpBuilder &builder, mlir::Location loc, |
| 112 | mlir::Value baseAddr, mlir::Value varPtrPtr, |
| 113 | llvm::StringRef name, llvm::ArrayRef<mlir::Value> bounds, |
| 114 | llvm::ArrayRef<mlir::Value> members, |
| 115 | mlir::ArrayAttr membersIndex, uint64_t mapType, |
| 116 | mlir::omp::VariableCaptureKind mapCaptureType, mlir::Type retTy, |
| 117 | bool partialMap = false, |
| 118 | mlir::FlatSymbolRefAttr mapperId = mlir::FlatSymbolRefAttr()); |
| 119 | |
| 120 | void insertChildMapInfoIntoParent( |
| 121 | Fortran::lower::AbstractConverter &converter, |
| 122 | Fortran::semantics::SemanticsContext &semaCtx, |
| 123 | Fortran::lower::StatementContext &stmtCtx, |
| 124 | std::map<Object, OmpMapParentAndMemberData> &parentMemberIndices, |
| 125 | llvm::SmallVectorImpl<mlir::Value> &mapOperands, |
| 126 | llvm::SmallVectorImpl<const semantics::Symbol *> &mapSyms); |
| 127 | |
| 128 | void generateMemberPlacementIndices( |
| 129 | const Object &object, llvm::SmallVectorImpl<int64_t> &indices, |
| 130 | Fortran::semantics::SemanticsContext &semaCtx); |
| 131 | |
| 132 | bool isMemberOrParentAllocatableOrPointer( |
| 133 | const Object &object, Fortran::semantics::SemanticsContext &semaCtx); |
| 134 | |
| 135 | mlir::Value createParentSymAndGenIntermediateMaps( |
| 136 | mlir::Location clauseLocation, Fortran::lower::AbstractConverter &converter, |
| 137 | semantics::SemanticsContext &semaCtx, lower::StatementContext &stmtCtx, |
| 138 | omp::ObjectList &objectList, llvm::SmallVectorImpl<int64_t> &indices, |
| 139 | OmpMapParentAndMemberData &parentMemberIndices, llvm::StringRef asFortran, |
| 140 | llvm::omp::OpenMPOffloadMappingFlags mapTypeBits); |
| 141 | |
| 142 | omp::ObjectList gatherObjectsOf(omp::Object derivedTypeMember, |
| 143 | semantics::SemanticsContext &semaCtx); |
| 144 | |
| 145 | mlir::Type getLoopVarType(lower::AbstractConverter &converter, |
| 146 | std::size_t loopVarTypeSize); |
| 147 | |
| 148 | semantics::Symbol * |
| 149 | getIterationVariableSymbol(const lower::pft::Evaluation &eval); |
| 150 | |
| 151 | void gatherFuncAndVarSyms( |
| 152 | const ObjectList &objects, mlir::omp::DeclareTargetCaptureClause clause, |
| 153 | llvm::SmallVectorImpl<DeclareTargetCapturePair> &symbolAndClause); |
| 154 | |
| 155 | int64_t getCollapseValue(const List<Clause> &clauses); |
| 156 | |
| 157 | void genObjectList(const ObjectList &objects, |
| 158 | lower::AbstractConverter &converter, |
| 159 | llvm::SmallVectorImpl<mlir::Value> &operands); |
| 160 | |
| 161 | void lastprivateModifierNotSupported(const omp::clause::Lastprivate &lastp, |
| 162 | mlir::Location loc); |
| 163 | |
| 164 | bool collectLoopRelatedInfo( |
| 165 | lower::AbstractConverter &converter, mlir::Location currentLocation, |
| 166 | lower::pft::Evaluation &eval, const omp::List<omp::Clause> &clauses, |
| 167 | mlir::omp::LoopRelatedClauseOps &result, |
| 168 | llvm::SmallVectorImpl<const semantics::Symbol *> &iv); |
| 169 | } // namespace omp |
| 170 | } // namespace lower |
| 171 | } // namespace Fortran |
| 172 | |
| 173 | #endif // FORTRAN_LOWER_OPENMPUTILS_H |
| 174 | |