LLVM: include/llvm/Frontend/OpenMP/ConstructDecompositionT.h Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18#ifndef LLVM_FRONTEND_OPENMP_CONSTRUCTDECOMPOSITIONT_H
19#define LLVM_FRONTEND_OPENMP_CONSTRUCTDECOMPOSITIONT_H
20
27
28#include
29#include
30#include
31#include
32#include <type_traits>
33#include <unordered_map>
34#include <unordered_set>
35#include
36#include
37
39 static llvm::omp::Directive worksharing[] = {
40 llvm::omp::Directive::OMPD_do, llvm::omp::Directive::OMPD_for,
41 llvm::omp::Directive::OMPD_scope, llvm::omp::Directive::OMPD_sections,
42 llvm::omp::Directive::OMPD_single, llvm::omp::Directive::OMPD_workshare,
43 };
44 return worksharing;
45}
46
48 static llvm::omp::Directive worksharingLoop[] = {
49 llvm::omp::Directive::OMPD_do,
50 llvm::omp::Directive::OMPD_for,
51 };
52 return worksharingLoop;
53}
54
56template <typename Container, typename Predicate>
57typename std::remove_reference_t::iterator
60 if (first == container.end())
61 return first;
62 auto second = std::find_if(std::next(first), container.end(), pred);
63 if (second == container.end())
64 return first;
65 return container.end();
66}
67}
68
69namespace tomp {
70
77
78
79
80
81
82
83
84
85
86
87
88template <typename ClauseType, typename HelperType>
91
92 using TypeTy = typename ClauseTy::TypeTy;
93 using IdTy = typename ClauseTy::IdTy;
94 using ExprTy = typename ClauseTy::ExprTy;
97
98 using ClauseSet = std::unordered_set<const ClauseTy *>;
99
101 llvm::omp::Directive dir,
103 : version(ver), construct(dir), helper(helper) {
105 nodes.push_back(&clause);
106
107 bool success = split();
108 if (!success)
109 return;
110
111
112
113
114
115 for (auto &leaf : leafs) {
116 output.push_back({leaf.id, {}});
117 auto &out = output.back();
118 for (const ClauseTy *c : leaf.clauses)
119 out.clauses.push_back(*c);
120 }
121 }
122
125
126private:
127 bool split();
128
130 errors.emplace_back(node, ec);
131 return false;
132 }
133
134 struct LeafReprInternal {
135 llvm::omp::Directive id = llvm::omp::Directive::OMPD_unknown;
137 };
138
139 LeafReprInternal *findDirective(llvm::omp::Directive dirId) {
141 leafs, [&](const LeafReprInternal &leaf) { return leaf.id == dirId; });
142 return found != leafs.end() ? &*found : nullptr;
143 }
144
146 if (auto found = syms.find(object.id()); found != syms.end())
147 return &found->second;
148 return nullptr;
149 }
150
151 template
152 ClauseTy *makeClause(llvm::omp::Clause clauseId, S &&specific) {
153 implicit.push_back(typename ClauseTy::BaseT{clauseId, std::move(specific)});
154 return &implicit.back();
155 }
156
157 void addClauseSymsToMap(const ObjectTy &object, const ClauseTy *);
160 void addClauseSymsToMap(const TypeTy &item, const ClauseTy *);
161 void addClauseSymsToMap(const ExprTy &item, const ClauseTy *);
162 void addClauseSymsToMap(const tomp::clause::MapT<TypeTy, IdTy, ExprTy> &item,
164
165 template
166 void addClauseSymsToMap(const std::optional &item, const ClauseTy *);
167 template
169 template <typename... U, size_t... Is>
170 void addClauseSymsToMap(const std::tuple<U...> &item, const ClauseTy *,
171 std::index_sequence<Is...> = {});
172 template
173 std::enable_if_t<std::is_enum_v<llvm::remove_cvref_t>, void>
174 addClauseSymsToMap(U &&item, const ClauseTy *);
175
176 template
177 std::enable_if_t<llvm::remove_cvref_t::EmptyTrait::value, void>
178 addClauseSymsToMap(U &&item, const ClauseTy *);
179
180 template
181 std::enable_if_t<llvm::remove_cvref_t::IncompleteTrait::value, void>
182 addClauseSymsToMap(U &&item, const ClauseTy *);
183
184 template
185 std::enable_if_t<llvm::remove_cvref_t::WrapperTrait::value, void>
186 addClauseSymsToMap(U &&item, const ClauseTy *);
187
188 template
189 std::enable_if_t<llvm::remove_cvref_t::TupleTrait::value, void>
190 addClauseSymsToMap(U &&item, const ClauseTy *);
191
192 template
193 std::enable_if_t<llvm::remove_cvref_t::UnionTrait::value, void>
194 addClauseSymsToMap(U &&item, const ClauseTy *);
195
196
197
198
199 bool applyToUnique(const ClauseTy *node);
200
201
202
203 template
205
206
207
208 bool applyToInnermost(const ClauseTy *node);
209
210
211
212 bool applyToOutermost(const ClauseTy *node);
213
214
215
216
217 template
219
220
221
222 bool applyToAll(const ClauseTy *node);
223
224 template
225 bool applyClause(Clause &&clause, const ClauseTy *node);
226
227 bool applyClause(const tomp::clause::AllocateT<TypeTy, IdTy, ExprTy> &clause,
229 bool applyClause(const tomp::clause::CollapseT<TypeTy, IdTy, ExprTy> &clause,
231 bool applyClause(const tomp::clause::DefaultT<TypeTy, IdTy, ExprTy> &clause,
233 bool
234 applyClause(const tomp::clause::FirstprivateT<TypeTy, IdTy, ExprTy> &clause,
236 bool applyClause(const tomp::clause::IfT<TypeTy, IdTy, ExprTy> &clause,
238 bool
239 applyClause(const tomp::clause::LastprivateT<TypeTy, IdTy, ExprTy> &clause,
241 bool applyClause(const tomp::clause::LinearT<TypeTy, IdTy, ExprTy> &clause,
243 bool applyClause(const tomp::clause::NowaitT<TypeTy, IdTy, ExprTy> &clause,
245 bool
246 applyClause(const tomp::clause::OmpxAttributeT<TypeTy, IdTy, ExprTy> &clause,
248 bool applyClause(const tomp::clause::OmpxBareT<TypeTy, IdTy, ExprTy> &clause,
250 bool applyClause(const tomp::clause::OrderT<TypeTy, IdTy, ExprTy> &clause,
252 bool applyClause(const tomp::clause::PrivateT<TypeTy, IdTy, ExprTy> &clause,
254 bool applyClause(const tomp::clause::ReductionT<TypeTy, IdTy, ExprTy> &clause,
256 bool applyClause(const tomp::clause::SharedT<TypeTy, IdTy, ExprTy> &clause,
258 bool
259 applyClause(const tomp::clause::ThreadLimitT<TypeTy, IdTy, ExprTy> &clause,
261
262 uint32_t version;
263 llvm::omp::Directive construct;
264 HelperType &helper;
267 std::list implicit;
268
269 std::unordered_map<IdTy, ClauseSet> syms;
270 std::unordered_set mapBases;
271};
272
273
274template <typename ClauseType, typename HelperType>
278
279template <typename C, typename H>
280void ConstructDecompositionT<C, H>::addClauseSymsToMap(const ObjectTy &object,
281 const ClauseTy *node) {
282 syms[object.id()].insert(node);
283}
284
285template <typename C, typename H>
286void ConstructDecompositionT<C, H>::addClauseSymsToMap(
288 for (auto &object : objects)
289 syms[object.id()].insert(node);
290}
291
292template <typename C, typename H>
293void ConstructDecompositionT<C, H>::addClauseSymsToMap(const TypeTy &item,
294 const ClauseTy *node) {
295
296}
297
298template <typename C, typename H>
299void ConstructDecompositionT<C, H>::addClauseSymsToMap(const ExprTy &item,
300 const ClauseTy *node) {
301
302}
303
304template <typename C, typename H>
305void ConstructDecompositionT<C, H>::addClauseSymsToMap(
306 const tomp::clause::MapT<TypeTy, IdTy, ExprTy> &item,
307 const ClauseTy *node) {
308 auto &objects = std::get<tomp::ObjectListT<IdTy, ExprTy>>(item.t);
309 addClauseSymsToMap(objects, node);
310 for (auto &object : objects) {
311 if (auto base = helper.getBaseObject(object))
312 mapBases.insert(base->id());
313 }
314}
315
316template <typename C, typename H>
317template
318void ConstructDecompositionT<C, H>::addClauseSymsToMap(
319 const std::optional &item, const ClauseTy *node) {
320 if (item)
321 addClauseSymsToMap(*item, node);
322}
323
324template <typename C, typename H>
325template
326void ConstructDecompositionT<C, H>::addClauseSymsToMap(
328 for (auto &s : item)
329 addClauseSymsToMap(s, node);
330}
331
332template <typename C, typename H>
333template <typename... U, size_t... Is>
334void ConstructDecompositionT<C, H>::addClauseSymsToMap(
335 const std::tuple<U...> &item, const ClauseTy *node,
336 std::index_sequence<Is...>) {
337 (void)node;
338 (addClauseSymsToMap(std::get(item), node), ...);
339}
340
341template <typename C, typename H>
342template
343std::enable_if_t<std::is_enum_v<llvm::remove_cvref_t>, void>
344ConstructDecompositionT<C, H>::addClauseSymsToMap(U &&item,
345 const ClauseTy *node) {
346
347}
348
349template <typename C, typename H>
350template
351std::enable_if_t<llvm::remove_cvref_t::EmptyTrait::value, void>
352ConstructDecompositionT<C, H>::addClauseSymsToMap(U &&item,
353 const ClauseTy *node) {
354
355}
356
357template <typename C, typename H>
358template
359std::enable_if_t<llvm::remove_cvref_t::IncompleteTrait::value, void>
360ConstructDecompositionT<C, H>::addClauseSymsToMap(U &&item,
361 const ClauseTy *node) {
362
363}
364
365template <typename C, typename H>
366template
367std::enable_if_t<llvm::remove_cvref_t::WrapperTrait::value, void>
368ConstructDecompositionT<C, H>::addClauseSymsToMap(U &&item,
369 const ClauseTy *node) {
370 addClauseSymsToMap(item.v, node);
371}
372
373template <typename C, typename H>
374template
375std::enable_if_t<llvm::remove_cvref_t::TupleTrait::value, void>
376ConstructDecompositionT<C, H>::addClauseSymsToMap(U &&item,
377 const ClauseTy *node) {
378 constexpr size_t tuple_size =
379 std::tuple_size_v<llvm::remove_cvref_t<decltype(item.t)>>;
380 addClauseSymsToMap(item.t, node, std::make_index_sequence<tuple_size>{});
381}
382
383template <typename C, typename H>
384template
385std::enable_if_t<llvm::remove_cvref_t::UnionTrait::value, void>
386ConstructDecompositionT<C, H>::addClauseSymsToMap(U &&item,
387 const ClauseTy *node) {
388 std::visit([&](auto &&s) { addClauseSymsToMap(s, node); }, item.u);
389}
390
391
392
393
394template <typename C, typename H>
395bool ConstructDecompositionT<C, H>::applyToUnique(const ClauseTy *node) {
397 return llvm::omp::isAllowedClauseForDirective(leaf.id, node->id, version);
398 });
399
400 if (unique != leafs.end()) {
401 unique->clauses.push_back(node);
402 return true;
403 }
404 return false;
405}
406
407
408
409template <typename C, typename H>
410template
411bool ConstructDecompositionT<C, H>::applyToFirst(
413 if (range.empty())
414 return false;
415
416 for (auto &leaf : range) {
417 if (!llvm::omp::isAllowedClauseForDirective(leaf.id, node->id, version))
418 continue;
419 leaf.clauses.push_back(node);
420 return true;
421 }
422 return false;
423}
424
425
426
427template <typename C, typename H>
428bool ConstructDecompositionT<C, H>::applyToInnermost(const ClauseTy *node) {
430}
431
432
433
434template <typename C, typename H>
435bool ConstructDecompositionT<C, H>::applyToOutermost(const ClauseTy *node) {
437}
438
439template <typename C, typename H>
440template
441bool ConstructDecompositionT<C, H>::applyIf(const ClauseTy *node,
443 bool applied = false;
444 for (auto &leaf : leafs) {
445 if (!llvm::omp::isAllowedClauseForDirective(leaf.id, node->id, version))
446 continue;
448 continue;
449 leaf.clauses.push_back(node);
450 applied = true;
451 }
452
453 return applied;
454}
455
456template <typename C, typename H>
457bool ConstructDecompositionT<C, H>::applyToAll(const ClauseTy *node) {
458 return applyIf(node, [](auto) { return true; });
459}
460
461template <typename C, typename H>
462template
463bool ConstructDecompositionT<C, H>::applyClause(Specific &&specific,
465
466
467
468
469
470
471
472 if (!applyToUnique(node))
474 return true;
475}
476
477
478
479
480
481
482
483
484
485
486
487
488template <typename C, typename H>
489bool ConstructDecompositionT<C, H>::applyClause(
491 const ClauseTy *node) {
492
493
494
495
496 bool applied = applyIf(node, [&](const auto &leaf) {
497 return llvm::any_of(leaf.clauses, [&](const ClauseTy *n) {
498 return llvm::omp::isPrivatizingClause(n->id);
499 });
500 });
501
502 if (!applied)
504 return true;
505}
506
507
508
509
510
511
512
513
514template <typename C, typename H>
515bool ConstructDecompositionT<C, H>::applyClause(
516 const tomp::clause::CollapseT<TypeTy, IdTy, ExprTy> &clause,
517 const ClauseTy *node) {
518 if (!applyToInnermost(node))
520 return true;
521}
522
523
524
525
526
527
528
529
530template <typename C, typename H>
531bool ConstructDecompositionT<C, H>::applyClause(
532 const tomp::clause::DefaultT<TypeTy, IdTy, ExprTy> &clause,
533 const ClauseTy *node) {
534
535 if (!applyToAll(node))
537 return true;
538}
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570template <typename C, typename H>
571bool ConstructDecompositionT<C, H>::applyClause(
572 const tomp::clause::FirstprivateT<TypeTy, IdTy, ExprTy> &clause,
573 const ClauseTy *node) {
574 bool applied = false;
575
576
577 auto dirDistribute = findDirective(llvm::omp::OMPD_distribute);
578 auto dirTeams = findDirective(llvm::omp::OMPD_teams);
579 if (dirDistribute != nullptr) {
580 dirDistribute->clauses.push_back(node);
581 applied = true;
582
583 if (dirTeams != nullptr) {
584 auto *shared = makeClause(
585 llvm::omp::Clause::OMPC_shared,
586 tomp::clause::SharedT<TypeTy, IdTy, ExprTy>{clause.v});
587 dirTeams->clauses.push_back(shared);
588 }
589 } else if (dirTeams != nullptr) {
590 dirTeams->clauses.push_back(node);
591 applied = true;
592 }
593
594
595 auto findWorksharing = [&]() {
597 for (auto &leaf : leafs) {
598 auto found = llvm::find(worksharing, leaf.id);
599 if (found != std::end(worksharing))
600 return &leaf;
601 }
602 return static_cast<typename decltype(leafs)::value_type *>(nullptr);
603 };
604
605 auto dirWorksharing = findWorksharing();
606 if (dirWorksharing != nullptr) {
607 dirWorksharing->clauses.push_back(node);
608 applied = true;
609 }
610
611
612 auto dirTaskloop = findDirective(llvm::omp::OMPD_taskloop);
613 if (dirTaskloop != nullptr) {
614 dirTaskloop->clauses.push_back(node);
615 applied = true;
616 }
617
618
619 auto dirParallel = findDirective(llvm::omp::OMPD_parallel);
620 if (dirParallel != nullptr) {
621 if (dirTaskloop == nullptr && dirWorksharing == nullptr) {
622 dirParallel->clauses.push_back(node);
623 applied = true;
624 } else {
625
626 auto *shared = makeClause(
627 llvm::omp::Clause::OMPC_shared,
628 tomp::clause::SharedT<TypeTy, IdTy, ExprTy>{clause.v});
629 dirParallel->clauses.push_back(shared);
630 }
631 }
632
633
634 auto inLastprivate = [&](const ObjectTy &object) {
635 if (ClauseSet *set = findClausesWith(object)) {
636 return llvm::find_if(*set, [](const ClauseTy *c) {
637 return c->id == llvm::omp::Clause::OMPC_lastprivate;
638 }) != set->end();
639 }
640 return false;
641 };
642
643 auto dirTarget = findDirective(llvm::omp::OMPD_target);
644 if (dirTarget != nullptr) {
647 clause.v, std::back_inserter(objects), [&](const ObjectTy &object) {
648 return !inLastprivate(object) && !mapBases.count(object.id());
649 });
650 if (!objects.empty()) {
651 auto *firstp = makeClause(
652 llvm::omp::Clause::OMPC_firstprivate,
653 tomp::clause::FirstprivateT<TypeTy, IdTy, ExprTy>{objects});
654 dirTarget->clauses.push_back(firstp);
655 applied = true;
656 }
657 }
658
659
660 if (auto dirTask = findDirective(llvm::omp::OMPD_task)) {
661 dirTask->clauses.push_back(node);
662 applied = true;
663 }
664
665 if (!applied)
667 return true;
668}
669
670
671
672
673
674
675
676
677
678
679
680
681template <typename C, typename H>
682bool ConstructDecompositionT<C, H>::applyClause(
683 const tomp::clause::IfT<TypeTy, IdTy, ExprTy> &clause,
684 const ClauseTy *node) {
685 using DirectiveNameModifier =
688 auto &modifier = std::get<std::optional>(clause.t);
689
690 if (modifier) {
691 llvm::omp::Directive dirId = *modifier;
692 auto *unmodified =
693 makeClause(llvm::omp::Clause::OMPC_if,
694 tomp::clause::IfT<TypeTy, IdTy, ExprTy>{
695 {std::nullopt,
696 std::get(clause.t)}});
697
698 if (auto *hasDir = findDirective(dirId)) {
699 hasDir->clauses.push_back(unmodified);
700 return true;
701 }
703 }
704
705 if (!applyToAll(node))
707 return true;
708}
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729template <typename C, typename H>
730bool ConstructDecompositionT<C, H>::applyClause(
731 const tomp::clause::LastprivateT<TypeTy, IdTy, ExprTy> &clause,
732 const ClauseTy *node) {
733
734 if (!applyToAll(node))
736
737 auto inFirstprivate = [&](const ObjectTy &object) {
738 if (ClauseSet *set = findClausesWith(object)) {
739 return llvm::find_if(*set, [](const ClauseTy *c) {
740 return c->id == llvm::omp::Clause::OMPC_firstprivate;
741 }) != set->end();
742 }
743 return false;
744 };
745
746 auto &objects = std::get<tomp::ObjectListT<IdTy, ExprTy>>(clause.t);
747
748
751 objects, std::back_inserter(sharedObjects),
752 [&](const ObjectTy &object) { return !inFirstprivate(object); });
753
754 if (!sharedObjects.empty()) {
755
756 if (auto dirParallel = findDirective(llvm::omp::OMPD_parallel)) {
757 auto *shared = makeClause(
758 llvm::omp::Clause::OMPC_shared,
759 tomp::clause::SharedT<TypeTy, IdTy, ExprTy>{sharedObjects});
760 dirParallel->clauses.push_back(shared);
761 }
762
763
764 if (auto dirTeams = findDirective(llvm::omp::OMPD_teams)) {
765 auto *shared = makeClause(
766 llvm::omp::Clause::OMPC_shared,
767 tomp::clause::SharedT<TypeTy, IdTy, ExprTy>{sharedObjects});
768 dirTeams->clauses.push_back(shared);
769 }
770 }
771
772
773 if (auto dirTarget = findDirective(llvm::omp::OMPD_target)) {
776 objects, std::back_inserter(tofrom),
777 [&](const ObjectTy &object) { return !mapBases.count(object.id()); });
778
779 if (!tofrom.empty()) {
780 using MapType =
781 typename tomp::clause::MapT<TypeTy, IdTy, ExprTy>::MapType;
782 auto *map =
783 makeClause(llvm::omp::Clause::OMPC_map,
784 tomp::clause::MapT<TypeTy, IdTy, ExprTy>{
785 {MapType::Tofrom,
786 std::nullopt,
787 std::nullopt,
788 std::nullopt,
789 std::nullopt, std::nullopt,
790 std::move(tofrom)}});
791 dirTarget->clauses.push_back(map);
792 }
793 }
794
795 return true;
796}
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815template <typename C, typename H>
816bool ConstructDecompositionT<C, H>::applyClause(
817 const tomp::clause::LinearT<TypeTy, IdTy, ExprTy> &clause,
818 const ClauseTy *node) {
819
820 if (!applyToInnermost(node))
822
823
824 auto dirSimd = findDirective(llvm::omp::Directive::OMPD_simd);
825 std::optional iterVar = helper.getLoopIterVar();
826 const auto &objects = std::get<tomp::ObjectListT<IdTy, ExprTy>>(clause.t);
827
828
829
831
832 for (const ObjectTy &object : objects) {
833 last.push_back(object);
834 if (!dirSimd || !iterVar || object.id() != iterVar->id())
835 first.push_back(object);
836 }
837
838 if (!first.empty()) {
839 auto *firstp = makeClause(
840 llvm::omp::Clause::OMPC_firstprivate,
841 tomp::clause::FirstprivateT<TypeTy, IdTy, ExprTy>{first});
842 nodes.push_back(firstp);
843 }
844 if (.empty()) {
845 auto *lastp =
846 makeClause(llvm::omp::Clause::OMPC_lastprivate,
847 tomp::clause::LastprivateT<TypeTy, IdTy, ExprTy>{
848 {std::nullopt, last}});
849 nodes.push_back(lastp);
850 }
851 return true;
852}
853
854
855
856
857
858
859
860
861
862template <typename C, typename H>
863bool ConstructDecompositionT<C, H>::applyClause(
864 const tomp::clause::NowaitT<TypeTy, IdTy, ExprTy> &clause,
865 const ClauseTy *node) {
866 if (!applyToOutermost(node))
868 return true;
869}
870
871
872template <typename C, typename H>
873bool ConstructDecompositionT<C, H>::applyClause(
874 const tomp::clause::OmpxAttributeT<TypeTy, IdTy, ExprTy> &clause,
875 const ClauseTy *node) {
876 if (!applyToAll(node))
878 return true;
879}
880
881
882template <typename C, typename H>
883bool ConstructDecompositionT<C, H>::applyClause(
884 const tomp::clause::OmpxBareT<TypeTy, IdTy, ExprTy> &clause,
885 const ClauseTy *node) {
886 if (!applyToOutermost(node))
888 return true;
889}
890
891
892
893
894
895
896
897
898template <typename C, typename H>
899bool ConstructDecompositionT<C, H>::applyClause(
900 const tomp::clause::OrderT<TypeTy, IdTy, ExprTy> &clause,
901 const ClauseTy *node) {
902
903 if (!applyToAll(node))
905 return true;
906}
907
908
909
910
911
912
913
914
915
916template <typename C, typename H>
917bool ConstructDecompositionT<C, H>::applyClause(
918 const tomp::clause::PrivateT<TypeTy, IdTy, ExprTy> &clause,
919 const ClauseTy *node) {
920 if (!applyToInnermost(node))
922 return true;
923}
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951template <typename C, typename H>
952bool ConstructDecompositionT<C, H>::applyClause(
953 const tomp::clause::ReductionT<TypeTy, IdTy, ExprTy> &clause,
954 const ClauseTy *node) {
955 using ReductionTy = tomp::clause::ReductionT<TypeTy, IdTy, ExprTy>;
956
957
958 bool applyToParallel = true, applyToTeams = true;
959
960 auto dirParallel = findDirective(llvm::omp::Directive::OMPD_parallel);
961 if (dirParallel) {
964 llvm::omp::Directive::OMPD_loop,
965 llvm::omp::Directive::OMPD_sections,
966 llvm::omp::Directive::OMPD_taskloop,
967 });
968 auto present = [&](llvm::omp::Directive id) {
969 return findDirective(id) != nullptr;
970 };
971
973 applyToParallel = false;
974 }
975
976 auto dirTeams = findDirective(llvm::omp::Directive::OMPD_teams);
977 if (dirTeams) {
978
979 if (findDirective(llvm::omp::Directive::OMPD_loop))
980 applyToTeams = false;
981 }
982
983 using ReductionModifier = typename ReductionTy::ReductionModifier;
984 using ReductionIdentifiers = typename ReductionTy::ReductionIdentifiers;
985
986 auto &objects = std::get<tomp::ObjectListT<IdTy, ExprTy>>(clause.t);
987 auto &modifier = std::get<std::optional>(clause.t);
988
989
990
991
992 bool applied = false;
993
994
995 auto isValidModifier = [](llvm::omp::Directive dir, ReductionModifier mod,
996 bool alreadyApplied) {
997 switch (mod) {
998 case ReductionModifier::Inscan:
999
1000
1001 return dir == llvm::omp::Directive::OMPD_simd ||
1003 case ReductionModifier::Task:
1004 if (alreadyApplied)
1005 return false;
1006
1007
1008 return dir == llvm::omp::Directive::OMPD_parallel ||
1010 case ReductionModifier::Default:
1011 return true;
1012 }
1014 };
1015
1016 auto *unmodified = makeClause(
1017 llvm::omp::Clause::OMPC_reduction,
1018 ReductionTy{
1019 {std::nullopt,
1020 std::get(clause.t),
1021 objects}});
1022
1023 ReductionModifier effective = modifier.value_or(ReductionModifier::Default);
1024 bool modifierApplied = false;
1025 bool allowingLeaf = false;
1026
1027
1029 if (!llvm::omp::isAllowedClauseForDirective(leaf.id, node->id, version))
1030 continue;
1031
1032
1033 allowingLeaf = true;
1034 if (!applyToParallel && &leaf == dirParallel)
1035 continue;
1036 if (!applyToTeams && &leaf == dirTeams)
1037 continue;
1038
1039 if (isValidModifier(leaf.id, effective, modifierApplied)) {
1040
1041 leaf.clauses.push_back(node);
1042 modifierApplied = true;
1043 } else {
1044
1045 leaf.clauses.push_back(unmodified);
1046 }
1047
1048 applied = modifierApplied;
1049 }
1050
1051 if (!allowingLeaf)
1053 if (!applied)
1055
1057 llvm::transform(objects, std::back_inserter(sharedObjects),
1058 [&](const ObjectTy &object) {
1059 auto maybeBase = helper.getBaseObject(object);
1060 return maybeBase ? *maybeBase : object;
1061 });
1062
1063
1064 if (!sharedObjects.empty()) {
1065 if (dirParallel && !applyToParallel) {
1066 auto *shared = makeClause(
1067 llvm::omp::Clause::OMPC_shared,
1068 tomp::clause::SharedT<TypeTy, IdTy, ExprTy>{sharedObjects});
1069 dirParallel->clauses.push_back(shared);
1070 }
1071 if (dirTeams && !applyToTeams) {
1072 auto *shared = makeClause(
1073 llvm::omp::Clause::OMPC_shared,
1074 tomp::clause::SharedT<TypeTy, IdTy, ExprTy>{sharedObjects});
1075 dirTeams->clauses.push_back(shared);
1076 }
1077 }
1078
1079
1080 auto dirTarget = findDirective(llvm::omp::Directive::OMPD_target);
1081 if (dirTarget && leafs.size() > 1) {
1083 llvm::copy_if(objects, std::back_inserter(tofrom),
1084 [&](const ObjectTy &object) {
1085 if (auto maybeBase = helper.getBaseObject(object))
1086 return !mapBases.count(maybeBase->id());
1087 return !mapBases.count(object.id());
1088 });
1089 if (!tofrom.empty()) {
1090 using MapType =
1091 typename tomp::clause::MapT<TypeTy, IdTy, ExprTy>::MapType;
1092 auto *map = makeClause(
1093 llvm::omp::Clause::OMPC_map,
1094 tomp::clause::MapT<TypeTy, IdTy, ExprTy>{
1095 {MapType::Tofrom, std::nullopt,
1096 std::nullopt, std::nullopt,
1097 std::nullopt, std::nullopt,
1098 std::move(tofrom)}});
1099
1100 dirTarget->clauses.push_back(map);
1101 }
1102 }
1103
1104 return true;
1105}
1106
1107
1108
1109
1110
1111
1112
1113
1114template <typename C, typename H>
1115bool ConstructDecompositionT<C, H>::applyClause(
1116 const tomp::clause::SharedT<TypeTy, IdTy, ExprTy> &clause,
1117 const ClauseTy *node) {
1118
1119 if (!applyToAll(node))
1121 return true;
1122}
1123
1124
1125
1126
1127
1128
1129
1130
1131template <typename C, typename H>
1132bool ConstructDecompositionT<C, H>::applyClause(
1133 const tomp::clause::ThreadLimitT<TypeTy, IdTy, ExprTy> &clause,
1134 const ClauseTy *node) {
1135
1136 if (!applyToAll(node))
1138 return true;
1139}
1140
1141
1142
1143template <typename C, typename H> bool ConstructDecompositionT<C, H>::split() {
1145
1146 auto isImplicit = [this](const ClauseTy *node) {
1148 };
1149
1150 for (llvm::omp::Directive leaf :
1152 leafs.push_back(LeafReprInternal{leaf, {}});
1153
1154 for (const ClauseTy *node : nodes)
1155 addClauseSymsToMap(*node, node);
1156
1157
1158
1159
1160
1162 for (const ClauseTy *node : nodes) {
1163 if (node->id == llvm::omp::Clause::OMPC_linear)
1165 }
1166 for (const auto *node : linears) {
1168 applyClause(std::get<tomp::clause::LinearT<TypeTy, IdTy, ExprTy>>(
1169 node->u),
1170 node);
1171 }
1172
1173
1174
1175 auto skip = [](const ClauseTy *node) {
1176 switch (node->id) {
1177 case llvm::omp::Clause::OMPC_allocate:
1178 case llvm::omp::Clause::OMPC_linear:
1179 return true;
1180 default:
1181 return false;
1182 }
1183 };
1184
1185
1186 for (const ClauseTy *node : nodes) {
1187 if (skip(node))
1188 continue;
1189 bool result =
1190 std::visit([&](auto &&s) { return applyClause(s, node); }, node->u);
1191 if (!isImplicit(node))
1193 }
1194
1195
1196 for (const ClauseTy *node : nodes) {
1197 if (node->id != llvm::omp::Clause::OMPC_allocate)
1198 continue;
1201 std::visit([&](auto &&s) { return applyClause(s, node); }, node->u);
1202 }
1203
1205}
1206
1207}
1208
1209#endif
Unify divergent function exit nodes
static llvm::ArrayRef< llvm::omp::Directive > getWorksharing()
Definition ConstructDecompositionT.h:38
static llvm::ArrayRef< llvm::omp::Directive > getWorksharingLoop()
Definition ConstructDecompositionT.h:47
static bool shouldApply(Function &F, ProfileSummaryInfo &PSI)
static bool skip(DataExtractor &Data, uint64_t &Offset, bool SkippedRanges)
Skip an InlineInfo object in the specified data at the specified offset.
This file defines the SmallVector class.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
std::remove_reference_t< Container >::iterator find_unique(Container &&container, Predicate &&pred)
Definition ConstructDecompositionT.h:58
LLVM_ABI ArrayRef< Directive > getLeafConstructsOrSelf(Directive D)
auto find(R &&Range, const T &Val)
Provide wrappers to std::find which take ranges instead of having to pass begin/end explicitly.
LLVM_ATTRIBUTE_ALWAYS_INLINE DynamicAPInt mod(const DynamicAPInt &LHS, const DynamicAPInt &RHS)
is always non-negative.
auto unique(Range &&R, Predicate P)
OutputIt copy_if(R &&Range, OutputIt Out, UnaryPredicate P)
Provide wrappers to std::copy_if which take ranges instead of having to pass begin/end explicitly.
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
OutputIt transform(R &&Range, OutputIt d_first, UnaryFunction F)
Wrapper function around std::transform to apply a function to a range and store the result elsewhere.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
auto reverse(ContainerTy &&C)
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
iterator_range(Container &&) -> iterator_range< llvm::detail::IterOfRange< Container > >
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
iterator_range< pointer_iterator< WrappedIteratorT > > make_pointer_range(RangeT &&Range)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
LogicalResult success(bool IsSuccess=true)
Utility function to generate a LogicalResult.
llvm::SmallVector< T, 0 > ListT
ErrorCode
Definition ConstructDecompositionT.h:71
@ InvalidDirNameMod
Definition ConstructDecompositionT.h:74
@ NoLeafAllowing
Definition ConstructDecompositionT.h:72
@ NoLeafPrivatizing
Definition ConstructDecompositionT.h:73
@ RedModNotApplied
Definition ConstructDecompositionT.h:75
type::ObjectListT< I, E > ObjectListT
ConstructDecompositionT(uint32_t, HelperType &, llvm::omp::Directive, llvm::ArrayRef< ClauseType >) -> ConstructDecompositionT< ClauseType, HelperType >
type::ObjectT< I, E > ObjectT
typename ClauseTy::ExprTy ExprTy
Definition ConstructDecompositionT.h:94
llvm::SmallVector< std::pair< const ClauseType *, ErrorCode > > errors
Definition ConstructDecompositionT.h:124
std::unordered_set< const ClauseTy * > ClauseSet
Definition ConstructDecompositionT.h:98
typename ClauseTy::TypeTy TypeTy
Definition ConstructDecompositionT.h:92
ClauseType ClauseTy
Definition ConstructDecompositionT.h:90
typename ClauseTy::IdTy IdTy
Definition ConstructDecompositionT.h:93
tomp::ObjectT< IdTy, ExprTy > ObjectTy
Definition ConstructDecompositionT.h:96
ConstructDecompositionT(uint32_t ver, HelperType &helper, llvm::omp::Directive dir, llvm::ArrayRef< ClauseTy > clauses)
Definition ConstructDecompositionT.h:100
HelperType HelperTy
Definition ConstructDecompositionT.h:95
tomp::ListT< DirectiveWithClauses< ClauseType > > output
Definition ConstructDecompositionT.h:123
type::DirectiveName DirectiveNameModifier
std::tuple< OPT(MapType), OPT(MapTypeModifiers), OPT(AttachModifier), OPT(RefModifier), OPT(Mappers), OPT(Iterator), LocatorList > t