90#include <system_error>
97#define DEBUG_TYPE "sample-profile"
98#define CSINLINE_DEBUG DEBUG_TYPE "-inline"
101 "Number of functions inlined with context sensitive profile");
103 "Number of functions not inlined with context sensitive profile");
105 "Number of functions with CFG mismatched profile");
106STATISTIC(NumMatchedProfile,
"Number of functions with CFG matched profile");
108 "Number of inlined callsites with a partial distribution factor");
111 "Number of functions with FDO inline stopped due to min size limit");
113 "Number of functions with FDO inline stopped due to max size limit");
115 NumCSInlinedHitGrowthLimit,
116 "Number of functions with FDO inline stopped due to growth size limit");
122 cl::desc(
"Sort profiled recursion by edge weights."));
126 cl::desc(
"The size growth ratio limit for priority-based sample profile "
127 "loader inlining."));
131 cl::desc(
"The lower bound of size growth limit for "
132 "priority-based sample profile loader inlining."));
136 cl::desc(
"The upper bound of size growth limit for "
137 "priority-based sample profile loader inlining."));
141 cl::desc(
"Hot callsite threshold for priority-based sample profile loader "
146 cl::desc(
"Threshold for inlining cold callsites"));
157using Edge = std::pair<const BasicBlock *, const BasicBlock *>;
161class GUIDToFuncNameMapper {
166 CurrentGUIDToFuncNameMap(GUIDToFuncNameMap) {
170 for (
const auto &
F : CurrentModule) {
172 CurrentGUIDToFuncNameMap.insert(
183 if (CanonName != OrigName)
184 CurrentGUIDToFuncNameMap.insert(
189 SetGUIDToFuncNameMapForAll(&CurrentGUIDToFuncNameMap);
192 ~GUIDToFuncNameMapper() {
196 CurrentGUIDToFuncNameMap.clear();
200 SetGUIDToFuncNameMapForAll(
nullptr);
205 std::queue<FunctionSamples *> FSToUpdate;
207 FSToUpdate.push(&IFS.second);
210 while (!FSToUpdate.empty()) {
213 FS->GUIDToFuncNameMap = Map;
214 for (
const auto &ICS : FS->getCallsiteSamples()) {
216 for (
const auto &IFS : FSMap) {
218 FSToUpdate.push(&FS);
230struct InlineCandidate {
232 const FunctionSamples *CalleeSamples;
240 float CallsiteDistribution;
244struct CandidateComparer {
245 bool operator()(
const InlineCandidate &
LHS,
const InlineCandidate &
RHS) {
246 if (
LHS.CallsiteCount !=
RHS.CallsiteCount)
247 return LHS.CallsiteCount <
RHS.CallsiteCount;
249 const FunctionSamples *LCS =
LHS.CalleeSamples;
250 const FunctionSamples *RCS =
RHS.CalleeSamples;
265using CandidateQueue =
277 const IPOOptions &Opts, StringRef Name, StringRef RemapName,
279 std::function<AssumptionCache &(
Function &)> GetAssumptionCache,
280 std::function<TargetTransformInfo &(
Function &)> GetTargetTransformInfo,
281 std::function<
const TargetLibraryInfo &(
Function &)> GetTLI,
282 LazyCallGraph &CG,
bool DisableSampleProfileInlining,
283 bool UseFlattenedProfile)
286 Opts(Opts), ProfileMergeInlinee(Opts.sample_profile_merge_inlinee),
287 ProfileSizeInline(
valueOr(Opts.sample_profile_inline_size,
false)),
288 CallsitePrioritizedInline(
289 valueOr(Opts.sample_profile_prioritized_inline,
false)),
290 AllowRecursiveInline(
292 UsePreInlinerDecision(
294 SalvageStaleProfile(
valueOr(Opts.salvage_stale_profile,
false)),
295 SalvageUnusedProfile(
valueOr(Opts.salvage_unused_profile,
false)),
296 GetAC(std::
move(GetAssumptionCache)),
297 GetTTI(std::
move(GetTargetTransformInfo)), GetTLI(std::
move(GetTLI)),
298 CG(CG), LTOPhase(LTOPhase),
299 AnnotatedPassName(Opts.annotate_sample_profile_inline_phase
303 DisableSampleProfileInlining(DisableSampleProfileInlining),
304 UseFlattenedProfile(UseFlattenedProfile) {}
308 ProfileSummaryInfo *_PSI);
311 const IPOOptions &Opts;
313 bool ProfileMergeInlinee;
314 bool ProfileSizeInline;
315 bool CallsitePrioritizedInline;
316 bool AllowRecursiveInline;
317 bool UsePreInlinerDecision;
318 bool SalvageStaleProfile;
319 bool SalvageUnusedProfile;
323 ErrorOr<uint64_t> getInstWeight(
const Instruction &
I)
override;
324 const FunctionSamples *findCalleeFunctionSamples(
const CallBase &
I)
const;
325 const FunctionSamples *
326 findFunctionSamples(
const Instruction &
I)
const override;
327 std::vector<const FunctionSamples *>
328 findIndirectCallFunctionSamples(
const Instruction &
I,
uint64_t &Sum)
const;
329 void findExternalInlineCandidate(CallBase *CB,
const FunctionSamples *Samples,
330 DenseSet<GlobalValue::GUID> &InlinedGUIDs,
333 bool tryPromoteAndInlineCandidate(
338 DenseSet<GlobalValue::GUID> &InlinedGUIDs);
339 std::optional<InlineCost> getExternalInlineAdvisorCost(CallBase &CB);
340 bool getExternalInlineAdvisorShouldInline(CallBase &CB);
341 InlineCost shouldInlineCandidate(InlineCandidate &Candidate);
342 bool getInlineCandidate(InlineCandidate *NewCandidate, CallBase *CB);
344 tryInlineCandidate(InlineCandidate &Candidate,
347 inlineHotFunctionsWithPriority(
Function &
F,
348 DenseSet<GlobalValue::GUID> &InlinedGUIDs);
350 bool shouldInlineColdCallee(CallBase &CallInst);
351 void emitOptimizationRemarksForInlineCandidates(
352 const SmallVectorImpl<CallBase *> &Candidates,
const Function &
F,
354 void promoteMergeNotInlinedContextSamples(
355 MapVector<CallBase *, const FunctionSamples *> NonInlinedCallSites,
357 std::vector<Function *> buildFunctionOrder(
Module &M, LazyCallGraph &CG);
358 std::unique_ptr<ProfiledCallGraph> buildProfiledCallGraph(
Module &M);
359 void generateMDProfMetadata(
Function &
F);
360 bool rejectHighStalenessProfile(
Module &M, ProfileSummaryInfo *PSI,
361 const SampleProfileMap &Profiles);
362 void removePseudoProbeInstsDiscriminator(
Module &M);
368 HashKeyMap<DenseMap, FunctionId, Function *> SymbolMap;
372 HashKeyMap<DenseMap, FunctionId, FunctionId> FuncNameToProfNameMap;
374 std::function<AssumptionCache &(
Function &)> GetAC;
375 std::function<TargetTransformInfo &(
Function &)> GetTTI;
376 std::function<
const TargetLibraryInfo &(
Function &)> GetTLI;
380 std::unique_ptr<SampleContextTracker> ContextTracker;
388 const std::string AnnotatedPassName;
392 std::shared_ptr<ProfileSymbolList> PSL;
397 struct NotInlinedProfileInfo {
400 DenseMap<Function *, NotInlinedProfileInfo> notInlinedCallInfo;
404 DenseMap<uint64_t, StringRef> GUIDToFuncNameMap;
411 bool ProfAccForSymsInList;
413 bool DisableSampleProfileInlining;
415 bool UseFlattenedProfile;
418 std::unique_ptr<InlineAdvisor> ExternalInlineAdvisor;
421 std::unique_ptr<SampleProfileMatcher> MatchingManager;
424 const char *getAnnotatedRemarkPassName()
const {
425 return AnnotatedPassName.c_str();
432inline bool SampleProfileInference<Function>::isExit(
const BasicBlock *BB) {
437inline void SampleProfileInference<Function>::findUnlikelyJumps(
438 const std::vector<const BasicBlockT *> &BasicBlocks,
440 for (
auto &Jump :
Func.Jumps) {
441 const auto *BB = BasicBlocks[Jump.Source];
442 const auto *Succ = BasicBlocks[Jump.Target];
446 const auto &Succs = Successors[BB];
447 if (Succs.size() == 2 && Succs.back() == Succ) {
449 Jump.IsUnlikely =
true;
456 Jump.IsUnlikely =
true;
477 return getProbeWeight(Inst);
481 return std::error_code();
487 return std::error_code();
497 if (!CB->isIndirectCall() && findCalleeFunctionSamples(*CB))
500 return getInstWeightImpl(Inst);
515const FunctionSamples *
516SampleProfileLoader::findCalleeFunctionSamples(
const CallBase &Inst)
const {
522 StringRef CalleeName;
524 CalleeName =
Callee->getName();
527 return ContextTracker->getCalleeContextSamplesFor(Inst, CalleeName);
529 const FunctionSamples *
FS = findFunctionSamples(Inst);
534 CalleeName, Reader->getRemapper(),
535 &FuncNameToProfNameMap);
541std::vector<const FunctionSamples *>
542SampleProfileLoader::findIndirectCallFunctionSamples(
543 const Instruction &Inst,
uint64_t &Sum)
const {
545 std::vector<const FunctionSamples *>
R;
551 auto FSCompare = [](
const FunctionSamples *
L,
const FunctionSamples *
R) {
552 assert(L && R &&
"Expect non-null FunctionSamples");
553 if (
L->getHeadSamplesEstimate() !=
R->getHeadSamplesEstimate())
554 return L->getHeadSamplesEstimate() >
R->getHeadSamplesEstimate();
555 return L->getGUID() <
R->getGUID();
560 ContextTracker->getIndirectCalleeContextSamplesFor(DIL);
561 if (CalleeSamples.empty())
567 for (
const auto *
const FS : CalleeSamples) {
568 Sum +=
FS->getHeadSamplesEstimate();
575 const FunctionSamples *
FS = findFunctionSamples(Inst);
581 if (
auto T =
FS->findCallTargetMapAt(CallSite))
582 for (
const auto &T_C : *
T)
587 for (
const auto &NameFS : *M) {
588 Sum += NameFS.second.getHeadSamplesEstimate();
589 R.push_back(&NameFS.second);
596const FunctionSamples *
597SampleProfileLoader::findFunctionSamples(
const Instruction &Inst)
const {
608 auto it = DILocation2SampleMap.try_emplace(DIL,
nullptr);
611 it.first->second = ContextTracker->getContextSamplesFor(DIL);
613 it.first->second = Samples->findFunctionSamples(
614 DIL, Reader->getRemapper(), &FuncNameToProfNameMap);
616 return it.first->second;
630 Opts.sample_profile_icp_max_prom,
634 if (ValueData.empty())
637 unsigned NumPromoted = 0;
638 for (
const auto &
V : ValueData) {
649 if (NumPromoted == Opts.sample_profile_icp_max_prom)
669 if (Opts.sample_profile_icp_max_prom == 0)
675 Opts.sample_profile_icp_max_prom, OldSum,
true);
681 "If sum is 0, assume only one element in CallTargets "
682 "with count being NOMORE_ICP_MAGICNUM");
684 for (
const auto &
V : ValueData)
685 ValueCountMap[
V.Value] =
V.Count;
691 OldSum -= Pair.first->second;
698 for (
const auto &
V : ValueData) {
700 ValueCountMap[
V.Value] =
V.Count;
703 for (
const auto &
Data : CallTargets) {
710 assert(Sum >=
Data.Count &&
"Sum should never be less than Data.Count");
716 for (
const auto &ValueCount : ValueCountMap) {
718 InstrProfValueData{ValueCount.first, ValueCount.second});
722 [](
const InstrProfValueData &L,
const InstrProfValueData &R) {
723 return std::tie(L.Count, L.Value) > std::tie(R.Count, R.Value);
727 std::min(NewCallTargets.
size(),
728 static_cast<size_t>(Opts.sample_profile_icp_max_prom));
730 NewCallTargets, Sum, IPVK_IndirectCallTarget, MaxMDCount);
743bool SampleProfileLoader::tryPromoteAndInlineCandidate(
747 if (DisableSampleProfileInlining)
752 if (Opts.sample_profile_icp_max_prom == 0)
754 auto CalleeFunctionName = Candidate.CalleeSamples->
getFunction();
755 auto R = SymbolMap.find(CalleeFunctionName);
756 if (R == SymbolMap.end() || !
R->second)
759 auto &CI = *Candidate.CallInstr;
763 const char *Reason =
"Callee function not available";
770 if (!
R->second->isDeclaration() &&
R->second->getSubprogram() &&
771 R->second->hasFnAttribute(
"use-sample-profile") &&
776 Function::getGUIDAssumingExternalLinkage(
R->second->getName()),
781 CI,
R->second, Candidate.CallsiteCount, Sum,
false, ORE);
783 Sum -= Candidate.CallsiteCount;
796 Candidate.CallInstr = DI;
798 bool Inlined = tryInlineCandidate(Candidate, InlinedCallSite);
803 *DI,
static_cast<float>(Candidate.CallsiteCount) / SumOrigin);
811 Candidate.CallInstr->
getName())<<
" because "
817bool SampleProfileLoader::shouldInlineColdCallee(CallBase &CallInst) {
818 if (!ProfileSizeInline)
826 GetTTI(*CallInst.
getCaller()), GetAC, GetTLI);
837void SampleProfileLoader::emitOptimizationRemarksForInlineCandidates(
838 const SmallVectorImpl<CallBase *> &Candidates,
const Function &
F,
840 for (
auto *
I : Candidates) {
841 Function *CalledFunction =
I->getCalledFunction();
842 if (CalledFunction) {
843 ORE->emit(OptimizationRemarkAnalysis(getAnnotatedRemarkPassName(),
844 "InlineAttempt",
I->getDebugLoc(),
846 <<
"previous inlining reattempted for "
847 << (
Hot ?
"hotness: '" :
"size: '")
848 <<
ore::NV(
"Callee", CalledFunction) <<
"' into '"
854void SampleProfileLoader::findExternalInlineCandidate(
855 CallBase *CB,
const FunctionSamples *Samples,
856 DenseSet<GlobalValue::GUID> &InlinedGUIDs,
uint64_t Threshold) {
860 if (CB && getExternalInlineAdvisorShouldInline(*CB)) {
864 InlinedGUIDs.
insert(Function::getGUIDAssumingExternalLinkage(
884 if (UsePreInlinerDecision)
890 ContextTrieNode *
Caller = ContextTracker->getContextNodeForProfile(Samples);
891 std::queue<ContextTrieNode *> CalleeList;
892 CalleeList.push(Caller);
893 while (!CalleeList.empty()) {
894 ContextTrieNode *
Node = CalleeList.front();
896 FunctionSamples *CalleeSample =
Node->getFunctionSamples();
905 UsePreInlinerDecision &&
912 if (!Func ||
Func->isDeclaration())
918 for (
const auto &TS : BS.second.getCallTargets())
919 if (TS.second > Threshold) {
921 if (!Callee ||
Callee->isDeclaration())
922 InlinedGUIDs.
insert(TS.first.getHashCode());
929 for (
auto &Child :
Node->getAllChildContext()) {
930 ContextTrieNode *CalleeNode = &Child.second;
931 CalleeList.push(CalleeNode);
958bool SampleProfileLoader::inlineHotFunctions(
959 Function &
F, DenseSet<GlobalValue::GUID> &InlinedGUIDs) {
962 assert((!ProfAccForSymsInList ||
963 (!Opts.profile_sample_accurate &&
964 !
F.hasFnAttribute(
"profile-sample-accurate"))) &&
965 "ProfAccForSymsInList should be false when profile-sample-accurate "
968 MapVector<CallBase *, const FunctionSamples *> LocalNotInlinedCallSites;
970 bool LocalChanged =
true;
971 while (LocalChanged) {
972 LocalChanged =
false;
979 const FunctionSamples *
FS =
nullptr;
982 if ((FS = findCalleeFunctionSamples(*CB))) {
984 "GUIDToFuncNameMap has to be populated");
986 if (
FS->getHeadSamplesEstimate() > 0 ||
988 LocalNotInlinedCallSites.
insert({CB,
FS});
991 else if (shouldInlineColdCallee(*CB))
993 }
else if (getExternalInlineAdvisorShouldInline(*CB)) {
999 if (
Hot || ExternalInlineAdvisor) {
1001 emitOptimizationRemarksForInlineCandidates(AllCandidates,
F,
true);
1004 emitOptimizationRemarksForInlineCandidates(ColdCandidates,
F,
false);
1007 for (CallBase *
I : CIS) {
1008 Function *CalledFunction =
I->getCalledFunction();
1009 InlineCandidate Candidate = {
I, LocalNotInlinedCallSites.
lookup(
I),
1013 if (CalledFunction == &
F)
1015 if (
I->isIndirectCall()) {
1017 for (
const auto *FS : findIndirectCallFunctionSamples(*
I, Sum)) {
1019 if (LTOPhase == ThinOrFullLTOPhase::ThinLTOPreLink) {
1020 findExternalInlineCandidate(
I, FS, InlinedGUIDs,
1021 PSI->getOrCompHotCountThreshold());
1027 Candidate = {
I,
FS,
FS->getHeadSamplesEstimate(), 1.0};
1028 if (tryPromoteAndInlineCandidate(
F, Candidate, SumOrigin, Sum)) {
1029 LocalNotInlinedCallSites.
erase(
I);
1030 LocalChanged =
true;
1033 }
else if (CalledFunction && CalledFunction->
getSubprogram() &&
1035 if (tryInlineCandidate(Candidate)) {
1036 LocalNotInlinedCallSites.
erase(
I);
1037 LocalChanged =
true;
1039 }
else if (LTOPhase == ThinOrFullLTOPhase::ThinLTOPreLink) {
1040 findExternalInlineCandidate(
I, findCalleeFunctionSamples(*
I),
1042 PSI->getOrCompHotCountThreshold());
1051 promoteMergeNotInlinedContextSamples(LocalNotInlinedCallSites,
F);
1055bool SampleProfileLoader::tryInlineCandidate(
1059 if (DisableSampleProfileInlining)
1062 CallBase &CB = *Candidate.CallInstr;
1064 assert(CalledFunction &&
"Expect a callee with definition");
1068 InlineCost
Cost = shouldInlineCandidate(Candidate);
1069 if (
Cost.isNever()) {
1070 ORE->emit(OptimizationRemarkAnalysis(getAnnotatedRemarkPassName(),
1071 "InlineFail", DLoc, BB)
1072 <<
"incompatible inlining");
1079 InlineFunctionInfo IFI(GetAC);
1080 IFI.UpdateProfile =
false;
1083 if (!
IR.isSuccess())
1088 Cost,
true, getAnnotatedRemarkPassName());
1091 if (InlinedCallSites) {
1092 InlinedCallSites->
clear();
1097 ContextTracker->markContextSamplesInlined(Candidate.CalleeSamples);
1107 if (Candidate.CallsiteDistribution < 1) {
1108 for (
auto &
I : IFI.InlinedCallSites) {
1111 Candidate.CallsiteDistribution);
1113 NumDuplicatedInlinesite++;
1119bool SampleProfileLoader::getInlineCandidate(InlineCandidate *NewCandidate,
1121 assert(CB &&
"Expect non-null call instruction");
1127 const FunctionSamples *CalleeSamples = findCalleeFunctionSamples(*CB);
1130 if (!CalleeSamples && !getExternalInlineAdvisorShouldInline(*CB))
1134 if (std::optional<PseudoProbe> Probe =
extractProbe(*CB))
1135 Factor = Probe->Factor;
1139 *NewCandidate = {CB, CalleeSamples, CallsiteCount, Factor};
1143std::optional<InlineCost>
1144SampleProfileLoader::getExternalInlineAdvisorCost(CallBase &CB) {
1145 std::unique_ptr<InlineAdvice> Advice =
nullptr;
1146 if (ExternalInlineAdvisor) {
1147 Advice = ExternalInlineAdvisor->getAdvice(CB);
1149 if (!Advice->isInliningRecommended()) {
1150 Advice->recordUnattemptedInlining();
1153 Advice->recordInlining();
1161bool SampleProfileLoader::getExternalInlineAdvisorShouldInline(CallBase &CB) {
1162 std::optional<InlineCost>
Cost = getExternalInlineAdvisorCost(CB);
1167SampleProfileLoader::shouldInlineCandidate(InlineCandidate &Candidate) {
1168 if (std::optional<InlineCost> ReplayCost =
1169 getExternalInlineAdvisorCost(*Candidate.CallInstr))
1174 if (CallsitePrioritizedInline) {
1175 if (Candidate.CallsiteCount > PSI->getHotCountThreshold())
1177 else if (!ProfileSizeInline)
1183 assert(Callee &&
"Expect a definition for inline candidate of direct call");
1196 GetTTI(*Caller), GetAC, GetTLI);
1199 if (
Cost.isNever() ||
Cost.isAlways())
1211 if (UsePreInlinerDecision && Candidate.CalleeSamples) {
1224 if (!CallsitePrioritizedInline) {
1233bool SampleProfileLoader::inlineHotFunctionsWithPriority(
1234 Function &
F, DenseSet<GlobalValue::GUID> &InlinedGUIDs) {
1237 assert((!ProfAccForSymsInList ||
1238 (!Opts.profile_sample_accurate &&
1239 !
F.hasFnAttribute(
"profile-sample-accurate"))) &&
1240 "ProfAccForSymsInList should be false when profile-sample-accurate "
1245 CandidateQueue CQueue;
1246 InlineCandidate NewCandidate;
1247 for (
auto &BB :
F) {
1249 if (getInlineCandidate(&NewCandidate, &CB))
1250 CQueue.push(NewCandidate);
1259 "Max inline size limit should not be smaller than min inline size "
1264 if (ExternalInlineAdvisor)
1265 SizeLimit = std::numeric_limits<unsigned>::max();
1267 MapVector<CallBase *, const FunctionSamples *> LocalNotInlinedCallSites;
1271 while (!CQueue.empty() &&
F.getInstructionCount() <
SizeLimit) {
1272 InlineCandidate Candidate = CQueue.top();
1274 CallBase *
I = Candidate.CallInstr;
1275 Function *CalledFunction =
I->getCalledFunction();
1277 if (CalledFunction == &
F)
1279 if (
I->isIndirectCall()) {
1281 auto CalleeSamples = findIndirectCallFunctionSamples(*
I, Sum);
1283 Sum *= Candidate.CallsiteDistribution;
1284 unsigned ICPCount = 0;
1285 for (
const auto *FS : CalleeSamples) {
1287 if (LTOPhase == ThinOrFullLTOPhase::ThinLTOPreLink) {
1288 findExternalInlineCandidate(
I, FS, InlinedGUIDs,
1289 PSI->getOrCompHotCountThreshold());
1293 FS->getHeadSamplesEstimate() * Candidate.CallsiteDistribution;
1298 if (ICPCount >= Opts.sample_profile_icp_relative_hotness_skip &&
1299 EntryCountDistributed * 100 <
1300 SumOrigin * Opts.sample_profile_icp_relative_hotness)
1309 if (!PSI->isHotCount(EntryCountDistributed))
1314 Candidate = {
I,
FS, EntryCountDistributed,
1315 Candidate.CallsiteDistribution};
1316 if (tryPromoteAndInlineCandidate(
F, Candidate, SumOrigin, Sum,
1317 &InlinedCallSites)) {
1318 for (
auto *CB : InlinedCallSites) {
1319 if (getInlineCandidate(&NewCandidate, CB))
1320 CQueue.emplace(NewCandidate);
1324 }
else if (!ContextTracker) {
1325 LocalNotInlinedCallSites.
insert({
I,
FS});
1328 }
else if (CalledFunction && CalledFunction->
getSubprogram() &&
1331 if (tryInlineCandidate(Candidate, &InlinedCallSites)) {
1332 for (
auto *CB : InlinedCallSites) {
1333 if (getInlineCandidate(&NewCandidate, CB))
1334 CQueue.emplace(NewCandidate);
1337 }
else if (!ContextTracker) {
1338 LocalNotInlinedCallSites.
insert({
I, Candidate.CalleeSamples});
1340 }
else if (LTOPhase == ThinOrFullLTOPhase::ThinLTOPreLink) {
1341 findExternalInlineCandidate(
I, findCalleeFunctionSamples(*
I),
1343 PSI->getOrCompHotCountThreshold());
1347 if (!CQueue.empty()) {
1349 ++NumCSInlinedHitMaxLimit;
1351 ++NumCSInlinedHitMinLimit;
1353 ++NumCSInlinedHitGrowthLimit;
1359 promoteMergeNotInlinedContextSamples(LocalNotInlinedCallSites,
F);
1363void SampleProfileLoader::promoteMergeNotInlinedContextSamples(
1364 MapVector<CallBase *, const FunctionSamples *> NonInlinedCallSites,
1367 for (
const auto &Pair : NonInlinedCallSites) {
1368 CallBase *
I = Pair.first;
1370 if (!Callee ||
Callee->isDeclaration())
1374 OptimizationRemarkAnalysis(getAnnotatedRemarkPassName(),
"NotInline",
1375 I->getDebugLoc(),
I->getParent())
1376 <<
"previous inlining not repeated: '" <<
ore::NV(
"Callee", Callee)
1377 <<
"' into '" <<
ore::NV(
"Caller", &
F) <<
"'");
1380 const FunctionSamples *
FS = Pair.second;
1381 if (
FS->getTotalSamples() == 0 &&
FS->getHeadSamplesEstimate() == 0) {
1389 if (ProfileMergeInlinee) {
1395 if (
FS->getHeadSamples() == 0) {
1398 const_cast<FunctionSamples *
>(
FS)->addHeadSamples(
1399 FS->getHeadSamplesEstimate());
1404 FunctionSamples *OutlineFS = Reader->getSamplesFor(*Callee);
1408 OutlineFS = &OutlineFunctionSamples[
1410 OutlineFS->
merge(*FS, 1);
1416 notInlinedCallInfo.try_emplace(Callee, NotInlinedProfileInfo{0});
1417 pair.first->second.entryCount +=
FS->getHeadSamplesEstimate();
1428 InstrProfValueData{
I.first.getHashCode(),
I.second});
1435void SampleProfileLoader::generateMDProfMetadata(
Function &
F) {
1438 LLVM_DEBUG(
dbgs() <<
"\nPropagation complete. Setting branch weights\n");
1439 LLVMContext &Ctx =
F.getContext();
1441 for (
auto &BI :
F) {
1444 if (BlockWeights[BB]) {
1445 for (
auto &
I : *BB) {
1452 const DILocation *DIL = DLoc;
1453 const FunctionSamples *
FS = findFunctionSamples(
I);
1457 ErrorOr<SampleRecord::CallTargetMap>
T =
1458 FS->findCallTargetMapAt(CallSite);
1459 if (!
T ||
T.get().empty())
1466 if (Probe->Factor < 1)
1473 for (
const auto &
C :
T.get())
1480 FS->findFunctionSamplesMapAt(CallSite)) {
1481 for (
const auto &NameFS : *M)
1482 Sum += NameFS.second.getHeadSamplesEstimate();
1487 else if (Opts.overwrite_existing_weights)
1488 I.setMetadata(LLVMContext::MD_prof,
nullptr);
1491 I, ArrayRef<uint32_t>{
static_cast<uint32_t
>(BlockWeights[BB])},
1495 }
else if (Opts.overwrite_existing_weights ||
1496 Opts.profile_sample_block_accurate) {
1499 for (
auto &
I : *BB) {
1502 I.setMetadata(LLVMContext::MD_prof,
nullptr);
1520 << ((BranchLoc) ? Twine(BranchLoc.
getLine())
1521 : Twine(
"<UNKNOWN LOCATION>"))
1523 SmallVector<uint32_t, 4> Weights;
1524 uint32_t MaxWeight = 0;
1529 DenseMap<const BasicBlock *, uint64_t> EdgeMultiplicity;
1530 std::vector<uint64_t> EdgeIndex;
1535 EdgeIndex[
I] = EdgeMultiplicity[Succ];
1536 EdgeMultiplicity[Succ]++;
1541 Edge E = std::make_pair(BB, Succ);
1547 if (Weight > std::numeric_limits<uint32_t>::max()) {
1549 Weight = std::numeric_limits<uint32_t>::max();
1554 Weights.
push_back(
static_cast<uint32_t
>(
1555 Weight == std::numeric_limits<uint32_t>::max() ? Weight
1560 uint64_t W = Weight / EdgeMultiplicity[Succ];
1562 if (EdgeIndex[
I] < Weight % EdgeMultiplicity[Succ])
1564 Weights.
push_back(
static_cast<uint32_t
>(W));
1567 if (Weight > MaxWeight) {
1569 MaxDestInst = &*Succ->getFirstNonPHIOrLifetime();
1586 Opts.overwrite_existing_weights)) {
1590 return OptimizationRemark(
DEBUG_TYPE,
"PopularDest", MaxDestInst)
1591 <<
"most popular destination for conditional branches at "
1592 <<
ore::NV(
"CondBranchesLoc", BranchLoc);
1595 if (Opts.overwrite_existing_weights) {
1611bool SampleProfileLoader::emitAnnotations(
Function &
F) {
1616 if (!ProbeManager->getDesc(
F))
1617 dbgs() <<
"Probe descriptor missing for Function " <<
F.getName()
1621 if (ProbeManager->profileIsValid(
F, *Samples)) {
1622 ++NumMatchedProfile;
1624 ++NumMismatchedProfile;
1626 dbgs() <<
"Profile is invalid due to CFG mismatch for Function "
1627 <<
F.getName() <<
"\n");
1628 if (!SalvageStaleProfile)
1632 if (getFunctionLoc(
F) == 0)
1636 <<
F.getName() <<
": " << getFunctionLoc(
F) <<
"\n");
1639 DenseSet<GlobalValue::GUID> InlinedGUIDs;
1640 if (CallsitePrioritizedInline)
1641 Changed |= inlineHotFunctionsWithPriority(
F, InlinedGUIDs);
1643 Changed |= inlineHotFunctions(
F, InlinedGUIDs);
1645 Changed |= computeAndPropagateWeights(
F, InlinedGUIDs);
1648 generateMDProfMetadata(
F);
1650 emitCoverageRemarks(
F);
1654std::unique_ptr<ProfiledCallGraph>
1655SampleProfileLoader::buildProfiledCallGraph(
Module &M) {
1656 std::unique_ptr<ProfiledCallGraph> ProfiledCG;
1658 ProfiledCG = std::make_unique<ProfiledCallGraph>(*ContextTracker);
1660 ProfiledCG = std::make_unique<ProfiledCallGraph>(Reader->getProfiles());
1668 ProfiledCG->addProfiledFunction(
1675std::vector<Function *>
1676SampleProfileLoader::buildFunctionOrder(
Module &M, LazyCallGraph &CG) {
1677 std::vector<Function *> FunctionOrderList;
1678 FunctionOrderList.reserve(
M.size());
1680 if (!Opts.sample_profile_top_down_load && Opts.use_profiled_call_graph)
1681 errs() <<
"WARNING: -use-profiled-call-graph ignored, should be used "
1682 "together with -sample-profile-top-down-load.\n";
1684 if (!Opts.sample_profile_top_down_load) {
1685 if (ProfileMergeInlinee) {
1691 ProfileMergeInlinee =
false;
1696 FunctionOrderList.push_back(&
F);
1697 return FunctionOrderList;
1700 if (Opts.use_profiled_call_graph) {
1749 std::unique_ptr<ProfiledCallGraph> ProfiledCG = buildProfiledCallGraph(M);
1750 scc_iterator<ProfiledCallGraph *> CGI =
scc_begin(ProfiledCG.get());
1755 scc_member_iterator<ProfiledCallGraph *>
SI(*CGI);
1758 for (
auto *Node :
Range) {
1761 FunctionOrderList.push_back(
F);
1765 std::reverse(FunctionOrderList.begin(), FunctionOrderList.end());
1770 dbgs() <<
"Function processing order:\n";
1771 for (
auto F : FunctionOrderList) {
1772 dbgs() <<
F->getName() <<
"\n";
1776 return FunctionOrderList;
1779bool SampleProfileLoader::doInitialization(
Module &M,
1781 auto &Ctx =
M.getContext();
1784 Filename, Ctx, *FS, FSDiscriminatorPass::Base, RemappingFilename);
1785 if (std::error_code EC = ReaderOrErr.getError()) {
1786 std::string
Msg =
"Could not open profile: " +
EC.message();
1790 Reader = std::move(ReaderOrErr.get());
1791 Reader->setSkipFlatProf(LTOPhase == ThinOrFullLTOPhase::ThinLTOPostLink);
1794 Reader->setModule(&M);
1795 if (std::error_code EC = Reader->read()) {
1796 std::string
Msg =
"profile reading failed: " +
EC.message();
1801 PSL = Reader->getProfileSymbolList();
1803 DisableSampleProfileInlining =
1804 !
valueOr(Opts.sample_loader_inlining, !DisableSampleProfileInlining);
1806 if (UseFlattenedProfile)
1808 Reader->profileIsCS());
1811 ProfAccForSymsInList = Opts.profile_accurate_for_symsinlist && PSL &&
1812 !Opts.profile_sample_accurate;
1813 if (ProfAccForSymsInList)
1814 CoverageTracker.setProfAccForSymsInList(
true);
1816 if (
FAM && !Opts.sample_profile_inline_replay.
empty()) {
1818 M, *
FAM, Ctx,
nullptr,
1819 ReplayInlinerSettings{Opts.sample_profile_inline_replay,
1820 Opts.sample_profile_inline_replay_scope,
1821 Opts.sample_profile_inline_replay_fallback,
1822 {Opts.sample_profile_inline_replay_format}},
1824 InlineContext{LTOPhase, InlinePass::ReplaySampleProfileInliner});
1828 if (Reader->profileIsCS() || Reader->profileIsPreInlined() ||
1829 Reader->profileIsProbeBased()) {
1837 ProfileSizeInline =
valueOr(Opts.sample_profile_inline_size,
true);
1838 CallsitePrioritizedInline =
1839 valueOr(Opts.sample_profile_prioritized_inline,
true);
1841 AllowRecursiveInline =
valueOr(Opts.sample_profile_recursive_inline,
true);
1843 if (Reader->profileIsPreInlined())
1844 UsePreInlinerDecision =
valueOr(Opts.sample_profile_use_preinliner,
true);
1851 if (Reader->profileIsProbeBased()) {
1852 SalvageStaleProfile =
valueOr(Opts.salvage_stale_profile,
true);
1853 SalvageUnusedProfile =
valueOr(Opts.salvage_unused_profile,
true);
1856 if (!Reader->profileIsCS()) {
1868 if (Reader->profileIsCS()) {
1870 ContextTracker = std::make_unique<SampleContextTracker>(
1871 Reader->getProfiles(), &GUIDToFuncNameMap);
1875 if (Reader->profileIsProbeBased()) {
1876 ProbeManager = std::make_unique<PseudoProbeManager>(M);
1877 if (!ProbeManager->moduleIsProbed(M)) {
1879 "Pseudo-probe-based profile requires SampleProfileProbePass";
1880 Ctx.
diagnose(DiagnosticInfoSampleProfile(
M.getModuleIdentifier(),
Msg,
1886 if (Opts.report_profile_staleness || Opts.persist_profile_staleness ||
1887 SalvageStaleProfile) {
1888 MatchingManager = std::make_unique<SampleProfileMatcher>(
1889 Opts, M, *Reader, CG, ProbeManager.get(), LTOPhase, SymbolMap, PSL,
1890 FuncNameToProfNameMap, SalvageStaleProfile, SalvageUnusedProfile);
1906bool SampleProfileLoader::rejectHighStalenessProfile(
1907 Module &M, ProfileSummaryInfo *PSI,
const SampleProfileMap &Profiles) {
1909 "Only support for probe-based profile");
1912 for (
const auto &
I : Profiles) {
1913 const auto &
FS =
I.second;
1914 const auto *FuncDesc = ProbeManager->getDesc(
FS.getGUID());
1920 FS.getTotalSamples()))
1924 if (ProbeManager->profileIsHashMismatched(*FuncDesc, FS) &&
1925 !ProbeManager->probeFromWeakSymbol(
FS.getGUID()))
1926 NumMismatchedFunc++;
1930 if (TotalHotFunc < Opts.min_functions_for_staleness_error)
1934 if (NumMismatchedFunc * 100 >=
1935 TotalHotFunc * Opts.percent_mismatch_for_staleness_error) {
1936 auto &Ctx =
M.getContext();
1938 "The input profile significantly mismatches current source code. "
1939 "Please recollect profile to avoid performance regression.";
1940 Ctx.
diagnose(DiagnosticInfoSampleProfile(
M.getModuleIdentifier(),
Msg));
1946void SampleProfileLoader::removePseudoProbeInstsDiscriminator(
Module &M) {
1948 std::vector<Instruction *> InstsToDel;
1949 for (
auto &BB :
F) {
1950 for (
auto &
I : BB) {
1952 InstsToDel.push_back(&
I);
1954 if (
const DILocation *DIL =
I.getDebugLoc().get()) {
1958 std::optional<uint32_t> DwarfDiscriminator =
1967 for (
auto *
I : InstsToDel)
1968 I->eraseFromParent();
1973 ProfileSummaryInfo *_PSI) {
1974 GUIDToFuncNameMapper
Mapper(M, *Reader, GUIDToFuncNameMap);
1977 if (
M.getProfileSummary(
false) ==
nullptr) {
1978 M.setProfileSummary(Reader->getSummary().getMD(
M.getContext()),
1984 rejectHighStalenessProfile(M, PSI, Reader->getProfiles()))
1987 auto Remapper = Reader->getRemapper();
1989 for (
const auto &N_F :
M.getValueSymbolTable()) {
1990 StringRef OrigName = N_F.getKey();
1992 if (
F ==
nullptr || OrigName.
empty())
1994 SymbolMap[FunctionId(OrigName)] =
F;
1996 if (OrigName != NewName && !NewName.
empty()) {
1997 auto r = SymbolMap.emplace(FunctionId(NewName),
F);
2003 r.first->second =
nullptr;
2008 if (
auto MapName = Remapper->lookUpNameInProfile(OrigName)) {
2009 if (*MapName != OrigName && !MapName->empty())
2010 SymbolMap.emplace(FunctionId(*MapName),
F);
2016 if (Opts.report_profile_staleness || Opts.persist_profile_staleness ||
2017 SalvageStaleProfile) {
2018 MatchingManager->runOnModule();
2019 MatchingManager->clearMatchingData();
2021 assert(SymbolMap.count(FunctionId()) == 0 &&
2022 "No empty StringRef should be added in SymbolMap");
2023 assert((SalvageUnusedProfile || FuncNameToProfNameMap.empty()) &&
2024 "FuncNameToProfNameMap is not empty when --salvage-unused-profile is "
2027 bool retval =
false;
2028 for (
auto *
F : buildFunctionOrder(M, CG)) {
2030 clearFunctionData();
2036 for (
const auto &[Fn, Info] : notInlinedCallInfo)
2039 if (Opts.sample_profile_remove_probe &&
2041 removePseudoProbeInstsDiscriminator(M);
2043 M.eraseNamedMetadata(FuncInfo);
2049bool SampleProfileLoader::runOnFunction(
Function &
F,
2051 LLVM_DEBUG(
dbgs() <<
"\n\nProcessing Function " <<
F.getName() <<
"\n");
2052 DILocation2SampleMap.clear();
2059 ProfAccForSymsInList = Opts.profile_accurate_for_symsinlist && PSL;
2060 if (Opts.profile_sample_accurate ||
2061 F.hasFnAttribute(
"profile-sample-accurate")) {
2064 initialEntryCount = 0;
2067 ProfAccForSymsInList =
false;
2069 CoverageTracker.setProfAccForSymsInList(ProfAccForSymsInList);
2075 if (ProfAccForSymsInList) {
2077 if (PSL->contains(
F.getName()))
2078 initialEntryCount = 0;
2093 Function::getGUIDAssumingExternalLinkage(CanonName))
2094 : Reader->contains(CanonName))
2095 initialEntryCount = -1;
2100 if (!
F.getEntryCount())
2101 F.setEntryCount(initialEntryCount);
2107 Samples = ContextTracker->getBaseSamplesFor(
F);
2109 Samples = Reader->getSamplesFor(
F);
2114 auto It = OutlineFunctionSamples.find(FunctionId(CanonName));
2115 if (It != OutlineFunctionSamples.end()) {
2116 Samples = &It->second;
2117 }
else if (
auto Remapper = Reader->getRemapper()) {
2118 if (
auto RemppedName = Remapper->lookUpNameInProfile(CanonName)) {
2119 It = OutlineFunctionSamples.find(FunctionId(*RemppedName));
2120 if (It != OutlineFunctionSamples.end())
2121 Samples = &It->second;
2127 if (Samples && !Samples->
empty())
2128 return emitAnnotations(
F);
2138 bool UseFlattenedProfile)
2139 : ProfileFileName(File), ProfileRemappingFileName(RemappingFile),
2140 LTOPhase(LTOPhase), FS(
std::
move(FS)),
2141 DisableSampleProfileInlining(DisableSampleProfileInlining),
2142 UseFlattenedProfile(UseFlattenedProfile) {}
2164 SampleProfileLoader SampleLoader(
2166 ProfileFileName.empty() ? Opts.sample_profile_file
2168 ProfileRemappingFileName.
empty() ? Opts.sample_profile_remapping_file
2170 LTOPhase, FS, GetAssumptionCache, GetTTI, GetTLI, CG,
2171 DisableSampleProfileInlining, UseFlattenedProfile);
2172 if (!SampleLoader.doInitialization(M, &
FAM))
2176 if (!SampleLoader.runOnModule(M, AM, PSI))
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Function Alias Analysis false
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
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 void updateIDTMetaData(const IPOOptions &Opts, Instruction &Inst, const SmallVectorImpl< InstrProfValueData > &CallTargets, uint64_t Sum)
Update indirect call target profile metadata for Inst.
static bool doesHistoryAllowICP(const IPOOptions &Opts, 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.
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...
LLVM_ABI Function * getCaller()
Helper to get the caller (the parent function).
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...
This is an important class for using LLVM in a threaded context.
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
static LLVM_ABI StringRef getSampleProfileFile(const LLVMContext &C)
Return -sample-profile-file.
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.
LLVMContext & getContext() const
All values hold a context through their type.
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.
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)
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.
bool succ_empty(const Instruction *I)
LLVM_ABI InlineCost getInlineCost(CallBase &Call, const InlineParams &Params, TargetTransformInfo &CallerTTI, 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 InlineParams getInlineParams(const LLVMContext &C)
Generate the parameters to tune the inline cost analysis based only on the commandline options.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
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.
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
LLVM_ABI cl::opt< int > SampleHotCallSiteThreshold
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...
LLVM_ABI cl::opt< int > ProfileInlineGrowthLimit
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.
LLVM_ABI std::string AnnotateInlinePassName(InlineContext IC)
ThinOrFullLTOPhase
This enumerates the LLVM full LTO or ThinLTO optimization phases.
LLVM_ABI cl::opt< bool > SampleProfileUseProfi
const IPOOptions & getIPOOptions(const LLVMContext &C)
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).
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)
LLVM_ABI cl::opt< int > ProfileInlineLimitMax
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 raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
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...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
LLVM_ABI cl::opt< int > SampleColdCallSiteThreshold
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
constexpr bool valueOr(BoolOrDefault X, bool Default)
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...
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI cl::opt< int > ProfileInlineLimitMin
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)