21#include <unordered_set>
26#define DEBUG_TYPE "sample-profile-matcher"
32 cl::desc(
"Consider a profile matches a function if the similarity of their "
33 "callee sequences is above the specified percentile."));
37 cl::desc(
"The minimum number of basic blocks required for a function to "
38 "run stale profile call graph matching."));
42 cl::desc(
"The minimum number of call anchors required for a function to "
43 "run stale profile call graph matching."));
48 "Load top-level profiles that the sample reader initially skipped for "
49 "the call-graph matching (only meaningful for extended binary "
59 cl::desc(
"The maximum number of callsites in a function, above which stale "
60 "profile matching will be skipped."));
64void SampleProfileMatcher::findIRAnchors(
const Function &
F,
69 auto FindTopLevelInlinedCallsite = [](
const DILocation *DIL) {
70 assert((DIL && DIL->getInlinedAt()) &&
"No inlined callsite");
74 DIL = DIL->getInlinedAt();
75 }
while (DIL->getInlinedAt());
79 StringRef CalleeName = PrevDIL->getSubprogramLinkageName();
80 return std::make_pair(Callsite, FunctionId(CalleeName));
83 auto GetCanonicalCalleeName = [](
const CallBase *CB) {
84 StringRef CalleeName = UnknownIndirectCallee;
85 if (Function *Callee = CB->getCalledFunction())
93 DILocation *DIL =
I.getDebugLoc();
100 if (DIL->getInlinedAt()) {
101 IRAnchors.emplace(FindTopLevelInlinedCallsite(DIL));
104 StringRef CalleeName;
108 CalleeName = GetCanonicalCalleeName(CB);
110 LineLocation Loc = LineLocation(Probe->Id, 0);
111 IRAnchors.emplace(Loc, FunctionId(CalleeName));
121 if (DIL->getInlinedAt()) {
122 IRAnchors.emplace(FindTopLevelInlinedCallsite(DIL));
127 IRAnchors.emplace(Callsite, FunctionId(CalleeName));
134void SampleProfileMatcher::findProfileAnchors(
const FunctionSamples &FS,
136 auto isInvalidLineOffset = [](uint32_t LineOffset) {
137 return LineOffset & 0x8000;
140 auto InsertAnchor = [](
const LineLocation &Loc,
const FunctionId &CalleeName,
142 auto Ret = ProfileAnchors.try_emplace(Loc, CalleeName);
146 Ret.first->second = FunctionId(UnknownIndirectCallee);
150 for (
const auto &
I :
FS.getBodySamples()) {
151 const LineLocation &Loc =
I.first;
154 for (
const auto &
C :
I.second.getCallTargets())
155 InsertAnchor(Loc,
C.first, ProfileAnchors);
158 for (
const auto &
I :
FS.getCallsiteSamples()) {
159 const LineLocation &Loc =
I.first;
162 for (
const auto &
C :
I.second)
163 InsertAnchor(Loc,
C.first, ProfileAnchors);
167bool SampleProfileMatcher::functionHasProfile(
const FunctionId &IRFuncName,
169 FuncWithoutProfile =
nullptr;
170 auto R = FunctionsWithoutProfile.find(IRFuncName);
171 if (R != FunctionsWithoutProfile.end())
172 FuncWithoutProfile =
R->second;
173 return !FuncWithoutProfile;
176bool SampleProfileMatcher::isProfileUnused(
const FunctionId &ProfileFuncName) {
177 return SymbolMap->find(ProfileFuncName) == SymbolMap->
end();
180bool SampleProfileMatcher::functionMatchesProfile(
182 bool FindMatchedProfileOnly) {
183 if (IRFuncName == ProfileFuncName)
191 if (functionHasProfile(IRFuncName, IRFunc) ||
192 !isProfileUnused(ProfileFuncName))
196 "IR function should be different from profile function to match");
197 return functionMatchesProfile(*IRFunc, ProfileFuncName,
198 FindMatchedProfileOnly);
202SampleProfileMatcher::longestCommonSequence(
const AnchorList &AnchorList1,
204 bool MatchUnusedFunction) {
207 AnchorList1, AnchorList2,
208 [&](
const FunctionId &
A,
const FunctionId &
B) {
209 return functionMatchesProfile(
214 [&](LineLocation
A, LineLocation
B) {
215 MatchedAnchors.try_emplace(
A,
B);
217 return MatchedAnchors;
220void SampleProfileMatcher::matchNonCallsiteLocs(
223 auto InsertMatching = [&](
const LineLocation &From,
const LineLocation &To) {
226 IRToProfileLocationMap.insert({From, To});
230 int32_t LocationDelta = 0;
232 for (
const auto &
IR : IRAnchors) {
233 const auto &Loc =
IR.first;
234 bool IsMatchedAnchor =
false;
236 auto R = MatchedAnchors.find(Loc);
237 if (R != MatchedAnchors.end()) {
238 const auto &Candidate =
R->second;
239 InsertMatching(Loc, Candidate);
241 <<
" is matched from " << Loc <<
" to " << Candidate
243 LocationDelta = Candidate.LineOffset - Loc.
LineOffset;
249 for (
size_t I = (LastMatchedNonAnchors.
size() + 1) / 2;
250 I < LastMatchedNonAnchors.
size();
I++) {
251 const auto &
L = LastMatchedNonAnchors[
I];
252 uint32_t CandidateLineOffset =
L.LineOffset + LocationDelta;
253 LineLocation Candidate(CandidateLineOffset,
L.Discriminator);
254 InsertMatching(L, Candidate);
256 <<
" to " << Candidate <<
"\n");
259 IsMatchedAnchor =
true;
260 LastMatchedNonAnchors.
clear();
264 if (!IsMatchedAnchor) {
265 uint32_t CandidateLineOffset = Loc.
LineOffset + LocationDelta;
266 LineLocation Candidate(CandidateLineOffset, Loc.
Discriminator);
267 InsertMatching(Loc, Candidate);
269 << Candidate <<
"\n");
277void SampleProfileMatcher::getFilteredAnchorList(
280 for (
const auto &
I : IRAnchors) {
281 if (
I.second.stringRef().empty())
283 FilteredIRAnchorsList.emplace_back(
I);
286 for (
const auto &
I : ProfileAnchors)
287 FilteredProfileAnchorList.emplace_back(
I);
307void SampleProfileMatcher::runStaleProfileMatching(
310 bool RunCFGMatching,
bool RunCGMatching) {
311 if (!RunCFGMatching && !RunCGMatching)
315 assert(IRToProfileLocationMap.empty() &&
316 "Run stale profile matching only once per function");
320 getFilteredAnchorList(IRAnchors, ProfileAnchors, FilteredIRAnchorsList,
321 FilteredProfileAnchorList);
323 if (FilteredIRAnchorsList.empty() || FilteredProfileAnchorList.empty())
329 <<
" because the number of callsites in the IR is "
330 << FilteredIRAnchorsList.size()
331 <<
" and in the profile is "
332 << FilteredProfileAnchorList.size() <<
"\n");
347 longestCommonSequence(FilteredIRAnchorsList, FilteredProfileAnchorList,
355 matchNonCallsiteLocs(MatchedAnchors, IRAnchors, IRToProfileLocationMap);
358void SampleProfileMatcher::runOnFunction(
Function &
F) {
365 const auto *FSForMatching = getFlattenedSamplesFor(
F);
368 auto R = FuncToProfileNameMap.find(&
F);
369 if (R != FuncToProfileNameMap.end()) {
370 FSForMatching = getFlattenedSamplesFor(
R->second);
374 FSForMatching = Reader.getSamplesFor(
R->second.stringRef());
384 findIRAnchors(
F, IRAnchors);
388 findProfileAnchors(*FSForMatching, ProfileAnchors);
392 recordCallsiteMatchStates(
F, IRAnchors, ProfileAnchors,
nullptr);
399 !ProbeManager->profileIsValid(
F, *FSForMatching);
400 bool RunCFGMatching =
408 F.addFnAttr(
"profile-checksum-mismatch");
412 auto &IRToProfileLocationMap = getIRToProfileLocationMap(
F);
413 runStaleProfileMatching(
F, IRAnchors, ProfileAnchors, IRToProfileLocationMap,
414 RunCFGMatching, RunCGMatching);
417 recordCallsiteMatchStates(
F, IRAnchors, ProfileAnchors,
418 &IRToProfileLocationMap);
421void SampleProfileMatcher::recordCallsiteMatchStates(
425 bool IsPostMatch = IRToProfileLocationMap !=
nullptr;
426 auto &CallsiteMatchStates =
429 auto MapIRLocToProfileLoc = [&](
const LineLocation &IRLoc) {
431 if (!IRToProfileLocationMap)
433 const auto &ProfileLoc = IRToProfileLocationMap->find(IRLoc);
434 if (ProfileLoc != IRToProfileLocationMap->end())
435 return ProfileLoc->second;
440 for (
const auto &
I : IRAnchors) {
443 const auto &ProfileLoc = MapIRLocToProfileLoc(
I.first);
444 const auto &IRCalleeId =
I.second;
445 const auto &It = ProfileAnchors.find(ProfileLoc);
446 if (It == ProfileAnchors.end())
448 const auto &ProfCalleeId = It->second;
449 if (IRCalleeId == ProfCalleeId) {
450 auto It = CallsiteMatchStates.find(ProfileLoc);
451 if (It == CallsiteMatchStates.end())
452 CallsiteMatchStates.emplace(ProfileLoc, MatchState::InitialMatch);
453 else if (IsPostMatch) {
454 if (It->second == MatchState::InitialMatch)
455 It->second = MatchState::UnchangedMatch;
456 else if (It->second == MatchState::InitialMismatch)
457 It->second = MatchState::RecoveredMismatch;
464 for (
const auto &
I : ProfileAnchors) {
465 const auto &Loc =
I.first;
466 assert(!
I.second.stringRef().empty() &&
"Callees should not be empty");
467 auto It = CallsiteMatchStates.find(Loc);
468 if (It == CallsiteMatchStates.end())
469 CallsiteMatchStates.emplace(Loc, MatchState::InitialMismatch);
470 else if (IsPostMatch) {
473 if (It->second == MatchState::InitialMismatch)
474 It->second = MatchState::UnchangedMismatch;
475 else if (It->second == MatchState::InitialMatch)
476 It->second = MatchState::RemovedMatch;
481void SampleProfileMatcher::countMismatchedFuncSamples(
const FunctionSamples &FS,
483 const auto *FuncDesc = ProbeManager->getDesc(
FS.getGUID());
488 if (ProbeManager->profileIsHashMismatched(*FuncDesc, FS)) {
490 NumStaleProfileFunc++;
495 MismatchedFunctionSamples +=
FS.getTotalSamples();
504 for (
const auto &
I :
FS.getCallsiteSamples())
505 for (
const auto &CS :
I.second)
506 countMismatchedFuncSamples(CS.second,
false);
509void SampleProfileMatcher::countMismatchedCallsiteSamples(
511 auto It = FuncCallsiteMatchStates.find(
FS.getFuncName());
513 if (It == FuncCallsiteMatchStates.end() || It->second.empty())
515 const auto &CallsiteMatchStates = It->second;
517 auto findMatchState = [&](
const LineLocation &Loc) {
518 auto It = CallsiteMatchStates.find(Loc);
519 if (It == CallsiteMatchStates.end())
520 return MatchState::Unknown;
524 auto AttributeMismatchedSamples = [&](
const enum MatchState &State,
526 if (isMismatchState(State))
527 MismatchedCallsiteSamples += Samples;
528 else if (State == MatchState::RecoveredMismatch)
529 RecoveredCallsiteSamples += Samples;
534 for (
const auto &
I :
FS.getBodySamples())
535 AttributeMismatchedSamples(findMatchState(
I.first),
I.second.getSamples());
538 for (
const auto &
I :
FS.getCallsiteSamples()) {
539 auto State = findMatchState(
I.first);
540 uint64_t CallsiteSamples = 0;
541 for (
const auto &CS :
I.second)
542 CallsiteSamples += CS.second.getTotalSamples();
543 AttributeMismatchedSamples(State, CallsiteSamples);
545 if (isMismatchState(State))
551 for (
const auto &CS :
I.second)
552 countMismatchedCallsiteSamples(CS.second);
556void SampleProfileMatcher::countMismatchCallsites(
const FunctionSamples &FS) {
557 auto It = FuncCallsiteMatchStates.find(
FS.getFuncName());
559 if (It == FuncCallsiteMatchStates.end() || It->second.empty())
561 const auto &MatchStates = It->second;
562 [[maybe_unused]]
bool OnInitialState =
563 isInitialState(MatchStates.begin()->second);
564 for (
const auto &
I : MatchStates) {
565 TotalProfiledCallsites++;
567 (OnInitialState ? isInitialState(
I.second) : isFinalState(
I.second)) &&
568 "Profile matching state is inconsistent");
570 if (isMismatchState(
I.second))
571 NumMismatchedCallsites++;
572 else if (
I.second == MatchState::RecoveredMismatch)
573 NumRecoveredCallsites++;
577void SampleProfileMatcher::countCallGraphRecoveredSamples(
579 std::unordered_set<FunctionId> &CallGraphRecoveredProfiles) {
580 if (CallGraphRecoveredProfiles.count(
FS.getFunction())) {
581 NumCallGraphRecoveredFuncSamples +=
FS.getTotalSamples();
585 for (
const auto &CM :
FS.getCallsiteSamples()) {
586 for (
const auto &CS : CM.second) {
587 countCallGraphRecoveredSamples(CS.second, CallGraphRecoveredProfiles);
592void SampleProfileMatcher::computeAndReportProfileStaleness() {
596 std::unordered_set<FunctionId> CallGraphRecoveredProfiles;
598 for (
const auto &
I : FuncToProfileNameMap) {
599 CallGraphRecoveredProfiles.insert(
I.second);
602 NumCallGraphRecoveredProfiledFunc++;
607 for (
const auto &
F : M) {
614 const auto *
FS = Reader.getSamplesFor(
F);
618 TotalFunctionSamples +=
FS->getTotalSamples();
621 countCallGraphRecoveredSamples(*FS, CallGraphRecoveredProfiles);
625 countMismatchedFuncSamples(*FS,
true);
628 countMismatchCallsites(*FS);
629 countMismatchedCallsiteSamples(*FS);
634 errs() <<
"(" << NumStaleProfileFunc <<
"/" << TotalProfiledFunc
635 <<
") of functions' profile are invalid and ("
636 << MismatchedFunctionSamples <<
"/" << TotalFunctionSamples
637 <<
") of samples are discarded due to function hash mismatch.\n";
640 errs() <<
"(" << NumCallGraphRecoveredProfiledFunc <<
"/"
641 << TotalProfiledFunc <<
") of functions' profile are matched and ("
642 << NumCallGraphRecoveredFuncSamples <<
"/" << TotalFunctionSamples
643 <<
") of samples are reused by call graph matching.\n";
646 errs() <<
"(" << (NumMismatchedCallsites + NumRecoveredCallsites) <<
"/"
647 << TotalProfiledCallsites
648 <<
") of callsites' profile are invalid and ("
649 << (MismatchedCallsiteSamples + RecoveredCallsiteSamples) <<
"/"
650 << TotalFunctionSamples
651 <<
") of samples are discarded due to callsite location mismatch.\n";
652 errs() <<
"(" << NumRecoveredCallsites <<
"/"
653 << (NumRecoveredCallsites + NumMismatchedCallsites)
654 <<
") of callsites and (" << RecoveredCallsiteSamples <<
"/"
655 << (RecoveredCallsiteSamples + MismatchedCallsiteSamples)
656 <<
") of samples are recovered by stale profile matching.\n";
660 LLVMContext &Ctx = M.getContext();
665 ProfStatsVec.
emplace_back(
"NumStaleProfileFunc", NumStaleProfileFunc);
666 ProfStatsVec.
emplace_back(
"TotalProfiledFunc", TotalProfiledFunc);
668 MismatchedFunctionSamples);
669 ProfStatsVec.
emplace_back(
"TotalFunctionSamples", TotalFunctionSamples);
673 ProfStatsVec.
emplace_back(
"NumCallGraphRecoveredProfiledFunc",
674 NumCallGraphRecoveredProfiledFunc);
675 ProfStatsVec.
emplace_back(
"NumCallGraphRecoveredFuncSamples",
676 NumCallGraphRecoveredFuncSamples);
679 ProfStatsVec.
emplace_back(
"NumMismatchedCallsites", NumMismatchedCallsites);
680 ProfStatsVec.
emplace_back(
"NumRecoveredCallsites", NumRecoveredCallsites);
681 ProfStatsVec.
emplace_back(
"TotalProfiledCallsites", TotalProfiledCallsites);
683 MismatchedCallsiteSamples);
685 RecoveredCallsiteSamples);
687 auto *MD = MDB.createLLVMStats(ProfStatsVec);
688 auto *NMD = M.getOrInsertNamedMetadata(
"llvm.stats");
693void SampleProfileMatcher::findFunctionsWithoutProfile() {
697 StringSet<> NamesInProfile;
698 if (
auto NameTable = Reader.getNameTable()) {
699 for (
auto Name : *NameTable)
706 if (
F.isDeclaration())
710 const auto *
FS = getFlattenedSamplesFor(
F);
717 if (NamesInProfile.
count(CanonFName))
722 if (PSL && PSL->contains(CanonFName))
726 <<
" is not in profile or profile symbol list.\n");
727 FunctionsWithoutProfile[FunctionId(CanonFName)] = &
F;
731bool SampleProfileMatcher::functionMatchesProfileHelper(
735 float Similarity = 0.0;
742 auto GetBaseName = [&](StringRef FName) {
743 auto FunctionName = FName.str();
744 if (
Demangler.partialDemangle(FunctionName.c_str()))
745 return std::string();
746 size_t BaseNameSize = 0;
750 char *BaseNamePtr =
Demangler.getFunctionBaseName(
nullptr, &BaseNameSize);
751 std::string
Result = (BaseNamePtr && BaseNameSize)
752 ? std::string(BaseNamePtr, BaseNameSize)
757 auto IRBaseName = GetBaseName(IRFunc.
getName());
758 auto ProfBaseName = GetBaseName(ProfFunc.
stringRef());
759 if (!IRBaseName.empty() && IRBaseName == ProfBaseName) {
761 << ProfFunc <<
"(Profile) share the same base name: "
762 << IRBaseName <<
".\n");
766 const auto *FSForMatching = getFlattenedSamplesFor(ProfFunc);
773 DenseSet<StringRef> TopLevelFunc({ProfFunc.
stringRef()});
774 if (std::error_code EC = Reader.read(TopLevelFunc))
776 FSForMatching = Reader.getSamplesFor(ProfFunc.
stringRef());
779 dbgs() <<
"Read top-level function " << ProfFunc
780 <<
" for call-graph matching\n";
795 const auto *FuncDesc = ProbeManager->getDesc(IRFunc);
797 !ProbeManager->profileIsHashMismatched(*FuncDesc, *FSForMatching)) {
799 <<
"(IR) and " << ProfFunc <<
"(Profile) match.\n");
806 findIRAnchors(IRFunc, IRAnchors);
808 findProfileAnchors(*FSForMatching, ProfileAnchors);
812 getFilteredAnchorList(IRAnchors, ProfileAnchors, FilteredIRAnchorsList,
813 FilteredProfileAnchorList);
826 longestCommonSequence(FilteredIRAnchorsList, FilteredProfileAnchorList,
829 Similarity =
static_cast<float>(MatchedAnchors.size()) /
830 FilteredProfileAnchorList.size();
833 <<
"(IR) and " << ProfFunc <<
"(profile) is "
834 <<
format(
"%.2f", Similarity) <<
"\n");
835 assert((Similarity >= 0 && Similarity <= 1.0) &&
836 "Similarity value should be in [0, 1]");
842bool SampleProfileMatcher::functionMatchesProfile(
Function &IRFunc,
844 bool FindMatchedProfileOnly) {
845 auto R = FuncProfileMatchCache.find({&IRFunc, ProfFunc});
846 if (R != FuncProfileMatchCache.end())
849 if (FindMatchedProfileOnly)
852 bool Matched = functionMatchesProfileHelper(IRFunc, ProfFunc);
853 FuncProfileMatchCache[{&IRFunc, ProfFunc}] = Matched;
855 FuncToProfileNameMap[&IRFunc] = ProfFunc;
857 <<
" matches profile:" << ProfFunc <<
"\n");
863void SampleProfileMatcher::UpdateWithSalvagedProfiles() {
864 DenseSet<StringRef> ProfileSalvagedFuncs;
866 for (
auto &
I : FuncToProfileNameMap) {
867 assert(
I.first &&
"New function is null");
868 FunctionId FuncName(
I.first->getName());
869 ProfileSalvagedFuncs.
insert(
I.second.stringRef());
870 FuncNameToProfNameMap->emplace(FuncName,
I.second);
874 SymbolMap->erase(FuncName);
875 SymbolMap->emplace(
I.second,
I.first);
882 Reader.read(ProfileSalvagedFuncs);
883 Reader.setFuncNameToProfNameMap(*FuncNameToProfNameMap);
890 findFunctionsWithoutProfile();
894 std::vector<Function *> TopDownFunctionList;
895 TopDownFunctionList.reserve(M.size());
897 for (
auto *
F : TopDownFunctionList) {
904 UpdateWithSalvagedProfiles();
907 distributeIRToProfileLocationMap();
909 computeAndReportProfileStaleness();
912void SampleProfileMatcher::distributeIRToProfileLocationMap(
914 const auto ProfileMappings = FuncMappings.
find(FS.getFuncName());
915 if (ProfileMappings != FuncMappings.
end()) {
916 FS.setIRToProfileLocationMap(&(ProfileMappings->second));
921 for (
auto &FS : Callees.second) {
922 distributeIRToProfileLocationMap(FS.second);
929void SampleProfileMatcher::distributeIRToProfileLocationMap() {
930 for (
auto &
I : Reader.getProfiles()) {
931 distributeIRToProfileLocationMap(
I.second);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
itanium_demangle::ManglingParser< DefaultAllocator > Demangler
Legalize the Machine IR a function s Machine IR
This file provides the interface for SampleProfileMatcher.
static bool isAvailableExternallyLinkage(LinkageTypes Linkage)
reference emplace_back(ArgTypes &&... Args)
iterator find(StringRef Key)
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
std::pair< typename Base::iterator, bool > insert(StringRef key)
LLVM_ABI 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 LLVM_ABI bool ProfileIsCS
static LLVM_ABI bool ProfileIsProbeBased
static StringRef getCanonicalFnName(const Function &F)
Return the canonical name for a function, taking into account suffix elision policy attributes.
static LLVM_ABI bool ProfileIsFS
If this profile uses flow sensitive discriminators.
static LLVM_ABI LineLocation getCallSiteIdentifier(const DILocation *DIL, bool ProfileIsFS=false)
Returns a unique call site identifier for a given debug location of a call instruction.
static LLVM_ABI bool UseMD5
Whether the profile uses MD5 to represent string.
static void flattenProfile(SampleProfileMap &ProfileMap, bool ProfileIsCS=false)
@ C
The default llvm calling convention, compatible with C.
initializer< Ty > init(const Ty &Val)
std::map< LineLocation, FunctionSamplesMap > CallsiteSampleMap
std::unordered_map< LineLocation, LineLocation, LineLocationHash > LocToLocMap
This is an optimization pass for GlobalISel generic memory operations.
cl::opt< bool > ReportProfileStaleness("report-profile-staleness", cl::Hidden, cl::init(false), cl::desc("Compute and report stale profile statistical metrics."))
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)."))
std::map< LineLocation, FunctionId > AnchorMap
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
static cl::opt< bool > LoadFuncProfileforCGMatching("load-func-profile-for-cg-matching", cl::Hidden, cl::init(true), cl::desc("Load top-level profiles that the sample reader initially skipped for " "the call-graph matching (only meaningful for extended binary " "format)"))
static void buildTopDownFuncOrder(LazyCallGraph &CG, std::vector< Function * > &FunctionOrderList)
@ ThinLTOPreLink
ThinLTO prelink (summary) phase.
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."))
LLVM_ABI std::optional< PseudoProbe > extractProbe(const Instruction &Inst)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
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."))
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
cl::opt< bool > SalvageStaleProfile("salvage-stale-profile", cl::Hidden, cl::init(false), cl::desc("Salvage stale profile by fuzzy matching and use the remapped " "location for sample profile query."))
void longestCommonSequence(AnchorList AnchorList1, AnchorList AnchorList2, llvm::function_ref< bool(const Function &, const Function &)> FunctionMatchesProfile, llvm::function_ref< void(Loc, Loc)> InsertMatching)
std::vector< std::pair< LineLocation, FunctionId > > AnchorList
static bool skipProfileForFunction(const Function &F)
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."))
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 > 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."))