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