File indexing completed on 2026-05-10 08:43:55
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018 #ifndef LLVM_FRONTEND_OPENMP_CONSTRUCTDECOMPOSITIONT_H
0019 #define LLVM_FRONTEND_OPENMP_CONSTRUCTDECOMPOSITIONT_H
0020
0021 #include "llvm/ADT/ArrayRef.h"
0022 #include "llvm/ADT/STLExtras.h"
0023 #include "llvm/ADT/SmallVector.h"
0024 #include "llvm/ADT/iterator_range.h"
0025 #include "llvm/Frontend/OpenMP/ClauseT.h"
0026 #include "llvm/Frontend/OpenMP/OMP.h"
0027
0028 #include <iterator>
0029 #include <list>
0030 #include <optional>
0031 #include <tuple>
0032 #include <type_traits>
0033 #include <unordered_map>
0034 #include <unordered_set>
0035 #include <utility>
0036 #include <variant>
0037
0038 static inline llvm::ArrayRef<llvm::omp::Directive> getWorksharing() {
0039 static llvm::omp::Directive worksharing[] = {
0040 llvm::omp::Directive::OMPD_do, llvm::omp::Directive::OMPD_for,
0041 llvm::omp::Directive::OMPD_scope, llvm::omp::Directive::OMPD_sections,
0042 llvm::omp::Directive::OMPD_single, llvm::omp::Directive::OMPD_workshare,
0043 };
0044 return worksharing;
0045 }
0046
0047 static inline llvm::ArrayRef<llvm::omp::Directive> getWorksharingLoop() {
0048 static llvm::omp::Directive worksharingLoop[] = {
0049 llvm::omp::Directive::OMPD_do,
0050 llvm::omp::Directive::OMPD_for,
0051 };
0052 return worksharingLoop;
0053 }
0054
0055 namespace detail {
0056 template <typename Container, typename Predicate>
0057 typename std::remove_reference_t<Container>::iterator
0058 find_unique(Container &&container, Predicate &&pred) {
0059 auto first = std::find_if(container.begin(), container.end(), pred);
0060 if (first == container.end())
0061 return first;
0062 auto second = std::find_if(std::next(first), container.end(), pred);
0063 if (second == container.end())
0064 return first;
0065 return container.end();
0066 }
0067 }
0068
0069 namespace tomp {
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082 template <typename ClauseType, typename HelperType>
0083 struct ConstructDecompositionT {
0084 using ClauseTy = ClauseType;
0085
0086 using TypeTy = typename ClauseTy::TypeTy;
0087 using IdTy = typename ClauseTy::IdTy;
0088 using ExprTy = typename ClauseTy::ExprTy;
0089 using HelperTy = HelperType;
0090 using ObjectTy = tomp::ObjectT<IdTy, ExprTy>;
0091
0092 using ClauseSet = std::unordered_set<const ClauseTy *>;
0093
0094 ConstructDecompositionT(uint32_t ver, HelperType &helper,
0095 llvm::omp::Directive dir,
0096 llvm::ArrayRef<ClauseTy> clauses)
0097 : version(ver), construct(dir), helper(helper) {
0098 for (const ClauseTy &clause : clauses)
0099 nodes.push_back(&clause);
0100
0101 bool success = split();
0102 if (!success)
0103 return;
0104
0105
0106
0107
0108
0109 for (auto &leaf : leafs) {
0110 output.push_back({leaf.id, {}});
0111 auto &out = output.back();
0112 for (const ClauseTy *c : leaf.clauses)
0113 out.clauses.push_back(*c);
0114 }
0115 }
0116
0117 tomp::ListT<DirectiveWithClauses<ClauseType>> output;
0118
0119 private:
0120 bool split();
0121
0122 struct LeafReprInternal {
0123 llvm::omp::Directive id = llvm::omp::Directive::OMPD_unknown;
0124 tomp::type::ListT<const ClauseTy *> clauses;
0125 };
0126
0127 LeafReprInternal *findDirective(llvm::omp::Directive dirId) {
0128 auto found = llvm::find_if(
0129 leafs, [&](const LeafReprInternal &leaf) { return leaf.id == dirId; });
0130 return found != leafs.end() ? &*found : nullptr;
0131 }
0132
0133 ClauseSet *findClausesWith(const ObjectTy &object) {
0134 if (auto found = syms.find(object.id()); found != syms.end())
0135 return &found->second;
0136 return nullptr;
0137 }
0138
0139 template <typename S>
0140 ClauseTy *makeClause(llvm::omp::Clause clauseId, S &&specific) {
0141 implicit.push_back(typename ClauseTy::BaseT{clauseId, std::move(specific)});
0142 return &implicit.back();
0143 }
0144
0145 void addClauseSymsToMap(const ObjectTy &object, const ClauseTy *);
0146 void addClauseSymsToMap(const tomp::ObjectListT<IdTy, ExprTy> &objects,
0147 const ClauseTy *);
0148 void addClauseSymsToMap(const TypeTy &item, const ClauseTy *);
0149 void addClauseSymsToMap(const ExprTy &item, const ClauseTy *);
0150 void addClauseSymsToMap(const tomp::clause::MapT<TypeTy, IdTy, ExprTy> &item,
0151 const ClauseTy *);
0152
0153 template <typename U>
0154 void addClauseSymsToMap(const std::optional<U> &item, const ClauseTy *);
0155 template <typename U>
0156 void addClauseSymsToMap(const tomp::ListT<U> &item, const ClauseTy *);
0157 template <typename... U, size_t... Is>
0158 void addClauseSymsToMap(const std::tuple<U...> &item, const ClauseTy *,
0159 std::index_sequence<Is...> = {});
0160 template <typename U>
0161 std::enable_if_t<std::is_enum_v<llvm::remove_cvref_t<U>>, void>
0162 addClauseSymsToMap(U &&item, const ClauseTy *);
0163
0164 template <typename U>
0165 std::enable_if_t<llvm::remove_cvref_t<U>::EmptyTrait::value, void>
0166 addClauseSymsToMap(U &&item, const ClauseTy *);
0167
0168 template <typename U>
0169 std::enable_if_t<llvm::remove_cvref_t<U>::IncompleteTrait::value, void>
0170 addClauseSymsToMap(U &&item, const ClauseTy *);
0171
0172 template <typename U>
0173 std::enable_if_t<llvm::remove_cvref_t<U>::WrapperTrait::value, void>
0174 addClauseSymsToMap(U &&item, const ClauseTy *);
0175
0176 template <typename U>
0177 std::enable_if_t<llvm::remove_cvref_t<U>::TupleTrait::value, void>
0178 addClauseSymsToMap(U &&item, const ClauseTy *);
0179
0180 template <typename U>
0181 std::enable_if_t<llvm::remove_cvref_t<U>::UnionTrait::value, void>
0182 addClauseSymsToMap(U &&item, const ClauseTy *);
0183
0184
0185
0186
0187 bool applyToUnique(const ClauseTy *node);
0188
0189
0190
0191 template <typename Iterator>
0192 bool applyToFirst(const ClauseTy *node, llvm::iterator_range<Iterator> range);
0193
0194
0195
0196 bool applyToInnermost(const ClauseTy *node);
0197
0198
0199
0200 bool applyToOutermost(const ClauseTy *node);
0201
0202 template <typename Predicate>
0203 bool applyIf(const ClauseTy *node, Predicate shouldApply);
0204
0205 bool applyToAll(const ClauseTy *node);
0206
0207 template <typename Clause>
0208 bool applyClause(Clause &&clause, const ClauseTy *node);
0209
0210 bool applyClause(const tomp::clause::CollapseT<TypeTy, IdTy, ExprTy> &clause,
0211 const ClauseTy *);
0212 bool applyClause(const tomp::clause::PrivateT<TypeTy, IdTy, ExprTy> &clause,
0213 const ClauseTy *);
0214 bool
0215 applyClause(const tomp::clause::FirstprivateT<TypeTy, IdTy, ExprTy> &clause,
0216 const ClauseTy *);
0217 bool
0218 applyClause(const tomp::clause::LastprivateT<TypeTy, IdTy, ExprTy> &clause,
0219 const ClauseTy *);
0220 bool applyClause(const tomp::clause::SharedT<TypeTy, IdTy, ExprTy> &clause,
0221 const ClauseTy *);
0222 bool applyClause(const tomp::clause::DefaultT<TypeTy, IdTy, ExprTy> &clause,
0223 const ClauseTy *);
0224 bool
0225 applyClause(const tomp::clause::ThreadLimitT<TypeTy, IdTy, ExprTy> &clause,
0226 const ClauseTy *);
0227 bool applyClause(const tomp::clause::OrderT<TypeTy, IdTy, ExprTy> &clause,
0228 const ClauseTy *);
0229 bool applyClause(const tomp::clause::AllocateT<TypeTy, IdTy, ExprTy> &clause,
0230 const ClauseTy *);
0231 bool applyClause(const tomp::clause::ReductionT<TypeTy, IdTy, ExprTy> &clause,
0232 const ClauseTy *);
0233 bool applyClause(const tomp::clause::IfT<TypeTy, IdTy, ExprTy> &clause,
0234 const ClauseTy *);
0235 bool applyClause(const tomp::clause::LinearT<TypeTy, IdTy, ExprTy> &clause,
0236 const ClauseTy *);
0237 bool applyClause(const tomp::clause::NowaitT<TypeTy, IdTy, ExprTy> &clause,
0238 const ClauseTy *);
0239 bool
0240 applyClause(const tomp::clause::OmpxAttributeT<TypeTy, IdTy, ExprTy> &clause,
0241 const ClauseTy *);
0242 bool applyClause(const tomp::clause::OmpxBareT<TypeTy, IdTy, ExprTy> &clause,
0243 const ClauseTy *);
0244
0245 uint32_t version;
0246 llvm::omp::Directive construct;
0247 HelperType &helper;
0248 ListT<LeafReprInternal> leafs;
0249 tomp::ListT<const ClauseTy *> nodes;
0250 std::list<ClauseTy> implicit;
0251
0252 std::unordered_map<IdTy, ClauseSet> syms;
0253 std::unordered_set<IdTy> mapBases;
0254 };
0255
0256
0257 template <typename ClauseType, typename HelperType>
0258 ConstructDecompositionT(uint32_t, HelperType &, llvm::omp::Directive,
0259 llvm::ArrayRef<ClauseType>)
0260 -> ConstructDecompositionT<ClauseType, HelperType>;
0261
0262 template <typename C, typename H>
0263 void ConstructDecompositionT<C, H>::addClauseSymsToMap(const ObjectTy &object,
0264 const ClauseTy *node) {
0265 syms[object.id()].insert(node);
0266 }
0267
0268 template <typename C, typename H>
0269 void ConstructDecompositionT<C, H>::addClauseSymsToMap(
0270 const tomp::ObjectListT<IdTy, ExprTy> &objects, const ClauseTy *node) {
0271 for (auto &object : objects)
0272 syms[object.id()].insert(node);
0273 }
0274
0275 template <typename C, typename H>
0276 void ConstructDecompositionT<C, H>::addClauseSymsToMap(const TypeTy &item,
0277 const ClauseTy *node) {
0278
0279 }
0280
0281 template <typename C, typename H>
0282 void ConstructDecompositionT<C, H>::addClauseSymsToMap(const ExprTy &item,
0283 const ClauseTy *node) {
0284
0285 }
0286
0287 template <typename C, typename H>
0288 void ConstructDecompositionT<C, H>::addClauseSymsToMap(
0289 const tomp::clause::MapT<TypeTy, IdTy, ExprTy> &item,
0290 const ClauseTy *node) {
0291 auto &objects = std::get<tomp::ObjectListT<IdTy, ExprTy>>(item.t);
0292 addClauseSymsToMap(objects, node);
0293 for (auto &object : objects) {
0294 if (auto base = helper.getBaseObject(object))
0295 mapBases.insert(base->id());
0296 }
0297 }
0298
0299 template <typename C, typename H>
0300 template <typename U>
0301 void ConstructDecompositionT<C, H>::addClauseSymsToMap(
0302 const std::optional<U> &item, const ClauseTy *node) {
0303 if (item)
0304 addClauseSymsToMap(*item, node);
0305 }
0306
0307 template <typename C, typename H>
0308 template <typename U>
0309 void ConstructDecompositionT<C, H>::addClauseSymsToMap(
0310 const tomp::ListT<U> &item, const ClauseTy *node) {
0311 for (auto &s : item)
0312 addClauseSymsToMap(s, node);
0313 }
0314
0315 template <typename C, typename H>
0316 template <typename... U, size_t... Is>
0317 void ConstructDecompositionT<C, H>::addClauseSymsToMap(
0318 const std::tuple<U...> &item, const ClauseTy *node,
0319 std::index_sequence<Is...>) {
0320 (void)node;
0321 (addClauseSymsToMap(std::get<Is>(item), node), ...);
0322 }
0323
0324 template <typename C, typename H>
0325 template <typename U>
0326 std::enable_if_t<std::is_enum_v<llvm::remove_cvref_t<U>>, void>
0327 ConstructDecompositionT<C, H>::addClauseSymsToMap(U &&item,
0328 const ClauseTy *node) {
0329
0330 }
0331
0332 template <typename C, typename H>
0333 template <typename U>
0334 std::enable_if_t<llvm::remove_cvref_t<U>::EmptyTrait::value, void>
0335 ConstructDecompositionT<C, H>::addClauseSymsToMap(U &&item,
0336 const ClauseTy *node) {
0337
0338 }
0339
0340 template <typename C, typename H>
0341 template <typename U>
0342 std::enable_if_t<llvm::remove_cvref_t<U>::IncompleteTrait::value, void>
0343 ConstructDecompositionT<C, H>::addClauseSymsToMap(U &&item,
0344 const ClauseTy *node) {
0345
0346 }
0347
0348 template <typename C, typename H>
0349 template <typename U>
0350 std::enable_if_t<llvm::remove_cvref_t<U>::WrapperTrait::value, void>
0351 ConstructDecompositionT<C, H>::addClauseSymsToMap(U &&item,
0352 const ClauseTy *node) {
0353 addClauseSymsToMap(item.v, node);
0354 }
0355
0356 template <typename C, typename H>
0357 template <typename U>
0358 std::enable_if_t<llvm::remove_cvref_t<U>::TupleTrait::value, void>
0359 ConstructDecompositionT<C, H>::addClauseSymsToMap(U &&item,
0360 const ClauseTy *node) {
0361 constexpr size_t tuple_size =
0362 std::tuple_size_v<llvm::remove_cvref_t<decltype(item.t)>>;
0363 addClauseSymsToMap(item.t, node, std::make_index_sequence<tuple_size>{});
0364 }
0365
0366 template <typename C, typename H>
0367 template <typename U>
0368 std::enable_if_t<llvm::remove_cvref_t<U>::UnionTrait::value, void>
0369 ConstructDecompositionT<C, H>::addClauseSymsToMap(U &&item,
0370 const ClauseTy *node) {
0371 std::visit([&](auto &&s) { addClauseSymsToMap(s, node); }, item.u);
0372 }
0373
0374
0375
0376
0377 template <typename C, typename H>
0378 bool ConstructDecompositionT<C, H>::applyToUnique(const ClauseTy *node) {
0379 auto unique = detail::find_unique(leafs, [=](const auto &leaf) {
0380 return llvm::omp::isAllowedClauseForDirective(leaf.id, node->id, version);
0381 });
0382
0383 if (unique != leafs.end()) {
0384 unique->clauses.push_back(node);
0385 return true;
0386 }
0387 return false;
0388 }
0389
0390
0391
0392 template <typename C, typename H>
0393 template <typename Iterator>
0394 bool ConstructDecompositionT<C, H>::applyToFirst(
0395 const ClauseTy *node, llvm::iterator_range<Iterator> range) {
0396 if (range.empty())
0397 return false;
0398
0399 for (auto &leaf : range) {
0400 if (!llvm::omp::isAllowedClauseForDirective(leaf.id, node->id, version))
0401 continue;
0402 leaf.clauses.push_back(node);
0403 return true;
0404 }
0405 return false;
0406 }
0407
0408
0409
0410 template <typename C, typename H>
0411 bool ConstructDecompositionT<C, H>::applyToInnermost(const ClauseTy *node) {
0412 return applyToFirst(node, llvm::reverse(leafs));
0413 }
0414
0415
0416
0417 template <typename C, typename H>
0418 bool ConstructDecompositionT<C, H>::applyToOutermost(const ClauseTy *node) {
0419 return applyToFirst(node, llvm::iterator_range(leafs));
0420 }
0421
0422 template <typename C, typename H>
0423 template <typename Predicate>
0424 bool ConstructDecompositionT<C, H>::applyIf(const ClauseTy *node,
0425 Predicate shouldApply) {
0426 bool applied = false;
0427 for (auto &leaf : leafs) {
0428 if (!llvm::omp::isAllowedClauseForDirective(leaf.id, node->id, version))
0429 continue;
0430 if (!shouldApply(leaf))
0431 continue;
0432 leaf.clauses.push_back(node);
0433 applied = true;
0434 }
0435
0436 return applied;
0437 }
0438
0439 template <typename C, typename H>
0440 bool ConstructDecompositionT<C, H>::applyToAll(const ClauseTy *node) {
0441 return applyIf(node, [](auto) { return true; });
0442 }
0443
0444 template <typename C, typename H>
0445 template <typename Specific>
0446 bool ConstructDecompositionT<C, H>::applyClause(Specific &&specific,
0447 const ClauseTy *node) {
0448
0449
0450
0451
0452
0453
0454
0455 if (applyToUnique(node))
0456 return true;
0457
0458 return false;
0459 }
0460
0461
0462
0463
0464
0465
0466
0467
0468 template <typename C, typename H>
0469 bool ConstructDecompositionT<C, H>::applyClause(
0470 const tomp::clause::CollapseT<TypeTy, IdTy, ExprTy> &clause,
0471 const ClauseTy *node) {
0472
0473
0474 if (!leafs.empty()) {
0475 auto &last = leafs.back();
0476
0477 if (llvm::omp::isAllowedClauseForDirective(last.id, node->id, version)) {
0478 last.clauses.push_back(node);
0479 return true;
0480 }
0481 }
0482
0483 return false;
0484 }
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494 template <typename C, typename H>
0495 bool ConstructDecompositionT<C, H>::applyClause(
0496 const tomp::clause::PrivateT<TypeTy, IdTy, ExprTy> &clause,
0497 const ClauseTy *node) {
0498 return applyToInnermost(node);
0499 }
0500
0501
0502
0503
0504
0505
0506
0507
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531 template <typename C, typename H>
0532 bool ConstructDecompositionT<C, H>::applyClause(
0533 const tomp::clause::FirstprivateT<TypeTy, IdTy, ExprTy> &clause,
0534 const ClauseTy *node) {
0535 bool applied = false;
0536
0537
0538 auto dirDistribute = findDirective(llvm::omp::OMPD_distribute);
0539 auto dirTeams = findDirective(llvm::omp::OMPD_teams);
0540 if (dirDistribute != nullptr) {
0541 dirDistribute->clauses.push_back(node);
0542 applied = true;
0543
0544 if (dirTeams != nullptr) {
0545 auto *shared = makeClause(
0546 llvm::omp::Clause::OMPC_shared,
0547 tomp::clause::SharedT<TypeTy, IdTy, ExprTy>{clause.v});
0548 dirTeams->clauses.push_back(shared);
0549 }
0550 } else if (dirTeams != nullptr) {
0551 dirTeams->clauses.push_back(node);
0552 applied = true;
0553 }
0554
0555
0556 auto findWorksharing = [&]() {
0557 auto worksharing = getWorksharing();
0558 for (auto &leaf : leafs) {
0559 auto found = llvm::find(worksharing, leaf.id);
0560 if (found != std::end(worksharing))
0561 return &leaf;
0562 }
0563 return static_cast<typename decltype(leafs)::value_type *>(nullptr);
0564 };
0565
0566 auto dirWorksharing = findWorksharing();
0567 if (dirWorksharing != nullptr) {
0568 dirWorksharing->clauses.push_back(node);
0569 applied = true;
0570 }
0571
0572
0573 auto dirTaskloop = findDirective(llvm::omp::OMPD_taskloop);
0574 if (dirTaskloop != nullptr) {
0575 dirTaskloop->clauses.push_back(node);
0576 applied = true;
0577 }
0578
0579
0580 auto dirParallel = findDirective(llvm::omp::OMPD_parallel);
0581 if (dirParallel != nullptr) {
0582 if (dirTaskloop == nullptr && dirWorksharing == nullptr) {
0583 dirParallel->clauses.push_back(node);
0584 applied = true;
0585 } else {
0586
0587 auto *shared = makeClause(
0588 llvm::omp::Clause::OMPC_shared,
0589 tomp::clause::SharedT<TypeTy, IdTy, ExprTy>{clause.v});
0590 dirParallel->clauses.push_back(shared);
0591 }
0592 }
0593
0594
0595 auto inLastprivate = [&](const ObjectTy &object) {
0596 if (ClauseSet *set = findClausesWith(object)) {
0597 return llvm::find_if(*set, [](const ClauseTy *c) {
0598 return c->id == llvm::omp::Clause::OMPC_lastprivate;
0599 }) != set->end();
0600 }
0601 return false;
0602 };
0603
0604 auto dirTarget = findDirective(llvm::omp::OMPD_target);
0605 if (dirTarget != nullptr) {
0606 tomp::ObjectListT<IdTy, ExprTy> objects;
0607 llvm::copy_if(
0608 clause.v, std::back_inserter(objects), [&](const ObjectTy &object) {
0609 return !inLastprivate(object) && !mapBases.count(object.id());
0610 });
0611 if (!objects.empty()) {
0612 auto *firstp = makeClause(
0613 llvm::omp::Clause::OMPC_firstprivate,
0614 tomp::clause::FirstprivateT<TypeTy, IdTy, ExprTy>{objects});
0615 dirTarget->clauses.push_back(firstp);
0616 applied = true;
0617 }
0618 }
0619
0620
0621 if (auto dirTask = findDirective(llvm::omp::OMPD_task)) {
0622 dirTask->clauses.push_back(node);
0623 applied = true;
0624 }
0625
0626 return applied;
0627 }
0628
0629
0630
0631
0632
0633
0634
0635
0636
0637
0638
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648 template <typename C, typename H>
0649 bool ConstructDecompositionT<C, H>::applyClause(
0650 const tomp::clause::LastprivateT<TypeTy, IdTy, ExprTy> &clause,
0651 const ClauseTy *node) {
0652 bool applied = false;
0653
0654
0655 applied = applyToAll(node);
0656 if (!applied)
0657 return false;
0658
0659 auto inFirstprivate = [&](const ObjectTy &object) {
0660 if (ClauseSet *set = findClausesWith(object)) {
0661 return llvm::find_if(*set, [](const ClauseTy *c) {
0662 return c->id == llvm::omp::Clause::OMPC_firstprivate;
0663 }) != set->end();
0664 }
0665 return false;
0666 };
0667
0668 auto &objects = std::get<tomp::ObjectListT<IdTy, ExprTy>>(clause.t);
0669
0670
0671 tomp::ObjectListT<IdTy, ExprTy> sharedObjects;
0672 llvm::copy_if(
0673 objects, std::back_inserter(sharedObjects),
0674 [&](const ObjectTy &object) { return !inFirstprivate(object); });
0675
0676 if (!sharedObjects.empty()) {
0677
0678 if (auto dirParallel = findDirective(llvm::omp::OMPD_parallel)) {
0679 auto *shared = makeClause(
0680 llvm::omp::Clause::OMPC_shared,
0681 tomp::clause::SharedT<TypeTy, IdTy, ExprTy>{sharedObjects});
0682 dirParallel->clauses.push_back(shared);
0683 applied = true;
0684 }
0685
0686
0687 if (auto dirTeams = findDirective(llvm::omp::OMPD_teams)) {
0688 auto *shared = makeClause(
0689 llvm::omp::Clause::OMPC_shared,
0690 tomp::clause::SharedT<TypeTy, IdTy, ExprTy>{sharedObjects});
0691 dirTeams->clauses.push_back(shared);
0692 applied = true;
0693 }
0694 }
0695
0696
0697 if (auto dirTarget = findDirective(llvm::omp::OMPD_target)) {
0698 tomp::ObjectListT<IdTy, ExprTy> tofrom;
0699 llvm::copy_if(
0700 objects, std::back_inserter(tofrom),
0701 [&](const ObjectTy &object) { return !mapBases.count(object.id()); });
0702
0703 if (!tofrom.empty()) {
0704 using MapType =
0705 typename tomp::clause::MapT<TypeTy, IdTy, ExprTy>::MapType;
0706 auto *map =
0707 makeClause(llvm::omp::Clause::OMPC_map,
0708 tomp::clause::MapT<TypeTy, IdTy, ExprTy>{
0709 {MapType::Tofrom,
0710 std::nullopt,
0711 std::nullopt, std::nullopt,
0712 std::move(tofrom)}});
0713 dirTarget->clauses.push_back(map);
0714 applied = true;
0715 }
0716 }
0717
0718 return applied;
0719 }
0720
0721
0722
0723
0724
0725
0726
0727
0728 template <typename C, typename H>
0729 bool ConstructDecompositionT<C, H>::applyClause(
0730 const tomp::clause::SharedT<TypeTy, IdTy, ExprTy> &clause,
0731 const ClauseTy *node) {
0732
0733 return applyToAll(node);
0734 }
0735
0736
0737
0738
0739
0740
0741
0742
0743 template <typename C, typename H>
0744 bool ConstructDecompositionT<C, H>::applyClause(
0745 const tomp::clause::DefaultT<TypeTy, IdTy, ExprTy> &clause,
0746 const ClauseTy *node) {
0747
0748 return applyToAll(node);
0749 }
0750
0751
0752
0753
0754
0755
0756
0757
0758 template <typename C, typename H>
0759 bool ConstructDecompositionT<C, H>::applyClause(
0760 const tomp::clause::ThreadLimitT<TypeTy, IdTy, ExprTy> &clause,
0761 const ClauseTy *node) {
0762
0763 return applyToAll(node);
0764 }
0765
0766
0767
0768
0769
0770
0771
0772
0773 template <typename C, typename H>
0774 bool ConstructDecompositionT<C, H>::applyClause(
0775 const tomp::clause::OrderT<TypeTy, IdTy, ExprTy> &clause,
0776 const ClauseTy *node) {
0777
0778 return applyToAll(node);
0779 }
0780
0781
0782
0783
0784
0785
0786
0787
0788
0789
0790 template <typename C, typename H>
0791 bool ConstructDecompositionT<C, H>::applyClause(
0792 const tomp::clause::AllocateT<TypeTy, IdTy, ExprTy> &clause,
0793 const ClauseTy *node) {
0794
0795
0796
0797
0798 auto canMakePrivateCopy = [](llvm::omp::Clause id) {
0799 switch (id) {
0800
0801 case llvm::omp::Clause::OMPC_firstprivate:
0802 case llvm::omp::Clause::OMPC_in_reduction:
0803 case llvm::omp::Clause::OMPC_lastprivate:
0804 case llvm::omp::Clause::OMPC_linear:
0805 case llvm::omp::Clause::OMPC_private:
0806 case llvm::omp::Clause::OMPC_reduction:
0807 case llvm::omp::Clause::OMPC_task_reduction:
0808 return true;
0809 default:
0810 return false;
0811 }
0812 };
0813
0814 bool applied = applyIf(node, [&](const auto &leaf) {
0815 return llvm::any_of(leaf.clauses, [&](const ClauseTy *n) {
0816 return canMakePrivateCopy(n->id);
0817 });
0818 });
0819
0820 return applied;
0821 }
0822
0823
0824
0825
0826
0827
0828
0829
0830
0831
0832
0833
0834
0835
0836
0837
0838
0839
0840
0841
0842
0843
0844
0845
0846
0847
0848
0849 template <typename C, typename H>
0850 bool ConstructDecompositionT<C, H>::applyClause(
0851 const tomp::clause::ReductionT<TypeTy, IdTy, ExprTy> &clause,
0852 const ClauseTy *node) {
0853 using ReductionTy = tomp::clause::ReductionT<TypeTy, IdTy, ExprTy>;
0854
0855
0856 bool applyToParallel = true, applyToTeams = true;
0857
0858 auto dirParallel = findDirective(llvm::omp::Directive::OMPD_parallel);
0859 if (dirParallel) {
0860 auto exclusions = llvm::concat<const llvm::omp::Directive>(
0861 getWorksharingLoop(), tomp::ListT<llvm::omp::Directive>{
0862 llvm::omp::Directive::OMPD_loop,
0863 llvm::omp::Directive::OMPD_sections,
0864 llvm::omp::Directive::OMPD_taskloop,
0865 });
0866 auto present = [&](llvm::omp::Directive id) {
0867 return findDirective(id) != nullptr;
0868 };
0869
0870 if (llvm::any_of(exclusions, present))
0871 applyToParallel = false;
0872 }
0873
0874 auto dirTeams = findDirective(llvm::omp::Directive::OMPD_teams);
0875 if (dirTeams) {
0876
0877 if (findDirective(llvm::omp::Directive::OMPD_loop))
0878 applyToTeams = false;
0879 }
0880
0881 using ReductionModifier = typename ReductionTy::ReductionModifier;
0882 using ReductionIdentifiers = typename ReductionTy::ReductionIdentifiers;
0883
0884 auto &objects = std::get<tomp::ObjectListT<IdTy, ExprTy>>(clause.t);
0885 auto &modifier = std::get<std::optional<ReductionModifier>>(clause.t);
0886
0887
0888
0889
0890 bool applied = false;
0891
0892
0893 auto isValidModifier = [](llvm::omp::Directive dir, ReductionModifier mod,
0894 bool alreadyApplied) {
0895 switch (mod) {
0896 case ReductionModifier::Inscan:
0897
0898
0899 return dir == llvm::omp::Directive::OMPD_simd ||
0900 llvm::is_contained(getWorksharingLoop(), dir);
0901 case ReductionModifier::Task:
0902 if (alreadyApplied)
0903 return false;
0904
0905
0906 return dir == llvm::omp::Directive::OMPD_parallel ||
0907 llvm::is_contained(getWorksharing(), dir);
0908 case ReductionModifier::Default:
0909 return true;
0910 }
0911 llvm_unreachable("Unexpected modifier");
0912 };
0913
0914 auto *unmodified = makeClause(
0915 llvm::omp::Clause::OMPC_reduction,
0916 ReductionTy{
0917 {std::nullopt,
0918 std::get<ReductionIdentifiers>(clause.t),
0919 objects}});
0920
0921 ReductionModifier effective = modifier.value_or(ReductionModifier::Default);
0922 bool effectiveApplied = false;
0923
0924
0925 for (auto &leaf : llvm::reverse(leafs)) {
0926 if (!llvm::omp::isAllowedClauseForDirective(leaf.id, node->id, version))
0927 continue;
0928 if (!applyToParallel && &leaf == dirParallel)
0929 continue;
0930 if (!applyToTeams && &leaf == dirTeams)
0931 continue;
0932
0933 if (isValidModifier(leaf.id, effective, effectiveApplied)) {
0934
0935 leaf.clauses.push_back(node);
0936 effectiveApplied = true;
0937 } else {
0938
0939 leaf.clauses.push_back(unmodified);
0940 }
0941
0942 applied = effectiveApplied;
0943 }
0944
0945 if (!applied)
0946 return false;
0947
0948 tomp::ObjectListT<IdTy, ExprTy> sharedObjects;
0949 llvm::transform(objects, std::back_inserter(sharedObjects),
0950 [&](const ObjectTy &object) {
0951 auto maybeBase = helper.getBaseObject(object);
0952 return maybeBase ? *maybeBase : object;
0953 });
0954
0955
0956 if (!sharedObjects.empty()) {
0957 if (dirParallel && !applyToParallel) {
0958 auto *shared = makeClause(
0959 llvm::omp::Clause::OMPC_shared,
0960 tomp::clause::SharedT<TypeTy, IdTy, ExprTy>{sharedObjects});
0961 dirParallel->clauses.push_back(shared);
0962 }
0963 if (dirTeams && !applyToTeams) {
0964 auto *shared = makeClause(
0965 llvm::omp::Clause::OMPC_shared,
0966 tomp::clause::SharedT<TypeTy, IdTy, ExprTy>{sharedObjects});
0967 dirTeams->clauses.push_back(shared);
0968 }
0969 }
0970
0971
0972 auto dirTarget = findDirective(llvm::omp::Directive::OMPD_target);
0973 if (dirTarget && leafs.size() > 1) {
0974 tomp::ObjectListT<IdTy, ExprTy> tofrom;
0975 llvm::copy_if(objects, std::back_inserter(tofrom),
0976 [&](const ObjectTy &object) {
0977 if (auto maybeBase = helper.getBaseObject(object))
0978 return !mapBases.count(maybeBase->id());
0979 return !mapBases.count(object.id());
0980 });
0981 if (!tofrom.empty()) {
0982 using MapType =
0983 typename tomp::clause::MapT<TypeTy, IdTy, ExprTy>::MapType;
0984 auto *map = makeClause(
0985 llvm::omp::Clause::OMPC_map,
0986 tomp::clause::MapT<TypeTy, IdTy, ExprTy>{
0987 {MapType::Tofrom, std::nullopt,
0988 std::nullopt, std::nullopt,
0989 std::move(tofrom)}});
0990
0991 dirTarget->clauses.push_back(map);
0992 applied = true;
0993 }
0994 }
0995
0996 return applied;
0997 }
0998
0999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010 template <typename C, typename H>
1011 bool ConstructDecompositionT<C, H>::applyClause(
1012 const tomp::clause::IfT<TypeTy, IdTy, ExprTy> &clause,
1013 const ClauseTy *node) {
1014 using DirectiveNameModifier =
1015 typename clause::IfT<TypeTy, IdTy, ExprTy>::DirectiveNameModifier;
1016 using IfExpression = typename clause::IfT<TypeTy, IdTy, ExprTy>::IfExpression;
1017 auto &modifier = std::get<std::optional<DirectiveNameModifier>>(clause.t);
1018
1019 if (modifier) {
1020 llvm::omp::Directive dirId = *modifier;
1021 auto *unmodified =
1022 makeClause(llvm::omp::Clause::OMPC_if,
1023 tomp::clause::IfT<TypeTy, IdTy, ExprTy>{
1024 {std::nullopt,
1025 std::get<IfExpression>(clause.t)}});
1026
1027 if (auto *hasDir = findDirective(dirId)) {
1028 hasDir->clauses.push_back(unmodified);
1029 return true;
1030 }
1031 return false;
1032 }
1033
1034 return applyToAll(node);
1035 }
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054 template <typename C, typename H>
1055 bool ConstructDecompositionT<C, H>::applyClause(
1056 const tomp::clause::LinearT<TypeTy, IdTy, ExprTy> &clause,
1057 const ClauseTy *node) {
1058
1059 if (!applyToInnermost(node))
1060 return false;
1061
1062
1063 auto dirSimd = findDirective(llvm::omp::Directive::OMPD_simd);
1064 std::optional<ObjectTy> iterVar = helper.getLoopIterVar();
1065 const auto &objects = std::get<tomp::ObjectListT<IdTy, ExprTy>>(clause.t);
1066
1067
1068
1069 tomp::ObjectListT<IdTy, ExprTy> first, last;
1070
1071 for (const ObjectTy &object : objects) {
1072 last.push_back(object);
1073 if (!dirSimd || !iterVar || object.id() != iterVar->id())
1074 first.push_back(object);
1075 }
1076
1077 if (!first.empty()) {
1078 auto *firstp = makeClause(
1079 llvm::omp::Clause::OMPC_firstprivate,
1080 tomp::clause::FirstprivateT<TypeTy, IdTy, ExprTy>{first});
1081 nodes.push_back(firstp);
1082 }
1083 if (!last.empty()) {
1084 auto *lastp =
1085 makeClause(llvm::omp::Clause::OMPC_lastprivate,
1086 tomp::clause::LastprivateT<TypeTy, IdTy, ExprTy>{
1087 {std::nullopt, last}});
1088 nodes.push_back(lastp);
1089 }
1090 return true;
1091 }
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101 template <typename C, typename H>
1102 bool ConstructDecompositionT<C, H>::applyClause(
1103 const tomp::clause::NowaitT<TypeTy, IdTy, ExprTy> &clause,
1104 const ClauseTy *node) {
1105 return applyToOutermost(node);
1106 }
1107
1108 template <typename C, typename H>
1109 bool ConstructDecompositionT<C, H>::applyClause(
1110 const tomp::clause::OmpxBareT<TypeTy, IdTy, ExprTy> &clause,
1111 const ClauseTy *node) {
1112 return applyToOutermost(node);
1113 }
1114
1115 template <typename C, typename H>
1116 bool ConstructDecompositionT<C, H>::applyClause(
1117 const tomp::clause::OmpxAttributeT<TypeTy, IdTy, ExprTy> &clause,
1118 const ClauseTy *node) {
1119 return applyToAll(node);
1120 }
1121
1122 template <typename C, typename H> bool ConstructDecompositionT<C, H>::split() {
1123 bool success = true;
1124
1125 auto isImplicit = [this](const ClauseTy *node) {
1126 return llvm::any_of(
1127 implicit, [node](const ClauseTy &clause) { return &clause == node; });
1128 };
1129
1130 for (llvm::omp::Directive leaf :
1131 llvm::omp::getLeafConstructsOrSelf(construct))
1132 leafs.push_back(LeafReprInternal{leaf, {}});
1133
1134 for (const ClauseTy *node : nodes)
1135 addClauseSymsToMap(*node, node);
1136
1137
1138
1139
1140
1141 llvm::SmallVector<const ClauseTy *> linears;
1142 for (const ClauseTy *node : nodes) {
1143 if (node->id == llvm::omp::Clause::OMPC_linear)
1144 linears.push_back(node);
1145 }
1146 for (const auto *node : linears) {
1147 success = success &&
1148 applyClause(std::get<tomp::clause::LinearT<TypeTy, IdTy, ExprTy>>(
1149 node->u),
1150 node);
1151 }
1152
1153
1154
1155 auto skip = [](const ClauseTy *node) {
1156 switch (node->id) {
1157 case llvm::omp::Clause::OMPC_allocate:
1158 case llvm::omp::Clause::OMPC_linear:
1159 return true;
1160 default:
1161 return false;
1162 }
1163 };
1164
1165
1166 for (const ClauseTy *node : nodes) {
1167 if (skip(node))
1168 continue;
1169 bool result =
1170 std::visit([&](auto &&s) { return applyClause(s, node); }, node->u);
1171 if (!isImplicit(node))
1172 success = success && result;
1173 }
1174
1175
1176 for (const ClauseTy *node : nodes) {
1177 if (node->id != llvm::omp::Clause::OMPC_allocate)
1178 continue;
1179 success =
1180 success &&
1181 std::visit([&](auto &&s) { return applyClause(s, node); }, node->u);
1182 }
1183
1184 return success;
1185 }
1186
1187 }
1188
1189 #endif