@@ -25,6 +25,54 @@ using namespace llvm::omp;
25
25
#define GEN_DIRECTIVES_IMPL
26
26
#include " llvm/Frontend/OpenMP/OMP.inc"
27
27
28
+ static iterator_range<ArrayRef<Directive>::iterator>
29
+ getFirstCompositeRange (iterator_range<ArrayRef<Directive>::iterator> Leafs) {
30
+ // OpenMP Spec 5.2: [17.3, 8-9]
31
+ // If directive-name-A and directive-name-B both correspond to loop-
32
+ // associated constructs then directive-name is a composite construct
33
+ // otherwise directive-name is a combined construct.
34
+ //
35
+ // In the list of leaf constructs, find the first loop-associated construct,
36
+ // this is the beginning of the returned range. Then, starting from the
37
+ // immediately following leaf construct, find the first sequence of adjacent
38
+ // loop-associated constructs. The last of those is the last one of the
39
+ // range, that is, the end of the range is one past that element.
40
+ // If such a sequence of adjacent loop-associated directives does not exist,
41
+ // return an empty range.
42
+ //
43
+ // The end of the returned range (including empty range) is intended to be
44
+ // a point from which the search for the next range could resume.
45
+ //
46
+ // Consequently, this function can't return a range with a single leaf
47
+ // construct in it.
48
+
49
+ auto firstLoopAssociated =
50
+ [](iterator_range<ArrayRef<Directive>::iterator> List) {
51
+ for (auto It = List.begin (), End = List.end (); It != End; ++It) {
52
+ if (getDirectiveAssociation (*It) == Association::Loop)
53
+ return It;
54
+ }
55
+ return List.end ();
56
+ };
57
+
58
+ auto Empty = llvm::make_range (Leafs.end (), Leafs.end ());
59
+
60
+ auto Begin = firstLoopAssociated (Leafs);
61
+ if (Begin == Leafs.end ())
62
+ return Empty;
63
+
64
+ auto End =
65
+ firstLoopAssociated (llvm::make_range (std::next (Begin), Leafs.end ()));
66
+ if (End == Leafs.end ())
67
+ return Empty;
68
+
69
+ for (; End != Leafs.end (); ++End) {
70
+ if (getDirectiveAssociation (*End) != Association::Loop)
71
+ break ;
72
+ }
73
+ return llvm::make_range (Begin, End);
74
+ }
75
+
28
76
namespace llvm ::omp {
29
77
ArrayRef<Directive> getLeafConstructs (Directive D) {
30
78
auto Idx = static_cast <std::size_t >(D);
@@ -34,6 +82,44 @@ ArrayRef<Directive> getLeafConstructs(Directive D) {
34
82
return ArrayRef (&Row[2 ], static_cast <int >(Row[1 ]));
35
83
}
36
84
85
+ ArrayRef<Directive> getLeafConstructsOrSelf (Directive D) {
86
+ if (auto Leafs = getLeafConstructs (D); !Leafs.empty ())
87
+ return Leafs;
88
+ auto Idx = static_cast <size_t >(D);
89
+ assert (Idx < Directive_enumSize && " Invalid directive" );
90
+ const auto *Row = LeafConstructTable[LeafConstructTableOrdering[Idx]];
91
+ // The first entry in the row is the directive itself.
92
+ return ArrayRef (&Row[0 ], &Row[0 ] + 1 );
93
+ }
94
+
95
+ ArrayRef<Directive>
96
+ getLeafOrCompositeConstructs (Directive D, SmallVectorImpl<Directive> &Output) {
97
+ using ArrayTy = ArrayRef<Directive>;
98
+ using IteratorTy = ArrayTy::iterator;
99
+ ArrayRef<Directive> Leafs = getLeafConstructsOrSelf (D);
100
+
101
+ IteratorTy Iter = Leafs.begin ();
102
+ do {
103
+ auto Range = getFirstCompositeRange (llvm::make_range (Iter, Leafs.end ()));
104
+ // All directives before the range are leaf constructs.
105
+ for (; Iter != Range.begin (); ++Iter)
106
+ Output.push_back (*Iter);
107
+ if (!Range.empty ()) {
108
+ Directive Comp =
109
+ getCompoundConstruct (ArrayTy (Range.begin (), Range.end ()));
110
+ assert (Comp != OMPD_unknown);
111
+ Output.push_back (Comp);
112
+ Iter = Range.end ();
113
+ // As of now, a composite construct must contain all constituent leaf
114
+ // constructs from some point until the end of all constituent leaf
115
+ // constructs.
116
+ assert (Iter == Leafs.end () && " Malformed directive" );
117
+ }
118
+ } while (Iter != Leafs.end ());
119
+
120
+ return Output;
121
+ }
122
+
37
123
Directive getCompoundConstruct (ArrayRef<Directive> Parts) {
38
124
if (Parts.empty ())
39
125
return OMPD_unknown;
@@ -88,20 +174,11 @@ Directive getCompoundConstruct(ArrayRef<Directive> Parts) {
88
174
bool isLeafConstruct (Directive D) { return getLeafConstructs (D).empty (); }
89
175
90
176
bool isCompositeConstruct (Directive D) {
91
- // OpenMP Spec 5.2: [17.3, 8-9]
92
- // If directive-name-A and directive-name-B both correspond to loop-
93
- // associated constructs then directive-name is a composite construct
94
- llvm::ArrayRef<Directive> Leafs{getLeafConstructs (D)};
95
- if (Leafs.empty ())
96
- return false ;
97
- if (getDirectiveAssociation (Leafs.front ()) != Association::Loop)
177
+ ArrayRef<Directive> Leafs = getLeafConstructsOrSelf (D);
178
+ if (Leafs.size () <= 1 )
98
179
return false ;
99
-
100
- size_t numLoopConstructs =
101
- llvm::count_if (Leafs.drop_front (), [](Directive L) {
102
- return getDirectiveAssociation (L) == Association::Loop;
103
- });
104
- return numLoopConstructs != 0 ;
180
+ auto Range = getFirstCompositeRange (Leafs);
181
+ return Range.begin () == Leafs.begin () && Range.end () == Leafs.end ();
105
182
}
106
183
107
184
bool isCombinedConstruct (Directive D) {
0 commit comments