1//===-- flang/lib/Semantics/openmp-modifiers.cpp --------------------------===//
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#include "flang/Semantics/openmp-modifiers.h"
10
11#include "flang/Parser/parse-tree.h"
12#include "llvm/ADT/ArrayRef.h"
13#include "llvm/Frontend/OpenMP/OMP.h"
14
15#include <algorithm>
16#include <cassert>
17#include <map>
18
19namespace Fortran::semantics {
20using namespace llvm::omp;
21
22/// Find the highest version that exists as a key in the given map,
23/// and is less than or equal to `version`.
24/// Account for "version" not being a value from getOpenMPVersions().
25template <typename ValueTy>
26static unsigned findVersion(
27 unsigned version, const std::map<unsigned, ValueTy> &map) {
28 llvm::ArrayRef<unsigned> versions{llvm::omp::getOpenMPVersions()};
29 assert(!versions.empty() && "getOpenMPVersions returned empty list");
30 version = std::clamp(val: version, lo: versions.front(), hi: versions.back());
31
32 // std::map is sorted with respect to keys, by default in the ascending
33 // order.
34 unsigned found{0};
35 for (auto &[v, _] : map) {
36 if (v <= version) {
37 found = v;
38 } else {
39 break;
40 }
41 }
42
43 // It can happen that the above search will not find any version, for
44 // example when the minimum version in the map is higher than the current
45 // version. This is really an error, but this situation should be handled
46 // gracefully, so make some sensible choice and return it.
47 if (found == 0) {
48 found = !map.empty() ? map.begin()->first : versions.front();
49 }
50 return found;
51}
52
53const OmpProperties &OmpModifierDescriptor::props(unsigned version) const {
54 return props_.at(findVersion(version, props_));
55}
56
57const OmpClauses &OmpModifierDescriptor::clauses(unsigned version) const {
58 return clauses_.at(findVersion(version, clauses_));
59}
60
61unsigned OmpModifierDescriptor::since(llvm::omp::Clause id) const {
62 unsigned found{[&]() {
63 for (auto &[v, cs] : clauses_) {
64 if (cs.test(id)) {
65 return v;
66 }
67 }
68 return ~0u;
69 }()};
70
71 return found <= 45 ? 0 : found;
72}
73
74// Note: The intent for these functions is to have them be automatically-
75// generated in the future.
76
77template <>
78const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpAlignment>() {
79 static const OmpModifierDescriptor desc{
80 /*name=*/"alignment",
81 /*props=*/
82 {
83 {45, {OmpProperty::Unique, OmpProperty::Ultimate, OmpProperty::Post}},
84 },
85 /*clauses=*/
86 {
87 {45, {Clause::OMPC_aligned}},
88 },
89 };
90 return desc;
91}
92
93template <>
94const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpAlignModifier>() {
95 static const OmpModifierDescriptor desc{
96 /*name=*/"align-modifier",
97 /*props=*/
98 {
99 {51, {OmpProperty::Unique}},
100 },
101 /*clauses=*/
102 {
103 {51, {Clause::OMPC_allocate}},
104 },
105 };
106 return desc;
107}
108
109template <>
110const OmpModifierDescriptor &
111OmpGetDescriptor<parser::OmpAllocatorComplexModifier>() {
112 static const OmpModifierDescriptor desc{
113 /*name=*/"allocator-complex-modifier",
114 /*props=*/
115 {
116 {51, {OmpProperty::Unique}},
117 },
118 /*clauses=*/
119 {
120 {51, {Clause::OMPC_allocate}},
121 },
122 };
123 return desc;
124}
125
126template <>
127const OmpModifierDescriptor &
128OmpGetDescriptor<parser::OmpAllocatorSimpleModifier>() {
129 static const OmpModifierDescriptor desc{
130 /*name=*/"allocator-simple-modifier",
131 /*props=*/
132 {
133 {50, {OmpProperty::Exclusive, OmpProperty::Unique}},
134 },
135 /*clauses=*/
136 {
137 {50, {Clause::OMPC_allocate}},
138 },
139 };
140 return desc;
141}
142
143template <>
144const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpChunkModifier>() {
145 static const OmpModifierDescriptor desc{
146 /*name=*/"chunk-modifier",
147 /*props=*/
148 {
149 {45, {OmpProperty::Unique}},
150 },
151 /*clauses=*/
152 {
153 {45, {Clause::OMPC_schedule}},
154 },
155 };
156 return desc;
157}
158
159template <>
160const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpContextSelector>() {
161 static const OmpModifierDescriptor desc{
162 /*name=*/"context-selector",
163 /*props=*/
164 {
165 {50, {OmpProperty::Required, OmpProperty::Unique}},
166 },
167 /*clauses=*/
168 {
169 // The MATCH clause takes a selector as an argument, not modifier.
170 {50, {Clause::OMPC_when}},
171 },
172 };
173 return desc;
174}
175
176template <>
177const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpDependenceType>() {
178 static const OmpModifierDescriptor desc{
179 /*name=*/"dependence-type",
180 /*props=*/
181 {
182 {45, {OmpProperty::Required, OmpProperty::Ultimate}},
183 },
184 /*clauses=*/
185 {
186 {45, {Clause::OMPC_depend}},
187 {51, {Clause::OMPC_depend, Clause::OMPC_update}},
188 {52, {Clause::OMPC_doacross}},
189 },
190 };
191 return desc;
192}
193
194template <>
195const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpDeviceModifier>() {
196 static const OmpModifierDescriptor desc{
197 /*name=*/"device-modifier",
198 /*props=*/
199 {
200 {45, {OmpProperty::Unique}},
201 },
202 /*clauses=*/
203 {
204 {45, {Clause::OMPC_device}},
205 },
206 };
207 return desc;
208}
209
210template <>
211const OmpModifierDescriptor &
212OmpGetDescriptor<parser::OmpDirectiveNameModifier>() {
213 static const OmpModifierDescriptor desc{
214 /*name=*/"directive-name-modifier",
215 /*props=*/
216 {
217 {45, {OmpProperty::Unique}},
218 },
219 /*clauses=*/
220 {
221 {45, {Clause::OMPC_if}},
222 },
223 };
224 return desc;
225}
226
227template <>
228const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpExpectation>() {
229 static const OmpModifierDescriptor desc{
230 /*name=*/"expectation",
231 /*props=*/
232 {
233 {51, {OmpProperty::Unique}},
234 },
235 /*clauses=*/
236 {
237 {51, {Clause::OMPC_from, Clause::OMPC_to}},
238 },
239 };
240 return desc;
241}
242
243template <>
244const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpInteropPreference>() {
245 static const OmpModifierDescriptor desc{
246 /*name=*/"interop-preference",
247 /*props=*/
248 {
249 {52, {OmpProperty::Unique}},
250 },
251 /*clauses=*/
252 {
253 {52, {Clause::OMPC_init}},
254 },
255 };
256 return desc;
257}
258
259template <>
260const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpInteropType>() {
261 static const OmpModifierDescriptor desc{
262 /*name=*/"interop-type",
263 /*props=*/
264 {
265 {52, {OmpProperty::Required}},
266 },
267 /*clauses=*/
268 {
269 {52, {Clause::OMPC_init}},
270 },
271 };
272 return desc;
273}
274
275template <>
276const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpIterator>() {
277 static const OmpModifierDescriptor desc{
278 /*name=*/"iterator",
279 /*props=*/
280 {
281 {50, {OmpProperty::Unique}},
282 },
283 /*clauses=*/
284 {
285 {50, {Clause::OMPC_affinity, Clause::OMPC_depend}},
286 {51,
287 {Clause::OMPC_affinity, Clause::OMPC_depend, Clause::OMPC_from,
288 Clause::OMPC_map, Clause::OMPC_to}},
289 },
290 };
291 return desc;
292}
293
294template <>
295const OmpModifierDescriptor &
296OmpGetDescriptor<parser::OmpLastprivateModifier>() {
297 static const OmpModifierDescriptor desc{
298 /*name=*/"lastprivate-modifier",
299 /*props=*/
300 {
301 {50, {OmpProperty::Unique}},
302 },
303 /*clauses=*/
304 {
305 {50, {Clause::OMPC_lastprivate}},
306 },
307 };
308 return desc;
309}
310
311template <>
312const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpLinearModifier>() {
313 static const OmpModifierDescriptor desc{
314 /*name=*/"linear-modifier",
315 /*props=*/
316 {
317 {45, {OmpProperty::Unique}},
318 },
319 /*clauses=*/
320 {
321 {45, {Clause::OMPC_linear}},
322 },
323 };
324 return desc;
325}
326
327template <> //
328const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpMapper>() {
329 static const OmpModifierDescriptor desc{
330 /*name=*/"mapper",
331 /*props=*/
332 {
333 {50, {OmpProperty::Unique}},
334 },
335 /*clauses=*/
336 {
337 {50, {Clause::OMPC_from, Clause::OMPC_map, Clause::OMPC_to}},
338 },
339 };
340 return desc;
341}
342
343template <>
344const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpMapType>() {
345 static const OmpModifierDescriptor desc{
346 /*name=*/"map-type",
347 /*props=*/
348 {
349 {45, {OmpProperty::Ultimate}},
350 },
351 /*clauses=*/
352 {
353 {45, {Clause::OMPC_map}},
354 },
355 };
356 return desc;
357}
358
359template <>
360const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpMapTypeModifier>() {
361 static const OmpModifierDescriptor desc{
362 /*name=*/"map-type-modifier",
363 /*props=*/
364 {
365 {45, {}}, // Repeatable
366 },
367 /*clauses=*/
368 {
369 {45, {Clause::OMPC_map}},
370 },
371 };
372 return desc;
373}
374
375template <>
376const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpOrderModifier>() {
377 static const OmpModifierDescriptor desc{
378 /*name=*/"order-modifier",
379 /*props=*/
380 {
381 {51, {OmpProperty::Unique}},
382 },
383 /*clauses=*/
384 {
385 {51, {Clause::OMPC_order}},
386 },
387 };
388 return desc;
389}
390
391template <>
392const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpOrderingModifier>() {
393 static const OmpModifierDescriptor desc{
394 /*name=*/"ordering-modifier",
395 /*props=*/
396 {
397 {45, {OmpProperty::Unique}},
398 },
399 /*clauses=*/
400 {
401 {45, {Clause::OMPC_schedule}},
402 },
403 };
404 return desc;
405}
406
407template <>
408const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpPrescriptiveness>() {
409 static const OmpModifierDescriptor desc{
410 /*name=*/"prescriptiveness",
411 /*props=*/
412 {
413 {51, {OmpProperty::Unique}},
414 },
415 /*clauses=*/
416 {
417 {51, {Clause::OMPC_grainsize, Clause::OMPC_num_tasks}},
418 },
419 };
420 return desc;
421}
422
423template <>
424const OmpModifierDescriptor &
425OmpGetDescriptor<parser::OmpReductionIdentifier>() {
426 static const OmpModifierDescriptor desc{
427 /*name=*/"reduction-identifier",
428 /*props=*/
429 {
430 {45, {OmpProperty::Required, OmpProperty::Ultimate}},
431 },
432 /*clauses=*/
433 {
434 {45, {Clause::OMPC_reduction}},
435 {50,
436 {Clause::OMPC_in_reduction, Clause::OMPC_reduction,
437 Clause::OMPC_task_reduction}},
438 },
439 };
440 return desc;
441}
442
443template <>
444const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpReductionModifier>() {
445 static const OmpModifierDescriptor desc{
446 /*name=*/"reduction-modifier",
447 /*props=*/
448 {
449 {45, {OmpProperty::Unique}},
450 },
451 /*clauses=*/
452 {
453 {45, {Clause::OMPC_reduction}},
454 },
455 };
456 return desc;
457}
458
459template <>
460const OmpModifierDescriptor &
461OmpGetDescriptor<parser::OmpStepComplexModifier>() {
462 static const OmpModifierDescriptor desc{
463 /*name=*/"step-complex-modifier",
464 /*props=*/
465 {
466 {52, {OmpProperty::Unique}},
467 },
468 /*clauses=*/
469 {
470 {52, {Clause::OMPC_linear}},
471 },
472 };
473 return desc;
474}
475
476template <>
477const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpStepSimpleModifier>() {
478 static const OmpModifierDescriptor desc{
479 /*name=*/"step-simple-modifier",
480 /*props=*/
481 {
482 {45, {OmpProperty::Unique, OmpProperty::Exclusive}},
483 },
484 /*clauses=*/
485 {
486 {45, {Clause::OMPC_linear}},
487 },
488 };
489 return desc;
490}
491
492template <>
493const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpTaskDependenceType>() {
494 static const OmpModifierDescriptor desc{
495 /*name=*/"task-dependence-type",
496 /*props=*/
497 {
498 {45, {OmpProperty::Required, OmpProperty::Ultimate}},
499 },
500 /*clauses=*/
501 {
502 {45, {Clause::OMPC_depend}},
503 {51, {Clause::OMPC_depend, Clause::OMPC_update}},
504 },
505 };
506 return desc;
507}
508
509template <>
510const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpVariableCategory>() {
511 static const OmpModifierDescriptor desc{
512 /*name=*/"variable-category",
513 /*props=*/
514 {
515 {45, {OmpProperty::Required, OmpProperty::Unique}},
516 {50, {OmpProperty::Unique}},
517 },
518 /*clauses=*/
519 {
520 {45, {Clause::OMPC_defaultmap}},
521 },
522 };
523 return desc;
524}
525} // namespace Fortran::semantics
526

Provided by KDAB

Privacy Policy
Improve your Profiling and Debugging skills
Find out more

source code of flang/lib/Semantics/openmp-modifiers.cpp