705 lines · cpp
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-exception6//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(version, versions.front(), versions.back());31 32 // std::map is sorted with respect to keys, by default in the ascending33 // 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, for44 // example when the minimum version in the map is higher than the current45 // version. This is really an error, but this situation should be handled46 // 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::OmpAccessGroup>() {79 static const OmpModifierDescriptor desc{80 /*name=*/"access-group",81 /*props=*/82 {83 {61, {OmpProperty::Unique}},84 },85 /*clauses=*/86 {87 {61, {Clause::OMPC_dyn_groupprivate}},88 },89 };90 return desc;91}92 93template <>94const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpAlignment>() {95 static const OmpModifierDescriptor desc{96 /*name=*/"alignment",97 /*props=*/98 {99 {45, {OmpProperty::Unique, OmpProperty::Ultimate, OmpProperty::Post}},100 },101 /*clauses=*/102 {103 {45, {Clause::OMPC_aligned}},104 },105 };106 return desc;107}108 109template <>110const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpAlignModifier>() {111 static const OmpModifierDescriptor desc{112 /*name=*/"align-modifier",113 /*props=*/114 {115 {51, {OmpProperty::Unique}},116 },117 /*clauses=*/118 {119 {51, {Clause::OMPC_allocate}},120 },121 };122 return desc;123}124 125template <>126const OmpModifierDescriptor &127OmpGetDescriptor<parser::OmpAllocatorComplexModifier>() {128 static const OmpModifierDescriptor desc{129 /*name=*/"allocator-complex-modifier",130 /*props=*/131 {132 {51, {OmpProperty::Unique}},133 },134 /*clauses=*/135 {136 {51, {Clause::OMPC_allocate}},137 },138 };139 return desc;140}141 142template <>143const OmpModifierDescriptor &144OmpGetDescriptor<parser::OmpAllocatorSimpleModifier>() {145 static const OmpModifierDescriptor desc{146 /*name=*/"allocator-simple-modifier",147 /*props=*/148 {149 {50, {OmpProperty::Exclusive, OmpProperty::Unique}},150 },151 /*clauses=*/152 {153 {50, {Clause::OMPC_allocate}},154 },155 };156 return desc;157}158 159template <>160const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpAlwaysModifier>() {161 static const OmpModifierDescriptor desc{162 /*name=*/"always-modifier",163 /*props=*/164 {165 {45, {OmpProperty::Unique}},166 },167 /*clauses=*/168 {169 {45, {Clause::OMPC_map}},170 },171 };172 return desc;173}174 175template <>176const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpAttachModifier>() {177 static const OmpModifierDescriptor desc{178 /*name=*/"attach-modifier",179 /*props=*/180 {181 {61, {OmpProperty::Unique}},182 },183 /*clauses=*/184 {185 {61, {Clause::OMPC_map}},186 },187 };188 return desc;189}190 191template <>192const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpAutomapModifier>() {193 static const OmpModifierDescriptor desc{194 /*name=*/"automap-modifier",195 /*props=*/196 {197 {60, {OmpProperty::Unique}},198 },199 /*clauses=*/200 {201 {60, {Clause::OMPC_enter}},202 },203 };204 return desc;205}206 207template <>208const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpChunkModifier>() {209 static const OmpModifierDescriptor desc{210 /*name=*/"chunk-modifier",211 /*props=*/212 {213 {45, {OmpProperty::Unique}},214 },215 /*clauses=*/216 {217 {45, {Clause::OMPC_schedule}},218 },219 };220 return desc;221}222 223template <>224const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpCloseModifier>() {225 static const OmpModifierDescriptor desc{226 /*name=*/"close-modifier",227 /*props=*/228 {229 {50, {OmpProperty::Unique}},230 },231 /*clauses=*/232 {233 {50, {Clause::OMPC_map}},234 },235 };236 return desc;237}238 239template <>240const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpContextSelector>() {241 static const OmpModifierDescriptor desc{242 /*name=*/"context-selector",243 /*props=*/244 {245 {50, {OmpProperty::Required, OmpProperty::Unique}},246 },247 /*clauses=*/248 {249 // The MATCH clause takes a selector as an argument, not modifier.250 {50, {Clause::OMPC_when}},251 },252 };253 return desc;254}255 256template <>257const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpDeleteModifier>() {258 static const OmpModifierDescriptor desc{259 /*name=*/"delete-modifier",260 /*props=*/261 {262 {45, {OmpProperty::Unique, OmpProperty::Ultimate}},263 {60, {OmpProperty::Unique}},264 },265 /*clauses=*/266 {267 {45, {Clause::OMPC_map}},268 },269 };270 return desc;271}272 273template <>274const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpDependenceType>() {275 static const OmpModifierDescriptor desc{276 /*name=*/"dependence-type",277 /*props=*/278 {279 {45, {OmpProperty::Required, OmpProperty::Ultimate}},280 },281 /*clauses=*/282 {283 {45, {Clause::OMPC_depend}},284 {51, {Clause::OMPC_depend, Clause::OMPC_update}},285 {52, {Clause::OMPC_doacross}},286 },287 };288 return desc;289}290 291template <>292const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpDeviceModifier>() {293 static const OmpModifierDescriptor desc{294 /*name=*/"device-modifier",295 /*props=*/296 {297 {45, {OmpProperty::Unique}},298 },299 /*clauses=*/300 {301 {45, {Clause::OMPC_device}},302 },303 };304 return desc;305}306 307template <>308const OmpModifierDescriptor &309OmpGetDescriptor<parser::OmpDirectiveNameModifier>() {310 static const OmpModifierDescriptor desc{311 /*name=*/"directive-name-modifier",312 /*props=*/313 {314 {45, {OmpProperty::Unique}},315 },316 /*clauses=*/317 {318 {45, {Clause::OMPC_if}},319 },320 };321 return desc;322}323 324template <>325const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpExpectation>() {326 static const OmpModifierDescriptor desc{327 /*name=*/"expectation",328 /*props=*/329 {330 {51, {OmpProperty::Unique}},331 },332 /*clauses=*/333 {334 {51, {Clause::OMPC_from, Clause::OMPC_to}},335 },336 };337 return desc;338}339 340template <>341const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpFallbackModifier>() {342 static const OmpModifierDescriptor desc{343 /*name=*/"fallback-modifier",344 /*props=*/345 {346 {61, {OmpProperty::Unique}},347 },348 /*clauses=*/349 {350 {61, {Clause::OMPC_dyn_groupprivate}},351 },352 };353 return desc;354}355 356template <>357const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpInteropPreference>() {358 static const OmpModifierDescriptor desc{359 /*name=*/"interop-preference",360 /*props=*/361 {362 {52, {OmpProperty::Unique}},363 },364 /*clauses=*/365 {366 {52, {Clause::OMPC_init}},367 },368 };369 return desc;370}371 372template <>373const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpInteropType>() {374 static const OmpModifierDescriptor desc{375 /*name=*/"interop-type",376 /*props=*/377 {378 {52, {OmpProperty::Required}},379 },380 /*clauses=*/381 {382 {52, {Clause::OMPC_init}},383 },384 };385 return desc;386}387 388template <>389const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpIterator>() {390 static const OmpModifierDescriptor desc{391 /*name=*/"iterator",392 /*props=*/393 {394 {50, {OmpProperty::Unique}},395 },396 /*clauses=*/397 {398 {50, {Clause::OMPC_affinity, Clause::OMPC_depend}},399 {51,400 {Clause::OMPC_affinity, Clause::OMPC_depend, Clause::OMPC_from,401 Clause::OMPC_map, Clause::OMPC_to}},402 },403 };404 return desc;405}406 407template <>408const OmpModifierDescriptor &409OmpGetDescriptor<parser::OmpLastprivateModifier>() {410 static const OmpModifierDescriptor desc{411 /*name=*/"lastprivate-modifier",412 /*props=*/413 {414 {50, {OmpProperty::Unique}},415 },416 /*clauses=*/417 {418 {50, {Clause::OMPC_lastprivate}},419 },420 };421 return desc;422}423 424template <>425const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpLinearModifier>() {426 static const OmpModifierDescriptor desc{427 /*name=*/"linear-modifier",428 /*props=*/429 {430 {45, {OmpProperty::Unique}},431 },432 /*clauses=*/433 {434 {45, {Clause::OMPC_linear}},435 },436 };437 return desc;438}439 440template <> //441const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpMapper>() {442 static const OmpModifierDescriptor desc{443 /*name=*/"mapper",444 /*props=*/445 {446 {50, {OmpProperty::Unique}},447 },448 /*clauses=*/449 {450 {50, {Clause::OMPC_from, Clause::OMPC_map, Clause::OMPC_to}},451 },452 };453 return desc;454}455 456template <>457const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpMapType>() {458 static const OmpModifierDescriptor desc{459 /*name=*/"map-type",460 /*props=*/461 {462 {45, {OmpProperty::Ultimate}},463 {60, {OmpProperty::Unique}},464 },465 /*clauses=*/466 {467 {45, {Clause::OMPC_map}},468 },469 };470 return desc;471}472 473template <>474const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpMapTypeModifier>() {475 static const OmpModifierDescriptor desc{476 /*name=*/"map-type-modifier",477 /*props=*/478 {479 {45, {}}, // Repeatable480 },481 /*clauses=*/482 {483 {45, {Clause::OMPC_map}},484 {60, {}},485 },486 };487 return desc;488}489 490template <>491const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpOrderModifier>() {492 static const OmpModifierDescriptor desc{493 /*name=*/"order-modifier",494 /*props=*/495 {496 {51, {OmpProperty::Unique}},497 },498 /*clauses=*/499 {500 {51, {Clause::OMPC_order}},501 },502 };503 return desc;504}505 506template <>507const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpOrderingModifier>() {508 static const OmpModifierDescriptor desc{509 /*name=*/"ordering-modifier",510 /*props=*/511 {512 {45, {OmpProperty::Unique}},513 },514 /*clauses=*/515 {516 {45, {Clause::OMPC_schedule}},517 },518 };519 return desc;520}521 522template <>523const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpPrescriptiveness>() {524 static const OmpModifierDescriptor desc{525 /*name=*/"prescriptiveness",526 /*props=*/527 {528 {51, {OmpProperty::Unique}},529 },530 /*clauses=*/531 {532 {51, {Clause::OMPC_grainsize, Clause::OMPC_num_tasks}},533 },534 };535 return desc;536}537 538template <>539const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpPresentModifier>() {540 static const OmpModifierDescriptor desc{541 /*name=*/"present-modifier",542 /*props=*/543 {544 {51, {OmpProperty::Unique}},545 },546 /*clauses=*/547 {548 {51, {Clause::OMPC_map}},549 },550 };551 return desc;552}553 554template <>555const OmpModifierDescriptor &556OmpGetDescriptor<parser::OmpReductionIdentifier>() {557 static const OmpModifierDescriptor desc{558 /*name=*/"reduction-identifier",559 /*props=*/560 {561 {45, {OmpProperty::Required, OmpProperty::Ultimate}},562 },563 /*clauses=*/564 {565 {45, {Clause::OMPC_reduction}},566 {50,567 {Clause::OMPC_in_reduction, Clause::OMPC_reduction,568 Clause::OMPC_task_reduction}},569 },570 };571 return desc;572}573 574template <>575const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpReductionModifier>() {576 static const OmpModifierDescriptor desc{577 /*name=*/"reduction-modifier",578 /*props=*/579 {580 {45, {OmpProperty::Unique}},581 },582 /*clauses=*/583 {584 {45, {Clause::OMPC_reduction}},585 },586 };587 return desc;588}589 590template <>591const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpRefModifier>() {592 static const OmpModifierDescriptor desc{593 /*name=*/"ref-modifier",594 /*props=*/595 {596 {60, {OmpProperty::Unique}},597 },598 /*clauses=*/599 {600 {60, {Clause::OMPC_map}},601 },602 };603 return desc;604}605 606template <>607const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpSelfModifier>() {608 static const OmpModifierDescriptor desc{609 /*name=*/"self-modifier",610 /*props=*/611 {612 {60, {OmpProperty::Unique}},613 },614 /*clauses=*/615 {616 {60, {Clause::OMPC_map}},617 },618 };619 return desc;620}621 622template <>623const OmpModifierDescriptor &624OmpGetDescriptor<parser::OmpStepComplexModifier>() {625 static const OmpModifierDescriptor desc{626 /*name=*/"step-complex-modifier",627 /*props=*/628 {629 {52, {OmpProperty::Unique}},630 },631 /*clauses=*/632 {633 {52, {Clause::OMPC_linear}},634 },635 };636 return desc;637}638 639template <>640const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpStepSimpleModifier>() {641 static const OmpModifierDescriptor desc{642 /*name=*/"step-simple-modifier",643 /*props=*/644 {645 {45, {OmpProperty::Unique, OmpProperty::Exclusive}},646 },647 /*clauses=*/648 {649 {45, {Clause::OMPC_linear}},650 },651 };652 return desc;653}654 655template <>656const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpTaskDependenceType>() {657 static const OmpModifierDescriptor desc{658 /*name=*/"task-dependence-type",659 /*props=*/660 {661 {45, {OmpProperty::Required, OmpProperty::Ultimate}},662 },663 /*clauses=*/664 {665 {45, {Clause::OMPC_depend}},666 {51, {Clause::OMPC_depend, Clause::OMPC_update}},667 },668 };669 return desc;670}671 672template <>673const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpVariableCategory>() {674 static const OmpModifierDescriptor desc{675 /*name=*/"variable-category",676 /*props=*/677 {678 {45, {OmpProperty::Required, OmpProperty::Unique}},679 {50, {OmpProperty::Unique}},680 },681 /*clauses=*/682 {683 {45, {Clause::OMPC_defaultmap}},684 },685 };686 return desc;687}688 689template <>690const OmpModifierDescriptor &OmpGetDescriptor<parser::OmpxHoldModifier>() {691 static const OmpModifierDescriptor desc{692 /*name=*/"ompx-hold-modifier",693 /*props=*/694 {695 {45, {OmpProperty::Unique}},696 },697 /*clauses=*/698 {699 {45, {Clause::OMPC_map}},700 },701 };702 return desc;703}704} // namespace Fortran::semantics705