21using namespace sampleprof;
23#define DEBUG_TYPE "sample-profile-matcher"
27 cl::desc(
"Consider a profile matches a function if the similarity of their "
28 "callee sequences is above the specified percentile."));
32 cl::desc(
"The minimum number of basic blocks required for a function to "
33 "run stale profile call graph matching."));
37 cl::desc(
"The minimum number of call anchors required for a function to "
38 "run stale profile call graph matching."));
43 "Load top-level profiles that the sample reader initially skipped for "
44 "the call-graph matching (only meaningful for extended binary "
54 cl::desc(
"The maximum number of callsites in a function, above which stale "
55 "profile matching will be skipped."));
57void SampleProfileMatcher::findIRAnchors(
const Function &
F,
62 auto FindTopLevelInlinedCallsite = [](
const DILocation *DIL) {
63 assert((DIL && DIL->getInlinedAt()) &&
"No inlined callsite");
67 DIL = DIL->getInlinedAt();
68 }
while (DIL->getInlinedAt());
72 StringRef CalleeName = PrevDIL->getSubprogramLinkageName();
73 return std::make_pair(Callsite,
FunctionId(CalleeName));
76 auto GetCanonicalCalleeName = [](
const CallBase *CB) {
77 StringRef CalleeName = UnknownIndirectCallee;
78 if (
Function *Callee = CB->getCalledFunction())
93 if (DIL->getInlinedAt()) {
94 IRAnchors.emplace(FindTopLevelInlinedCallsite(DIL));
98 if (
const auto *CB = dyn_cast<CallBase>(&
I)) {
100 if (!isa<IntrinsicInst>(&
I))
101 CalleeName = GetCanonicalCalleeName(CB);
104 IRAnchors.emplace(Loc,
FunctionId(CalleeName));
111 if (!isa<CallBase>(&
I) || isa<IntrinsicInst>(&
I))
114 if (DIL->getInlinedAt()) {
115 IRAnchors.emplace(FindTopLevelInlinedCallsite(DIL));
119 StringRef CalleeName = GetCanonicalCalleeName(dyn_cast<CallBase>(&
I));
120 IRAnchors.emplace(Callsite,
FunctionId(CalleeName));
127void SampleProfileMatcher::findProfileAnchors(
const FunctionSamples &FS,
129 auto isInvalidLineOffset = [](
uint32_t LineOffset) {
130 return LineOffset & 0x8000;
135 auto Ret = ProfileAnchors.try_emplace(Loc, CalleeName);
143 for (
const auto &
I :
FS.getBodySamples()) {
147 for (
const auto &
C :
I.second.getCallTargets())
148 InsertAnchor(Loc,
C.first, ProfileAnchors);
151 for (
const auto &
I :
FS.getCallsiteSamples()) {
155 for (
const auto &
C :
I.second)
156 InsertAnchor(Loc,
C.first, ProfileAnchors);
160bool SampleProfileMatcher::functionHasProfile(
const FunctionId &IRFuncName,
162 FuncWithoutProfile =
nullptr;
163 auto R = FunctionsWithoutProfile.find(IRFuncName);
164 if (R != FunctionsWithoutProfile.end())
165 FuncWithoutProfile =
R->second;
166 return !FuncWithoutProfile;
169bool SampleProfileMatcher::isProfileUnused(
const FunctionId &ProfileFuncName) {
170 return SymbolMap->find(ProfileFuncName) == SymbolMap->end();
173bool SampleProfileMatcher::functionMatchesProfile(
175 bool FindMatchedProfileOnly) {
176 if (IRFuncName == ProfileFuncName)
184 if (functionHasProfile(IRFuncName, IRFunc) ||
185 !isProfileUnused(ProfileFuncName))
189 "IR function should be different from profile function to match");
190 return functionMatchesProfile(*IRFunc, ProfileFuncName,
191 FindMatchedProfileOnly);
195SampleProfileMatcher::longestCommonSequence(
const AnchorList &AnchorList1,
197 bool MatchUnusedFunction) {
199 llvm::longestCommonSequence<LineLocation, FunctionId>(
200 AnchorList1, AnchorList2,
202 return functionMatchesProfile(
208 MatchedAnchors.try_emplace(
A,
B);
210 return MatchedAnchors;
213void SampleProfileMatcher::matchNonCallsiteLocs(
219 IRToProfileLocationMap.insert({
From, To});
223 int32_t LocationDelta = 0;
225 for (
const auto &
IR : IRAnchors) {
226 const auto &Loc =
IR.first;
227 bool IsMatchedAnchor =
false;
229 auto R = MatchedAnchors.find(Loc);
230 if (R != MatchedAnchors.end()) {
231 const auto &Candidate =
R->second;
232 InsertMatching(Loc, Candidate);
234 <<
" is matched from " << Loc <<
" to " << Candidate
236 LocationDelta = Candidate.LineOffset - Loc.
LineOffset;
242 for (
size_t I = (LastMatchedNonAnchors.
size() + 1) / 2;
243 I < LastMatchedNonAnchors.
size();
I++) {
244 const auto &
L = LastMatchedNonAnchors[
I];
245 uint32_t CandidateLineOffset =
L.LineOffset + LocationDelta;
246 LineLocation Candidate(CandidateLineOffset,
L.Discriminator);
247 InsertMatching(L, Candidate);
249 <<
" to " << Candidate <<
"\n");
252 IsMatchedAnchor =
true;
253 LastMatchedNonAnchors.
clear();
257 if (!IsMatchedAnchor) {
260 InsertMatching(Loc, Candidate);
262 << Candidate <<
"\n");
270void SampleProfileMatcher::getFilteredAnchorList(
273 for (
const auto &
I : IRAnchors) {
274 if (
I.second.stringRef().empty())
276 FilteredIRAnchorsList.emplace_back(
I);
279 for (
const auto &
I : ProfileAnchors)
280 FilteredProfileAnchorList.emplace_back(
I);
300void SampleProfileMatcher::runStaleProfileMatching(
303 bool RunCFGMatching,
bool RunCGMatching) {
304 if (!RunCFGMatching && !RunCGMatching)
308 assert(IRToProfileLocationMap.empty() &&
309 "Run stale profile matching only once per function");
313 getFilteredAnchorList(IRAnchors, ProfileAnchors, FilteredIRAnchorsList,
314 FilteredProfileAnchorList);
316 if (FilteredIRAnchorsList.empty() || FilteredProfileAnchorList.empty())
322 <<
" because the number of callsites in the IR is "
323 << FilteredIRAnchorsList.size()
324 <<
" and in the profile is "
325 << FilteredProfileAnchorList.size() <<
"\n");
340 longestCommonSequence(FilteredIRAnchorsList, FilteredProfileAnchorList,
348 matchNonCallsiteLocs(MatchedAnchors, IRAnchors, IRToProfileLocationMap);
351void SampleProfileMatcher::runOnFunction(
Function &
F) {
358 const auto *FSForMatching = getFlattenedSamplesFor(
F);
361 auto R = FuncToProfileNameMap.find(&
F);
362 if (R != FuncToProfileNameMap.end()) {
363 FSForMatching = getFlattenedSamplesFor(
R->second);
377 findIRAnchors(
F, IRAnchors);
381 findProfileAnchors(*FSForMatching, ProfileAnchors);
385 recordCallsiteMatchStates(
F, IRAnchors, ProfileAnchors,
nullptr);
393 bool RunCFGMatching =
401 F.addFnAttr(
"profile-checksum-mismatch");
405 auto &IRToProfileLocationMap = getIRToProfileLocationMap(
F);
406 runStaleProfileMatching(
F, IRAnchors, ProfileAnchors, IRToProfileLocationMap,
407 RunCFGMatching, RunCGMatching);
410 recordCallsiteMatchStates(
F, IRAnchors, ProfileAnchors,
411 &IRToProfileLocationMap);
414void SampleProfileMatcher::recordCallsiteMatchStates(
418 bool IsPostMatch = IRToProfileLocationMap !=
nullptr;
419 auto &CallsiteMatchStates =
422 auto MapIRLocToProfileLoc = [&](
const LineLocation &IRLoc) {
424 if (!IRToProfileLocationMap)
426 const auto &ProfileLoc = IRToProfileLocationMap->find(IRLoc);
427 if (ProfileLoc != IRToProfileLocationMap->end())
428 return ProfileLoc->second;
433 for (
const auto &
I : IRAnchors) {
436 const auto &ProfileLoc = MapIRLocToProfileLoc(
I.first);
437 const auto &IRCalleeId =
I.second;
438 const auto &It = ProfileAnchors.find(ProfileLoc);
439 if (It == ProfileAnchors.end())
441 const auto &ProfCalleeId = It->second;
442 if (IRCalleeId == ProfCalleeId) {
443 auto It = CallsiteMatchStates.find(ProfileLoc);
444 if (It == CallsiteMatchStates.end())
445 CallsiteMatchStates.emplace(ProfileLoc, MatchState::InitialMatch);
446 else if (IsPostMatch) {
447 if (It->second == MatchState::InitialMatch)
448 It->second = MatchState::UnchangedMatch;
449 else if (It->second == MatchState::InitialMismatch)
450 It->second = MatchState::RecoveredMismatch;
457 for (
const auto &
I : ProfileAnchors) {
458 const auto &Loc =
I.first;
459 assert(!
I.second.stringRef().empty() &&
"Callees should not be empty");
460 auto It = CallsiteMatchStates.find(Loc);
461 if (It == CallsiteMatchStates.end())
462 CallsiteMatchStates.emplace(Loc, MatchState::InitialMismatch);
463 else if (IsPostMatch) {
466 if (It->second == MatchState::InitialMismatch)
467 It->second = MatchState::UnchangedMismatch;
468 else if (It->second == MatchState::InitialMatch)
469 It->second = MatchState::RemovedMatch;
474void SampleProfileMatcher::countMismatchedFuncSamples(
const FunctionSamples &FS,
476 const auto *FuncDesc = ProbeManager->
getDesc(
FS.getGUID());
483 NumStaleProfileFunc++;
488 MismatchedFunctionSamples +=
FS.getTotalSamples();
497 for (
const auto &
I :
FS.getCallsiteSamples())
498 for (
const auto &CS :
I.second)
499 countMismatchedFuncSamples(CS.second,
false);
502void SampleProfileMatcher::countMismatchedCallsiteSamples(
504 auto It = FuncCallsiteMatchStates.find(
FS.getFuncName());
506 if (It == FuncCallsiteMatchStates.end() || It->second.empty())
508 const auto &CallsiteMatchStates = It->second;
511 auto It = CallsiteMatchStates.find(Loc);
512 if (It == CallsiteMatchStates.end())
513 return MatchState::Unknown;
517 auto AttributeMismatchedSamples = [&](
const enum MatchState &State,
519 if (isMismatchState(State))
520 MismatchedCallsiteSamples += Samples;
521 else if (State == MatchState::RecoveredMismatch)
522 RecoveredCallsiteSamples += Samples;
527 for (
const auto &
I :
FS.getBodySamples())
528 AttributeMismatchedSamples(findMatchState(
I.first),
I.second.getSamples());
531 for (
const auto &
I :
FS.getCallsiteSamples()) {
532 auto State = findMatchState(
I.first);
534 for (
const auto &CS :
I.second)
535 CallsiteSamples += CS.second.getTotalSamples();
536 AttributeMismatchedSamples(State, CallsiteSamples);
538 if (isMismatchState(State))
544 for (
const auto &CS :
I.second)
545 countMismatchedCallsiteSamples(CS.second);
549void SampleProfileMatcher::countMismatchCallsites(
const FunctionSamples &FS) {
550 auto It = FuncCallsiteMatchStates.find(
FS.getFuncName());
552 if (It == FuncCallsiteMatchStates.end() || It->second.empty())
554 const auto &MatchStates = It->second;
555 [[maybe_unused]]
bool OnInitialState =
556 isInitialState(MatchStates.begin()->second);
557 for (
const auto &
I : MatchStates) {
558 TotalProfiledCallsites++;
560 (OnInitialState ? isInitialState(
I.second) : isFinalState(
I.second)) &&
561 "Profile matching state is inconsistent");
563 if (isMismatchState(
I.second))
564 NumMismatchedCallsites++;
565 else if (
I.second == MatchState::RecoveredMismatch)
566 NumRecoveredCallsites++;
570void SampleProfileMatcher::countCallGraphRecoveredSamples(
572 std::unordered_set<FunctionId> &CallGraphRecoveredProfiles) {
573 if (CallGraphRecoveredProfiles.count(
FS.getFunction())) {
574 NumCallGraphRecoveredFuncSamples +=
FS.getTotalSamples();
578 for (
const auto &CM :
FS.getCallsiteSamples()) {
579 for (
const auto &CS : CM.second) {
580 countCallGraphRecoveredSamples(CS.second, CallGraphRecoveredProfiles);
585void SampleProfileMatcher::computeAndReportProfileStaleness() {
589 std::unordered_set<FunctionId> CallGraphRecoveredProfiles;
591 for (
const auto &
I : FuncToProfileNameMap) {
592 CallGraphRecoveredProfiles.insert(
I.second);
595 NumCallGraphRecoveredProfiledFunc++;
600 for (
const auto &
F : M) {
611 TotalFunctionSamples +=
FS->getTotalSamples();
614 countCallGraphRecoveredSamples(*FS, CallGraphRecoveredProfiles);
618 countMismatchedFuncSamples(*FS,
true);
621 countMismatchCallsites(*FS);
622 countMismatchedCallsiteSamples(*FS);
627 errs() <<
"(" << NumStaleProfileFunc <<
"/" << TotalProfiledFunc
628 <<
") of functions' profile are invalid and ("
629 << MismatchedFunctionSamples <<
"/" << TotalFunctionSamples
630 <<
") of samples are discarded due to function hash mismatch.\n";
633 errs() <<
"(" << NumCallGraphRecoveredProfiledFunc <<
"/"
634 << TotalProfiledFunc <<
") of functions' profile are matched and ("
635 << NumCallGraphRecoveredFuncSamples <<
"/" << TotalFunctionSamples
636 <<
") of samples are reused by call graph matching.\n";
639 errs() <<
"(" << (NumMismatchedCallsites + NumRecoveredCallsites) <<
"/"
640 << TotalProfiledCallsites
641 <<
") of callsites' profile are invalid and ("
642 << (MismatchedCallsiteSamples + RecoveredCallsiteSamples) <<
"/"
643 << TotalFunctionSamples
644 <<
") of samples are discarded due to callsite location mismatch.\n";
645 errs() <<
"(" << NumRecoveredCallsites <<
"/"
646 << (NumRecoveredCallsites + NumMismatchedCallsites)
647 <<
") of callsites and (" << RecoveredCallsiteSamples <<
"/"
648 << (RecoveredCallsiteSamples + MismatchedCallsiteSamples)
649 <<
") of samples are recovered by stale profile matching.\n";
658 ProfStatsVec.
emplace_back(
"NumStaleProfileFunc", NumStaleProfileFunc);
659 ProfStatsVec.
emplace_back(
"TotalProfiledFunc", TotalProfiledFunc);
661 MismatchedFunctionSamples);
662 ProfStatsVec.
emplace_back(
"TotalFunctionSamples", TotalFunctionSamples);
666 ProfStatsVec.
emplace_back(
"NumCallGraphRecoveredProfiledFunc",
667 NumCallGraphRecoveredProfiledFunc);
668 ProfStatsVec.
emplace_back(
"NumCallGraphRecoveredFuncSamples",
669 NumCallGraphRecoveredFuncSamples);
672 ProfStatsVec.
emplace_back(
"NumMismatchedCallsites", NumMismatchedCallsites);
673 ProfStatsVec.
emplace_back(
"NumRecoveredCallsites", NumRecoveredCallsites);
674 ProfStatsVec.
emplace_back(
"TotalProfiledCallsites", TotalProfiledCallsites);
676 MismatchedCallsiteSamples);
678 RecoveredCallsiteSamples);
680 auto *MD = MDB.createLLVMStats(ProfStatsVec);
681 auto *NMD =
M.getOrInsertNamedMetadata(
"llvm.stats");
686void SampleProfileMatcher::findFunctionsWithoutProfile() {
692 for (
auto Name : *NameTable)
699 if (
F.isDeclaration())
703 const auto *
FS = getFlattenedSamplesFor(
F);
710 if (NamesInProfile.
count(CanonFName))
715 if (PSL && PSL->contains(CanonFName))
719 <<
" is not in profile or profile symbol list.\n");
720 FunctionsWithoutProfile[
FunctionId(CanonFName)] = &
F;
724bool SampleProfileMatcher::functionMatchesProfileHelper(
728 float Similarity = 0.0;
730 const auto *FSForMatching = getFlattenedSamplesFor(ProfFunc);
738 if (std::error_code EC = Reader.
read(TopLevelFunc))
743 dbgs() <<
"Read top-level function " << ProfFunc
744 <<
" for call-graph matching\n";
759 const auto *FuncDesc = ProbeManager->
getDesc(IRFunc);
763 <<
"(IR) and " << ProfFunc <<
"(Profile) match.\n");
770 findIRAnchors(IRFunc, IRAnchors);
772 findProfileAnchors(*FSForMatching, ProfileAnchors);
776 getFilteredAnchorList(IRAnchors, ProfileAnchors, FilteredIRAnchorsList,
777 FilteredProfileAnchorList);
790 longestCommonSequence(FilteredIRAnchorsList, FilteredProfileAnchorList,
794 static_cast<float>(MatchedAnchors.size()) * 2 /
795 (FilteredIRAnchorsList.size() + FilteredProfileAnchorList.size());
798 <<
"(IR) and " << ProfFunc <<
"(profile) is "
799 <<
format(
"%.2f", Similarity) <<
"\n");
800 assert((Similarity >= 0 && Similarity <= 1.0) &&
801 "Similarity value should be in [0, 1]");
807bool SampleProfileMatcher::functionMatchesProfile(
Function &IRFunc,
809 bool FindMatchedProfileOnly) {
810 auto R = FuncProfileMatchCache.find({&IRFunc, ProfFunc});
811 if (R != FuncProfileMatchCache.end())
814 if (FindMatchedProfileOnly)
817 bool Matched = functionMatchesProfileHelper(IRFunc, ProfFunc);
818 FuncProfileMatchCache[{&IRFunc, ProfFunc}] = Matched;
820 FuncToProfileNameMap[&IRFunc] = ProfFunc;
822 <<
" matches profile:" << ProfFunc <<
"\n");
828void SampleProfileMatcher::UpdateWithSalvagedProfiles() {
831 for (
auto &
I : FuncToProfileNameMap) {
832 assert(
I.first &&
"New function is null");
834 ProfileSalvagedFuncs.
insert(
I.second.stringRef());
835 FuncNameToProfNameMap->emplace(FuncName,
I.second);
839 SymbolMap->erase(FuncName);
840 SymbolMap->emplace(
I.second,
I.first);
847 Reader.
read(ProfileSalvagedFuncs);
855 findFunctionsWithoutProfile();
859 std::vector<Function *> TopDownFunctionList;
860 TopDownFunctionList.reserve(M.size());
862 for (
auto *
F : TopDownFunctionList) {
869 UpdateWithSalvagedProfiles();
872 distributeIRToProfileLocationMap();
874 computeAndReportProfileStaleness();
877void SampleProfileMatcher::distributeIRToProfileLocationMap(
879 const auto ProfileMappings = FuncMappings.
find(FS.getFuncName());
880 if (ProfileMappings != FuncMappings.
end()) {
881 FS.setIRToProfileLocationMap(&(ProfileMappings->second));
886 for (
auto &FS : Callees.second) {
887 distributeIRToProfileLocationMap(FS.second);
894void SampleProfileMatcher::distributeIRToProfileLocationMap() {
896 distributeIRToProfileLocationMap(
I.second);
BlockVerifier::State From
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
Legalize the Machine IR a function s Machine IR
static cl::opt< bool > SalvageStaleProfile("memprof-salvage-stale-profile", cl::desc("Salvage stale MemProf profile"), cl::init(false), cl::Hidden)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static cl::opt< unsigned > MinCallCountForCGMatching("min-call-count-for-cg-matching", cl::Hidden, cl::init(3), cl::desc("The minimum number of call anchors required for a function to " "run stale profile call graph matching."))
cl::opt< bool > ReportProfileStaleness
static cl::opt< bool > LoadFuncProfileforCGMatching("load-func-profile-for-cg-matching", cl::Hidden, cl::init(false), cl::desc("Load top-level profiles that the sample reader initially skipped for " "the call-graph matching (only meaningful for extended binary " "format)"))
static cl::opt< unsigned > FuncProfileSimilarityThreshold("func-profile-similarity-threshold", cl::Hidden, cl::init(80), cl::desc("Consider a profile matches a function if the similarity of their " "callee sequences is above the specified percentile."))
cl::opt< bool > SalvageStaleProfile
static cl::opt< unsigned > SalvageStaleProfileMaxCallsites("salvage-stale-profile-max-callsites", cl::Hidden, cl::init(UINT_MAX), cl::desc("The maximum number of callsites in a function, above which stale " "profile matching will be skipped."))
static cl::opt< unsigned > MinFuncCountForCGMatching("min-func-count-for-cg-matching", cl::Hidden, cl::init(5), cl::desc("The minimum number of basic blocks required for a function to " "run stale profile call graph matching."))
cl::opt< bool > SalvageUnusedProfile
cl::opt< bool > PersistProfileStaleness
This file provides the interface for SampleProfileMatcher.
cl::opt< bool > SalvageUnusedProfile("salvage-unused-profile", cl::Hidden, cl::init(false), cl::desc("Salvage unused profile by matching with new " "functions on call graph."))
cl::opt< bool > PersistProfileStaleness("persist-profile-staleness", cl::Hidden, cl::init(false), cl::desc("Compute stale profile statistical metrics and write it into the " "native object file(.llvm_stats section)."))
cl::opt< bool > ReportProfileStaleness("report-profile-staleness", cl::Hidden, cl::init(false), cl::desc("Compute and report stale profile statistical metrics."))
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Implements a dense probed hash-table based set.
static bool isAvailableExternallyLinkage(LinkageTypes Linkage)
This is an important class for using LLVM in a threaded context.
bool profileIsHashMismatched(const PseudoProbeDescriptor &FuncDesc, const FunctionSamples &Samples) const
bool profileIsValid(const Function &F, const FunctionSamples &Samples) const
const PseudoProbeDescriptor * getDesc(uint64_t GUID) const
reference emplace_back(ArgTypes &&... Args)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
iterator find(StringRef Key)
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
StringRef - Represent a constant reference to a string, i.e.
StringSet - A wrapper for StringMap that provides set-like functionality.
std::pair< typename Base::iterator, bool > insert(StringRef key)
StringRef getName() const
Return a constant reference to the value's name.
std::pair< iterator, bool > insert(const ValueT &V)
This class represents a function that is read from a sample profile.
StringRef stringRef() const
Convert to StringRef.
Representation of the samples collected for a function.
static bool ProfileIsProbeBased
static StringRef getCanonicalFnName(const Function &F)
Return the canonical name for a function, taking into account suffix elision policy attributes.
static bool ProfileIsFS
If this profile uses flow sensitive discriminators.
static LineLocation getCallSiteIdentifier(const DILocation *DIL, bool ProfileIsFS=false)
Returns a unique call site identifier for a given debug location of a call instruction.
static bool UseMD5
Whether the profile uses MD5 to represent string.
static void flattenProfile(SampleProfileMap &ProfileMap, bool ProfileIsCS=false)
SampleProfileMap & getProfiles()
Return all the profiles.
FunctionSamples * getSamplesFor(const Function &F)
Return the samples collected for function F.
std::error_code read()
The interface to read sample profiles from the associated file.
void setFuncNameToProfNameMap(const HashKeyMap< std::unordered_map, FunctionId, FunctionId > &FPMap)
virtual std::vector< FunctionId > * getNameTable()
It includes all the names that have samples either in outline instance or inline instance.
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
std::unordered_map< LineLocation, LineLocation, LineLocationHash > LocToLocMap
std::map< LineLocation, FunctionSamplesMap > CallsiteSampleMap
This is an optimization pass for GlobalISel generic memory operations.
std::vector< std::pair< LineLocation, FunctionId > > AnchorList
std::map< LineLocation, FunctionId > AnchorMap
static void buildTopDownFuncOrder(LazyCallGraph &CG, std::vector< Function * > &FunctionOrderList)
@ ThinLTOPreLink
ThinLTO prelink (summary) phase.
std::optional< PseudoProbe > extractProbe(const Instruction &Inst)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
static bool skipProfileForFunction(const Function &F)
Represents the relative location of an instruction.