LLVM: lib/CodeGen/BasicBlockSectionsProfileReader.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
30
31using namespace llvm;
32
35 "bbsections-profile-reader",
36 "Reads and parses a basic block sections profile.", false,
37 false)
38
42 S.split(Parts, '.');
43 if (Parts.size() > 2)
44 return createProfileParseError(Twine("unable to parse basic block id: '") +
45 S + "'");
46 unsigned long long BaseBBID;
48 return createProfileParseError(
49 Twine("unable to parse BB id: '" + Parts[0]) +
50 "': unsigned integer expected");
51 unsigned long long CloneID = 0;
53 return createProfileParseError(Twine("unable to parse clone id: '") +
54 Parts[1] + "': unsigned integer expected");
55 return UniqueBBID{static_cast<unsigned>(BaseBBID),
56 static_cast<unsigned>(CloneID)};
57}
58
61}
62
63std::pair<bool, SmallVector>
66 auto R = ProgramPathAndClusterInfo.find(getAliasName(FuncName));
67 return R != ProgramPathAndClusterInfo.end()
68 ? std::pair(true, R->second.ClusterInfo)
70}
71
75 return ProgramPathAndClusterInfo.lookup(getAliasName(FuncName)).ClonePaths;
76}
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133Error BasicBlockSectionsProfileReader::ReadV1Profile() {
134 auto FI = ProgramPathAndClusterInfo.end();
135
136
137 unsigned CurrentCluster = 0;
138
139 unsigned CurrentPosition = 0;
140
141
142
144
145
146
148
149 for (; !LineIt.is_at_eof(); ++LineIt) {
151 char Specifier = S[0];
152 S = S.drop_front().trim();
154 S.split(Values, ' ');
155 switch (Specifier) {
156 case '@':
157 continue;
158 case 'm':
159 if (Values.size() != 1) {
160 return createProfileParseError(Twine("invalid module name value: '") +
161 S + "'");
162 }
164 continue;
165 case 'f': {
166 bool FunctionFound = any_of(Values, [&](StringRef Alias) {
167 auto It = FunctionNameToDIFilename.find(Alias);
168
169 if (It == FunctionNameToDIFilename.end())
170 return false;
171
172
173 return DIFilename.empty() || It->second == DIFilename;
174 });
175 if (!FunctionFound) {
176
177
178 FI = ProgramPathAndClusterInfo.end();
179 DIFilename = "";
180 continue;
181 }
182 for (size_t i = 1; i < Values.size(); ++i)
183 FuncAliasMap.try_emplace(Values[i], Values.front());
184
185
186
187 auto R = ProgramPathAndClusterInfo.try_emplace(Values.front());
188
189
190 if (.second)
191 return createProfileParseError("duplicate profile for function '" +
192 Values.front() + "'");
193 FI = R.first;
194 CurrentCluster = 0;
195 FuncBBIDs.clear();
196
197
198 DIFilename = "";
199 continue;
200 }
201 case 'c':
202
203
204 if (FI == ProgramPathAndClusterInfo.end())
205 continue;
206
207 CurrentPosition = 0;
208 for (auto BasicBlockIDStr : Values) {
209 auto BasicBlockID = parseUniqueBBID(BasicBlockIDStr);
210 if (!BasicBlockID)
211 return BasicBlockID.takeError();
212 if (!FuncBBIDs.insert(*BasicBlockID).second)
213 return createProfileParseError(
214 Twine("duplicate basic block id found '") + BasicBlockIDStr +
215 "'");
216
217 FI->second.ClusterInfo.emplace_back(BBClusterInfo{
218 *std::move(BasicBlockID), CurrentCluster, CurrentPosition++});
219 }
220 CurrentCluster++;
221 continue;
222 case 'p': {
223
224
225 if (FI == ProgramPathAndClusterInfo.end())
226 continue;
228 FI->second.ClonePaths.push_back({});
229 for (size_t I = 0; I < Values.size(); ++I) {
230 auto BaseBBIDStr = Values[I];
231 unsigned long long BaseBBID = 0;
233 return createProfileParseError(Twine("unsigned integer expected: '") +
234 BaseBBIDStr + "'");
235 if (I != 0 && !BBsInPath.insert(BaseBBID).second)
236 return createProfileParseError(
237 Twine("duplicate cloned block in path: '") + BaseBBIDStr + "'");
238 FI->second.ClonePaths.back().push_back(BaseBBID);
239 }
240 continue;
241 }
242 default:
243 return createProfileParseError(Twine("invalid specifier: '") +
244 Twine(Specifier) + "'");
245 }
246 llvm_unreachable("should not break from this switch statement");
247 }
249}
250
251Error BasicBlockSectionsProfileReader::ReadV0Profile() {
252 auto FI = ProgramPathAndClusterInfo.end();
253
254 unsigned CurrentCluster = 0;
255
256 unsigned CurrentPosition = 0;
257
258
259
261
262 for (; !LineIt.is_at_eof(); ++LineIt) {
264 if (S[0] == '@')
265 continue;
266
267 if (!S.consume_front("!") || S.empty())
268 break;
269
270 if (S.consume_front("!")) {
271
272
273 if (FI == ProgramPathAndClusterInfo.end())
274 continue;
276 S.split(BBIDs, ' ');
277
278 CurrentPosition = 0;
279 for (auto BBIDStr : BBIDs) {
280 unsigned long long BBID;
282 return createProfileParseError(Twine("unsigned integer expected: '") +
283 BBIDStr + "'");
284 if (!FuncBBIDs.insert(BBID).second)
285 return createProfileParseError(
286 Twine("duplicate basic block id found '") + BBIDStr + "'");
287
288 FI->second.ClusterInfo.emplace_back(
290 CurrentCluster,
291 CurrentPosition++}));
292 }
293 CurrentCluster++;
294 } else {
295
296
297 auto [AliasesStr, DIFilenameStr] = S.split(' ');
299 if (DIFilenameStr.starts_with("M=")) {
300 DIFilename =
302 if (DIFilename.empty())
303 return createProfileParseError("empty module name specifier");
304 } else if (!DIFilenameStr.empty()) {
305 return createProfileParseError("unknown string found: '" +
306 DIFilenameStr + "'");
307 }
308
309
310
312 AliasesStr.split(Aliases, '/');
313 bool FunctionFound = any_of(Aliases, [&](StringRef Alias) {
314 auto It = FunctionNameToDIFilename.find(Alias);
315
316 if (It == FunctionNameToDIFilename.end())
317 return false;
318
319
320 return DIFilename.empty() || It->second == DIFilename;
321 });
322 if (!FunctionFound) {
323
324
325 FI = ProgramPathAndClusterInfo.end();
326 continue;
327 }
328 for (size_t i = 1; i < Aliases.size(); ++i)
329 FuncAliasMap.try_emplace(Aliases[i], Aliases.front());
330
331
332
333 auto R = ProgramPathAndClusterInfo.try_emplace(Aliases.front());
334
335
336 if (.second)
337 return createProfileParseError("duplicate profile for function '" +
338 Aliases.front() + "'");
339 FI = R.first;
340 CurrentCluster = 0;
341 FuncBBIDs.clear();
342 }
343 }
345}
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364Error BasicBlockSectionsProfileReader::ReadProfile() {
366
367 unsigned long long Version = 0;
369 if (FirstLine.consume_front("v")) {
371 return createProfileParseError(Twine("version number expected: '") +
372 FirstLine + "'");
373 }
375 return createProfileParseError(Twine("invalid profile version: ") +
377 }
378 ++LineIt;
379 }
380
382 case 0:
383
384 return ReadV0Profile();
385 case 1:
386 return ReadV1Profile();
387 default:
389 }
390}
391
394 return false;
395
396 BBSPR.FunctionNameToDIFilename.clear();
399 if (F.isDeclaration())
400 continue;
402 if (Subprogram) {
404 if (CU)
406 }
407 [[maybe_unused]] bool inserted =
408 BBSPR.FunctionNameToDIFilename.try_emplace(F.getName(), DIFilename)
409 .second;
411 }
412 if (auto Err = BBSPR.ReadProfile())
414 return false;
415}
416
418
423}
424
428}
429
430std::pair<bool, SmallVector>
434}
435
440}
441
445}
446
450}
This file defines the StringMap class.
This file defines the DenseSet and SmallDenseSet classes.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallSet class.
This file defines the SmallString class.
This file defines the SmallVector class.
A container for analyses that lazily runs them and caches their results.
Result run(Function &F, FunctionAnalysisManager &AM)
bool doInitialization(Module &M) override
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
BasicBlockSectionsProfileReader BBSPR
BasicBlockSectionsProfileReader & getBBSPR()
SmallVector< SmallVector< unsigned > > getClonePathsForFunction(StringRef FuncName) const
bool isFunctionHot(StringRef FuncName) const
std::pair< bool, SmallVector< BBClusterInfo > > getClusterInfoForFunction(StringRef FuncName) const
bool isFunctionHot(StringRef FuncName) const
std::pair< bool, SmallVector< BBClusterInfo > > getClusterInfoForFunction(StringRef FuncName) const
SmallVector< SmallVector< unsigned > > getClonePathsForFunction(StringRef FuncName) const
Implements a dense probed hash-table based set.
Lightweight error class with error context and mandatory checking.
static ErrorSuccess success()
Create a success value.
Tagged union holding either a T or a Error.
ImmutablePass class - This class is used to provide information that does not need to be run.
This interface provides simple read-only access to a block of memory, and provides simple methods for...
A Module instance is used to store all the information related to an LLVM module.
SmallSet - This maintains a set of unique values, optimizing for the case when the set is small (less...
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
const MemoryBuffer * getBBSectionsFuncListBuf() const
Get the list of functions and basic block ids that need unique sections.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
std::pair< iterator, bool > insert(const ValueT &V)
bool is_at_eof() const
Return true if we've reached EOF or are an "end" iterator.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
StringRef remove_leading_dotslash(StringRef path LLVM_LIFETIME_BOUND, Style style=Style::native)
Remove redundant leading "./" pieces and consecutive separators.
This is an optimization pass for GlobalISel generic memory operations.
ImmutablePass * createBasicBlockSectionsProfileReaderWrapperPass(const MemoryBuffer *Buf)
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
bool getAsUnsignedInteger(StringRef Str, unsigned Radix, unsigned long long &Result)
Helper functions for StringRef::getAsInteger.
Implement std::hash so that hash_code can be used in STL containers.
A special type used by analysis passes to provide an address that identifies that particular analysis...