89#include <system_error>
96#define DEBUG_TYPE "sample-profile"
97#define CSINLINE_DEBUG DEBUG_TYPE "-inline"
100 "Number of functions inlined with context sensitive profile");
102 "Number of functions not inlined with context sensitive profile");
104 "Number of functions with CFG mismatched profile");
105STATISTIC(NumMatchedProfile,
"Number of functions with CFG matched profile");
107 "Number of inlined callsites with a partial distribution factor");
110 "Number of functions with FDO inline stopped due to min size limit");
112 "Number of functions with FDO inline stopped due to max size limit");
114 NumCSInlinedHitGrowthLimit,
115 "Number of functions with FDO inline stopped due to growth size limit");
134 cl::desc(
"Salvage stale profile by fuzzy matching and use the remapped "
135 "location for sample profile query."));
138 cl::desc(
"Salvage unused profile by matching with new "
139 "functions on call graph."));
143 cl::desc(
"Compute and report stale profile statistical metrics."));
147 cl::desc(
"Compute stale profile statistical metrics and write it into the "
148 "native object file(.llvm_stats section)."));
152 cl::desc(
"If the sample profile is accurate, we will mark all un-sampled "
153 "callsite and function as having 0 samples. Otherwise, treat "
154 "un-sampled callsites and functions conservatively as unknown. "));
158 cl::desc(
"If the sample profile is accurate, we will mark all un-sampled "
159 "branches and calls as having 0 samples. Otherwise, treat "
160 "them conservatively as unknown. "));
164 cl::desc(
"For symbols in profile symbol list, regard their profiles to "
165 "be accurate. It may be overridden by profile-sample-accurate. "));
169 cl::desc(
"Merge past inlinee's profile to outline version if sample "
170 "profile loader decided not to inline a call site. It will "
171 "only be enabled when top-down order of profile loading is "
176 cl::desc(
"Do profile annotation and inlining for functions in top-down "
177 "order of call graph during sample profile loading. It only "
178 "works for new pass manager. "));
182 cl::desc(
"Process functions in a top-down order "
183 "defined by the profiled call graph when "
184 "-sample-profile-top-down-load is on."));
188 cl::desc(
"Inline cold call sites in profile loader if it's beneficial "
197 "If true, artificially skip inline transformation in sample-loader "
198 "pass, and merge (or scale) profiles (as configured by "
199 "--sample-profile-merge-inlinee)."));
203 cl::desc(
"Sort profiled recursion by edge weights."));
207 cl::desc(
"The size growth ratio limit for proirity-based sample profile "
208 "loader inlining."));
212 cl::desc(
"The lower bound of size growth limit for "
213 "proirity-based sample profile loader inlining."));
217 cl::desc(
"The upper bound of size growth limit for "
218 "proirity-based sample profile loader inlining."));
222 cl::desc(
"Hot callsite threshold for proirity-based sample profile loader "
227 cl::desc(
"Threshold for inlining cold callsites"));
233 "Relative hotness percentage threshold for indirect "
234 "call promotion in proirity-based sample profile loader inlining."));
239 "Skip relative hotness check for ICP up to given number of targets."));
243 cl::desc(
"A function is considered hot for staleness error check if its "
244 "total sample count is above the specified percentile"));
248 cl::desc(
"Skip the check if the number of hot functions is smaller than "
249 "the specified number."));
253 cl::desc(
"Reject the profile if the mismatch percent is higher than the "
257 "sample-profile-prioritized-inline",
cl::Hidden,
258 cl::desc(
"Use call site prioritized inlining for sample profile loader. "
259 "Currently only CSSPGO is supported."));
263 cl::desc(
"Use the preinliner decisions stored in profile context."));
266 "sample-profile-recursive-inline",
cl::Hidden,
267 cl::desc(
"Allow sample loader inliner to inline recursive calls."));
271 cl::desc(
"Remove pseudo-probe after sample profile annotation."));
276 "Optimization remarks file containing inline remarks to be replayed "
277 "by inlining from sample profile loader."),
281 "sample-profile-inline-replay-scope",
284 "Replay on functions that have remarks associated "
285 "with them (default)"),
287 "Replay on the entire module")),
288 cl::desc(
"Whether inline replay should be applied to the entire "
289 "Module or just the Functions (default) that are present as "
290 "callers in remarks during sample profile inlining."),
294 "sample-profile-inline-replay-fallback",
299 "All decisions not in replay send to original advisor (default)"),
301 "AlwaysInline",
"All decisions not in replay are inlined"),
303 "All decisions not in replay are not inlined")),
304 cl::desc(
"How sample profile inline replay treats sites that don't come "
305 "from the replay. Original: defers to original advisor, "
306 "AlwaysInline: inline all sites not in replay, NeverInline: "
307 "inline no sites not in replay"),
311 "sample-profile-inline-replay-format",
316 "<Line Number>:<Column Number>"),
318 "LineDiscriminator",
"<Line Number>.<Discriminator>"),
320 "LineColumnDiscriminator",
321 "<Line Number>:<Column Number>.<Discriminator> (default)")),
326 cl::desc(
"Max number of promotions for a single indirect "
327 "call callsite in sample profile loader"));
331 cl::desc(
"Ignore existing branch weights on IR and always overwrite."));
335 cl::desc(
"Annotate LTO phase (prelink / postlink), or main (no LTO) for "
336 "sample-profile inline pass name."));
346using Edge = std::pair<const BasicBlock *, const BasicBlock *>;
350class GUIDToFuncNameMapper {
355 CurrentGUIDToFuncNameMap(GUIDToFuncNameMap) {
359 for (
const auto &
F : CurrentModule) {
361 CurrentGUIDToFuncNameMap.insert(
372 if (CanonName != OrigName)
373 CurrentGUIDToFuncNameMap.insert(
378 SetGUIDToFuncNameMapForAll(&CurrentGUIDToFuncNameMap);
381 ~GUIDToFuncNameMapper() {
385 CurrentGUIDToFuncNameMap.clear();
389 SetGUIDToFuncNameMapForAll(
nullptr);
394 std::queue<FunctionSamples *> FSToUpdate;
396 FSToUpdate.push(&IFS.second);
399 while (!FSToUpdate.empty()) {
402 FS->GUIDToFuncNameMap = Map;
403 for (
const auto &ICS : FS->getCallsiteSamples()) {
405 for (
const auto &IFS : FSMap) {
407 FSToUpdate.push(&FS);
419struct InlineCandidate {
421 const FunctionSamples *CalleeSamples;
429 float CallsiteDistribution;
433struct CandidateComparer {
434 bool operator()(
const InlineCandidate &
LHS,
const InlineCandidate &
RHS) {
435 if (
LHS.CallsiteCount !=
RHS.CallsiteCount)
436 return LHS.CallsiteCount <
RHS.CallsiteCount;
438 const FunctionSamples *LCS =
LHS.CalleeSamples;
439 const FunctionSamples *RCS =
RHS.CalleeSamples;
454using CandidateQueue =
467 IntrusiveRefCntPtr<vfs::FileSystem> FS,
468 std::function<AssumptionCache &(
Function &)> GetAssumptionCache,
469 std::function<TargetTransformInfo &(
Function &)> GetTargetTransformInfo,
470 std::function<
const TargetLibraryInfo &(
Function &)> GetTLI,
471 LazyCallGraph &CG,
bool DisableSampleProfileInlining,
472 bool UseFlattenedProfile)
475 GetAC(std::
move(GetAssumptionCache)),
476 GetTTI(std::
move(GetTargetTransformInfo)), GetTLI(std::
move(GetTLI)),
477 CG(CG), LTOPhase(LTOPhase),
482 DisableSampleProfileInlining(DisableSampleProfileInlining),
483 UseFlattenedProfile(UseFlattenedProfile) {}
487 ProfileSummaryInfo *_PSI);
492 ErrorOr<uint64_t> getInstWeight(
const Instruction &
I)
override;
493 const FunctionSamples *findCalleeFunctionSamples(
const CallBase &
I)
const;
494 const FunctionSamples *
495 findFunctionSamples(
const Instruction &
I)
const override;
496 std::vector<const FunctionSamples *>
497 findIndirectCallFunctionSamples(
const Instruction &
I,
uint64_t &Sum)
const;
498 void findExternalInlineCandidate(CallBase *CB,
const FunctionSamples *Samples,
499 DenseSet<GlobalValue::GUID> &InlinedGUIDs,
502 bool tryPromoteAndInlineCandidate(
507 DenseSet<GlobalValue::GUID> &InlinedGUIDs);
508 std::optional<InlineCost> getExternalInlineAdvisorCost(CallBase &CB);
509 bool getExternalInlineAdvisorShouldInline(CallBase &CB);
510 InlineCost shouldInlineCandidate(InlineCandidate &Candidate);
511 bool getInlineCandidate(InlineCandidate *NewCandidate, CallBase *CB);
513 tryInlineCandidate(InlineCandidate &Candidate,
516 inlineHotFunctionsWithPriority(
Function &
F,
517 DenseSet<GlobalValue::GUID> &InlinedGUIDs);
519 bool shouldInlineColdCallee(CallBase &CallInst);
520 void emitOptimizationRemarksForInlineCandidates(
521 const SmallVectorImpl<CallBase *> &Candidates,
const Function &
F,
523 void promoteMergeNotInlinedContextSamples(
524 MapVector<CallBase *, const FunctionSamples *> NonInlinedCallSites,
526 std::vector<Function *> buildFunctionOrder(
Module &M, LazyCallGraph &CG);
527 std::unique_ptr<ProfiledCallGraph> buildProfiledCallGraph(
Module &M);
528 void generateMDProfMetadata(
Function &
F);
529 bool rejectHighStalenessProfile(
Module &M, ProfileSummaryInfo *PSI,
530 const SampleProfileMap &Profiles);
531 void removePseudoProbeInstsDiscriminator(
Module &M);
537 HashKeyMap<DenseMap, FunctionId, Function *> SymbolMap;
541 HashKeyMap<DenseMap, FunctionId, FunctionId> FuncNameToProfNameMap;
543 std::function<AssumptionCache &(
Function &)> GetAC;
544 std::function<TargetTransformInfo &(
Function &)> GetTTI;
545 std::function<
const TargetLibraryInfo &(
Function &)> GetTLI;
549 std::unique_ptr<SampleContextTracker> ContextTracker;
557 const std::string AnnotatedPassName;
561 std::shared_ptr<ProfileSymbolList> PSL;
566 struct NotInlinedProfileInfo {
569 DenseMap<Function *, NotInlinedProfileInfo> notInlinedCallInfo;
573 DenseMap<uint64_t, StringRef> GUIDToFuncNameMap;
580 bool ProfAccForSymsInList;
582 bool DisableSampleProfileInlining;
584 bool UseFlattenedProfile;
587 std::unique_ptr<InlineAdvisor> ExternalInlineAdvisor;
590 std::unique_ptr<SampleProfileMatcher> MatchingManager;
593 const char *getAnnotatedRemarkPassName()
const {
594 return AnnotatedPassName.c_str();
601inline bool SampleProfileInference<Function>::isExit(
const BasicBlock *BB) {
606inline void SampleProfileInference<Function>::findUnlikelyJumps(
607 const std::vector<const BasicBlockT *> &BasicBlocks,
609 for (
auto &Jump :
Func.Jumps) {
610 const auto *BB = BasicBlocks[Jump.Source];
611 const auto *Succ = BasicBlocks[Jump.Target];
615 const auto &Succs = Successors[BB];
616 if (Succs.size() == 2 && Succs.back() == Succ) {
618 Jump.IsUnlikely =
true;
625 Jump.IsUnlikely =
true;
646 return getProbeWeight(Inst);
650 return std::error_code();
656 return std::error_code();
666 if (!CB->isIndirectCall() && findCalleeFunctionSamples(*CB))
669 return getInstWeightImpl(Inst);
684const FunctionSamples *
685SampleProfileLoader::findCalleeFunctionSamples(
const CallBase &Inst)
const {
691 StringRef CalleeName;
693 CalleeName =
Callee->getName();
696 return ContextTracker->getCalleeContextSamplesFor(Inst, CalleeName);
698 const FunctionSamples *
FS = findFunctionSamples(Inst);
703 CalleeName, Reader->getRemapper(),
704 &FuncNameToProfNameMap);
710std::vector<const FunctionSamples *>
711SampleProfileLoader::findIndirectCallFunctionSamples(
712 const Instruction &Inst,
uint64_t &Sum)
const {
714 std::vector<const FunctionSamples *>
R;
720 auto FSCompare = [](
const FunctionSamples *
L,
const FunctionSamples *
R) {
721 assert(L && R &&
"Expect non-null FunctionSamples");
722 if (
L->getHeadSamplesEstimate() !=
R->getHeadSamplesEstimate())
723 return L->getHeadSamplesEstimate() >
R->getHeadSamplesEstimate();
724 return L->getGUID() <
R->getGUID();
729 ContextTracker->getIndirectCalleeContextSamplesFor(DIL);
730 if (CalleeSamples.empty())
736 for (
const auto *
const FS : CalleeSamples) {
737 Sum +=
FS->getHeadSamplesEstimate();
744 const FunctionSamples *
FS = findFunctionSamples(Inst);
750 if (
auto T =
FS->findCallTargetMapAt(CallSite))
751 for (
const auto &T_C : *
T)
756 for (
const auto &NameFS : *M) {
757 Sum += NameFS.second.getHeadSamplesEstimate();
758 R.push_back(&NameFS.second);
765const FunctionSamples *
766SampleProfileLoader::findFunctionSamples(
const Instruction &Inst)
const {
777 auto it = DILocation2SampleMap.try_emplace(DIL,
nullptr);
780 it.first->second = ContextTracker->getContextSamplesFor(DIL);
782 it.first->second = Samples->findFunctionSamples(
783 DIL, Reader->getRemapper(), &FuncNameToProfNameMap);
785 return it.first->second;
801 if (ValueData.empty())
804 unsigned NumPromoted = 0;
805 for (
const auto &V : ValueData) {
847 "If sum is 0, assume only one element in CallTargets "
848 "with count being NOMORE_ICP_MAGICNUM");
850 for (
const auto &V : ValueData)
851 ValueCountMap[V.Value] = V.Count;
857 OldSum -= Pair.first->second;
864 for (
const auto &V : ValueData) {
866 ValueCountMap[V.Value] = V.Count;
869 for (
const auto &
Data : CallTargets) {
876 assert(Sum >=
Data.Count &&
"Sum should never be less than Data.Count");
882 for (
const auto &ValueCount : ValueCountMap) {
884 InstrProfValueData{ValueCount.first, ValueCount.second});
888 [](
const InstrProfValueData &L,
const InstrProfValueData &R) {
889 return std::tie(L.Count, L.Value) > std::tie(R.Count, R.Value);
895 NewCallTargets, Sum, IPVK_IndirectCallTarget, MaxMDCount);
908bool SampleProfileLoader::tryPromoteAndInlineCandidate(
912 if (DisableSampleProfileInlining)
919 auto CalleeFunctionName = Candidate.CalleeSamples->
getFunction();
920 auto R = SymbolMap.find(CalleeFunctionName);
921 if (R == SymbolMap.end() || !
R->second)
924 auto &CI = *Candidate.CallInstr;
928 const char *Reason =
"Callee function not available";
935 if (!
R->second->isDeclaration() &&
R->second->getSubprogram() &&
936 R->second->hasFnAttribute(
"use-sample-profile") &&
941 Function::getGUIDAssumingExternalLinkage(
R->second->getName()),
946 CI,
R->second, Candidate.CallsiteCount, Sum,
false, ORE);
948 Sum -= Candidate.CallsiteCount;
961 Candidate.CallInstr = DI;
963 bool Inlined = tryInlineCandidate(Candidate, InlinedCallSite);
968 *DI,
static_cast<float>(Candidate.CallsiteCount) / SumOrigin);
976 Candidate.CallInstr->
getName())<<
" because "
982bool SampleProfileLoader::shouldInlineColdCallee(CallBase &CallInst) {
987 if (Callee ==
nullptr)
1002void SampleProfileLoader::emitOptimizationRemarksForInlineCandidates(
1003 const SmallVectorImpl<CallBase *> &Candidates,
const Function &
F,
1005 for (
auto *
I : Candidates) {
1006 Function *CalledFunction =
I->getCalledFunction();
1007 if (CalledFunction) {
1008 ORE->emit(OptimizationRemarkAnalysis(getAnnotatedRemarkPassName(),
1009 "InlineAttempt",
I->getDebugLoc(),
1011 <<
"previous inlining reattempted for "
1012 << (
Hot ?
"hotness: '" :
"size: '")
1013 <<
ore::NV(
"Callee", CalledFunction) <<
"' into '"
1019void SampleProfileLoader::findExternalInlineCandidate(
1020 CallBase *CB,
const FunctionSamples *Samples,
1021 DenseSet<GlobalValue::GUID> &InlinedGUIDs,
uint64_t Threshold) {
1025 if (CB && getExternalInlineAdvisorShouldInline(*CB)) {
1029 InlinedGUIDs.
insert(Function::getGUIDAssumingExternalLinkage(
1055 ContextTrieNode *
Caller = ContextTracker->getContextNodeForProfile(Samples);
1056 std::queue<ContextTrieNode *> CalleeList;
1057 CalleeList.push(Caller);
1058 while (!CalleeList.empty()) {
1059 ContextTrieNode *
Node = CalleeList.front();
1061 FunctionSamples *CalleeSample =
Node->getFunctionSamples();
1077 if (!Func ||
Func->isDeclaration())
1083 for (
const auto &TS : BS.second.getCallTargets())
1084 if (TS.second > Threshold) {
1086 if (!Callee ||
Callee->isDeclaration())
1087 InlinedGUIDs.
insert(TS.first.getHashCode());
1094 for (
auto &Child :
Node->getAllChildContext()) {
1095 ContextTrieNode *CalleeNode = &Child.second;
1096 CalleeList.push(CalleeNode);
1123bool SampleProfileLoader::inlineHotFunctions(
1124 Function &
F, DenseSet<GlobalValue::GUID> &InlinedGUIDs) {
1127 assert((!ProfAccForSymsInList ||
1129 !
F.hasFnAttribute(
"profile-sample-accurate"))) &&
1130 "ProfAccForSymsInList should be false when profile-sample-accurate "
1133 MapVector<CallBase *, const FunctionSamples *> LocalNotInlinedCallSites;
1135 bool LocalChanged =
true;
1136 while (LocalChanged) {
1137 LocalChanged =
false;
1139 for (
auto &BB :
F) {
1143 for (
auto &
I : BB) {
1144 const FunctionSamples *
FS =
nullptr;
1147 if ((FS = findCalleeFunctionSamples(*CB))) {
1149 "GUIDToFuncNameMap has to be populated");
1151 if (
FS->getHeadSamplesEstimate() > 0 ||
1153 LocalNotInlinedCallSites.
insert({CB,
FS});
1156 else if (shouldInlineColdCallee(*CB))
1158 }
else if (getExternalInlineAdvisorShouldInline(*CB)) {
1164 if (
Hot || ExternalInlineAdvisor) {
1166 emitOptimizationRemarksForInlineCandidates(AllCandidates,
F,
true);
1169 emitOptimizationRemarksForInlineCandidates(ColdCandidates,
F,
false);
1172 for (CallBase *
I : CIS) {
1173 Function *CalledFunction =
I->getCalledFunction();
1174 InlineCandidate Candidate = {
I, LocalNotInlinedCallSites.
lookup(
I),
1178 if (CalledFunction == &
F)
1180 if (
I->isIndirectCall()) {
1182 for (
const auto *FS : findIndirectCallFunctionSamples(*
I, Sum)) {
1184 if (LTOPhase == ThinOrFullLTOPhase::ThinLTOPreLink) {
1185 findExternalInlineCandidate(
I, FS, InlinedGUIDs,
1186 PSI->getOrCompHotCountThreshold());
1192 Candidate = {
I,
FS,
FS->getHeadSamplesEstimate(), 1.0};
1193 if (tryPromoteAndInlineCandidate(
F, Candidate, SumOrigin, Sum)) {
1194 LocalNotInlinedCallSites.
erase(
I);
1195 LocalChanged =
true;
1198 }
else if (CalledFunction && CalledFunction->
getSubprogram() &&
1200 if (tryInlineCandidate(Candidate)) {
1201 LocalNotInlinedCallSites.
erase(
I);
1202 LocalChanged =
true;
1204 }
else if (LTOPhase == ThinOrFullLTOPhase::ThinLTOPreLink) {
1205 findExternalInlineCandidate(
I, findCalleeFunctionSamples(*
I),
1207 PSI->getOrCompHotCountThreshold());
1216 promoteMergeNotInlinedContextSamples(LocalNotInlinedCallSites,
F);
1220bool SampleProfileLoader::tryInlineCandidate(
1224 if (DisableSampleProfileInlining)
1227 CallBase &CB = *Candidate.CallInstr;
1229 assert(CalledFunction &&
"Expect a callee with definition");
1233 InlineCost
Cost = shouldInlineCandidate(Candidate);
1234 if (
Cost.isNever()) {
1235 ORE->emit(OptimizationRemarkAnalysis(getAnnotatedRemarkPassName(),
1236 "InlineFail", DLoc, BB)
1237 <<
"incompatible inlining");
1244 InlineFunctionInfo IFI(GetAC);
1245 IFI.UpdateProfile =
false;
1248 if (!
IR.isSuccess())
1253 Cost,
true, getAnnotatedRemarkPassName());
1256 if (InlinedCallSites) {
1257 InlinedCallSites->
clear();
1262 ContextTracker->markContextSamplesInlined(Candidate.CalleeSamples);
1272 if (Candidate.CallsiteDistribution < 1) {
1273 for (
auto &
I : IFI.InlinedCallSites) {
1276 Candidate.CallsiteDistribution);
1278 NumDuplicatedInlinesite++;
1284bool SampleProfileLoader::getInlineCandidate(InlineCandidate *NewCandidate,
1286 assert(CB &&
"Expect non-null call instruction");
1292 const FunctionSamples *CalleeSamples = findCalleeFunctionSamples(*CB);
1295 if (!CalleeSamples && !getExternalInlineAdvisorShouldInline(*CB))
1299 if (std::optional<PseudoProbe> Probe =
extractProbe(*CB))
1300 Factor = Probe->Factor;
1304 *NewCandidate = {CB, CalleeSamples, CallsiteCount, Factor};
1308std::optional<InlineCost>
1309SampleProfileLoader::getExternalInlineAdvisorCost(CallBase &CB) {
1310 std::unique_ptr<InlineAdvice> Advice =
nullptr;
1311 if (ExternalInlineAdvisor) {
1312 Advice = ExternalInlineAdvisor->getAdvice(CB);
1314 if (!Advice->isInliningRecommended()) {
1315 Advice->recordUnattemptedInlining();
1318 Advice->recordInlining();
1326bool SampleProfileLoader::getExternalInlineAdvisorShouldInline(CallBase &CB) {
1327 std::optional<InlineCost>
Cost = getExternalInlineAdvisorCost(CB);
1332SampleProfileLoader::shouldInlineCandidate(InlineCandidate &Candidate) {
1333 if (std::optional<InlineCost> ReplayCost =
1334 getExternalInlineAdvisorCost(*Candidate.CallInstr))
1340 if (Candidate.CallsiteCount > PSI->getHotCountThreshold())
1347 assert(Callee &&
"Expect a definition for inline candidate of direct call");
1360 GetTTI(*Callee), GetAC, GetTLI);
1363 if (
Cost.isNever() ||
Cost.isAlways())
1397bool SampleProfileLoader::inlineHotFunctionsWithPriority(
1398 Function &
F, DenseSet<GlobalValue::GUID> &InlinedGUIDs) {
1401 assert((!ProfAccForSymsInList ||
1403 !
F.hasFnAttribute(
"profile-sample-accurate"))) &&
1404 "ProfAccForSymsInList should be false when profile-sample-accurate "
1409 CandidateQueue CQueue;
1410 InlineCandidate NewCandidate;
1411 for (
auto &BB :
F) {
1413 if (getInlineCandidate(&NewCandidate, &CB))
1414 CQueue.push(NewCandidate);
1423 "Max inline size limit should not be smaller than min inline size "
1428 if (ExternalInlineAdvisor)
1429 SizeLimit = std::numeric_limits<unsigned>::max();
1431 MapVector<CallBase *, const FunctionSamples *> LocalNotInlinedCallSites;
1435 while (!CQueue.empty() &&
F.getInstructionCount() <
SizeLimit) {
1436 InlineCandidate Candidate = CQueue.top();
1438 CallBase *
I = Candidate.CallInstr;
1439 Function *CalledFunction =
I->getCalledFunction();
1441 if (CalledFunction == &
F)
1443 if (
I->isIndirectCall()) {
1445 auto CalleeSamples = findIndirectCallFunctionSamples(*
I, Sum);
1447 Sum *= Candidate.CallsiteDistribution;
1448 unsigned ICPCount = 0;
1449 for (
const auto *FS : CalleeSamples) {
1451 if (LTOPhase == ThinOrFullLTOPhase::ThinLTOPreLink) {
1452 findExternalInlineCandidate(
I, FS, InlinedGUIDs,
1453 PSI->getOrCompHotCountThreshold());
1457 FS->getHeadSamplesEstimate() * Candidate.CallsiteDistribution;
1472 if (!PSI->isHotCount(EntryCountDistributed))
1477 Candidate = {
I,
FS, EntryCountDistributed,
1478 Candidate.CallsiteDistribution};
1479 if (tryPromoteAndInlineCandidate(
F, Candidate, SumOrigin, Sum,
1480 &InlinedCallSites)) {
1481 for (
auto *CB : InlinedCallSites) {
1482 if (getInlineCandidate(&NewCandidate, CB))
1483 CQueue.emplace(NewCandidate);
1487 }
else if (!ContextTracker) {
1488 LocalNotInlinedCallSites.
insert({
I,
FS});
1491 }
else if (CalledFunction && CalledFunction->
getSubprogram() &&
1494 if (tryInlineCandidate(Candidate, &InlinedCallSites)) {
1495 for (
auto *CB : InlinedCallSites) {
1496 if (getInlineCandidate(&NewCandidate, CB))
1497 CQueue.emplace(NewCandidate);
1500 }
else if (!ContextTracker) {
1501 LocalNotInlinedCallSites.
insert({
I, Candidate.CalleeSamples});
1503 }
else if (LTOPhase == ThinOrFullLTOPhase::ThinLTOPreLink) {
1504 findExternalInlineCandidate(
I, findCalleeFunctionSamples(*
I),
1506 PSI->getOrCompHotCountThreshold());
1510 if (!CQueue.empty()) {
1512 ++NumCSInlinedHitMaxLimit;
1514 ++NumCSInlinedHitMinLimit;
1516 ++NumCSInlinedHitGrowthLimit;
1522 promoteMergeNotInlinedContextSamples(LocalNotInlinedCallSites,
F);
1526void SampleProfileLoader::promoteMergeNotInlinedContextSamples(
1527 MapVector<CallBase *, const FunctionSamples *> NonInlinedCallSites,
1530 for (
const auto &Pair : NonInlinedCallSites) {
1531 CallBase *
I = Pair.first;
1533 if (!Callee ||
Callee->isDeclaration())
1537 OptimizationRemarkAnalysis(getAnnotatedRemarkPassName(),
"NotInline",
1538 I->getDebugLoc(),
I->getParent())
1539 <<
"previous inlining not repeated: '" <<
ore::NV(
"Callee", Callee)
1540 <<
"' into '" <<
ore::NV(
"Caller", &
F) <<
"'");
1543 const FunctionSamples *
FS = Pair.second;
1544 if (
FS->getTotalSamples() == 0 &&
FS->getHeadSamplesEstimate() == 0) {
1558 if (
FS->getHeadSamples() == 0) {
1561 const_cast<FunctionSamples *
>(
FS)->addHeadSamples(
1562 FS->getHeadSamplesEstimate());
1567 FunctionSamples *OutlineFS = Reader->getSamplesFor(*Callee);
1571 OutlineFS = &OutlineFunctionSamples[
1573 OutlineFS->
merge(*FS, 1);
1579 notInlinedCallInfo.try_emplace(Callee, NotInlinedProfileInfo{0});
1580 pair.first->second.entryCount +=
FS->getHeadSamplesEstimate();
1591 InstrProfValueData{
I.first.getHashCode(),
I.second});
1598void SampleProfileLoader::generateMDProfMetadata(
Function &
F) {
1601 LLVM_DEBUG(
dbgs() <<
"\nPropagation complete. Setting branch weights\n");
1602 LLVMContext &Ctx =
F.getContext();
1604 for (
auto &BI :
F) {
1607 if (BlockWeights[BB]) {
1608 for (
auto &
I : *BB) {
1615 const DILocation *DIL = DLoc;
1616 const FunctionSamples *
FS = findFunctionSamples(
I);
1620 ErrorOr<SampleRecord::CallTargetMap>
T =
1621 FS->findCallTargetMapAt(CallSite);
1622 if (!
T ||
T.get().empty())
1629 if (Probe->Factor < 1)
1636 for (
const auto &
C :
T.get())
1643 FS->findFunctionSamplesMapAt(CallSite)) {
1644 for (
const auto &NameFS : *M)
1645 Sum += NameFS.second.getHeadSamplesEstimate();
1651 I.setMetadata(LLVMContext::MD_prof,
nullptr);
1654 I, ArrayRef<uint32_t>{
static_cast<uint32_t
>(BlockWeights[BB])},
1661 for (
auto &
I : *BB) {
1664 I.setMetadata(LLVMContext::MD_prof,
nullptr);
1682 << ((BranchLoc) ? Twine(BranchLoc.
getLine())
1683 : Twine(
"<UNKNOWN LOCATION>"))
1685 SmallVector<uint32_t, 4> Weights;
1686 uint32_t MaxWeight = 0;
1691 DenseMap<const BasicBlock *, uint64_t> EdgeMultiplicity;
1692 std::vector<uint64_t> EdgeIndex;
1697 EdgeIndex[
I] = EdgeMultiplicity[Succ];
1698 EdgeMultiplicity[Succ]++;
1703 Edge E = std::make_pair(BB, Succ);
1709 if (Weight > std::numeric_limits<uint32_t>::max()) {
1711 Weight = std::numeric_limits<uint32_t>::max();
1716 Weights.
push_back(
static_cast<uint32_t
>(
1717 Weight == std::numeric_limits<uint32_t>::max() ? Weight
1722 uint64_t W = Weight / EdgeMultiplicity[Succ];
1724 if (EdgeIndex[
I] < Weight % EdgeMultiplicity[Succ])
1726 Weights.
push_back(
static_cast<uint32_t
>(W));
1729 if (Weight > MaxWeight) {
1731 MaxDestInst = &*Succ->getFirstNonPHIOrLifetime();
1747 if (MaxWeight > 0 &&
1752 return OptimizationRemark(
DEBUG_TYPE,
"PopularDest", MaxDestInst)
1753 <<
"most popular destination for conditional branches at "
1754 <<
ore::NV(
"CondBranchesLoc", BranchLoc);
1773bool SampleProfileLoader::emitAnnotations(
Function &
F) {
1778 if (!ProbeManager->getDesc(
F))
1779 dbgs() <<
"Probe descriptor missing for Function " <<
F.getName()
1783 if (ProbeManager->profileIsValid(
F, *Samples)) {
1784 ++NumMatchedProfile;
1786 ++NumMismatchedProfile;
1788 dbgs() <<
"Profile is invalid due to CFG mismatch for Function "
1789 <<
F.getName() <<
"\n");
1794 if (getFunctionLoc(
F) == 0)
1798 <<
F.getName() <<
": " << getFunctionLoc(
F) <<
"\n");
1801 DenseSet<GlobalValue::GUID> InlinedGUIDs;
1803 Changed |= inlineHotFunctionsWithPriority(
F, InlinedGUIDs);
1805 Changed |= inlineHotFunctions(
F, InlinedGUIDs);
1807 Changed |= computeAndPropagateWeights(
F, InlinedGUIDs);
1810 generateMDProfMetadata(
F);
1812 emitCoverageRemarks(
F);
1816std::unique_ptr<ProfiledCallGraph>
1817SampleProfileLoader::buildProfiledCallGraph(
Module &M) {
1818 std::unique_ptr<ProfiledCallGraph> ProfiledCG;
1820 ProfiledCG = std::make_unique<ProfiledCallGraph>(*ContextTracker);
1822 ProfiledCG = std::make_unique<ProfiledCallGraph>(Reader->getProfiles());
1830 ProfiledCG->addProfiledFunction(
1837std::vector<Function *>
1838SampleProfileLoader::buildFunctionOrder(
Module &M, LazyCallGraph &CG) {
1839 std::vector<Function *> FunctionOrderList;
1840 FunctionOrderList.reserve(
M.size());
1843 errs() <<
"WARNING: -use-profiled-call-graph ignored, should be used "
1844 "together with -sample-profile-top-down-load.\n";
1858 FunctionOrderList.push_back(&
F);
1859 return FunctionOrderList;
1912 std::unique_ptr<ProfiledCallGraph> ProfiledCG = buildProfiledCallGraph(M);
1913 scc_iterator<ProfiledCallGraph *> CGI =
scc_begin(ProfiledCG.get());
1918 scc_member_iterator<ProfiledCallGraph *>
SI(*CGI);
1921 for (
auto *Node :
Range) {
1924 FunctionOrderList.push_back(
F);
1928 std::reverse(FunctionOrderList.begin(), FunctionOrderList.end());
1933 dbgs() <<
"Function processing order:\n";
1934 for (
auto F : FunctionOrderList) {
1935 dbgs() <<
F->getName() <<
"\n";
1939 return FunctionOrderList;
1942bool SampleProfileLoader::doInitialization(
Module &M,
1944 auto &Ctx =
M.getContext();
1947 Filename, Ctx, *FS, FSDiscriminatorPass::Base, RemappingFilename);
1948 if (std::error_code EC = ReaderOrErr.getError()) {
1949 std::string
Msg =
"Could not open profile: " +
EC.message();
1953 Reader = std::move(ReaderOrErr.get());
1954 Reader->setSkipFlatProf(LTOPhase == ThinOrFullLTOPhase::ThinLTOPostLink);
1957 Reader->setModule(&M);
1958 if (std::error_code EC = Reader->read()) {
1959 std::string
Msg =
"profile reading failed: " +
EC.message();
1964 PSL = Reader->getProfileSymbolList();
1969 if (UseFlattenedProfile)
1971 Reader->profileIsCS());
1974 ProfAccForSymsInList =
1976 if (ProfAccForSymsInList)
1977 CoverageTracker.setProfAccForSymsInList(
true);
1981 M, *
FAM, Ctx,
nullptr,
1986 false, InlineContext{LTOPhase, InlinePass::ReplaySampleProfileInliner});
1990 if (Reader->profileIsCS() || Reader->profileIsPreInlined() ||
1991 Reader->profileIsProbeBased()) {
2007 if (Reader->profileIsPreInlined()) {
2017 if (Reader->profileIsProbeBased()) {
2024 if (!Reader->profileIsCS()) {
2036 if (Reader->profileIsCS()) {
2038 ContextTracker = std::make_unique<SampleContextTracker>(
2039 Reader->getProfiles(), &GUIDToFuncNameMap);
2043 if (Reader->profileIsProbeBased()) {
2044 ProbeManager = std::make_unique<PseudoProbeManager>(M);
2045 if (!ProbeManager->moduleIsProbed(M)) {
2047 "Pseudo-probe-based profile requires SampleProfileProbePass";
2048 Ctx.
diagnose(DiagnosticInfoSampleProfile(
M.getModuleIdentifier(),
Msg,
2056 MatchingManager = std::make_unique<SampleProfileMatcher>(
2057 M, *Reader, CG, ProbeManager.get(), LTOPhase, SymbolMap, PSL,
2058 FuncNameToProfNameMap);
2074bool SampleProfileLoader::rejectHighStalenessProfile(
2075 Module &M, ProfileSummaryInfo *PSI,
const SampleProfileMap &Profiles) {
2077 "Only support for probe-based profile");
2080 for (
const auto &
I : Profiles) {
2081 const auto &
FS =
I.second;
2082 const auto *FuncDesc = ProbeManager->getDesc(
FS.getGUID());
2088 FS.getTotalSamples()))
2092 if (ProbeManager->profileIsHashMismatched(*FuncDesc, FS) &&
2093 !ProbeManager->probeFromWeakSymbol(
FS.getGUID()))
2094 NumMismatchedFunc++;
2102 if (NumMismatchedFunc * 100 >=
2104 auto &Ctx =
M.getContext();
2106 "The input profile significantly mismatches current source code. "
2107 "Please recollect profile to avoid performance regression.";
2108 Ctx.
diagnose(DiagnosticInfoSampleProfile(
M.getModuleIdentifier(),
Msg));
2114void SampleProfileLoader::removePseudoProbeInstsDiscriminator(
Module &M) {
2116 std::vector<Instruction *> InstsToDel;
2117 for (
auto &BB :
F) {
2118 for (
auto &
I : BB) {
2120 InstsToDel.push_back(&
I);
2122 if (
const DILocation *DIL =
I.getDebugLoc().get()) {
2126 std::optional<uint32_t> DwarfDiscriminator =
2135 for (
auto *
I : InstsToDel)
2136 I->eraseFromParent();
2141 ProfileSummaryInfo *_PSI) {
2142 GUIDToFuncNameMapper
Mapper(M, *Reader, GUIDToFuncNameMap);
2145 if (
M.getProfileSummary(
false) ==
nullptr) {
2146 M.setProfileSummary(Reader->getSummary().getMD(
M.getContext()),
2152 rejectHighStalenessProfile(M, PSI, Reader->getProfiles()))
2155 auto Remapper = Reader->getRemapper();
2157 for (
const auto &N_F :
M.getValueSymbolTable()) {
2158 StringRef OrigName = N_F.getKey();
2160 if (
F ==
nullptr || OrigName.
empty())
2162 SymbolMap[FunctionId(OrigName)] =
F;
2164 if (OrigName != NewName && !NewName.
empty()) {
2165 auto r = SymbolMap.emplace(FunctionId(NewName),
F);
2171 r.first->second =
nullptr;
2176 if (
auto MapName = Remapper->lookUpNameInProfile(OrigName)) {
2177 if (*MapName != OrigName && !MapName->empty())
2178 SymbolMap.emplace(FunctionId(*MapName),
F);
2186 MatchingManager->runOnModule();
2187 MatchingManager->clearMatchingData();
2189 assert(SymbolMap.count(FunctionId()) == 0 &&
2190 "No empty StringRef should be added in SymbolMap");
2192 "FuncNameToProfNameMap is not empty when --salvage-unused-profile is "
2195 bool retval =
false;
2196 for (
auto *
F : buildFunctionOrder(M, CG)) {
2198 clearFunctionData();
2204 for (
const auto &[Fn, Info] : notInlinedCallInfo)
2209 removePseudoProbeInstsDiscriminator(M);
2211 M.eraseNamedMetadata(FuncInfo);
2217bool SampleProfileLoader::runOnFunction(
Function &
F,
2219 LLVM_DEBUG(
dbgs() <<
"\n\nProcessing Function " <<
F.getName() <<
"\n");
2220 DILocation2SampleMap.clear();
2231 initialEntryCount = 0;
2234 ProfAccForSymsInList =
false;
2236 CoverageTracker.setProfAccForSymsInList(ProfAccForSymsInList);
2242 if (ProfAccForSymsInList) {
2244 if (PSL->contains(
F.getName()))
2245 initialEntryCount = 0;
2260 Function::getGUIDAssumingExternalLinkage(CanonName))
2261 : Reader->contains(CanonName))
2262 initialEntryCount = -1;
2267 if (!
F.getEntryCount())
2268 F.setEntryCount(initialEntryCount);
2274 Samples = ContextTracker->getBaseSamplesFor(
F);
2276 Samples = Reader->getSamplesFor(
F);
2281 auto It = OutlineFunctionSamples.find(FunctionId(CanonName));
2282 if (It != OutlineFunctionSamples.end()) {
2283 Samples = &It->second;
2284 }
else if (
auto Remapper = Reader->getRemapper()) {
2285 if (
auto RemppedName = Remapper->lookUpNameInProfile(CanonName)) {
2286 It = OutlineFunctionSamples.find(FunctionId(*RemppedName));
2287 if (It != OutlineFunctionSamples.end())
2288 Samples = &It->second;
2294 if (Samples && !Samples->
empty())
2295 return emitAnnotations(
F);
2301 bool UseFlattenedProfile)
2302 : ProfileFileName(File), ProfileRemappingFileName(RemappingFile),
2303 LTOPhase(LTOPhase), FS(
std::
move(FS)),
2304 DisableSampleProfileInlining(DisableSampleProfileInlining),
2305 UseFlattenedProfile(UseFlattenedProfile) {}
2326 SampleProfileLoader SampleLoader(
2329 : ProfileRemappingFileName,
2330 LTOPhase, FS, GetAssumptionCache, GetTTI, GetTLI, CG,
2331 DisableSampleProfileInlining, UseFlattenedProfile);
2332 if (!SampleLoader.doInitialization(M, &
FAM))
2336 if (!SampleLoader.runOnModule(M, AM, PSI))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
This file defines the DenseMap class.
This file defines the DenseSet and SmallDenseSet classes.
static bool runOnFunction(Function &F, bool PostInlining)
Provides ErrorOr<T> smart pointer.
static cl::opt< unsigned > SizeLimit("eif-limit", cl::init(6), cl::Hidden, cl::desc("Size limit in Hexagon early if-conversion"))
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
static LVReader * CurrentReader
Implements a lazy call graph analysis and related passes for the new pass manager.
Legalize the Machine IR a function s Machine IR
Machine Check Debug Module
This file implements a map that provides insertion order iteration.
static const Function * getCalledFunction(const Value *V)
ConstantRange Range(APInt(BitWidth, Low), APInt(BitWidth, High))
static constexpr StringLiteral Filename
FunctionAnalysisManager FAM
This file defines the PriorityQueue class.
This file contains the declarations for profiling metadata utility functions.
This builds on the llvm/ADT/GraphTraits.h file to find the strongly connected components (SCCs) of a ...
std::pair< BasicBlock *, BasicBlock * > Edge
This file provides the interface for context-sensitive profile tracker used by CSSPGO.
This file provides the interface for the sampled PGO profile loader base implementation.
This file provides the utility functions for the sampled PGO loader base implementation.
This file provides the interface for SampleProfileMatcher.
This file provides the interface for the pseudo probe implementation for AutoFDO.
static cl::opt< unsigned > MinfuncsForStalenessError("min-functions-for-staleness-error", cl::Hidden, cl::init(50), cl::desc("Skip the check if the number of hot functions is smaller than " "the specified number."))
static cl::opt< unsigned > PrecentMismatchForStalenessError("precent-mismatch-for-staleness-error", cl::Hidden, cl::init(80), cl::desc("Reject the profile if the mismatch percent is higher than the " "given number."))
static cl::opt< bool > RemoveProbeAfterProfileAnnotation("sample-profile-remove-probe", cl::Hidden, cl::init(false), cl::desc("Remove pseudo-probe after sample profile annotation."))
static cl::opt< unsigned > MaxNumPromotions("sample-profile-icp-max-prom", cl::init(3), cl::Hidden, cl::desc("Max number of promotions for a single indirect " "call callsite in sample profile loader"))
static cl::opt< ReplayInlinerSettings::Fallback > ProfileInlineReplayFallback("sample-profile-inline-replay-fallback", cl::init(ReplayInlinerSettings::Fallback::Original), cl::values(clEnumValN(ReplayInlinerSettings::Fallback::Original, "Original", "All decisions not in replay send to original advisor (default)"), clEnumValN(ReplayInlinerSettings::Fallback::AlwaysInline, "AlwaysInline", "All decisions not in replay are inlined"), clEnumValN(ReplayInlinerSettings::Fallback::NeverInline, "NeverInline", "All decisions not in replay are not inlined")), cl::desc("How sample profile inline replay treats sites that don't come " "from the replay. Original: defers to original advisor, " "AlwaysInline: inline all sites not in replay, NeverInline: " "inline no sites not in replay"), cl::Hidden)
static cl::opt< bool > OverwriteExistingWeights("overwrite-existing-weights", cl::Hidden, cl::init(false), cl::desc("Ignore existing branch weights on IR and always overwrite."))
static void updateIDTMetaData(Instruction &Inst, const SmallVectorImpl< InstrProfValueData > &CallTargets, uint64_t Sum)
Update indirect call target profile metadata for Inst.
static cl::opt< bool > AnnotateSampleProfileInlinePhase("annotate-sample-profile-inline-phase", cl::Hidden, cl::init(false), cl::desc("Annotate LTO phase (prelink / postlink), or main (no LTO) for " "sample-profile inline pass name."))
static cl::opt< std::string > ProfileInlineReplayFile("sample-profile-inline-replay", cl::init(""), cl::value_desc("filename"), cl::desc("Optimization remarks file containing inline remarks to be replayed " "by inlining from sample profile loader."), cl::Hidden)
static cl::opt< bool > CallsitePrioritizedInline("sample-profile-prioritized-inline", cl::Hidden, cl::desc("Use call site prioritized inlining for sample profile loader. " "Currently only CSSPGO is supported."))
static bool doesHistoryAllowICP(const Instruction &Inst, StringRef Candidate)
Check whether the indirect call promotion history of Inst allows the promotion for Candidate.
static SmallVector< InstrProfValueData, 2 > GetSortedValueDataFromCallTargets(const SampleRecord::CallTargetMap &M)
Returns the sorted CallTargetMap M by count in descending order.
static cl::opt< ReplayInlinerSettings::Scope > ProfileInlineReplayScope("sample-profile-inline-replay-scope", cl::init(ReplayInlinerSettings::Scope::Function), cl::values(clEnumValN(ReplayInlinerSettings::Scope::Function, "Function", "Replay on functions that have remarks associated " "with them (default)"), clEnumValN(ReplayInlinerSettings::Scope::Module, "Module", "Replay on the entire module")), cl::desc("Whether inline replay should be applied to the entire " "Module or just the Functions (default) that are present as " "callers in remarks during sample profile inlining."), cl::Hidden)
static cl::opt< unsigned > ProfileICPRelativeHotness("sample-profile-icp-relative-hotness", cl::Hidden, cl::init(25), cl::desc("Relative hotness percentage threshold for indirect " "call promotion in proirity-based sample profile loader inlining."))
static cl::opt< unsigned > ProfileICPRelativeHotnessSkip("sample-profile-icp-relative-hotness-skip", cl::Hidden, cl::init(1), cl::desc("Skip relative hotness check for ICP up to given number of targets."))
static cl::opt< bool > UsePreInlinerDecision("sample-profile-use-preinliner", cl::Hidden, cl::desc("Use the preinliner decisions stored in profile context."))
static cl::opt< bool > AllowRecursiveInline("sample-profile-recursive-inline", cl::Hidden, cl::desc("Allow sample loader inliner to inline recursive calls."))
static cl::opt< CallSiteFormat::Format > ProfileInlineReplayFormat("sample-profile-inline-replay-format", cl::init(CallSiteFormat::Format::LineColumnDiscriminator), cl::values(clEnumValN(CallSiteFormat::Format::Line, "Line", "<Line Number>"), clEnumValN(CallSiteFormat::Format::LineColumn, "LineColumn", "<Line Number>:<Column Number>"), clEnumValN(CallSiteFormat::Format::LineDiscriminator, "LineDiscriminator", "<Line Number>.<Discriminator>"), clEnumValN(CallSiteFormat::Format::LineColumnDiscriminator, "LineColumnDiscriminator", "<Line Number>:<Column Number>.<Discriminator> (default)")), cl::desc("How sample profile inline replay file is formatted"), cl::Hidden)
static cl::opt< unsigned > HotFuncCutoffForStalenessError("hot-func-cutoff-for-staleness-error", cl::Hidden, cl::init(800000), cl::desc("A function is considered hot for staleness error check if its " "total sample count is above the specified percentile"))
This file provides the interface for the sampled PGO loader pass.
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Defines the virtual file system interface vfs::FileSystem.
bool empty() const
Returns true if the analysis manager has an empty results cache.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
A function analysis which provides an AssumptionCache.
A cache of @llvm.assume calls within a function.
LLVM Basic Block Representation.
const Function * getParent() const
Return the enclosing method, or null if none.
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
static bool isPseudoProbeDiscriminator(unsigned Discriminator)
const DILocation * cloneWithDiscriminator(unsigned Discriminator) const
Returns a new DILocation with updated Discriminator.
LLVM_ABI unsigned getLine() const
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Represents either an error or a value T.
DISubprogram * getSubprogram() const
Get the attached subprogram.
static LLVM_ABI GUID getGUIDAssumingExternalLinkage(StringRef GlobalName)
Return a 64-bit global unique ID constructed from the name of a global symbol.
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
static InlineCost getNever(const char *Reason, std::optional< CostBenefitPair > CostBenefit=std::nullopt)
static InlineCost getAlways(const char *Reason, std::optional< CostBenefitPair > CostBenefit=std::nullopt)
static InlineCost get(int Cost, int Threshold, int StaticBonus=0)
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
const DebugLoc & getDebugLoc() const
Return the debug location for this node as a DebugLoc.
LLVM_ABI bool extractProfTotalWeight(uint64_t &TotalVal) const
Retrieve total raw weight values of a branch.
LLVM_ABI BasicBlock * getSuccessor(unsigned Idx) const LLVM_READONLY
Return the specified successor. This instruction must be a terminator.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
LLVM_ABI void diagnose(const DiagnosticInfo &DI)
Report a message to the currently installed diagnostic handler.
An analysis pass which computes the call graph for a module.
A lazily constructed view of the call graph of a module.
ValueT lookup(const KeyT &Key) const
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
VectorType::iterator erase(typename VectorType::iterator Iterator)
Remove the element given by Iterator.
A Module instance is used to store all the information related to an LLVM module.
PostDominatorTree Class - Concrete subclass of DominatorTree that is used to compute the post-dominat...
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PriorityQueue - This class behaves like std::priority_queue and provides a few additional convenience...
An analysis pass based on the new PM to deliver ProfileSummaryInfo.
Analysis providing profile information.
LLVM_ABI void refresh(std::unique_ptr< ProfileSummary > &&Other=nullptr)
If a summary is provided as argument, use that.
LLVM_ABI bool isHotCountNthPercentile(int PercentileCutoff, uint64_t C) const
Returns true if count C is considered hot with regard to a given hot percentile cutoff value.
void computeDominanceAndLoopInfo(FunctionT &F)
PostDominatorTreePtrT PDT
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
LLVM_ABI SampleProfileLoaderPass(std::string File="", std::string RemappingFile="", ThinOrFullLTOPhase LTOPhase=ThinOrFullLTOPhase::None, IntrusiveRefCntPtr< vfs::FileSystem > FS=nullptr, bool DisableSampleProfileInlining=false, bool UseFlattenedProfile=false)
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
iterator insert(iterator I, T &&Elt)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
constexpr bool empty() const
Check if the string is empty.
Analysis pass providing the TargetTransformInfo.
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
LLVM Value Representation.
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
int getNumOccurrences() const
std::pair< iterator, bool > insert(const ValueT &V)
const ParentTy * getParent() const
Representation of the samples collected for a function.
static LLVM_ABI std::atomic< bool > UseMD5
Whether the profile uses MD5 to represent string.
FunctionId getFunction() const
Return the function name.
SampleContext & getContext() const LLVM_LIFETIME_BOUND
static StringRef getCanonicalFnName(const Function &F)
Return the canonical name for a function, taking into account suffix elision policy attributes.
void setContextSynthetic()
static LLVM_ABI std::atomic< bool > ProfileIsProbeBased
const BodySampleMap & getBodySamples() const LLVM_LIFETIME_BOUND
Return all the samples collected in the body of the function.
sampleprof_error merge(const FunctionSamples &Other, uint64_t Weight=1)
Merge the samples in Other into this one.
static LLVM_ABI std::atomic< bool > ProfileIsCS
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.
void findInlinedFunctions(DenseSet< GlobalValue::GUID > &S, const HashKeyMap< DenseMap, FunctionId, Function * > &SymbolMap, uint64_t Threshold) const
Recursively traverses all children, if the total sample count of the corresponding function is no les...
uint64_t getHeadSamplesEstimate() const
Return an estimate of the sample count of the function entry basic block.
uint64_t getGUID() const
Return the GUID of the context's name.
static void flattenProfile(SampleProfileMap &ProfileMap, bool ProfileIsCS=false)
bool hasAttribute(ContextAttributeMask A)
static LLVM_ABI ErrorOr< std::unique_ptr< SampleProfileReader > > create(StringRef Filename, LLVMContext &C, vfs::FileSystem &FS, FSDiscriminatorPass P=FSDiscriminatorPass::Base, StringRef RemapFilename="")
Create a sample profile reader appropriate to the file format.
static SortedCallTargetSet sortCallTargets(const CallTargetMap &Targets)
Sort call targets in descending order of call frequency.
static const CallTargetMap adjustCallTargets(const CallTargetMap &Targets, float DistributionFactor)
Prorate call targets by a distribution factor.
SortedVectorMap< FunctionId, uint64_t, 0 > CallTargetMap
bool isAtEnd() const
Direct loop termination test which is more efficient than comparison with end().
@ BasicBlock
Various leaf nodes.
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
LLVM_ABI void checkExpectAnnotations(const Instruction &I, ArrayRef< uint32_t > ExistingWeights, bool IsFrontend)
checkExpectAnnotations - compares PGO counters to the thresholds used for llvm.expect and warns if th...
DiagnosticInfoOptimizationBase::Argument NV
LLVM_ABI CallBase & promoteIndirectCall(CallBase &CB, Function *F, uint64_t Count, uint64_t TotalCount, bool AttachProfToDirectCall, OptimizationRemarkEmitter *ORE)
NodeAddr< NodeBase * > Node
NodeAddr< FuncNode * > Func
static FunctionId getRepInFormat(StringRef Name)
Get the proper representation of a string according to whether the current Format uses MD5 to represe...
@ ContextDuplicatedIntoBase
std::map< FunctionId, FunctionSamples > FunctionSamplesMap
LLVM_ABI bool callsiteIsHot(const FunctionSamples *CallsiteFS, ProfileSummaryInfo *PSI, bool ProfAccForSymsInList)
Return true if the given callsite is hot wrt to hot cutoff threshold.
friend class Instruction
Iterator for Instructions in a `BasicBlock.
LLVM_ABI IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
This is an optimization pass for GlobalISel generic memory operations.
static bool isIndirectCall(const MachineInstr &MI)
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)."))
LLVM_ABI bool isLegalToPromote(const CallBase &CB, Function *Callee, const char **FailureReason=nullptr)
Return true if the given indirect call site can be made to call Callee.
LLVM_ABI cl::opt< int > ProfileInlineLimitMin
bool succ_empty(const Instruction *I)
static cl::opt< bool > ProfileAccurateForSymsInList("profile-accurate-for-symsinlist", cl::Hidden, cl::init(true), cl::desc("For symbols in profile symbol list, regard their profiles to " "be accurate. It may be overridden by profile-sample-accurate. "))
static cl::opt< bool > ProfileMergeInlinee("sample-profile-merge-inlinee", cl::Hidden, cl::init(true), cl::desc("Merge past inlinee's profile to outline version if sample " "profile loader decided not to inline a call site. It will " "only be enabled when top-down order of profile loading is " "enabled. "))
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
static cl::opt< bool > DisableSampleLoaderInlining("disable-sample-loader-inlining", cl::Hidden, cl::init(false), cl::desc("If true, artificially skip inline transformation in sample-loader " "pass, and merge (or scale) profiles (as configured by " "--sample-profile-merge-inlinee)."))
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
scc_iterator< T > scc_begin(const T &G)
Construct the begin iterator for a deduced graph type T.
static cl::opt< bool > UseProfiledCallGraph("use-profiled-call-graph", cl::init(true), cl::Hidden, cl::desc("Process functions in a top-down order " "defined by the profiled call graph when " "-sample-profile-top-down-load is on."))
static cl::opt< bool > ProfileSampleAccurate("profile-sample-accurate", cl::Hidden, cl::init(false), cl::desc("If the sample profile is accurate, we will mark all un-sampled " "callsite and function as having 0 samples. Otherwise, treat " "un-sampled callsites and functions conservatively as unknown. "))
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
static void buildTopDownFuncOrder(LazyCallGraph &CG, std::vector< Function * > &FunctionOrderList)
LLVM_ABI InlineResult InlineFunction(CallBase &CB, InlineFunctionInfo &IFI, bool MergeAttributes=false, AAResults *CalleeAAR=nullptr, bool InsertLifetime=true, bool TrackInlineHistory=false, Function *ForwardVarArgsTo=nullptr, OptimizationRemarkEmitter *ORE=nullptr)
This function inlines the called function into the basic block of the caller.
LLVM_ABI void setProbeDistributionFactor(Instruction &Inst, float Factor)
LLVM_ABI void setBranchWeights(Instruction &I, ArrayRef< uint32_t > Weights, bool IsExpected, bool ElideAllZero=false)
Create a new branch_weights metadata node and add or overwrite a prof metadata reference to instructi...
auto make_isa_range(RangeT &&Range)
Return a range over Range containing only elements for which isa<T> holds, casting each of them to T.
static cl::opt< bool > ProfileSampleBlockAccurate("profile-sample-block-accurate", cl::Hidden, cl::init(false), cl::desc("If the sample profile is accurate, we will mark all un-sampled " "branches and calls as having 0 samples. Otherwise, treat " "them conservatively as unknown. "))
LLVM_ABI std::string AnnotateInlinePassName(InlineContext IC)
ThinOrFullLTOPhase
This enumerates the LLVM full LTO or ThinLTO optimization phases.
LLVM_ABI cl::opt< bool > SampleProfileUseProfi
LLVM_ABI void annotateValueSite(Module &M, Instruction &Inst, const InstrProfRecord &InstrProfR, InstrProfValueKind ValueKind, uint32_t SiteIndx, uint32_t MaxMDCount=3)
Get the value profile data for value site SiteIdx from InstrProfR and annotate the instruction Inst w...
void sort(IteratorTy Start, IteratorTy End)
LLVM_ABI llvm::cl::opt< bool > UseIterativeBFIInference
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.
LLVM_ABI void emitInlinedIntoBasedOnCost(OptimizationRemarkEmitter &ORE, DebugLoc DLoc, const BasicBlock *Block, const Function &Callee, const Function &Caller, const InlineCost &IC, bool ForProfileContext=false, const char *PassName=nullptr)
Emit ORE message based in cost (default heuristic).
static cl::opt< std::string > SampleProfileRemappingFile("sample-profile-remapping-file", cl::init(""), cl::value_desc("filename"), cl::desc("Profile remapping file loaded by -sample-profile"), cl::Hidden)
LLVM_ABI SmallVector< InstrProfValueData, 4 > getValueProfDataFromInst(const Instruction &Inst, InstrProfValueKind ValueKind, uint32_t MaxNumValueData, uint64_t &TotalC, bool GetNoICPValue=false)
Extract the value profile data from Inst and returns them if Inst is annotated with value profile dat...
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
LLVM_ABI std::unique_ptr< InlineAdvisor > getReplayInlineAdvisor(Module &M, FunctionAnalysisManager &FAM, LLVMContext &Context, std::unique_ptr< InlineAdvisor > OriginalAdvisor, const ReplayInlinerSettings &ReplaySettings, bool EmitRemarks, InlineContext IC)
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...
LLVM_ABI cl::opt< int > SampleHotCallSiteThreshold
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ABI InlineCost getInlineCost(CallBase &Call, const InlineParams &Params, TargetTransformInfo &CalleeTTI, function_ref< AssumptionCache &(Function &)> GetAssumptionCache, function_ref< const TargetLibraryInfo &(Function &)> GetTLI, function_ref< BlockFrequencyInfo &(Function &)> GetBFI=nullptr, ProfileSummaryInfo *PSI=nullptr, OptimizationRemarkEmitter *ORE=nullptr, function_ref< EphemeralValuesCache &(Function &)> GetEphValuesCache=nullptr)
Get an InlineCost object representing the cost of inlining this callsite.
LLVM_ABI void updateProfileCallee(Function *Callee, int64_t EntryDelta, const ValueMap< const Value *, WeakTrackingVH > *VMap=nullptr)
Updates profile information by adjusting the entry count by adding EntryDelta then scaling callsite i...
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."))
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
LLVM_ABI cl::opt< int > SampleColdCallSiteThreshold
LLVM_ABI InlineParams getInlineParams()
Generate the parameters to tune the inline cost analysis based only on the commandline options.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
static bool skipProfileForFunction(const Function &F)
LLVM_ABI cl::opt< bool > SortProfiledSCC
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< bool > ProfileTopDownLoad("sample-profile-top-down-load", cl::Hidden, cl::init(true), cl::desc("Do profile annotation and inlining for functions in top-down " "order of call graph during sample profile loading. It only " "works for new pass manager. "))
LLVM_ABI cl::opt< int > ProfileInlineLimitMax
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
cl::opt< bool > EnableExtTspBlockPlacement
const uint64_t NOMORE_ICP_MAGICNUM
Magic number in the value profile metadata showing a target has been promoted for the instruction and...
LLVM_ABI cl::opt< int > ProfileInlineGrowthLimit
static cl::opt< bool > ProfileSizeInline("sample-profile-inline-size", cl::Hidden, cl::init(false), cl::desc("Inline cold call sites in profile loader if it's beneficial " "for code size."))
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
cl::opt< std::string > SampleProfileFile
constexpr const char * PseudoProbeDescMetadataName
Implement std::hash so that hash_code can be used in STL containers.
A wrapper of binary function with basic blocks and jumps.
std::optional< bool > AllowRecursiveCall
Indicate whether we allow inlining for recursive call.
std::optional< bool > ComputeFullInlineCost
Compute inline cost even when the cost has exceeded the threshold.
static std::optional< uint32_t > extractDwarfBaseDiscriminator(uint32_t Value)