-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[Frontend][OpenMP] Implement getLeafOrCompositeConstructs #89104
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c9ee93f
7af7e9d
e291fad
d56c859
3d9ec39
0416ec4
ec0ed50
f725fac
291dc48
a889f30
0d92781
46770f8
de93771
065b54c
e799507
a803e4a
cb7c0f8
8f935fb
4593582
a626be8
a37ae86
62b72ef
02bbf90
cc539db
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,54 @@ using namespace llvm::omp; | |
#define GEN_DIRECTIVES_IMPL | ||
#include "llvm/Frontend/OpenMP/OMP.inc" | ||
|
||
static iterator_range<ArrayRef<Directive>::iterator> | ||
getFirstCompositeRange(iterator_range<ArrayRef<Directive>::iterator> Leafs) { | ||
// OpenMP Spec 5.2: [17.3, 8-9] | ||
// If directive-name-A and directive-name-B both correspond to loop- | ||
// associated constructs then directive-name is a composite construct | ||
// otherwise directive-name is a combined construct. | ||
// | ||
// In the list of leaf constructs, find the first loop-associated construct, | ||
// this is the beginning of the returned range. Then, starting from the | ||
// immediately following leaf construct, find the first sequence of adjacent | ||
// loop-associated constructs. The last of those is the last one of the | ||
// range, that is, the end of the range is one past that element. | ||
// If such a sequence of adjacent loop-associated directives does not exist, | ||
// return an empty range. | ||
// | ||
// The end of the returned range (including empty range) is intended to be | ||
// a point from which the search for the next range could resume. | ||
// | ||
// Consequently, this function can't return a range with a single leaf | ||
// construct in it. | ||
|
||
auto firstLoopAssociated = | ||
[](iterator_range<ArrayRef<Directive>::iterator> List) { | ||
for (auto It = List.begin(), End = List.end(); It != End; ++It) { | ||
if (getDirectiveAssociation(*It) == Association::Loop) | ||
return It; | ||
} | ||
return List.end(); | ||
}; | ||
|
||
auto Empty = llvm::make_range(Leafs.end(), Leafs.end()); | ||
|
||
auto Begin = firstLoopAssociated(Leafs); | ||
if (Begin == Leafs.end()) | ||
return Empty; | ||
|
||
auto End = | ||
firstLoopAssociated(llvm::make_range(std::next(Begin), Leafs.end())); | ||
if (End == Leafs.end()) | ||
return Empty; | ||
|
||
for (; End != Leafs.end(); ++End) { | ||
if (getDirectiveAssociation(*End) != Association::Loop) | ||
break; | ||
} | ||
return llvm::make_range(Begin, End); | ||
} | ||
|
||
namespace llvm::omp { | ||
ArrayRef<Directive> getLeafConstructs(Directive D) { | ||
auto Idx = static_cast<std::size_t>(D); | ||
|
@@ -34,6 +82,44 @@ ArrayRef<Directive> getLeafConstructs(Directive D) { | |
return ArrayRef(&Row[2], static_cast<int>(Row[1])); | ||
} | ||
|
||
ArrayRef<Directive> getLeafConstructsOrSelf(Directive D) { | ||
if (auto Leafs = getLeafConstructs(D); !Leafs.empty()) | ||
return Leafs; | ||
auto Idx = static_cast<size_t>(D); | ||
assert(Idx < Directive_enumSize && "Invalid directive"); | ||
const auto *Row = LeafConstructTable[LeafConstructTableOrdering[Idx]]; | ||
// The first entry in the row is the directive itself. | ||
return ArrayRef(&Row[0], &Row[0] + 1); | ||
} | ||
|
||
ArrayRef<Directive> | ||
getLeafOrCompositeConstructs(Directive D, SmallVectorImpl<Directive> &Output) { | ||
using ArrayTy = ArrayRef<Directive>; | ||
using IteratorTy = ArrayTy::iterator; | ||
ArrayRef<Directive> Leafs = getLeafConstructsOrSelf(D); | ||
|
||
IteratorTy Iter = Leafs.begin(); | ||
do { | ||
auto Range = getFirstCompositeRange(llvm::make_range(Iter, Leafs.end())); | ||
// All directives before the range are leaf constructs. | ||
for (; Iter != Range.begin(); ++Iter) | ||
Output.push_back(*Iter); | ||
if (!Range.empty()) { | ||
Directive Comp = | ||
getCompoundConstruct(ArrayTy(Range.begin(), Range.end())); | ||
assert(Comp != OMPD_unknown); | ||
Output.push_back(Comp); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should check here that Do we need to return the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This starts with an actual directive We don't need to return
|
||
Iter = Range.end(); | ||
// As of now, a composite construct must contain all constituent leaf | ||
// constructs from some point until the end of all constituent leaf | ||
// constructs. | ||
assert(Iter == Leafs.end() && "Malformed directive"); | ||
} | ||
} while (Iter != Leafs.end()); | ||
|
||
return Output; | ||
} | ||
|
||
Directive getCompoundConstruct(ArrayRef<Directive> Parts) { | ||
if (Parts.empty()) | ||
return OMPD_unknown; | ||
|
@@ -88,20 +174,11 @@ Directive getCompoundConstruct(ArrayRef<Directive> Parts) { | |
bool isLeafConstruct(Directive D) { return getLeafConstructs(D).empty(); } | ||
|
||
bool isCompositeConstruct(Directive D) { | ||
// OpenMP Spec 5.2: [17.3, 8-9] | ||
// If directive-name-A and directive-name-B both correspond to loop- | ||
// associated constructs then directive-name is a composite construct | ||
llvm::ArrayRef<Directive> Leafs{getLeafConstructs(D)}; | ||
if (Leafs.empty()) | ||
return false; | ||
if (getDirectiveAssociation(Leafs.front()) != Association::Loop) | ||
ArrayRef<Directive> Leafs = getLeafConstructsOrSelf(D); | ||
if (Leafs.size() <= 1) | ||
return false; | ||
|
||
size_t numLoopConstructs = | ||
llvm::count_if(Leafs.drop_front(), [](Directive L) { | ||
return getDirectiveAssociation(L) == Association::Loop; | ||
}); | ||
return numLoopConstructs != 0; | ||
auto Range = getFirstCompositeRange(Leafs); | ||
return Range.begin() == Leafs.begin() && Range.end() == Leafs.end(); | ||
} | ||
|
||
bool isCombinedConstruct(Directive D) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My understanding is that there can only be at most a single composite construct when decomposing any given compound construct. So there wouldn't be a "first" composite range, but rather one composite range or none. In fact, if there is a composite range, it must also be at the end of the construct.
So, something like this:
<composite-construct><other-leaf>
can't happen. Decomposing a single compound construct into a list of leaves while keeping composite constructs as a unit should be as simple as forwarding all block-associated leaves until finding a loop-associated leaf and then aggregating (viagetCompoundConstruct()
) everything from there until the end of the leaf list to append one composite or single loop construct.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is intended to be a general utility to find the first sequence of leaf constructs that together constitute a composite construct. The input leafs aren't assumed to represent a legal construct.
It's also used in
isCompositeConstruct
as well, where I break up the given directive into leafs and check if the "first composite range" is equal to the sequence of leafs.Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any reason for these functions to allow unsupported lists of directives as input? I think it's worth having a simpler implementation over allowing all sorts of invalid lists of leaf constructs as input, unless there's a good reason why we'd need that.
Not saying that the compiler should crash in that case, but they can just return empty ranges for unsupported lists of leaf constructs rather than trying to find subsets that match what we're looking for.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I created the concept that this function implements as a common element in implementing other functions. This is a utility function that has a clearly defined functionality, that only depends on what is considered a "composite" construct. It is not an API function and it doesn't have to concern itself with validating the inputs, that's left to the API functions.
There are other ways to implement the breakdown of compound constructs, yours is likely another valid approach, but I've picked this one because of its flexibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you mean. It still feels a bit overkill to me, but I don't have a big issue with it since it's a private function to this compilation unit, so it's not a blocker.