Skip to content

Commit 4593582

Browse files
committed
[LLVM][OpenMP] Implement getLeafOrCompositeConstructs
This function will break up a construct into constituent leaf and composite constructs, e.g. if OMPD_c_d_e and OMPD_d_e are composite constructs, then OMPD_a_b_c_d_e will be broken up into the list {OMPD_a, OMPD_b, OMPD_c_d_e}.
1 parent 8f935fb commit 4593582

File tree

3 files changed

+113
-13
lines changed

3 files changed

+113
-13
lines changed

llvm/include/llvm/Frontend/OpenMP/OMP.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,15 @@
1616
#include "llvm/Frontend/OpenMP/OMP.h.inc"
1717

1818
#include "llvm/ADT/ArrayRef.h"
19+
#include "llvm/ADT/SmallVector.h"
1920

2021
namespace llvm::omp {
2122
ArrayRef<Directive> getLeafConstructs(Directive D);
23+
ArrayRef<Directive> getLeafConstructsOrSelf(Directive D);
24+
25+
ArrayRef<Directive>
26+
getLeafOrCompositeConstructs(Directive D, SmallVectorImpl<Directive> &Output);
27+
2228
Directive getCompoundConstruct(ArrayRef<Directive> Parts);
2329

2430
bool isLeafConstruct(Directive D);

llvm/lib/Frontend/OpenMP/OMP.cpp

Lines changed: 75 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,43 @@ using namespace llvm::omp;
2525
#define GEN_DIRECTIVES_IMPL
2626
#include "llvm/Frontend/OpenMP/OMP.inc"
2727

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 range. Then, starting from the immediately
37+
// following leaf construct, find the first sequence of adjacent loop-
38+
// -associated constructs. The last of those is the last one of the range.
39+
40+
auto firstLoopAssociated =
41+
[](iterator_range<ArrayRef<Directive>::iterator> List) {
42+
for (auto It = List.begin(), End = List.end(); It != End; ++It) {
43+
if (getDirectiveAssociation(*It) == Association::Loop)
44+
return It;
45+
}
46+
return List.end();
47+
};
48+
49+
auto Begin = firstLoopAssociated(Leafs);
50+
if (Begin == Leafs.end())
51+
return llvm::make_range(Leafs.end(), Leafs.end());
52+
53+
auto End =
54+
firstLoopAssociated(llvm::make_range(std::next(Begin), Leafs.end()));
55+
if (End == Leafs.end())
56+
return llvm::make_range(Begin, std::next(Begin));
57+
58+
for (; End != Leafs.end(); ++End) {
59+
if (getDirectiveAssociation(*End) != Association::Loop)
60+
break;
61+
}
62+
return llvm::make_range(Begin, End);
63+
}
64+
2865
namespace llvm::omp {
2966
ArrayRef<Directive> getLeafConstructs(Directive D) {
3067
auto Idx = static_cast<std::size_t>(D);
@@ -34,6 +71,40 @@ ArrayRef<Directive> getLeafConstructs(Directive D) {
3471
return ArrayRef(&Row[2], &Row[2] + static_cast<int>(Row[1]));
3572
}
3673

74+
ArrayRef<Directive> getLeafConstructsOrSelf(Directive D) {
75+
if (auto Leafs = getLeafConstructs(D); !Leafs.empty())
76+
return Leafs;
77+
auto Idx = static_cast<size_t>(D);
78+
assert(Idx < Directive_enumSize && "Invalid directive");
79+
const auto *Row = LeafConstructTable[LeafConstructTableOrdering[Idx]];
80+
// The first entry in the row is the directive itself.
81+
return ArrayRef(&Row[0], &Row[0] + 1);
82+
}
83+
84+
ArrayRef<Directive>
85+
getLeafOrCompositeConstructs(Directive D, SmallVectorImpl<Directive> &Output) {
86+
using ArrayTy = ArrayRef<Directive>;
87+
using IteratorTy = ArrayTy::iterator;
88+
ArrayRef<Directive> Leafs = getLeafConstructsOrSelf(D);
89+
90+
IteratorTy Iter = Leafs.begin();
91+
do {
92+
auto Range = getFirstCompositeRange(llvm::make_range(Iter, Leafs.end()));
93+
// All directives before the range are leaf constructs.
94+
for (; Iter != Range.begin(); ++Iter)
95+
Output.push_back(*Iter);
96+
if (!Range.empty()) {
97+
Directive Comp =
98+
getCompoundConstruct(ArrayTy(Range.begin(), Range.end()));
99+
assert(Comp != OMPD_unknown);
100+
Output.push_back(Comp);
101+
}
102+
Iter = Range.end();
103+
} while (Iter != Leafs.end());
104+
105+
return Output;
106+
}
107+
37108
Directive getCompoundConstruct(ArrayRef<Directive> Parts) {
38109
if (Parts.empty())
39110
return OMPD_unknown;
@@ -88,20 +159,11 @@ Directive getCompoundConstruct(ArrayRef<Directive> Parts) {
88159
bool isLeafConstruct(Directive D) { return getLeafConstructs(D).empty(); }
89160

90161
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)
162+
ArrayRef<Directive> Leafs = getLeafConstructsOrSelf(D);
163+
if (Leafs.size() <= 1)
98164
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;
165+
auto Range = getFirstCompositeRange(Leafs);
166+
return Range.begin() == Leafs.begin() && Range.end() == Leafs.end();
105167
}
106168

107169
bool isCombinedConstruct(Directive D) {

llvm/unittests/Frontend/OpenMPCompositionTest.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "llvm/ADT/ArrayRef.h"
10+
#include "llvm/ADT/SmallVector.h"
1011
#include "llvm/Frontend/OpenMP/OMP.h"
1112
#include "gtest/gtest.h"
1213

@@ -38,6 +39,37 @@ TEST(Composition, GetCompoundConstruct) {
3839
ASSERT_EQ(C6, OMPD_parallel_for_simd);
3940
}
4041

42+
TEST(Composition, GetLeafOrCompositeConstructs) {
43+
SmallVector<Directive> Out1;
44+
auto Ret1 = getLeafOrCompositeConstructs(
45+
OMPD_target_teams_distribute_parallel_for, Out1);
46+
ASSERT_EQ(Ret1, ArrayRef<Directive>(Out1));
47+
ASSERT_EQ((ArrayRef<Directive>(Out1)),
48+
(ArrayRef<Directive>{OMPD_target, OMPD_teams,
49+
OMPD_distribute_parallel_for}));
50+
51+
SmallVector<Directive> Out2;
52+
auto Ret2 =
53+
getLeafOrCompositeConstructs(OMPD_parallel_masked_taskloop_simd, Out2);
54+
ASSERT_EQ(Ret2, ArrayRef<Directive>(Out2));
55+
ASSERT_EQ(
56+
(ArrayRef<Directive>(Out2)),
57+
(ArrayRef<Directive>{OMPD_parallel, OMPD_masked, OMPD_taskloop_simd}));
58+
59+
SmallVector<Directive> Out3;
60+
auto Ret3 =
61+
getLeafOrCompositeConstructs(OMPD_distribute_parallel_do_simd, Out3);
62+
ASSERT_EQ(Ret3, ArrayRef<Directive>(Out3));
63+
ASSERT_EQ((ArrayRef<Directive>(Out3)),
64+
(ArrayRef<Directive>{OMPD_distribute_parallel_do_simd}));
65+
66+
SmallVector<Directive> Out4;
67+
auto Ret4 = getLeafOrCompositeConstructs(OMPD_target_parallel_loop, Out4);
68+
ASSERT_EQ(Ret4, ArrayRef<Directive>(Out4));
69+
ASSERT_EQ((ArrayRef<Directive>(Out4)),
70+
(ArrayRef<Directive>{OMPD_target, OMPD_parallel, OMPD_loop}));
71+
}
72+
4173
TEST(Composition, IsLeafConstruct) {
4274
ASSERT_TRUE(isLeafConstruct(OMPD_loop));
4375
ASSERT_TRUE(isLeafConstruct(OMPD_teams));

0 commit comments

Comments
 (0)