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 | |