LLVM: lib/CodeGen/BasicBlockSectionsProfileReader.cpp Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
31
32using namespace llvm;
33
36 "bbsections-profile-reader",
37 "Reads and parses a basic block sections profile.", false,
38 false)
39
43 S.split(Parts, '.');
44 if (Parts.size() > 2)
45 return createProfileParseError(Twine("unable to parse basic block id: '") +
46 S + "'");
47 unsigned long long BaseBBID;
49 return createProfileParseError(
50 Twine("unable to parse BB id: '" + Parts[0]) +
51 "': unsigned integer expected");
52 unsigned long long CloneID = 0;
54 return createProfileParseError(Twine("unable to parse clone id: '") +
55 Parts[1] + "': unsigned integer expected");
56 return UniqueBBID{static_cast<unsigned>(BaseBBID),
57 static_cast<unsigned>(CloneID)};
58}
59
62}
63
67 auto R = ProgramPathAndClusterInfo.find(getAliasName(FuncName));
68 return R != ProgramPathAndClusterInfo.end() ? R->second.ClusterInfo
70}
71
75 auto R = ProgramPathAndClusterInfo.find(getAliasName(FuncName));
76 return R != ProgramPathAndClusterInfo.end()
77 ? R->second.ClonePaths
79}
80
84 auto It = ProgramPathAndClusterInfo.find(getAliasName(FuncName));
85 if (It == ProgramPathAndClusterInfo.end())
86 return 0;
87 auto NodeIt = It->second.EdgeCounts.find(SrcBBID);
88 if (NodeIt == It->second.EdgeCounts.end())
89 return 0;
90 auto EdgeIt = NodeIt->second.find(SinkBBID);
91 if (EdgeIt == NodeIt->second.end())
92 return 0;
93 return EdgeIt->second;
94}
95
96std::pair<bool, FunctionPathAndClusterInfo>
99 auto R = ProgramPathAndClusterInfo.find(getAliasName(FuncName));
100 return R != ProgramPathAndClusterInfo.end()
101 ? std::pair(true, R->second)
102 : std::pair(false, FunctionPathAndClusterInfo());
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160Error BasicBlockSectionsProfileReader::ReadV1Profile() {
161 auto FI = ProgramPathAndClusterInfo.end();
162
163
164 unsigned CurrentCluster = 0;
165
166 unsigned CurrentPosition = 0;
167
168
169
170 DenseSet FuncBBIDs;
171
172
173
174 StringRef DIFilename;
175
176 for (; !LineIt.is_at_eof(); ++LineIt) {
177 StringRef S(*LineIt);
179 S = S.drop_front().trim();
181 S.split(Values, ' ');
182 switch (Specifier) {
183 case '@':
184 continue;
185 case 'm':
186 if (Values.size() != 1) {
187 return createProfileParseError(Twine("invalid module name value: '") +
188 S + "'");
189 }
191 continue;
192 case 'f': {
193 bool FunctionFound = any_of(Values, [&](StringRef Alias) {
194 auto It = FunctionNameToDIFilename.find(Alias);
195
196 if (It == FunctionNameToDIFilename.end())
197 return false;
198
199
200 return DIFilename.empty() || It->second == DIFilename;
201 });
202 if (!FunctionFound) {
203
204
205 FI = ProgramPathAndClusterInfo.end();
206 DIFilename = "";
207 continue;
208 }
209 for (size_t i = 1; i < Values.size(); ++i)
210 FuncAliasMap.try_emplace(Values[i], Values.front());
211
212
213
214 auto R = ProgramPathAndClusterInfo.try_emplace(Values.front());
215
216
217 if (.second)
218 return createProfileParseError("duplicate profile for function '" +
219 Values.front() + "'");
220 FI = R.first;
221 CurrentCluster = 0;
222 FuncBBIDs.clear();
223
224
225 DIFilename = "";
226 continue;
227 }
228 case 'c':
229
230
231 if (FI == ProgramPathAndClusterInfo.end())
232 continue;
233
234 CurrentPosition = 0;
235 for (auto BasicBlockIDStr : Values) {
236 auto BasicBlockID = parseUniqueBBID(BasicBlockIDStr);
237 if (!BasicBlockID)
238 return BasicBlockID.takeError();
239 if (!FuncBBIDs.insert(*BasicBlockID).second)
240 return createProfileParseError(
241 Twine("duplicate basic block id found '") + BasicBlockIDStr +
242 "'");
243
244 FI->second.ClusterInfo.emplace_back(BBClusterInfo{
245 *std::move(BasicBlockID), CurrentCluster, CurrentPosition++});
246 }
247 CurrentCluster++;
248 continue;
249 case 'p': {
250
251
252 if (FI == ProgramPathAndClusterInfo.end())
253 continue;
254 SmallSet<unsigned, 5> BBsInPath;
255 FI->second.ClonePaths.push_back({});
256 for (size_t I = 0; I < Values.size(); ++I) {
257 auto BaseBBIDStr = Values[I];
258 unsigned long long BaseBBID = 0;
260 return createProfileParseError(Twine("unsigned integer expected: '") +
261 BaseBBIDStr + "'");
262 if (I != 0 && !BBsInPath.insert(BaseBBID).second)
263 return createProfileParseError(
264 Twine("duplicate cloned block in path: '") + BaseBBIDStr + "'");
265 FI->second.ClonePaths.back().push_back(BaseBBID);
266 }
267 continue;
268 }
269 case 'g': {
270
271
272 if (FI == ProgramPathAndClusterInfo.end())
273 continue;
274
275
276 for (auto BasicBlockEdgeProfile : Values) {
277 if (BasicBlockEdgeProfile.empty())
278 continue;
280 BasicBlockEdgeProfile.split(NodeEdgeCounts, ',');
281 UniqueBBID SrcBBID;
282 for (size_t i = 0; i < NodeEdgeCounts.size(); ++i) {
283 auto [BBIDStr, CountStr] = NodeEdgeCounts[i].split(':');
284 auto BBID = parseUniqueBBID(BBIDStr);
285 if (!BBID)
286 return BBID.takeError();
287 unsigned long long Count = 0;
289 return createProfileParseError(
290 Twine("unsigned integer expected: '") + CountStr + "'");
291 if (i == 0) {
292
293 FI->second.NodeCounts[SrcBBID = *BBID] = Count;
294 continue;
295 }
296 FI->second.EdgeCounts[SrcBBID][*BBID] = Count;
297 }
298 }
299 continue;
300 }
301 case 'h': {
302
303
304 if (FI == ProgramPathAndClusterInfo.end())
305 continue;
306 for (auto BBIDHashStr : Values) {
307 auto [BBIDStr, HashStr] = BBIDHashStr.split(':');
308 unsigned long long BBID = 0, Hash = 0;
310 return createProfileParseError(Twine("unsigned integer expected: '") +
311 BBIDStr + "'");
313 return createProfileParseError(
314 Twine("unsigned integer expected in hex format: '") + HashStr +
315 "'");
316 FI->second.BBHashes[BBID] = Hash;
317 }
318 continue;
319 }
320 default:
321 return createProfileParseError(Twine("invalid specifier: '") +
322 Twine(Specifier) + "'");
323 }
324 llvm_unreachable("should not break from this switch statement");
325 }
327}
328
329Error BasicBlockSectionsProfileReader::ReadV0Profile() {
330 auto FI = ProgramPathAndClusterInfo.end();
331
332 unsigned CurrentCluster = 0;
333
334 unsigned CurrentPosition = 0;
335
336
337
338 SmallSet<unsigned, 4> FuncBBIDs;
339
340 for (; !LineIt.is_at_eof(); ++LineIt) {
341 StringRef S(*LineIt);
342 if (S[0] == '@')
343 continue;
344
345 if (!S.consume_front("!") || S.empty())
346 break;
347
348 if (S.consume_front("!")) {
349
350
351 if (FI == ProgramPathAndClusterInfo.end())
352 continue;
354 S.split(BBIDs, ' ');
355
356 CurrentPosition = 0;
357 for (auto BBIDStr : BBIDs) {
358 unsigned long long BBID;
360 return createProfileParseError(Twine("unsigned integer expected: '") +
361 BBIDStr + "'");
362 if (!FuncBBIDs.insert(BBID).second)
363 return createProfileParseError(
364 Twine("duplicate basic block id found '") + BBIDStr + "'");
365
366 FI->second.ClusterInfo.emplace_back(
367 BBClusterInfo({{static_cast<unsigned>(BBID), 0},
368 CurrentCluster,
369 CurrentPosition++}));
370 }
371 CurrentCluster++;
372 } else {
373
374
375 auto [AliasesStr, DIFilenameStr] = S.split(' ');
376 SmallString<128> DIFilename;
377 if (DIFilenameStr.starts_with("M=")) {
378 DIFilename =
380 if (DIFilename.empty())
381 return createProfileParseError("empty module name specifier");
382 } else if (!DIFilenameStr.empty()) {
383 return createProfileParseError("unknown string found: '" +
384 DIFilenameStr + "'");
385 }
386
387
388
390 AliasesStr.split(Aliases, '/');
391 bool FunctionFound = any_of(Aliases, [&](StringRef Alias) {
392 auto It = FunctionNameToDIFilename.find(Alias);
393
394 if (It == FunctionNameToDIFilename.end())
395 return false;
396
397
398 return DIFilename.empty() || It->second == DIFilename;
399 });
400 if (!FunctionFound) {
401
402
403 FI = ProgramPathAndClusterInfo.end();
404 continue;
405 }
406 for (size_t i = 1; i < Aliases.size(); ++i)
407 FuncAliasMap.try_emplace(Aliases[i], Aliases.front());
408
409
410
411 auto R = ProgramPathAndClusterInfo.try_emplace(Aliases.front());
412
413
414 if (.second)
415 return createProfileParseError("duplicate profile for function '" +
416 Aliases.front() + "'");
417 FI = R.first;
418 CurrentCluster = 0;
419 FuncBBIDs.clear();
420 }
421 }
423}
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442Error BasicBlockSectionsProfileReader::ReadProfile() {
444
445 unsigned long long Version = 0;
446 StringRef FirstLine(*LineIt);
447 if (FirstLine.consume_front("v")) {
449 return createProfileParseError(Twine("version number expected: '") +
450 FirstLine + "'");
451 }
453 return createProfileParseError(Twine("invalid profile version: ") +
455 }
456 ++LineIt;
457 }
458
460 case 0:
461
462 return ReadV0Profile();
463 case 1:
464 return ReadV1Profile();
465 default:
467 }
468}
469
472 return false;
473
474 BBSPR.FunctionNameToDIFilename.clear();
477 if (F.isDeclaration())
478 continue;
480 if (Subprogram) {
482 if (CU)
484 }
485 [[maybe_unused]] bool inserted =
486 BBSPR.FunctionNameToDIFilename.try_emplace(F.getName(), DIFilename)
487 .second;
489 }
490 if (auto Err = BBSPR.ReadProfile())
492 return false;
493}
494
496
502
505 return BBSPR.isFunctionHot(FuncName);
506}
507
511 return BBSPR.getClusterInfoForFunction(FuncName);
512}
513
517 return BBSPR.getClonePathsForFunction(FuncName);
518}
519
523 return BBSPR.getEdgeCount(FuncName, SrcBBID, SinkBBID);
524}
525
526std::pair<bool, FunctionPathAndClusterInfo>
529 return BBSPR.getFunctionPathAndClusterInfo(FuncName);
530}
531
536
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
Function Alias Analysis false
This file defines the DenseSet and SmallDenseSet classes.
#define INITIALIZE_PASS(passName, arg, name, cfg, analysis)
This file defines the SmallSet class.
This file defines the SmallString class.
This file defines the SmallVector class.
Result run(Function &F, FunctionAnalysisManager &AM)
Definition BasicBlockSectionsProfileReader.cpp:498
bool doInitialization(Module &M) override
doInitialization - Virtual method overridden by subclasses to do any necessary initialization before ...
Definition BasicBlockSectionsProfileReader.cpp:470
BasicBlockSectionsProfileReader BBSPR
BasicBlockSectionsProfileReader & getBBSPR()
Definition BasicBlockSectionsProfileReader.cpp:533
SmallVector< SmallVector< unsigned > > getClonePathsForFunction(StringRef FuncName) const
Definition BasicBlockSectionsProfileReader.cpp:515
SmallVector< BBClusterInfo > getClusterInfoForFunction(StringRef FuncName) const
Definition BasicBlockSectionsProfileReader.cpp:509
bool isFunctionHot(StringRef FuncName) const
Definition BasicBlockSectionsProfileReader.cpp:503
std::pair< bool, FunctionPathAndClusterInfo > getFunctionPathAndClusterInfo(StringRef FuncName) const
Definition BasicBlockSectionsProfileReader.cpp:527
uint64_t getEdgeCount(StringRef FuncName, const UniqueBBID &SrcBBID, const UniqueBBID &DestBBID) const
Definition BasicBlockSectionsProfileReader.cpp:520
std::pair< bool, FunctionPathAndClusterInfo > getFunctionPathAndClusterInfo(StringRef FuncName) const
bool isFunctionHot(StringRef FuncName) const
SmallVector< SmallVector< unsigned > > getClonePathsForFunction(StringRef FuncName) const
uint64_t getEdgeCount(StringRef FuncName, const UniqueBBID &SrcBBID, const UniqueBBID &SinkBBID) const
SmallVector< BBClusterInfo > getClusterInfoForFunction(StringRef FuncName) const
Subprogram description. Uses SubclassData1.
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.
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.
std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
constexpr bool empty() const
empty - Check if the string is empty.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
std::pair< iterator, bool > insert(const ValueT &V)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI 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)
Definition BasicBlockSectionsProfileReader.cpp:537
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
FunctionAddr VTableAddr uintptr_t uintptr_t Version
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
FunctionAddr VTableAddr Count
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI bool getAsUnsignedInteger(StringRef Str, unsigned Radix, unsigned long long &Result)
Helper functions for StringRef::getAsInteger.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
A special type used by analysis passes to provide an address that identifies that particular analysis...