36 "bbsections-profile-reader",
37 "Reads and parses a basic block sections profile.",
false,
45 return createProfileParseError(
Twine(
"unable to parse basic block id: '") +
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)};
67 auto R = ProgramOptimizationProfile.find(getAliasName(FuncName));
68 return R != ProgramOptimizationProfile.end() ?
R->second.ClusterInfo
75 auto R = ProgramOptimizationProfile.find(getAliasName(FuncName));
76 return R != ProgramOptimizationProfile.end()
77 ?
R->second.ClonePaths
87 auto NodeIt =
CFG->EdgeCounts.find(SrcBBID);
88 if (NodeIt ==
CFG->EdgeCounts.end())
90 auto EdgeIt = NodeIt->second.find(SinkBBID);
91 if (EdgeIt == NodeIt->second.end())
93 return EdgeIt->second;
99 auto R = ProgramOptimizationProfile.find(getAliasName(FuncName));
100 return R != ProgramOptimizationProfile.end() ?
R->second.PrefetchTargets
108 ProgramOptimizationProfile.find(getAliasName(FuncName));
109 return It != ProgramOptimizationProfile.end() ? It->second.PrefetchHints
218Error BasicBlockSectionsProfileReader::ReadV1Profile() {
219 auto FI = ProgramOptimizationProfile.end();
222 unsigned CurrentCluster = 0;
224 unsigned CurrentPosition = 0;
228 DenseSet<UniqueBBID> FuncBBIDs;
232 StringRef DIFilename;
234 for (; !LineIt.is_at_eof(); ++LineIt) {
235 StringRef S(*LineIt);
237 S = S.drop_front().trim();
239 S.split(Values,
' ');
244 if (Values.
size() != 1) {
245 return createProfileParseError(Twine(
"invalid module name value: '") +
251 bool FunctionFound =
any_of(Values, [&](StringRef Alias) {
252 auto It = FunctionNameToDIFilename.find(Alias);
254 if (It == FunctionNameToDIFilename.end())
258 return DIFilename.
empty() || It->second == DIFilename;
260 if (!FunctionFound) {
263 FI = ProgramOptimizationProfile.end();
267 for (
size_t i = 1; i < Values.
size(); ++i)
268 FuncAliasMap.try_emplace(Values[i], Values.
front());
272 auto R = ProgramOptimizationProfile.try_emplace(Values.
front());
276 return createProfileParseError(
"duplicate profile for function '" +
277 Values.
front() +
"'");
289 if (FI == ProgramOptimizationProfile.end())
293 for (
auto BasicBlockIDStr : Values) {
294 auto BasicBlockID = parseUniqueBBID(BasicBlockIDStr);
296 return BasicBlockID.takeError();
297 if (!FuncBBIDs.
insert(*BasicBlockID).second)
298 return createProfileParseError(
299 Twine(
"duplicate basic block id found '") + BasicBlockIDStr +
302 FI->second.ClusterInfo.emplace_back(BBClusterInfo{
303 *std::move(BasicBlockID), CurrentCluster, CurrentPosition++});
310 if (FI == ProgramOptimizationProfile.end())
312 SmallSet<unsigned, 5> BBsInPath;
313 FI->second.ClonePaths.push_back({});
314 for (
size_t I = 0;
I < Values.size(); ++
I) {
315 auto BaseBBIDStr = Values[
I];
316 unsigned long long BaseBBID = 0;
318 return createProfileParseError(Twine(
"unsigned integer expected: '") +
320 if (
I != 0 && !BBsInPath.
insert(BaseBBID).second)
321 return createProfileParseError(
322 Twine(
"duplicate cloned block in path: '") + BaseBBIDStr +
"'");
323 FI->second.ClonePaths.back().push_back(BaseBBID);
330 if (FI == ProgramOptimizationProfile.end())
334 for (
auto BasicBlockEdgeProfile : Values) {
335 if (BasicBlockEdgeProfile.empty())
338 BasicBlockEdgeProfile.split(NodeEdgeCounts,
',');
340 for (
size_t i = 0; i < NodeEdgeCounts.
size(); ++i) {
341 auto [BBIDStr, CountStr] = NodeEdgeCounts[i].split(
':');
342 auto BBID = parseUniqueBBID(BBIDStr);
344 return BBID.takeError();
345 unsigned long long Count = 0;
347 return createProfileParseError(
348 Twine(
"unsigned integer expected: '") + CountStr +
"'");
351 FI->second.CFG.NodeCounts[SrcBBID = *BBID] =
Count;
354 FI->second.CFG.EdgeCounts[SrcBBID][*BBID] =
Count;
362 if (FI == ProgramOptimizationProfile.end())
364 for (
auto BBIDHashStr : Values) {
365 auto [BBIDStr, HashStr] = BBIDHashStr.split(
':');
366 unsigned long long BBID = 0, Hash = 0;
368 return createProfileParseError(Twine(
"unsigned integer expected: '") +
371 return createProfileParseError(
372 Twine(
"unsigned integer expected in hex format: '") + HashStr +
374 FI->second.CFG.BBHashes[BBID] = Hash;
381 if (FI == ProgramOptimizationProfile.end())
384 Values[0].split(PrefetchTargetStr,
',');
385 if (PrefetchTargetStr.
size() != 2)
386 return createProfileParseError(Twine(
"Callsite target expected: ") +
388 auto TargetBBID = parseUniqueBBID(PrefetchTargetStr[0]);
390 return TargetBBID.takeError();
393 return createProfileParseError(Twine(
"signed integer expected: '") +
394 PrefetchTargetStr[1]);
395 FI->second.PrefetchTargets.push_back(
396 CallsiteID{*TargetBBID,
static_cast<unsigned>(
CallsiteIndex)});
403 if (FI == ProgramOptimizationProfile.end())
405 if (Values.size() != 2)
406 return createProfileParseError(
407 Twine(
"Prefetch hint expected of format '<prefetch-site> "
408 "<prefetch-target>': " +
411 Values[0].split(PrefetchSiteStr,
',');
412 if (PrefetchSiteStr.
size() != 2)
413 return createProfileParseError(Twine(
"Prefetch site expected of format "
414 "'<block-id>,<callsite-id>': ") +
416 auto SiteBBID = parseUniqueBBID(PrefetchSiteStr[0]);
418 return SiteBBID.takeError();
419 unsigned long long SiteCallsiteIndex;
421 return createProfileParseError(Twine(
"unsigned integer expected: '") +
425 Values[1].split(PrefetchTargetStr,
',');
426 if (PrefetchTargetStr.
size() != 3)
427 return createProfileParseError(
428 Twine(
"Prefetch target expected of format "
429 "'<function-name>,<block-id>,<callsite-id>': ") +
431 auto TargetBBID = parseUniqueBBID(PrefetchTargetStr[1]);
433 return TargetBBID.takeError();
434 unsigned long long TargetCallsiteIndex;
436 return createProfileParseError(Twine(
"unsigned integer expected: '") +
437 PrefetchTargetStr[2]);
438 FI->second.PrefetchHints.push_back(PrefetchHint{
439 CallsiteID{*SiteBBID,
static_cast<unsigned>(SiteCallsiteIndex)},
440 PrefetchTargetStr[0],
441 CallsiteID{*TargetBBID,
static_cast<unsigned>(TargetCallsiteIndex)}});
445 return createProfileParseError(Twine(
"invalid specifier: '") +
446 Twine(Specifier) +
"'");
453Error BasicBlockSectionsProfileReader::ReadV0Profile() {
454 auto FI = ProgramOptimizationProfile.end();
456 unsigned CurrentCluster = 0;
458 unsigned CurrentPosition = 0;
462 SmallSet<unsigned, 4> FuncBBIDs;
464 for (; !LineIt.is_at_eof(); ++LineIt) {
465 StringRef S(*LineIt);
469 if (!S.consume_front(
"!") || S.empty())
472 if (S.consume_front(
"!")) {
475 if (FI == ProgramOptimizationProfile.end())
481 for (
auto BBIDStr : BBIDs) {
482 unsigned long long BBID;
484 return createProfileParseError(Twine(
"unsigned integer expected: '") +
486 if (!FuncBBIDs.
insert(BBID).second)
487 return createProfileParseError(
488 Twine(
"duplicate basic block id found '") + BBIDStr +
"'");
490 FI->second.ClusterInfo.emplace_back(
491 BBClusterInfo({{
static_cast<unsigned>(BBID), 0},
493 CurrentPosition++}));
499 auto [AliasesStr, DIFilenameStr] = S.split(
' ');
500 SmallString<128> DIFilename;
501 if (DIFilenameStr.starts_with(
"M=")) {
504 if (DIFilename.
empty())
505 return createProfileParseError(
"empty module name specifier");
506 }
else if (!DIFilenameStr.empty()) {
507 return createProfileParseError(
"unknown string found: '" +
508 DIFilenameStr +
"'");
514 AliasesStr.
split(Aliases,
'/');
515 bool FunctionFound =
any_of(Aliases, [&](StringRef Alias) {
516 auto It = FunctionNameToDIFilename.find(Alias);
518 if (It == FunctionNameToDIFilename.end())
522 return DIFilename.
empty() || It->second == DIFilename;
524 if (!FunctionFound) {
527 FI = ProgramOptimizationProfile.end();
530 for (
size_t i = 1; i < Aliases.
size(); ++i)
531 FuncAliasMap.try_emplace(Aliases[i], Aliases.
front());
535 auto R = ProgramOptimizationProfile.try_emplace(Aliases.
front());
539 return createProfileParseError(
"duplicate profile for function '" +
540 Aliases.
front() +
"'");
566Error BasicBlockSectionsProfileReader::ReadProfile() {
569 unsigned long long Version = 0;
570 StringRef FirstLine(*LineIt);
571 if (FirstLine.consume_front(
"v")) {
573 return createProfileParseError(Twine(
"version number expected: '") +
577 return createProfileParseError(Twine(
"invalid profile version: ") +
586 return ReadV0Profile();
588 return ReadV1Profile();
598 BBSPR.FunctionNameToDIFilename.clear();
601 if (
F.isDeclaration())
609 [[maybe_unused]]
bool inserted =
610 BBSPR.FunctionNameToDIFilename.try_emplace(
F.getName(), DIFilename)
614 if (
auto Err =
BBSPR.ReadProfile())
629 return BBSPR.isFunctionHot(FuncName);
635 return BBSPR.getClusterInfoForFunction(FuncName);
641 return BBSPR.getClonePathsForFunction(FuncName);
647 return BBSPR.getFunctionCFGProfile(FuncName);
653 return BBSPR.getEdgeCount(FuncName, SrcBBID, SinkBBID);
659 return BBSPR.getPrefetchTargetsForFunction(FuncName);
665 return BBSPR.getPrefetchHintsForFunction(FuncName);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file defines the StringMap class.
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)
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
SmallVector< BBClusterInfo > getClusterInfoForFunction(StringRef FuncName) const
SmallVector< CallsiteID > getPrefetchTargetsForFunction(StringRef FuncName) const
const CFGProfile * getFunctionCFGProfile(StringRef FuncName) const
bool isFunctionHot(StringRef FuncName) const
uint64_t getEdgeCount(StringRef FuncName, const UniqueBBID &SrcBBID, const UniqueBBID &DestBBID) const
SmallVector< PrefetchHint > getPrefetchHintsForFunction(StringRef FuncName) const
SmallVector< PrefetchHint > getPrefetchHintsForFunction(StringRef FuncName) const
bool isFunctionHot(StringRef FuncName) const
SmallVector< SmallVector< unsigned > > getClonePathsForFunction(StringRef FuncName) const
const CFGProfile * getFunctionCFGProfile(StringRef FuncName) const
SmallVector< CallsiteID > getPrefetchTargetsForFunction(StringRef FuncName) const
uint64_t getEdgeCount(StringRef FuncName, const UniqueBBID &SrcBBID, const UniqueBBID &DestBBID) 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.
StringMapIterBase< ValueTy, true > const_iterator
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)
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...