LLVM 24.0.0git
OMP.cpp
Go to the documentation of this file.
1//===- OMP.cpp ------ Collection of helpers for OpenMP --------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
11#include "llvm/ADT/ArrayRef.h"
12#include "llvm/ADT/Sequence.h"
13#include "llvm/ADT/SmallSet.h"
15#include "llvm/ADT/StringRef.h"
19
20#include <algorithm>
21#include <cstdio>
22#include <iterator>
23#include <string>
24#include <type_traits>
25
26using namespace llvm;
27using namespace llvm::omp;
28
29#define GEN_DIRECTIVES_IMPL
30#include "llvm/Frontend/OpenMP/OMP.inc"
31
34 // OpenMP Spec 5.2: [17.3, 8-9]
35 // If directive-name-A and directive-name-B both correspond to loop-
36 // associated constructs then directive-name is a composite construct
37 // otherwise directive-name is a combined construct.
38 //
39 // In the list of leaf constructs, find the first loop-associated construct,
40 // this is the beginning of the returned range. Then, starting from the
41 // immediately following leaf construct, find the first sequence of adjacent
42 // loop-associated constructs. The last of those is the last one of the
43 // range, that is, the end of the range is one past that element.
44 // If such a sequence of adjacent loop-associated directives does not exist,
45 // return an empty range.
46 //
47 // The end of the returned range (including empty range) is intended to be
48 // a point from which the search for the next range could resume.
49 //
50 // Consequently, this function can't return a range with a single leaf
51 // construct in it.
52
53 auto firstLoopAssociated =
55 for (auto It = List.begin(), End = List.end(); It != End; ++It) {
56 if (getDirectiveAssociation(*It) == Association::LoopNest)
57 return It;
58 }
59 return List.end();
60 };
61
62 auto Empty = llvm::make_range(Leafs.end(), Leafs.end());
63
64 auto Begin = firstLoopAssociated(Leafs);
65 if (Begin == Leafs.end())
66 return Empty;
67
68 auto End =
69 firstLoopAssociated(llvm::make_range(std::next(Begin), Leafs.end()));
70 if (End == Leafs.end())
71 return Empty;
72
73 for (; End != Leafs.end(); ++End) {
74 if (getDirectiveAssociation(*End) != Association::LoopNest)
75 break;
76 }
77 return llvm::make_range(Begin, End);
78}
79
80static void
82 unsigned Version) {
84 for (auto C : clauses()) {
85 if (isPrivatizingClause(C, Version))
86 Privatizing.insert(C);
87 }
88
89 for (auto D : directives()) {
90 bool AllowsPrivatizing = llvm::any_of(Privatizing, [&](Clause C) {
91 return isAllowedClauseForDirective(D, C, Version);
92 });
93 if (AllowsPrivatizing)
94 Constructs.insert(D);
95 }
96}
97
98namespace llvm::omp {
100 auto Idx = static_cast<std::size_t>(D);
101 if (Idx >= Directive_enumSize)
102 return {};
103 const auto *Row = LeafConstructTable[LeafConstructTableOrdering[Idx]];
104 return ArrayRef(&Row[2], static_cast<int>(Row[1]));
105}
106
108 if (auto Leafs = getLeafConstructs(D); !Leafs.empty())
109 return Leafs;
110 auto Idx = static_cast<size_t>(D);
111 assert(Idx < Directive_enumSize && "Invalid directive");
112 const auto *Row = LeafConstructTable[LeafConstructTableOrdering[Idx]];
113 // The first entry in the row is the directive itself.
114 return ArrayRef(&Row[0], &Row[0] + 1);
115}
116
119 using ArrayTy = ArrayRef<Directive>;
120 using IteratorTy = ArrayTy::iterator;
122
123 IteratorTy Iter = Leafs.begin();
124 do {
125 auto Range = getFirstCompositeRange(llvm::make_range(Iter, Leafs.end()));
126 // All directives before the range are leaf constructs.
127 for (; Iter != Range.begin(); ++Iter)
128 Output.push_back(*Iter);
129 if (!Range.empty()) {
130 Directive Comp =
131 getCompoundConstruct(ArrayTy(Range.begin(), Range.end()));
132 assert(Comp != OMPD_unknown);
133 Output.push_back(Comp);
134 Iter = Range.end();
135 // As of now, a composite construct must contain all constituent leaf
136 // constructs from some point until the end of all constituent leaf
137 // constructs.
138 assert(Iter == Leafs.end() && "Malformed directive");
139 }
140 } while (Iter != Leafs.end());
141
142 return Output;
143}
144
146 if (Parts.empty())
147 return OMPD_unknown;
148
149 // Parts don't have to be leafs, so expand them into leafs first.
150 // Store the expanded leafs in the same format as rows in the leaf
151 // table (generated by tablegen).
152 SmallVector<Directive> RawLeafs(2);
153 for (Directive P : Parts) {
155 if (!Ls.empty())
156 RawLeafs.append(Ls.begin(), Ls.end());
157 else
158 RawLeafs.push_back(P);
159 }
160
161 // RawLeafs will be used as key in the binary search. The search doesn't
162 // guarantee that the exact same entry will be found (since RawLeafs may
163 // not correspond to any compound directive). Because of that, we will
164 // need to compare the search result with the given set of leafs.
165 // Also, if there is only one leaf in the list, it corresponds to itself,
166 // no search is necessary.
167 auto GivenLeafs{ArrayRef<Directive>(RawLeafs).drop_front(2)};
168 if (GivenLeafs.size() == 1)
169 return GivenLeafs.front();
170 RawLeafs[1] = static_cast<Directive>(GivenLeafs.size());
171
172 auto Iter = std::lower_bound(
173 LeafConstructTable, LeafConstructTableEndDirective,
174 static_cast<std::decay_t<decltype(*LeafConstructTable)>>(RawLeafs.data()),
175 [](const llvm::omp::Directive *RowA, const llvm::omp::Directive *RowB) {
176 const auto *BeginA = &RowA[2];
177 const auto *EndA = BeginA + static_cast<int>(RowA[1]);
178 const auto *BeginB = &RowB[2];
179 const auto *EndB = BeginB + static_cast<int>(RowB[1]);
180 if (BeginA == EndA && BeginB == EndB)
181 return static_cast<int>(RowA[0]) < static_cast<int>(RowB[0]);
182 return std::lexicographical_compare(BeginA, EndA, BeginB, EndB);
183 });
184
185 if (Iter == std::end(LeafConstructTable))
186 return OMPD_unknown;
187
188 // Verify that we got a match.
189 Directive Found = (*Iter)[0];
190 ArrayRef<Directive> FoundLeafs = getLeafConstructs(Found);
191 if (FoundLeafs == GivenLeafs)
192 return Found;
193 return OMPD_unknown;
194}
195
197
200 if (Leafs.size() <= 1)
201 return false;
202 auto Range = getFirstCompositeRange(Leafs);
203 return Range.begin() == Leafs.begin() && Range.end() == Leafs.end();
204}
205
207 // OpenMP Spec 5.2: [17.3, 9-10]
208 // Otherwise directive-name is a combined construct.
209 return !getLeafConstructs(D).empty() && !isCompositeConstruct(D);
210}
211
213 static unsigned Versions[]{31, 40, 45, 50, 51, 52, 60, 61};
214 return Versions;
215}
216
218 static llvm::SmallSet<Directive, 16> Privatizing;
219 [[maybe_unused]] static bool Init =
220 (collectPrivatizingConstructs(Privatizing, Version), true);
221
222 // As of OpenMP 6.0, privatizing constructs (with the test being if they
223 // allow a privatizing clause) are: dispatch, distribute, do, for, loop,
224 // parallel, scope, sections, simd, single, target, target_data, task,
225 // taskgroup, taskloop, and teams.
226 return llvm::is_contained(Privatizing, D);
227}
228
230 // All names must be lowercase.
231 static StringRef names[]{"omp_all_memory"};
232 return names;
233}
234
235std::string prettifyFunctionName(StringRef FunctionName) {
236 // Internalized functions have the right name, but simply a suffix.
237 if (FunctionName.ends_with(".internalized"))
238 return FunctionName.drop_back(sizeof("internalized")).str() +
239 " (internalized)";
240 unsigned LineNo = 0;
241 auto ParentName = deconstructOpenMPKernelName(FunctionName, LineNo);
242 if (LineNo == 0)
243 return FunctionName.str();
244 return ("omp target in " + ParentName + " @ " + std::to_string(LineNo) +
245 " (" + FunctionName + ")")
246 .str();
247}
248
250 unsigned &LineNo) {
251
252 // Only handle functions with an OpenMP kernel prefix for now. Naming scheme:
253 // __omp_offloading_<hex_hash1>_<hex_hash2>_<name>_l<line>_[<count>_]<suffix>
255 return "";
256
257 auto PrettyName = KernelName.drop_front(
258 sizeof(TargetRegionEntryInfo::KernelNamePrefix) - /*'\0'*/ 1);
259 for (int I = 0; I < 3; ++I) {
260 PrettyName = PrettyName.drop_while([](char c) { return c != '_'; });
261 PrettyName = PrettyName.drop_front();
262 }
263
264 // Look for the last '_l<line>'.
265 size_t LineIdx = PrettyName.rfind("_l");
266 if (LineIdx == StringRef::npos)
267 return "";
268 if (PrettyName.drop_front(LineIdx + 2).consumeInteger(10, LineNo))
269 return "";
270 return demangle(PrettyName.take_front(LineIdx));
271}
272} // namespace llvm::omp
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
#define I(x, y, z)
Definition MD5.cpp:57
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static iterator_range< ArrayRef< Directive >::iterator > getFirstCompositeRange(iterator_range< ArrayRef< Directive >::iterator > Leafs)
Definition OMP.cpp:33
static void collectPrivatizingConstructs(llvm::SmallSet< Directive, 16 > &Constructs, unsigned Version)
Definition OMP.cpp:81
#define P(N)
Provides some synthesis utilities to produce sequences of values.
This file defines the SmallSet class.
This file defines the SmallVector class.
LocallyHashedType DenseMapInfo< LocallyHashedType >::Empty
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
iterator end() const
Definition ArrayRef.h:130
size_t size() const
Get the array size.
Definition ArrayRef.h:141
const_pointer iterator
Definition ArrayRef.h:47
iterator begin() const
Definition ArrayRef.h:129
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
Definition SmallSet.h:134
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:184
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
void push_back(const T &Elt)
pointer data()
Return a pointer to the vector's buffer, even if empty().
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
static constexpr size_t npos
Definition StringRef.h:58
std::string str() const
Get the contents as an std::string.
Definition StringRef.h:222
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition StringRef.h:258
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition StringRef.h:635
size_t rfind(char C, size_t From=npos) const
Search for the last character C in the string.
Definition StringRef.h:365
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Definition StringRef.h:270
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
Definition StringRef.h:642
A range adaptor for a pair of iterators.
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
static constexpr auto clauses()
Definition OMP.h:37
LLVM_ABI ArrayRef< unsigned > getOpenMPVersions()
Definition OMP.cpp:212
LLVM_ABI bool isCombinedConstruct(Directive D)
Definition OMP.cpp:206
LLVM_ABI std::string deconstructOpenMPKernelName(StringRef KernelName, unsigned &LineNo)
Deconstruct an OpenMP kernel name into the parent function name and the line number.
Definition OMP.cpp:249
LLVM_ABI ArrayRef< Directive > getLeafOrCompositeConstructs(Directive D, SmallVectorImpl< Directive > &Output)
Definition OMP.cpp:118
LLVM_ABI bool isPrivatizingConstruct(Directive D, unsigned Version)
Can directive D, under some circumstances, create a private copy of a variable in given OpenMP versio...
Definition OMP.cpp:217
LLVM_ABI bool isCompositeConstruct(Directive D)
Definition OMP.cpp:198
LLVM_ABI Directive getCompoundConstruct(ArrayRef< Directive > Parts)
Definition OMP.cpp:145
LLVM_ABI ArrayRef< StringRef > getReservedLocatorNames()
Definition OMP.cpp:229
LLVM_ABI bool isLeafConstruct(Directive D)
Definition OMP.cpp:196
LLVM_ABI ArrayRef< Directive > getLeafConstructsOrSelf(Directive D)
Definition OMP.cpp:107
LLVM_ABI std::string prettifyFunctionName(StringRef FunctionName)
Create a nicer version of a function name for humans to look at.
Definition OMP.cpp:235
static constexpr auto directives()
Definition OMP.h:41
LLVM_ABI ArrayRef< Directive > getLeafConstructs(Directive D)
Definition OMP.cpp:99
static constexpr bool isPrivatizingClause(Clause C, unsigned Version)
Definition OMP.h:61
This is an optimization pass for GlobalISel generic memory operations.
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1746
ArrayRef(const T &OneElt) -> ArrayRef< T >
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
DEMANGLE_ABI std::string demangle(std::string_view MangledName)
Attempt to demangle a string using different demangling schemes.
Definition Demangle.cpp:21
static constexpr const char * KernelNamePrefix
The prefix used for kernel names.