FLANG
ClauseProcessor.h
1//===-- Lower/OpenMP/ClauseProcessor.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// Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/
10//
11//===----------------------------------------------------------------------===//
12#ifndef FORTRAN_LOWER_CLAUSEPROCESSOR_H
13#define FORTRAN_LOWER_CLAUSEPROCESSOR_H
14
15#include "ClauseFinder.h"
16#include "Utils.h"
17#include "flang/Lower/AbstractConverter.h"
18#include "flang/Lower/Bridge.h"
19#include "flang/Lower/DirectivesCommon.h"
20#include "flang/Lower/OpenMP/Clauses.h"
21#include "flang/Lower/Support/ReductionProcessor.h"
22#include "flang/Optimizer/Builder/Todo.h"
23#include "flang/Parser/char-block.h"
24#include "mlir/Dialect/OpenMP/OpenMPDialect.h"
25
26namespace fir {
27class FirOpBuilder;
28} // namespace fir
29
30namespace Fortran {
31namespace lower {
32namespace omp {
33
34// Container type for tracking user specified Defaultmaps for a target region
35using DefaultMapsTy = std::map<clause::Defaultmap::VariableCategory,
36 clause::Defaultmap::ImplicitBehavior>;
37
52class ClauseProcessor {
53public:
54 ClauseProcessor(lower::AbstractConverter &converter,
56 const List<Clause> &clauses)
57 : converter(converter), semaCtx(semaCtx), clauses(clauses) {}
58
59 // 'Unique' clauses: They can appear at most once in the clause list.
60 bool processAlign(mlir::omp::AlignClauseOps &result) const;
61 bool processAllocator(lower::StatementContext &stmtCtx,
62 mlir::omp::AllocatorClauseOps &result) const;
63 bool processBind(mlir::omp::BindClauseOps &result) const;
64 bool processCancelDirectiveName(
65 mlir::omp::CancelDirectiveNameClauseOps &result) const;
66 bool
67 processCollapse(mlir::Location currentLocation, lower::pft::Evaluation &eval,
68 mlir::omp::LoopRelatedClauseOps &loopResult,
69 mlir::omp::CollapseClauseOps &collapseResult,
71 bool processSizes(StatementContext &stmtCtx,
72 mlir::omp::SizesClauseOps &result) const;
73 bool processLooprange(StatementContext &stmtCtx,
74 mlir::omp::LooprangeClauseOps &result,
75 int64_t &count) const;
76 bool processDevice(lower::StatementContext &stmtCtx,
77 mlir::omp::DeviceClauseOps &result) const;
78 bool processDeviceType(mlir::omp::DeviceTypeClauseOps &result) const;
79 bool processDistSchedule(lower::StatementContext &stmtCtx,
80 mlir::omp::DistScheduleClauseOps &result) const;
81 bool processExclusive(mlir::Location currentLocation,
82 mlir::omp::ExclusiveClauseOps &result) const;
83 bool processFilter(lower::StatementContext &stmtCtx,
84 mlir::omp::FilterClauseOps &result) const;
85 bool processFinal(lower::StatementContext &stmtCtx,
86 mlir::omp::FinalClauseOps &result) const;
87 bool processGrainsize(lower::StatementContext &stmtCtx,
88 mlir::omp::GrainsizeClauseOps &result) const;
89 bool
90 processHasDeviceAddr(lower::StatementContext &stmtCtx,
91 mlir::omp::HasDeviceAddrClauseOps &result,
92 llvm::SmallVectorImpl<Object> &hasDeviceObjects) const;
93 bool processHint(mlir::omp::HintClauseOps &result) const;
94 bool processInbranch(mlir::omp::InbranchClauseOps &result) const;
95 bool processInclusive(mlir::Location currentLocation,
96 mlir::omp::InclusiveClauseOps &result) const;
97 bool processInitializer(
98 lower::SymMap &symMap,
99 ReductionProcessor::GenInitValueCBTy &genInitValueCB,
100 const parser::OmpStylizedInstance *parserInitInstance = nullptr,
101 unsigned instanceIdx = 0) const;
102 bool processMergeable(mlir::omp::MergeableClauseOps &result) const;
103 bool processNocontext(lower::StatementContext &stmtCtx,
104 mlir::omp::NocontextClauseOps &result) const;
105 bool processNogroup(mlir::omp::NogroupClauseOps &result) const;
106 bool processNotinbranch(mlir::omp::NotinbranchClauseOps &result) const;
107 bool processNovariants(lower::StatementContext &stmtCtx,
108 mlir::omp::NovariantsClauseOps &result) const;
109 bool processNowait(mlir::omp::NowaitClauseOps &result) const;
110 bool processNumTasks(lower::StatementContext &stmtCtx,
111 mlir::omp::NumTasksClauseOps &result) const;
112 bool processNumTeams(lower::StatementContext &stmtCtx,
113 mlir::omp::NumTeamsClauseOps &result) const;
114 bool processNumThreads(lower::StatementContext &stmtCtx,
115 mlir::omp::NumThreadsClauseOps &result) const;
116 bool processOrder(mlir::omp::OrderClauseOps &result) const;
117 bool processOrdered(mlir::omp::OrderedClauseOps &result) const;
118 bool processFull() const;
119 bool processPartial(std::optional<int64_t> &result) const;
120 bool processPriority(lower::StatementContext &stmtCtx,
121 mlir::omp::PriorityClauseOps &result) const;
122 bool processProcBind(mlir::omp::ProcBindClauseOps &result) const;
123 bool processTileSizes(lower::pft::Evaluation &eval,
124 mlir::omp::LoopNestOperands &result) const;
125 bool processSafelen(mlir::omp::SafelenClauseOps &result) const;
126 bool processSchedule(lower::StatementContext &stmtCtx,
127 mlir::omp::ScheduleClauseOps &result) const;
128 bool processSimdlen(mlir::omp::SimdlenClauseOps &result) const;
129 bool processSimd(mlir::omp::OrderedRegionOperands &result) const;
130 bool processThreadLimit(lower::StatementContext &stmtCtx,
131 mlir::omp::ThreadLimitClauseOps &result) const;
132 bool processThreadset(mlir::omp::ThreadsetClauseOps &result) const;
133 bool processUntied(mlir::omp::UntiedClauseOps &result) const;
134 bool processDetach(mlir::omp::DetachClauseOps &result) const;
135 // 'Repeatable' clauses: They can appear multiple times in the clause list.
136 bool processAffinity(mlir::omp::AffinityClauseOps &result) const;
137 bool processAligned(mlir::omp::AlignedClauseOps &result) const;
138 bool processAllocate(mlir::omp::AllocateClauseOps &result,
139 bool supportAlignment = false) const;
140 bool processCopyin() const;
141 bool processCopyprivate(mlir::Location currentLocation,
142 mlir::omp::CopyprivateClauseOps &result) const;
143 bool processDefaultMap(lower::StatementContext &stmtCtx,
144 DefaultMapsTy &result) const;
145 bool processDepend(lower::SymMap &symMap, lower::StatementContext &stmtCtx,
146 mlir::omp::DependClauseOps &result) const;
147 bool
148 processDynGroupprivate(lower::StatementContext &stmtCtx,
149 mlir::omp::DynGroupprivateClauseOps &result) const;
150 bool
151 processEnter(llvm::SmallVectorImpl<DeclareTargetCaptureInfo> &result) const;
152 bool processIf(omp::clause::If::DirectiveNameModifier directiveName,
153 mlir::omp::IfClauseOps &result) const;
154 bool
155 processInReduction(mlir::Location currentLocation,
156 mlir::omp::InReductionClauseOps &result,
157 llvm::SmallVectorImpl<Object> &outReductionObjects) const;
158 bool processIsDevicePtr(lower::StatementContext &stmtCtx,
159 mlir::omp::IsDevicePtrClauseOps &result,
160 llvm::SmallVectorImpl<Object> &isDeviceObjects) const;
161 bool
162 processLinear(mlir::omp::LinearClauseOps &result, bool isDeclareSimd = false,
164 nullptr) const;
165 bool
166 processLink(llvm::SmallVectorImpl<DeclareTargetCaptureInfo> &result) const;
167
168 // This method is used to process a map clause.
169 // The optional parameter mapObjects is used to store the original Fortran
170 // objects for the map operands. It may be used later on to create the
171 // block_arguments for some of the directives that require it.
172 bool processMap(mlir::Location currentLocation,
174 mlir::omp::MapClauseOps &result,
175 llvm::omp::Directive directive = llvm::omp::OMPD_unknown,
176 llvm::SmallVectorImpl<Object> *mapObjects = nullptr) const;
177 bool processMotionClauses(lower::StatementContext &stmtCtx,
178 mlir::omp::MapClauseOps &result);
179 bool processNontemporal(mlir::omp::NontemporalClauseOps &result) const;
180 bool processReduction(mlir::Location currentLocation,
181 mlir::omp::ReductionClauseOps &result,
182 llvm::SmallVectorImpl<Object> &reductionObjects,
183 llvm::DenseMap<const semantics::Symbol *, mlir::Value>
184 *reductionVarCache = nullptr) const;
185 bool processTaskReduction(
186 mlir::Location currentLocation, mlir::omp::TaskReductionClauseOps &result,
187 llvm::SmallVectorImpl<Object> &outReductionObjects) const;
188 bool processTo(llvm::SmallVectorImpl<DeclareTargetCaptureInfo> &result) const;
189 bool
190 processUseDeviceAddr(lower::StatementContext &stmtCtx,
191 mlir::omp::UseDeviceAddrClauseOps &result,
192 llvm::SmallVectorImpl<Object> &useDeviceObjects) const;
193 bool
194 processUseDevicePtr(lower::StatementContext &stmtCtx,
195 mlir::omp::UseDevicePtrClauseOps &result,
196 llvm::SmallVectorImpl<Object> &useDeviceObjects) const;
197 bool processUniform(mlir::omp::UniformClauseOps &result) const;
198
199 // Call this method for these clauses that should be supported but are not
200 // implemented yet. It triggers a compilation error if any of the given
201 // clauses is found.
202 template <typename... Ts>
203 void processTODO(mlir::Location currentLocation,
204 llvm::omp::Directive directive) const;
205
206private:
207 using ClauseIterator = List<Clause>::const_iterator;
208
212 template <typename T>
213 const T *findUniqueClause(const parser::CharBlock **source = nullptr) const;
214
217 template <typename T>
218 bool findRepeatableClause(
219 std::function<void(const T &, const parser::CharBlock &source)>
220 callbackFn) const;
221
223 template <typename T>
224 bool markClauseOccurrence(mlir::UnitAttr &result) const;
225
226 void processMapObjects(
227 lower::StatementContext &stmtCtx, mlir::Location clauseLocation,
228 const omp::ObjectList &objects, mlir::omp::ClauseMapFlags mapTypeBits,
229 std::map<Object, OmpMapParentAndMemberData> &parentMemberIndices,
232 llvm::StringRef mapperIdNameRef = "", bool isMotionModifier = false,
233 llvm::omp::Directive directive = llvm::omp::OMPD_unknown) const;
234
235 lower::AbstractConverter &converter;
237 List<Clause> clauses;
238};
239
240template <typename... Ts>
241void ClauseProcessor::processTODO(mlir::Location currentLocation,
242 llvm::omp::Directive directive) const {
243 auto checkUnhandledClause = [&](llvm::omp::Clause id, const auto *x) {
244 if (!x)
245 return;
246 llvm::omp::Version version = semaCtx.langOptions().getOpenMPVersion();
247 bool isSimdDirective = llvm::omp::getOpenMPDirectiveName(directive, version)
248 .upper()
249 .find("SIMD") != llvm::StringRef::npos;
250 if (!semaCtx.langOptions().OpenMPSimd || isSimdDirective)
251 TODO(currentLocation,
252 "Unhandled clause " + llvm::omp::getOpenMPClauseName(id).upper() +
253 " in " +
254 llvm::omp::getOpenMPDirectiveName(directive, version).upper() +
255 " construct");
256 };
257
258 for (ClauseIterator it = clauses.begin(); it != clauses.end(); ++it)
259 (checkUnhandledClause(it->id, std::get_if<Ts>(&it->u)), ...);
260}
261
262template <typename T>
263const T *
264ClauseProcessor::findUniqueClause(const parser::CharBlock **source) const {
265 return ClauseFinder::findUniqueClause<T>(clauses, source);
266}
267
268template <typename T>
269bool ClauseProcessor::findRepeatableClause(
270 std::function<void(const T &, const parser::CharBlock &source)> callbackFn)
271 const {
272 return ClauseFinder::findRepeatableClause<T>(clauses, callbackFn);
273}
274
275template <typename T>
276bool ClauseProcessor::markClauseOccurrence(mlir::UnitAttr &result) const {
277 if (findUniqueClause<T>()) {
278 result = converter.getFirOpBuilder().getUnitAttr();
279 return true;
280 }
281 return false;
282}
283
284} // namespace omp
285} // namespace lower
286} // namespace Fortran
287
288#endif // FORTRAN_LOWER_CLAUSEPROCESSOR_H
Definition AbstractConverter.h:87
Definition StatementContext.h:46
Definition SymbolMap.h:181
static bool findRepeatableClause(const List< Clause > &clauses, std::function< void(const T &, const parser::CharBlock &source)> callbackFn)
Definition ClauseFinder.h:54
static const T * findUniqueClause(const List< Clause > &clauses, const parser::CharBlock **source=nullptr)
Definition ClauseFinder.h:40
Definition char-block.h:27
Definition semantics.h:71
Definition FIRBuilder.h:66
Definition OpenACC.h:22
Definition ParserActions.h:24
Definition bit-population-count.h:20
Definition AbstractConverter.h:37
Definition PFTBuilder.h:222
Definition parse-tree.h:3659