LLVM 20.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/STLExtras.h"
15#include "llvm/ADT/StringRef.h"
21
22#include <algorithm>
23#include <cstdio>
24#include <iterator>
25#include <string>
26#include <type_traits>
27
28using namespace llvm;
29using namespace llvm::omp;
30
31#define GEN_DIRECTIVES_IMPL
32#include "llvm/Frontend/OpenMP/OMP.inc"
33
36 // OpenMP Spec 5.2: [17.3, 8-9]
37 // If directive-name-A and directive-name-B both correspond to loop-
38 // associated constructs then directive-name is a composite construct
39 // otherwise directive-name is a combined construct.
40 //
41 // In the list of leaf constructs, find the first loop-associated construct,
42 // this is the beginning of the returned range. Then, starting from the
43 // immediately following leaf construct, find the first sequence of adjacent
44 // loop-associated constructs. The last of those is the last one of the
45 // range, that is, the end of the range is one past that element.
46 // If such a sequence of adjacent loop-associated directives does not exist,
47 // return an empty range.
48 //
49 // The end of the returned range (including empty range) is intended to be
50 // a point from which the search for the next range could resume.
51 //
52 // Consequently, this function can't return a range with a single leaf
53 // construct in it.
54
55 auto firstLoopAssociated =
57 for (auto It = List.begin(), End = List.end(); It != End; ++It) {
58 if (getDirectiveAssociation(*It) == Association::Loop)
59 return It;
60 }
61 return List.end();
62 };
63
64 auto Empty = llvm::make_range(Leafs.end(), Leafs.end());
65
66 auto Begin = firstLoopAssociated(Leafs);
67 if (Begin == Leafs.end())
68 return Empty;
69
70 auto End =
71 firstLoopAssociated(llvm::make_range(std::next(Begin), Leafs.end()));
72 if (End == Leafs.end())
73 return Empty;
74
75 for (; End != Leafs.end(); ++End) {
76 if (getDirectiveAssociation(*End) != Association::Loop)
77 break;
78 }
79 return llvm::make_range(Begin, End);
80}
81
82namespace llvm::omp {
84 auto Idx = static_cast<std::size_t>(D);
85 if (Idx >= Directive_enumSize)
86 return std::nullopt;
87 const auto *Row = LeafConstructTable[LeafConstructTableOrdering[Idx]];
88 return ArrayRef(&Row[2], static_cast<int>(Row[1]));
89}
90
92 if (auto Leafs = getLeafConstructs(D); !Leafs.empty())
93 return Leafs;
94 auto Idx = static_cast<size_t>(D);
95 assert(Idx < Directive_enumSize && "Invalid directive");
96 const auto *Row = LeafConstructTable[LeafConstructTableOrdering[Idx]];
97 // The first entry in the row is the directive itself.
98 return ArrayRef(&Row[0], &Row[0] + 1);
99}
100
103 using ArrayTy = ArrayRef<Directive>;
104 using IteratorTy = ArrayTy::iterator;
106
107 IteratorTy Iter = Leafs.begin();
108 do {
109 auto Range = getFirstCompositeRange(llvm::make_range(Iter, Leafs.end()));
110 // All directives before the range are leaf constructs.
111 for (; Iter != Range.begin(); ++Iter)
112 Output.push_back(*Iter);
113 if (!Range.empty()) {
114 Directive Comp =
115 getCompoundConstruct(ArrayTy(Range.begin(), Range.end()));
116 assert(Comp != OMPD_unknown);
117 Output.push_back(Comp);
118 Iter = Range.end();
119 // As of now, a composite construct must contain all constituent leaf
120 // constructs from some point until the end of all constituent leaf
121 // constructs.
122 assert(Iter == Leafs.end() && "Malformed directive");
123 }
124 } while (Iter != Leafs.end());
125
126 return Output;
127}
128
130 if (Parts.empty())
131 return OMPD_unknown;
132
133 // Parts don't have to be leafs, so expand them into leafs first.
134 // Store the expanded leafs in the same format as rows in the leaf
135 // table (generated by tablegen).
136 SmallVector<Directive> RawLeafs(2);
137 for (Directive P : Parts) {
139 if (!Ls.empty())
140 RawLeafs.append(Ls.begin(), Ls.end());
141 else
142 RawLeafs.push_back(P);
143 }
144
145 // RawLeafs will be used as key in the binary search. The search doesn't
146 // guarantee that the exact same entry will be found (since RawLeafs may
147 // not correspond to any compound directive). Because of that, we will
148 // need to compare the search result with the given set of leafs.
149 // Also, if there is only one leaf in the list, it corresponds to itself,
150 // no search is necessary.
151 auto GivenLeafs{ArrayRef<Directive>(RawLeafs).drop_front(2)};
152 if (GivenLeafs.size() == 1)
153 return GivenLeafs.front();
154 RawLeafs[1] = static_cast<Directive>(GivenLeafs.size());
155
156 auto Iter = std::lower_bound(
157 LeafConstructTable, LeafConstructTableEndDirective,
158 static_cast<std::decay_t<decltype(*LeafConstructTable)>>(RawLeafs.data()),
159 [](const llvm::omp::Directive *RowA, const llvm::omp::Directive *RowB) {
160 const auto *BeginA = &RowA[2];
161 const auto *EndA = BeginA + static_cast<int>(RowA[1]);
162 const auto *BeginB = &RowB[2];
163 const auto *EndB = BeginB + static_cast<int>(RowB[1]);
164 if (BeginA == EndA && BeginB == EndB)
165 return static_cast<int>(RowA[0]) < static_cast<int>(RowB[0]);
166 return std::lexicographical_compare(BeginA, EndA, BeginB, EndB);
167 });
168
169 if (Iter == std::end(LeafConstructTable))
170 return OMPD_unknown;
171
172 // Verify that we got a match.
173 Directive Found = (*Iter)[0];
174 ArrayRef<Directive> FoundLeafs = getLeafConstructs(Found);
175 if (FoundLeafs == GivenLeafs)
176 return Found;
177 return OMPD_unknown;
178}
179
181
184 if (Leafs.size() <= 1)
185 return false;
186 auto Range = getFirstCompositeRange(Leafs);
187 return Range.begin() == Leafs.begin() && Range.end() == Leafs.end();
188}
189
191 // OpenMP Spec 5.2: [17.3, 9-10]
192 // Otherwise directive-name is a combined construct.
193 return !getLeafConstructs(D).empty() && !isCompositeConstruct(D);
194}
195
196std::string prettifyFunctionName(StringRef FunctionName) {
197 // Internalized functions have the right name, but simply a suffix.
198 if (FunctionName.ends_with(".internalized"))
199 return FunctionName.drop_back(sizeof("internalized")).str() +
200 " (internalized)";
201 unsigned LineNo = 0;
202 auto ParentName = deconstructOpenMPKernelName(FunctionName, LineNo);
203 if (LineNo == 0)
204 return FunctionName.str();
205 return ("omp target in " + ParentName + " @ " + std::to_string(LineNo) +
206 " (" + FunctionName + ")")
207 .str();
208}
209
211 unsigned &LineNo) {
212
213 // Only handle functions with an OpenMP kernel prefix for now. Naming scheme:
214 // __omp_offloading_<hex_hash1>_<hex_hash2>_<name>_l<line>_[<count>_]<suffix>
216 return "";
217
218 auto PrettyName = KernelName.drop_front(
219 sizeof(TargetRegionEntryInfo::KernelNamePrefix) - /*'\0'*/ 1);
220 for (int I = 0; I < 3; ++I) {
221 PrettyName = PrettyName.drop_while([](char c) { return c != '_'; });
222 PrettyName = PrettyName.drop_front();
223 }
224
225 // Look for the last '_l<line>'.
226 size_t LineIdx = PrettyName.rfind("_l");
227 if (LineIdx == StringRef::npos)
228 return "";
229 if (PrettyName.drop_front(LineIdx + 2).consumeInteger(10, LineNo))
230 return "";
231 return demangle(PrettyName.take_front(LineIdx));
232}
233} // namespace llvm::omp
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
bool End
Definition: ELF_riscv.cpp:480
#define I(x, y, z)
Definition: MD5.cpp:58
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static iterator_range< ArrayRef< Directive >::iterator > getFirstCompositeRange(iterator_range< ArrayRef< Directive >::iterator > Leafs)
Definition: OMP.cpp:35
#define P(N)
const NodeList & List
Definition: RDFGraph.cpp:201
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file contains some templates that are useful if you are working with the STL at all.
This file defines the SmallString class.
This file defines the SmallVector class.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
Definition: ArrayRef.h:204
iterator end() const
Definition: ArrayRef.h:154
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:165
iterator begin() const
Definition: ArrayRef.h:153
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:160
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:586
void append(ItTy in_start, ItTy in_end)
Add the specified range to the end of the SmallVector.
Definition: SmallVector.h:696
void push_back(const T &Elt)
Definition: SmallVector.h:426
pointer data()
Return a pointer to the vector's buffer, even if empty().
Definition: SmallVector.h:299
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1209
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
std::string str() const
str - Get the contents as an std::string.
Definition: StringRef.h:215
bool starts_with(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:250
StringRef drop_front(size_t N=1) const
Return a StringRef equal to 'this' but with the first N elements dropped.
Definition: StringRef.h:594
size_t rfind(char C, size_t From=npos) const
Search for the last character C in the string.
Definition: StringRef.h:332
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
Definition: StringRef.h:262
static constexpr size_t npos
Definition: StringRef.h:52
StringRef drop_while(function_ref< bool(char)> F) const
Return a StringRef equal to 'this', but with all characters satisfying the given predicate dropped fr...
Definition: StringRef.h:608
StringRef drop_back(size_t N=1) const
Return a StringRef equal to 'this' but with the last N elements dropped.
Definition: StringRef.h:601
A range adaptor for a pair of iterators.
Definition: OMP.h:22
bool isCombinedConstruct(Directive D)
Definition: OMP.cpp:190
std::string deconstructOpenMPKernelName(StringRef KernelName, unsigned &LineNo)
Deconstruct an OpenMP kernel name into the parent function name and the line number.
Definition: OMP.cpp:210
ArrayRef< Directive > getLeafOrCompositeConstructs(Directive D, SmallVectorImpl< Directive > &Output)
Definition: OMP.cpp:102
bool isCompositeConstruct(Directive D)
Definition: OMP.cpp:182
Directive getCompoundConstruct(ArrayRef< Directive > Parts)
Definition: OMP.cpp:129
bool isLeafConstruct(Directive D)
Definition: OMP.cpp:180
ArrayRef< Directive > getLeafConstructsOrSelf(Directive D)
Definition: OMP.cpp:91
std::string prettifyFunctionName(StringRef FunctionName)
Create a nicer version of a function name for humans to look at.
Definition: OMP.cpp:196
ArrayRef< Directive > getLeafConstructs(Directive D)
Definition: OMP.cpp:83
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
std::string demangle(std::string_view MangledName)
Attempt to demangle a string using different demangling schemes.
Definition: Demangle.cpp:20
static constexpr const char * KernelNamePrefix
The prefix used for kernel names.
Definition: OMPIRBuilder.h:204