128#include <unordered_map>
135#define DEBUG_TYPE "pgo-instrumentation"
137STATISTIC(NumOfPGOInstrument,
"Number of edges instrumented.");
138STATISTIC(NumOfPGOSelectInsts,
"Number of select instruction instrumented.");
139STATISTIC(NumOfPGOMemIntrinsics,
"Number of mem intrinsics instrumented.");
142STATISTIC(NumOfPGOSplit,
"Number of critical edge splits.");
143STATISTIC(NumOfPGOFunc,
"Number of functions having valid profile counts.");
144STATISTIC(NumOfPGOMismatch,
"Number of functions having mismatch profile.");
145STATISTIC(NumOfPGOMissing,
"Number of functions without profile.");
146STATISTIC(NumOfPGOICall,
"Number of indirect call value instrumentations.");
147STATISTIC(NumOfCSPGOInstrument,
"Number of edges instrumented in CSPGO.");
149 "Number of select instruction instrumented in CSPGO.");
151 "Number of mem intrinsics instrumented in CSPGO.");
153STATISTIC(NumOfCSPGOBB,
"Number of basic-blocks in CSPGO.");
154STATISTIC(NumOfCSPGOSplit,
"Number of critical edge splits in CSPGO.");
156 "Number of functions having valid profile counts in CSPGO.");
158 "Number of functions having mismatch profile in CSPGO.");
159STATISTIC(NumOfCSPGOMissing,
"Number of functions without profile in CSPGO.");
160STATISTIC(NumCoveredBlocks,
"Number of basic blocks that were executed");
168 cl::desc(
"Use this option to turn off/on "
169 "warnings about profile cfg mismatch."));
188 return InstrumentationOptions::Global.pgo_instrument_cold_function_only;
192class FunctionInstrumenter final {
193 const InstrumentationOptions &Opts;
197 std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers;
208 bool isValueProfilingDisabled()
const {
215 return Opts.disable_vp ||
220 bool shouldInstrumentEntryBB()
const {
221 return valueOr(Opts.pgo_instrument_entry,
false) ||
222 InstrumentationType == PGOInstrumentationType::CTXPROF;
225 bool shouldInstrumentLoopEntries()
const {
226 return valueOr(Opts.pgo_instrument_loop_entries,
false);
230 FunctionInstrumenter(
232 TargetLibraryInfo &TLI,
233 std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers,
234 BranchProbabilityInfo *BPI =
nullptr, BlockFrequencyInfo *BFI =
nullptr,
235 LoopInfo *LI =
nullptr,
237 : Opts(Opts), M(M), F(F), TLI(TLI), ComdatMembers(ComdatMembers),
238 BPI(BPI), BFI(BFI), LI(LI), InstrumentationType(InstrumentationType) {}
249 return std::string();
254 return std::string();
266 else if (CV->
isOne())
277#define VALUE_PROF_KIND(Enumerator, Value, Descr) Descr,
291 if (
valueOr(Opts.pgo_instrument_entry,
false) ||
294 if (
valueOr(Opts.pgo_instrument_loop_entries,
false))
298 if (Opts.pgo_function_entry_coverage)
301 if (Opts.pgo_block_coverage)
303 if (Opts.pgo_temporal_instrumentation)
310 Triple TT(M.getTargetTriple());
311 if (TT.supportsCOMDAT()) {
313 IRLevelVersionVariable->setComdat(M.getOrInsertComdat(VarName));
315 return IRLevelVersionVariable;
325enum VisitMode { VM_counting, VM_instrument, VM_annotate };
329struct SelectInstVisitor :
public InstVisitor<SelectInstVisitor> {
330 const InstrumentationOptions &Opts;
333 VisitMode Mode = VM_counting;
334 unsigned *CurCtrIdx =
nullptr;
335 unsigned TotalNumCtrs = 0;
336 GlobalValue *FuncNameVar =
nullptr;
338 PGOUseFunc *UseFunc =
nullptr;
339 bool HasSingleByteCoverage;
341 SelectInstVisitor(
const InstrumentationOptions &Opts,
Function &Func,
342 bool HasSingleByteCoverage)
343 : Opts(Opts), F(
Func), HasSingleByteCoverage(HasSingleByteCoverage) {}
345 void countSelects() {
355 void instrumentSelects(
unsigned *Ind,
unsigned TotalNC, GlobalValue *FNV,
357 Mode = VM_instrument;
359 TotalNumCtrs = TotalNC;
366 void annotateSelects(PGOUseFunc *UF,
unsigned *Ind) {
373 void instrumentOneSelectInst(SelectInst &SI);
374 void annotateOneSelectInst(SelectInst &SI);
377 void visitSelectInst(SelectInst &SI);
381 unsigned getNumOfSelectInsts()
const {
return NSIs; }
393 bool Removed =
false;
394 bool IsCritical =
false;
396 PGOEdge(BasicBlock *Src, BasicBlock *Dest,
uint64_t W = 1)
397 : SrcBB(Src), DestBB(Dest), Weight(
W) {}
400 std::string infoString()
const {
401 return (Twine(Removed ?
"-" :
" ") + (InMST ?
" " :
"*") +
402 (IsCritical ?
"c" :
" ") +
" W=" + Twine(Weight))
413 PGOBBInfo(
unsigned IX) : Group(this), Index(IX) {}
416 std::string infoString()
const {
417 return (Twine(
"Index=") + Twine(Index)).str();
422template <
class Edge,
class BBInfo>
class FuncPGOInstrumentation {
424 const InstrumentationOptions &Opts;
431 std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers;
433 ValueProfileCollector VPC;
435 void computeCFGHash();
436 void renameComdatFunction();
439 const TargetLibraryInfo &TLI;
440 std::vector<std::vector<VPCandidateInfo>> ValueSites;
441 SelectInstVisitor SIVisitor;
442 std::string FuncName;
443 std::string DeprecatedFuncName;
444 GlobalVariable *FuncNameVar;
450 CFGMST<Edge, BBInfo> MST;
452 const std::optional<BlockCoverageInference> BCI;
454 static std::optional<BlockCoverageInference>
455 constructBCI(
Function &Func,
bool HasSingleByteCoverage,
456 bool InstrumentFuncEntry) {
457 if (HasSingleByteCoverage)
458 return BlockCoverageInference(Func, InstrumentFuncEntry);
464 void getInstrumentBBs(std::vector<BasicBlock *> &InstrumentBBs);
471 BBInfo &getBBInfo(
const BasicBlock *BB)
const {
return MST.getBBInfo(BB); }
474 BBInfo *findBBInfo(
const BasicBlock *BB)
const {
return MST.findBBInfo(BB); }
477 void dumpInfo(StringRef Str =
"")
const {
478 MST.dumpEdges(
dbgs(), Twine(
"Dump Function ") + FuncName +
479 " Hash: " + Twine(FunctionHash) +
"\t" + Str);
482 FuncPGOInstrumentation(
483 const InstrumentationOptions &Opts,
Function &Func,
484 TargetLibraryInfo &TLI,
485 std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers,
486 bool CreateGlobalVar =
false, BranchProbabilityInfo *BPI =
nullptr,
487 BlockFrequencyInfo *BFI =
nullptr, LoopInfo *LI =
nullptr,
488 bool IsCS =
false,
bool InstrumentFuncEntry =
true,
489 bool InstrumentLoopEntries =
false,
bool HasSingleByteCoverage =
false)
490 : Opts(Opts), F(
Func), IsCS(IsCS), ComdatMembers(ComdatMembers),
491 VPC(
Func, TLI), TLI(TLI), ValueSites(IPVK_Last + 1),
492 SIVisitor(Opts,
Func, HasSingleByteCoverage),
493 MST(F, InstrumentFuncEntry, InstrumentLoopEntries, BPI, BFI, LI),
494 BCI(constructBCI(
Func, HasSingleByteCoverage, InstrumentFuncEntry)) {
495 if (BCI && Opts.pgo_view_block_coverage_graph)
496 BCI->viewBlockCoverageGraph();
498 SIVisitor.countSelects();
499 ValueSites[IPVK_MemOPSize] = VPC.get(IPVK_MemOPSize);
501 NumOfPGOSelectInsts += SIVisitor.getNumOfSelectInsts();
502 NumOfPGOMemIntrinsics += ValueSites[IPVK_MemOPSize].size();
503 NumOfPGOBB += MST.bbInfoSize();
504 ValueSites[IPVK_IndirectCallTarget] = VPC.get(IPVK_IndirectCallTarget);
506 ValueSites[IPVK_VTableTarget] = VPC.get(IPVK_VTableTarget);
508 NumOfCSPGOSelectInsts += SIVisitor.getNumOfSelectInsts();
509 NumOfCSPGOMemIntrinsics += ValueSites[IPVK_MemOPSize].size();
510 NumOfCSPGOBB += MST.bbInfoSize();
516 if (!ComdatMembers.empty())
517 renameComdatFunction();
520 for (
const auto &
E : MST.allEdges()) {
523 IsCS ? NumOfCSPGOEdge++ : NumOfPGOEdge++;
525 IsCS ? NumOfCSPGOInstrument++ : NumOfPGOInstrument++;
538template <
class Edge,
class BBInfo>
539void FuncPGOInstrumentation<Edge, BBInfo>::computeCFGHash() {
540 std::vector<uint8_t> Indexes;
544 auto BI = findBBInfo(Succ);
548 for (
int J = 0; J < 4; J++)
549 Indexes.push_back((
uint8_t)(Index >> (J * 8)));
556 auto updateJCH = [&JCH](
uint64_t Num) {
561 updateJCH((
uint64_t)SIVisitor.getNumOfSelectInsts());
562 updateJCH((
uint64_t)ValueSites[IPVK_IndirectCallTarget].
size());
565 updateJCH(BCI->getInstrumentedBlocksHash());
578 LLVM_DEBUG(
dbgs() <<
"Function Hash Computation for " <<
F.getName() <<
":\n"
579 <<
" CRC = " << JC.
getCRC()
580 <<
", Selects = " << SIVisitor.getNumOfSelectInsts()
581 <<
", Edges = " << MST.
numEdges() <<
", ICSites = "
582 << ValueSites[IPVK_IndirectCallTarget].size()
583 <<
", Memops = " << ValueSites[IPVK_MemOPSize].size()
584 <<
", High32 CRC = " << JCH.
getCRC()
585 <<
", Hash = " << FunctionHash <<
"\n";);
587 if (Opts.pgo_trace_func_hash !=
"-" &&
588 F.getName().contains(Opts.pgo_trace_func_hash))
589 dbgs() <<
"Funcname=" <<
F.getName() <<
", Hash=" << FunctionHash
590 <<
" in building " <<
F.getParent()->getSourceFileName() <<
"\n";
595 const InstrumentationOptions &Opts,
Function &
F,
596 std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers) {
608 for (
auto &&CM :
make_range(ComdatMembers.equal_range(
C))) {
618template <
class Edge,
class BBInfo>
619void FuncPGOInstrumentation<Edge, BBInfo>::renameComdatFunction() {
622 std::string OrigName =
F.getName().str();
623 std::string NewFuncName =
625 F.setName(
Twine(NewFuncName));
627 FuncName =
Twine(FuncName +
"." +
Twine(FunctionHash)).
str();
633 if (!
F.hasComdat()) {
635 NewComdat = M->getOrInsertComdat(
StringRef(NewFuncName));
637 F.setComdat(NewComdat);
642 Comdat *OrigComdat =
F.getComdat();
643 std::string NewComdatName =
645 NewComdat = M->getOrInsertComdat(
StringRef(NewComdatName));
648 for (
auto &&CM :
make_range(ComdatMembers.equal_range(OrigComdat))) {
656template <
class Edge,
class BBInfo>
657void FuncPGOInstrumentation<Edge, BBInfo>::getInstrumentBBs(
658 std::vector<BasicBlock *> &InstrumentBBs) {
661 if (BCI->shouldInstrumentBlock(BB))
662 InstrumentBBs.push_back(&BB);
667 std::vector<Edge *> EdgeList;
670 EdgeList.push_back(
E.get());
672 for (
auto &
E : EdgeList) {
675 InstrumentBBs.push_back(InstrBB);
681template <
class Edge,
class BBInfo>
682BasicBlock *FuncPGOInstrumentation<Edge, BBInfo>::getInstrBB(Edge *
E) {
683 if (
E->InMST ||
E->Removed)
689 if (SrcBB ==
nullptr)
691 if (DestBB ==
nullptr)
706 return canInstrument(SrcBB);
708 return canInstrument(DestBB);
717 dbgs() <<
"Fail to split critical edge: not instrument this edge.\n");
722 IsCS ? NumOfCSPGOSplit++ : NumOfPGOSplit++;
723 LLVM_DEBUG(
dbgs() <<
"Split critical edge: " << getBBInfo(SrcBB).Index
724 <<
" --> " << getBBInfo(DestBB).Index <<
"\n");
726 MST.
addEdge(SrcBB, InstrBB, 0);
728 Edge &NewEdge1 = MST.
addEdge(InstrBB, DestBB, 0);
729 NewEdge1.InMST =
true;
732 return canInstrument(InstrBB);
751 std::optional<OperandBundleUse> ParentFunclet =
759 if (!BlockColors.
empty()) {
760 const ColorVector &CV = BlockColors.
find(OrigCall->getParent())->second;
761 assert(CV.
size() == 1 &&
"non-unique color for block!");
763 if (EHPadIt->isEHPad())
771void FunctionInstrumenter::instrument() {
772 if (!Opts.pgo_block_coverage) {
778 const bool IsCtxProf = InstrumentationType == PGOInstrumentationType::CTXPROF;
779 FuncPGOInstrumentation<PGOEdge, PGOBBInfo> FuncInfo(
780 Opts,
F, TLI, ComdatMembers, !IsCtxProf, BPI, BFI, LI,
781 InstrumentationType == PGOInstrumentationType::CSFDO,
782 shouldInstrumentEntryBB(), shouldInstrumentLoopEntries(),
783 Opts.pgo_block_coverage);
786 auto *
const CFGHash =
787 ConstantInt::get(Type::getInt64Ty(
M.getContext()), FuncInfo.FunctionHash);
791 Name, PointerType::get(
M.getContext(), 0));
792 if (Opts.pgo_function_entry_coverage) {
793 auto &EntryBB =
F.getEntryBlock();
794 IRBuilder<> Builder(EntryBB.getFirstNonPHIOrDbgOrAlloca());
797 Builder.CreateIntrinsic(
798 Intrinsic::instrprof_cover,
799 {NormalizedNamePtr, CFGHash, Builder.getInt32(1), Builder.getInt32(0)});
803 std::vector<BasicBlock *> InstrumentBBs;
804 FuncInfo.getInstrumentBBs(InstrumentBBs);
805 unsigned NumCounters =
806 InstrumentBBs.size() + FuncInfo.SIVisitor.getNumOfSelectInsts();
810 Opts.ctx_prof_skip_callsite_instr);
822 auto Visit = [&](llvm::function_ref<void(CallBase * CB)> Visitor) {
824 for (
auto &Instr : BB)
828 if (CS->getCalledFunction() &&
829 SkipCSInstr.contains(CS->getCalledFunction()->getName()))
835 uint32_t TotalNumCallsites = 0;
836 Visit([&TotalNumCallsites](
auto *) { ++TotalNumCallsites; });
840 Visit([&](
auto *CB) {
842 Builder.CreateCall(CSIntrinsic,
843 {
Name, CFGHash, Builder.getInt32(TotalNumCallsites),
845 CB->getCalledOperand()});
850 if (Opts.pgo_temporal_instrumentation) {
851 NumCounters += Opts.pgo_block_coverage ? 8 : 1;
852 auto &EntryBB =
F.getEntryBlock();
853 IRBuilder<> Builder(EntryBB.getFirstNonPHIOrDbgOrAlloca());
856 Builder.CreateIntrinsic(Intrinsic::instrprof_timestamp,
857 {NormalizedNamePtr, CFGHash,
858 Builder.getInt32(NumCounters),
859 Builder.getInt32(
I)});
860 I += Opts.pgo_block_coverage ? 8 : 1;
863 for (
auto *InstrBB : InstrumentBBs) {
865 assert(Builder.GetInsertPoint() != InstrBB->
end() &&
866 "Cannot get the Instrumentation point");
869 Builder.CreateIntrinsic(
870 Opts.pgo_block_coverage ? Intrinsic::instrprof_cover
871 : Intrinsic::instrprof_increment,
872 {NormalizedNamePtr, CFGHash, Builder.getInt32(NumCounters),
873 Builder.getInt32(I++)});
877 FuncInfo.SIVisitor.instrumentSelects(&
I, NumCounters, Name,
878 FuncInfo.FunctionHash);
881 if (isValueProfilingDisabled())
884 NumOfPGOICall += FuncInfo.ValueSites[IPVK_IndirectCallTarget].size();
890 DenseMap<BasicBlock *, ColorVector> BlockColors;
891 if (
F.hasPersonalityFn() &&
896 for (uint32_t Kind = IPVK_First;
Kind <= IPVK_Last; ++
Kind) {
897 unsigned SiteIndex = 0;
898 if (Kind == IPVK_MemOPSize && !Opts.pgo_instr_memop)
903 <<
" site: CallSite Index = " << SiteIndex <<
"\n");
906 assert(Builder.GetInsertPoint() != Cand.InsertPt->getParent()->end() &&
907 "Cannot get the Instrumentation point");
909 Value *ToProfile =
nullptr;
910 if (Cand.V->getType()->isIntegerTy())
911 ToProfile = Builder.CreateZExtOrTrunc(Cand.V, Builder.getInt64Ty());
912 else if (Cand.V->getType()->isPointerTy())
913 ToProfile = Builder.CreatePtrToInt(Cand.V, Builder.getInt64Ty());
914 assert(ToProfile &&
"value profiling Value is of unexpected type");
917 Name, PointerType::get(
M.getContext(), 0));
923 Intrinsic::instrprof_value_profile),
924 {NormalizedNamePtr, Builder.getInt64(FuncInfo.FunctionHash),
925 ToProfile, Builder.getInt32(Kind), Builder.getInt32(SiteIndex++)},
934struct PGOUseEdge :
public PGOEdge {
935 using PGOEdge::PGOEdge;
937 std::optional<uint64_t>
Count;
943 std::string infoString()
const {
945 return PGOEdge::infoString();
946 return (Twine(PGOEdge::infoString()) +
" Count=" + Twine(*
Count)).str();
953struct PGOUseBBInfo :
public PGOBBInfo {
954 std::optional<uint64_t>
Count;
955 int32_t UnknownCountInEdge = 0;
956 int32_t UnknownCountOutEdge = 0;
958 DirectEdges OutEdges;
960 PGOUseBBInfo(
unsigned IX) : PGOBBInfo(IX) {}
966 std::string infoString()
const {
968 return PGOBBInfo::infoString();
969 return (Twine(PGOBBInfo::infoString()) +
" Count=" + Twine(*
Count)).str();
973 void addOutEdge(PGOUseEdge *
E) {
974 OutEdges.push_back(
E);
975 UnknownCountOutEdge++;
979 void addInEdge(PGOUseEdge *
E) {
980 InEdges.push_back(
E);
981 UnknownCountInEdge++;
990 for (
const auto &
E : Edges) {
1003 PGOUseFunc(
const InstrumentationOptions &Opts,
Function &Func,
Module *Modu,
1004 TargetLibraryInfo &TLI,
1005 std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers,
1006 BranchProbabilityInfo *BPI, BlockFrequencyInfo *BFIin,
1007 LoopInfo *LI, ProfileSummaryInfo *PSI,
bool IsCS,
1008 bool InstrumentFuncEntry,
bool InstrumentLoopEntries,
1009 bool HasSingleByteCoverage)
1010 : Opts(Opts),
F(
Func),
M(Modu), BFI(BFIin), PSI(PSI),
1011 FuncInfo(Opts,
Func, TLI, ComdatMembers,
false, BPI, BFIin, LI, IsCS,
1012 InstrumentFuncEntry, InstrumentLoopEntries,
1013 HasSingleByteCoverage),
1014 FreqAttr(FFA_Normal), IsCS(IsCS), VPC(
Func, TLI) {}
1016 void handleInstrProfError(
Error Err,
uint64_t MismatchedFuncSum);
1021 bool getRecord(IndexedInstrProfReader *PGOReader);
1024 bool readCounters(
bool &AllZeros,
1028 void populateCounters();
1031 void populateCoverage();
1037 void annotateValueSites();
1040 void annotateValueSites(uint32_t Kind);
1043 void annotateIrrLoopHeaderWeights();
1046 void setBlockUniformityAttribute();
1049 enum FuncFreqAttr { FFA_Normal, FFA_Cold, FFA_Hot };
1052 FuncFreqAttr getFuncFreqAttr()
const {
return FreqAttr; }
1058 NamedInstrProfRecord &getProfileRecord() {
return ProfileRecord; }
1061 PGOUseBBInfo &getBBInfo(
const BasicBlock *BB)
const {
1062 return FuncInfo.getBBInfo(BB);
1066 PGOUseBBInfo *findBBInfo(
const BasicBlock *BB)
const {
1067 return FuncInfo.findBBInfo(BB);
1072 void dumpInfo(StringRef Str =
"")
const { FuncInfo.dumpInfo(Str); }
1074 uint64_t getProgramMaxCount()
const {
return ProgramMaxCount; }
1077 const InstrumentationOptions &Opts;
1080 BlockFrequencyInfo *BFI;
1081 ProfileSummaryInfo *PSI;
1084 FuncPGOInstrumentation<PGOUseEdge, PGOUseBBInfo> FuncInfo;
1091 uint32_t CountPosition = 0;
1094 uint32_t ProfileCountSize = 0;
1097 NamedInstrProfRecord ProfileRecord;
1100 FuncFreqAttr FreqAttr;
1105 ValueProfileCollector VPC;
1108 bool setInstrumentedCounts(
const std::vector<uint64_t> &CountFromProfile);
1121 FreqAttr = FFA_Cold;
1129 const FuncPGOInstrumentation<PGOUseEdge, PGOUseBBInfo> &FuncInfo) {
1133 for (
const auto &
E : FuncInfo.MST.allEdges()) {
1138 PGOUseBBInfo &SrcInfo = FuncInfo.getBBInfo(SrcBB);
1139 PGOUseBBInfo &DestInfo = FuncInfo.getBBInfo(DestBB);
1140 SrcInfo.addOutEdge(
E.get());
1141 DestInfo.addInEdge(
E.get());
1147bool PGOUseFunc::setInstrumentedCounts(
1148 const std::vector<uint64_t> &CountFromProfile) {
1150 std::vector<BasicBlock *> InstrumentBBs;
1151 FuncInfo.getInstrumentBBs(InstrumentBBs);
1155 unsigned NumInstrumentedBBs = InstrumentBBs.size();
1156 unsigned NumSelects = FuncInfo.SIVisitor.getNumOfSelectInsts();
1157 unsigned NumCounters = NumInstrumentedBBs + NumSelects;
1160 if (NumCounters != CountFromProfile.size()) {
1162 dbgs() <<
"PGO COUNTER MISMATCH for function " <<
F.getName() <<
":\n";
1163 dbgs() <<
" Expected counters: " << NumCounters <<
"\n";
1164 dbgs() <<
" - From instrumented edges: " << NumInstrumentedBBs <<
"\n";
1165 for (
size_t i = 0; i < InstrumentBBs.size(); ++i) {
1166 dbgs() <<
" " << i <<
": ";
1167 InstrumentBBs[i]->printAsOperand(
dbgs(),
false);
1170 dbgs() <<
" - From select instructions: " << NumSelects <<
"\n";
1171 dbgs() <<
" Actual counters from profile: " << CountFromProfile.size()
1176 auto *FuncEntry = &*
F.begin();
1180 for (BasicBlock *InstrBB : InstrumentBBs) {
1181 uint64_t CountValue = CountFromProfile[
I++];
1182 PGOUseBBInfo &
Info = getBBInfo(InstrBB);
1186 if (InstrBB == FuncEntry && CountValue == 0)
1188 Info.setBBInfoCount(CountValue);
1190 ProfileCountSize = CountFromProfile.size();
1194 auto setEdgeCount = [
this](PGOUseEdge *
E,
uint64_t Value) ->
void {
1196 this->getBBInfo(
E->SrcBB).UnknownCountOutEdge--;
1197 this->getBBInfo(
E->DestBB).UnknownCountInEdge--;
1203 for (
const auto &
E : FuncInfo.MST.allEdges()) {
1204 if (
E->Removed ||
E->InMST)
1207 PGOUseBBInfo &SrcInfo = getBBInfo(SrcBB);
1211 if (SrcInfo.Count && SrcInfo.OutEdges.size() == 1)
1212 setEdgeCount(
E.get(), *SrcInfo.Count);
1215 PGOUseBBInfo &DestInfo = getBBInfo(DestBB);
1218 if (DestInfo.Count && DestInfo.InEdges.size() == 1)
1219 setEdgeCount(
E.get(), *DestInfo.Count);
1225 setEdgeCount(
E.get(), 0);
1232void PGOUseFunc::setEdgeCount(DirectEdges &Edges,
uint64_t Value) {
1233 for (
auto &
E : Edges) {
1238 getBBInfo(
E->SrcBB).UnknownCountOutEdge--;
1239 getBBInfo(
E->DestBB).UnknownCountInEdge--;
1247 const char MetadataName[] =
"instr_prof_hash_mismatch";
1250 auto *Existing =
F.getMetadata(LLVMContext::MD_annotation);
1253 for (
const auto &
N : Tuple->operands()) {
1254 if (
N.equalsStr(MetadataName))
1263 F.setMetadata(LLVMContext::MD_annotation, MD);
1266void PGOUseFunc::handleInstrProfError(
Error Err,
uint64_t MismatchedFuncSum) {
1268 auto &Ctx =
M->getContext();
1269 auto Err = IPE.
get();
1270 bool SkipWarning =
false;
1272 << FuncInfo.FuncName <<
": ");
1273 if (Err == instrprof_error::unknown_function) {
1274 IsCS ? NumOfCSPGOMissing++ : NumOfPGOMissing++;
1275 SkipWarning = !Opts.pgo_warn_missing_function;
1277 }
else if (Err == instrprof_error::hash_mismatch ||
1278 Err == instrprof_error::malformed) {
1279 IsCS ? NumOfCSPGOMismatch++ : NumOfPGOMismatch++;
1282 (Opts.no_pgo_warn_mismatch_comdat_weak &&
1285 LLVM_DEBUG(
dbgs() <<
"hash mismatch (hash= " << FuncInfo.FunctionHash
1286 <<
" skip=" << SkipWarning <<
")");
1296 IPE.
message() + std::string(
" ") +
F.getName().str() +
1297 std::string(
" Hash = ") + std::to_string(FuncInfo.FunctionHash) +
1298 std::string(
" up to ") + std::to_string(MismatchedFuncSum) +
1299 std::string(
" count discarded");
1306bool PGOUseFunc::getRecord(IndexedInstrProfReader *PGOReader) {
1309 FuncInfo.FuncName, FuncInfo.FunctionHash, FuncInfo.DeprecatedFuncName,
1310 &MismatchedFuncSum);
1312 handleInstrProfError(std::move(
E), MismatchedFuncSum);
1315 ProfileRecord = std::move(
Result.get());
1323bool PGOUseFunc::readCounters(
bool &AllZeros,
1325 auto &Ctx =
M->getContext();
1330 std::vector<uint64_t> &CountFromProfile = ProfileRecord.
Counts;
1332 IsCS ? NumOfCSPGOFunc++ : NumOfPGOFunc++;
1336 for (
unsigned I = 0, S = CountFromProfile.size();
I < S;
I++) {
1338 ValueSum += CountFromProfile[
I];
1340 AllZeros = (ValueSum == 0);
1344 getBBInfo(
nullptr).UnknownCountOutEdge = 2;
1345 getBBInfo(
nullptr).UnknownCountInEdge = 2;
1347 if (!setInstrumentedCounts(CountFromProfile)) {
1349 dbgs() <<
"Inconsistent number of counts, skipping this function");
1350 Ctx.diagnose(DiagnosticInfoPGOProfile(
1351 M->getName().data(),
1352 Twine(
"Inconsistent number of counts in ") +
F.getName().str() +
1353 Twine(
": the profile may be stale or there is a function name "
1361void PGOUseFunc::populateCoverage() {
1362 IsCS ? NumOfCSPGOFunc++ : NumOfPGOFunc++;
1364 ArrayRef<uint64_t> CountsFromProfile = ProfileRecord.
Counts;
1365 DenseMap<const BasicBlock *, bool>
Coverage;
1368 if (FuncInfo.BCI->shouldInstrumentBlock(BB))
1373 DenseMap<const BasicBlock *, DenseSet<const BasicBlock *>>
1374 InverseDependencies;
1375 for (
auto &BB :
F) {
1376 for (
auto *Dep : FuncInfo.BCI->getDependencies(BB)) {
1378 InverseDependencies[Dep].
insert(&BB);
1383 std::stack<const BasicBlock *> CoveredBlocksToProcess;
1384 for (
auto &[BB, IsCovered] : Coverage)
1386 CoveredBlocksToProcess.push(BB);
1388 while (!CoveredBlocksToProcess.empty()) {
1389 auto *CoveredBlock = CoveredBlocksToProcess.top();
1390 assert(Coverage[CoveredBlock]);
1391 CoveredBlocksToProcess.pop();
1392 for (
auto *BB : InverseDependencies[CoveredBlock]) {
1398 CoveredBlocksToProcess.push(BB);
1403 MDBuilder MDB(
F.getContext());
1406 F.setEntryCount(Coverage[&
F.getEntryBlock()] ? 10000 : 0);
1407 for (
auto &BB :
F) {
1414 SmallVector<uint32_t, 4> Weights;
1416 Weights.
push_back((Coverage[Succ] || !Coverage[&BB]) ? 1 : 0);
1417 if (Weights.
size() >= 2)
1422 unsigned NumCorruptCoverage = 0;
1425 BranchProbabilityInfo BPI(
F, CI);
1426 BlockFrequencyInfo BFI(
F, BPI, CI);
1427 auto IsBlockDead = [&](
const BasicBlock &BB) -> std::optional<bool> {
1432 LLVM_DEBUG(
dbgs() <<
"Block Coverage: (Instrumented=*, Covered=X)\n");
1433 for (
auto &BB :
F) {
1434 LLVM_DEBUG(
dbgs() << (FuncInfo.BCI->shouldInstrumentBlock(BB) ?
"* " :
" ")
1435 << (Coverage[&BB] ?
"X " :
" ") <<
" " << BB.getName()
1442 if (Cov == IsBlockDead(BB).value_or(
false)) {
1444 dbgs() <<
"Found inconsistent block covearge for " << BB.getName()
1445 <<
": BCI=" << (Cov ?
"Covered" :
"Dead") <<
" BFI="
1446 << (IsBlockDead(BB).value() ?
"Dead" :
"Covered") <<
"\n");
1447 ++NumCorruptCoverage;
1452 if (Opts.pgo_verify_bfi && NumCorruptCoverage) {
1453 auto &Ctx =
M->getContext();
1454 Ctx.diagnose(DiagnosticInfoPGOProfile(
1455 M->getName().data(),
1456 Twine(
"Found inconsistent block coverage for function ") +
F.getName() +
1457 " in " + Twine(NumCorruptCoverage) +
" blocks.",
1460 if (Opts.pgo_view_block_coverage_graph)
1461 FuncInfo.BCI->viewBlockCoverageGraph(&Coverage);
1466void PGOUseFunc::populateCounters() {
1467 bool Changes =
true;
1468 unsigned NumPasses = 0;
1476 PGOUseBBInfo *UseBBInfo = findBBInfo(&BB);
1477 if (UseBBInfo ==
nullptr)
1479 if (!UseBBInfo->Count) {
1480 if (UseBBInfo->UnknownCountOutEdge == 0) {
1483 }
else if (UseBBInfo->UnknownCountInEdge == 0) {
1488 if (UseBBInfo->Count) {
1489 if (UseBBInfo->UnknownCountOutEdge == 1) {
1495 if (*UseBBInfo->Count > OutSum)
1496 Total = *UseBBInfo->Count - OutSum;
1497 setEdgeCount(UseBBInfo->OutEdges,
Total);
1500 if (UseBBInfo->UnknownCountInEdge == 1) {
1503 if (*UseBBInfo->Count > InSum)
1504 Total = *UseBBInfo->Count - InSum;
1505 setEdgeCount(UseBBInfo->InEdges,
Total);
1512 LLVM_DEBUG(
dbgs() <<
"Populate counts in " << NumPasses <<
" passes.\n");
1516 for (
auto &BB :
F) {
1517 auto BI = findBBInfo(&BB);
1520 assert(BI->Count &&
"BB count is not valid");
1524 FuncInfo.SIVisitor.annotateSelects(
this, &CountPosition);
1525 assert(CountPosition == ProfileCountSize);
1529 for (
auto &BB :
F) {
1530 auto BI = findBBInfo(&BB);
1533 FuncMaxCount = std::max(FuncMaxCount, *BI->Count);
1542 LLVM_DEBUG(FuncInfo.dumpInfo(
"after reading profile."));
1546void PGOUseFunc::setBranchWeights() {
1548 LLVM_DEBUG(
dbgs() <<
"\nSetting branch weights for func " <<
F.getName()
1549 <<
" IsCS=" << IsCS <<
"\n");
1550 for (
auto &BB :
F) {
1559 const PGOUseBBInfo &BBCountInfo = getBBInfo(&BB);
1560 if (!*BBCountInfo.Count)
1567 unsigned OutEdgesCount = BBCountInfo.OutEdges.size();
1568 unsigned SuccessorCount = BB.getTerminator()->getNumSuccessors();
1569 assert(OutEdgesCount <= SuccessorCount);
1573 for (
unsigned It = 0; It < OutEdgesCount; It++) {
1574 const PGOUseEdge *
E = BBCountInfo.OutEdges[It];
1577 if (DestBB ==
nullptr)
1581 if (EdgeCount > MaxCount)
1582 MaxCount = EdgeCount;
1583 EdgeCounts[SuccNum] = EdgeCount;
1592 auto &Ctx =
M->getContext();
1593 Ctx.diagnose(DiagnosticInfoPGOProfile(
1594 M->getName().data(),
1595 Twine(
"Profile in ") +
F.getName().str() +
1596 Twine(
" partially ignored") +
1597 Twine(
", possibly due to the lack of a return path."),
1611void PGOUseFunc::annotateIrrLoopHeaderWeights() {
1612 LLVM_DEBUG(
dbgs() <<
"\nAnnotating irreducible loop header weights.\n");
1614 for (
auto &BB :
F) {
1620 const PGOUseBBInfo &BBCountInfo = getBBInfo(&BB);
1626void PGOUseFunc::setBlockUniformityAttribute() {
1637 std::vector<BasicBlock *> InstrumentBBs;
1638 FuncInfo.getInstrumentBBs(InstrumentBBs);
1640 LLVMContext &Ctx =
F.getContext();
1641 Type *Int1Ty = Type::getInt1Ty(Ctx);
1643 for (
size_t I = 0,
E = InstrumentBBs.size();
I <
E; ++
I) {
1655 dbgs() <<
"PGO: Set block uniformity profile for " <<
F.getName() <<
": ";
1656 for (
size_t I = 0,
E = InstrumentBBs.size();
I <
E; ++
I)
1662void SelectInstVisitor::instrumentOneSelectInst(SelectInst &SI) {
1665 Type *Int64Ty = Builder.getInt64Ty();
1671 auto *Step = Builder.CreateZExt(
Cond, Int64Ty);
1672 auto *NormalizedFuncNameVarPtr =
1674 FuncNameVar, PointerType::get(
M->getContext(), 0));
1675 Builder.CreateIntrinsic(Intrinsic::instrprof_increment_step,
1676 {NormalizedFuncNameVarPtr, Builder.getInt64(
FuncHash),
1677 Builder.getInt32(TotalNumCtrs),
1678 Builder.getInt32(*CurCtrIdx), Step});
1682void SelectInstVisitor::annotateOneSelectInst(SelectInst &SI) {
1683 std::vector<uint64_t> &CountFromProfile = UseFunc->getProfileRecord().Counts;
1684 assert(*CurCtrIdx < CountFromProfile.size() &&
1685 "Out of bound access of counters");
1687 SCounts[0] = CountFromProfile[*CurCtrIdx];
1690 auto BI = UseFunc->findBBInfo(
SI.getParent());
1691 if (BI !=
nullptr) {
1692 TotalCount = *BI->Count;
1695 if (TotalCount < SCounts[0])
1696 BI->Count = SCounts[0];
1699 SCounts[1] = (TotalCount > SCounts[0] ? TotalCount - SCounts[0] : 0);
1700 uint64_t MaxCount = std::max(SCounts[0], SCounts[1]);
1705void SelectInstVisitor::visitSelectInst(SelectInst &SI) {
1706 if (!Opts.pgo_instr_select || Opts.pgo_function_entry_coverage ||
1707 HasSingleByteCoverage)
1710 if (
SI.getCondition()->getType()->isVectorTy())
1718 instrumentOneSelectInst(SI);
1721 annotateOneSelectInst(SI);
1730 if (ValueProfKind == IPVK_MemOPSize)
1731 return Opts.memop_max_annotations;
1732 if (ValueProfKind == llvm::IPVK_VTableTarget)
1734 return Opts.icp_max_annotations;
1738void PGOUseFunc::annotateValueSites() {
1739 if (Opts.disable_vp)
1742 for (uint32_t Kind = IPVK_First;
Kind <= IPVK_Last; ++
Kind)
1743 annotateValueSites(Kind);
1747void PGOUseFunc::annotateValueSites(uint32_t Kind) {
1748 assert(Kind <= IPVK_Last);
1749 unsigned ValueSiteIndex = 0;
1763 NumValueSites != FuncInfo.ValueSites[IPVK_VTableTarget].size() &&
1765 FuncInfo.ValueSites[IPVK_VTableTarget] = VPC.
get(IPVK_VTableTarget);
1766 auto &ValueSites = FuncInfo.ValueSites[
Kind];
1768 auto &Ctx =
M->getContext();
1769 Ctx.
diagnose(DiagnosticInfoPGOProfile(
1770 M->getName().data(),
1771 Twine(
"Inconsistent number of value sites for ") +
1774 Twine(
"\", possibly due to the use of a stale profile."),
1780 LLVM_DEBUG(
dbgs() <<
"Read one value site profile (kind = " << Kind
1781 <<
"): Index = " << ValueSiteIndex <<
" out of "
1784 *M, *
I.AnnotatedInst, ProfileRecord,
1794 const InstrumentationOptions &Opts,
Module &M,
1795 std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers) {
1796 if (!Opts.do_comdat_renaming)
1800 ComdatMembers.insert(std::make_pair(
C, &
F));
1802 if (
Comdat *
C = GV.getComdat())
1803 ComdatMembers.insert(std::make_pair(
C, &GV));
1805 if (
Comdat *
C = GA.getComdat())
1806 ComdatMembers.insert(std::make_pair(
C, &GA));
1811 if (
F.isDeclaration())
1816 unsigned NumCriticalEdges = 0;
1817 for (
auto &BB :
F) {
1824 if (NumCriticalEdges > Opts.pgo_critical_edge_threshold) {
1826 <<
", NumCriticalEdges=" << NumCriticalEdges
1827 <<
" exceed the threshold. Skip PGO.\n");
1837 if (
F.hasFnAttribute(llvm::Attribute::Naked))
1839 if (
F.hasFnAttribute(llvm::Attribute::NoProfile))
1841 if (
F.hasFnAttribute(llvm::Attribute::SkipProfile))
1843 if (
F.getInstructionCount() < Opts.pgo_function_size_threshold)
1845 if (Opts.pgo_instrument_cold_function_only) {
1846 if (
auto EntryCount =
F.getEntryCount())
1847 return *EntryCount > Opts.pgo_cold_instrument_entry_threshold;
1848 return !Opts.pgo_treat_unknown_as_cold;
1854 const InstrumentationOptions &Opts,
Module &M,
1865 Triple TT(M.getTargetTriple());
1870 Twine(
"VTable value profiling is presently not "
1871 "supported for non-ELF object formats"),
1873 std::unordered_multimap<Comdat *, GlobalValue *> ComdatMembers;
1883 FunctionInstrumenter FI(Opts, M,
F, TLI, ComdatMembers, BPI, BFI, LI,
1884 InstrumentationType);
1898 if (ProfileSampling)
1923 LookupBPI, LookupBFI, LookupLI,
1924 InstrumentationType))
1937 auto BFIEntryCount =
F.getEntryCount();
1938 assert(BFIEntryCount && (*BFIEntryCount > 0) &&
"Invalid BFI Entrycount");
1942 for (
auto &BBI :
F) {
1945 if (!Func.findBBInfo(&BBI))
1948 CountValue = *Func.getBBInfo(&BBI).Count;
1949 BFICountValue = *BFICount;
1953 if (SumCount.isZero())
1957 "Incorrect sum of BFI counts");
1960 double Scale = (SumCount / SumBFICount).convertToDouble();
1961 if (Scale < 1.001 && Scale > 0.999)
1966 if (NewEntryCount == 0)
1969 F.setEntryCount(NewEntryCount);
1972 << NewEntryCount <<
"\n");
1985 bool HotBBOnly = Opts.pgo_verify_hot_bfi;
1989 unsigned BBNum = 0, BBMisMatchNum = 0, NonZeroBBNum = 0;
1990 for (
auto &BBI :
F) {
1991 PGOUseBBInfo *BBInfo = Func.findBBInfo(&BBI);
1995 uint64_t CountValue = BBInfo->Count.value_or(CountValue);
2003 BFICountValue = *BFICount;
2006 bool rawIsHot = CountValue >= HotCountThreshold;
2007 bool BFIIsHot = BFICountValue >= HotCountThreshold;
2009 bool ShowCount =
false;
2010 if (rawIsHot && !BFIIsHot) {
2011 Msg =
"raw-Hot to BFI-nonHot";
2013 }
else if (rawIsCold && BFIIsHot) {
2014 Msg =
"raw-Cold to BFI-Hot";
2020 if ((CountValue < Opts.pgo_verify_bfi_cutoff) &&
2021 (BFICountValue < Opts.pgo_verify_bfi_cutoff))
2023 uint64_t Diff = (BFICountValue >= CountValue)
2024 ? BFICountValue - CountValue
2025 : CountValue - BFICountValue;
2026 if (Diff <= CountValue / 100 * Opts.pgo_verify_bfi_ratio)
2033 F.getSubprogram(), &BBI);
2035 <<
" Count=" <<
ore::NV(
"Count", CountValue)
2036 <<
" BFI_Count=" <<
ore::NV(
"Count", BFICountValue);
2045 F.getSubprogram(), &
F.getEntryBlock())
2046 <<
"In Func " <<
ore::NV(
"Function",
F.getName())
2047 <<
": Num_of_BB=" <<
ore::NV(
"Count", BBNum)
2048 <<
", Num_of_non_zerovalue_BB=" <<
ore::NV(
"Count", NonZeroBBNum)
2049 <<
", Num_of_mis_matching_BB=" <<
ore::NV(
"Count", BBMisMatchNum);
2054 const InstrumentationOptions &Opts,
Module &M,
StringRef ProfileFileName,
2062 auto &Ctx = M.getContext();
2065 ProfileRemappingFileName);
2066 if (
Error E = ReaderOrErr.takeError()) {
2074 std::unique_ptr<IndexedInstrProfReader> PGOReader =
2075 std::move(ReaderOrErr.get());
2081 if (!PGOReader->hasCSIRLevelProfile() && IsCS)
2085 if (!PGOReader->isIRLevelProfile()) {
2087 ProfileFileName.
data(),
"Not an IR level instrumentation profile"));
2090 if (PGOReader->functionEntryOnly()) {
2092 ProfileFileName.
data(),
2093 "Function entry profiles are not yet supported for optimization"));
2100 M.setProfileSummary(PGOReader->getSummary(IsCS).getMD(M.getContext()),
2105 std::unordered_multimap<Comdat *, GlobalValue *> ComdatMembers;
2107 std::vector<Function *> HotFunctions;
2108 std::vector<Function *> ColdFunctions;
2112 bool InstrumentFuncEntry =
2113 valueOr(Opts.pgo_instrument_entry, PGOReader->instrEntryBBEnabled());
2114 bool InstrumentLoopEntries =
valueOr(Opts.pgo_instrument_loop_entries,
2115 PGOReader->instrLoopEntriesEnabled());
2117 bool HasSingleByteCoverage = PGOReader->hasSingleByteCoverage();
2125 if (!HasSingleByteCoverage) {
2131 PGOUseFunc Func(Opts,
F, &M, TLI, ComdatMembers, BPI, BFI, LI, PSI, IsCS,
2132 InstrumentFuncEntry, InstrumentLoopEntries,
2133 HasSingleByteCoverage);
2134 if (!Func.getRecord(PGOReader.get()))
2136 if (HasSingleByteCoverage) {
2137 Func.populateCoverage();
2145 bool AllZeros =
false;
2146 if (!Func.readCounters(AllZeros, PseudoKind))
2150 if (Func.getProgramMaxCount() != 0)
2151 ColdFunctions.push_back(&
F);
2156 if (
F.hasFnAttribute(Attribute::Cold))
2157 F.removeFnAttr(Attribute::Cold);
2160 F.addFnAttr(Attribute::Hot);
2163 Func.populateCounters();
2164 Func.setBranchWeights();
2165 Func.annotateValueSites();
2166 Func.annotateIrrLoopHeaderWeights();
2167 Func.setBlockUniformityAttribute();
2168 PGOUseFunc::FuncFreqAttr FreqAttr = Func.getFuncFreqAttr();
2169 if (FreqAttr == PGOUseFunc::FFA_Cold)
2170 ColdFunctions.push_back(&
F);
2171 else if (FreqAttr == PGOUseFunc::FFA_Hot)
2172 HotFunctions.push_back(&
F);
2178 std::unique_ptr<BranchProbabilityInfo> NewBPI =
2179 std::make_unique<BranchProbabilityInfo>(
F, CI);
2180 std::unique_ptr<BlockFrequencyInfo> NewBFI =
2181 std::make_unique<BlockFrequencyInfo>(
F, *NewBPI, CI);
2185 dbgs() <<
"pgo-view-counts: " << Func.getFunc().getName() <<
"\n";
2186 NewBFI->print(
dbgs());
2196 ViewGraph(&Func,
Twine(
"PGORawCounts_") + Func.getFunc().getName());
2197 else if (Opts.pgo_view_raw_counts ==
PGOVCT_Text) {
2198 dbgs() <<
"pgo-view-raw-counts: " << Func.getFunc().getName() <<
"\n";
2203 if (Opts.pgo_verify_bfi || Opts.pgo_verify_hot_bfi ||
2204 Opts.pgo_fix_entry_count) {
2210 if (Opts.pgo_fix_entry_count)
2215 if (Opts.pgo_verify_hot_bfi) {
2228 for (
auto &
F : HotFunctions) {
2229 F->addFnAttr(Attribute::InlineHint);
2230 LLVM_DEBUG(
dbgs() <<
"Set inline attribute to function: " <<
F->getName()
2233 for (
auto &
F : ColdFunctions) {
2236 if (
F->hasFnAttribute(Attribute::Hot)) {
2237 auto &Ctx = M.getContext();
2238 std::string
Msg = std::string(
"Function ") +
F->getName().str() +
2239 std::string(
" is annotated as a hot function but"
2240 " the profile is cold");
2245 F->addFnAttr(Attribute::Cold);
2246 LLVM_DEBUG(
dbgs() <<
"Set cold attribute to function: " <<
F->getName()
2253 std::string
Filename, std::string RemappingFilename,
bool IsCS,
2256 ProfileRemappingFileName(
std::
move(RemappingFilename)), IsCS(IsCS),
2258 const InstrumentationOptions &Opts = InstrumentationOptions::Global;
2259 if (!Opts.pgo_test_profile_file.empty())
2260 ProfileFileName = Opts.pgo_test_profile_file;
2261 if (!Opts.pgo_test_profile_remapping_file.empty())
2262 ProfileRemappingFileName = Opts.pgo_test_profile_remapping_file;
2286 ProfileRemappingFileName, *FS, LookupTLI, LookupBPI,
2287 LookupBFI, LookupLI, PSI, IsCS))
2294 if (!
Node->getName().empty())
2295 return Node->getName().str();
2297 std::string SimpleNodeName;
2300 return SimpleNodeName;
2304 uint64_t MaxCount) {
2307 LLVM_DEBUG(
dbgs() <<
"Weight is: ";
for (
const auto &W : Weights) {
2315 if (InstrumentationOptions::Global.pgo_emit_branch_prob) {
2317 if (BrCondStr.empty())
2321 std::accumulate(Weights.begin(), Weights.end(), (uint64_t)0,
2322 [](uint64_t w1, uint64_t w2) { return w1 + w2; });
2323 uint64_t TotalCount =
2324 std::accumulate(EdgeCounts.
begin(), EdgeCounts.
end(), (uint64_t)0,
2325 [](uint64_t c1, uint64_t c2) { return c1 + c2; });
2329 std::string BranchProbStr;
2332 OS <<
" (total count : " << TotalCount <<
")";
2337 << BrCondStr <<
" is true with probability : " << BranchProbStr;
2356 return &
G->getFunc().front();
2379 return std::string(
G->getFunc().getName());
2387 PGOUseBBInfo *BI = Graph->findBBInfo(
Node);
2389 if (BI && BI->Count)
2390 OS << *BI->Count <<
"\\l";
2394 if (!InstrumentationOptions::Global.pgo_instr_select)
2401 OS <<
"SELECT : { T = ";
2405 OS <<
"Unknown, F = Unknown }\\l";
2407 OS << TC <<
", F = " << FC <<
" }\\l";
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file implements a class to represent arbitrary precision integral constant values and operations...
Function Alias Analysis false
This file contains the simple types necessary to represent the attributes associated with functions a...
This file finds the minimum set of blocks on a CFG that must be instrumented to infer execution cover...
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 contains the declarations for the subclasses of Constant, which represent the different fla...
This file declares the LLVM IR specialization of the GenericCycle templates.
post inline ee instrument
static BasicBlock * getInstrBB(CFGMST< Edge, BBInfo > &MST, Edge &E, const DenseSet< const BasicBlock * > &ExecBlocks)
This file provides various utilities for inspecting and working with the control flow graph in LLVM I...
Module.h This file contains the declarations for the Module class.
This header defines various interfaces for pass management in LLVM.
#define INSTR_PROF_QUOTE(x)
#define VARIANT_MASK_CSIR_PROF
#define VARIANT_MASK_DBG_CORRELATE
#define INSTR_PROF_RAW_VERSION
#define INSTR_PROF_RAW_VERSION_VAR
#define VARIANT_MASK_TEMPORAL_PROF
#define VARIANT_MASK_IR_PROF
#define VARIANT_MASK_BYTE_COVERAGE
#define VARIANT_MASK_INSTR_ENTRY
#define VARIANT_MASK_FUNCTION_ENTRY_ONLY
#define VARIANT_MASK_INSTR_LOOP_ENTRIES
Machine Check Debug Module
static cl::opt< unsigned > ColdCountThreshold("mfs-count-threshold", cl::desc("Minimum number of times a block must be executed to be retained."), cl::init(1), cl::Hidden)
static constexpr StringLiteral Filename
static void annotateFunctionWithHashMismatch(Function &F, LLVMContext &ctx)
static bool instrumentAllFunctions(const InstrumentationOptions &Opts, Module &M, function_ref< TargetLibraryInfo &(Function &)> LookupTLI, function_ref< BranchProbabilityInfo *(Function &)> LookupBPI, function_ref< BlockFrequencyInfo *(Function &)> LookupBFI, function_ref< LoopInfo *(Function &)> LookupLI, PGOInstrumentationType InstrumentationType)
static bool skipPGOGen(const InstrumentationOptions &Opts, const Function &F)
static void fixFuncEntryCount(PGOUseFunc &Func, CycleInfo &CI, BranchProbabilityInfo &NBPI)
static void populateEHOperandBundle(VPCandidateInfo &Cand, DenseMap< BasicBlock *, ColorVector > &BlockColors, SmallVectorImpl< OperandBundleDef > &OpBundles)
static void collectComdatMembers(const InstrumentationOptions &Opts, Module &M, std::unordered_multimap< Comdat *, GlobalValue * > &ComdatMembers)
static void setupBBInfoEdges(const FuncPGOInstrumentation< PGOUseEdge, PGOUseBBInfo > &FuncInfo)
Set up InEdges/OutEdges for all BBs in the MST.
ValueProfileCollector::CandidateInfo VPCandidateInfo
static bool skipPGOUse(const InstrumentationOptions &Opts, const Function &F)
static uint64_t sumEdgeCount(const ArrayRef< PGOUseEdge * > Edges)
static uint32_t getMaxNumAnnotations(const InstrumentationOptions &Opts, InstrProfValueKind ValueProfKind)
static std::string getSimpleNodeName(const BasicBlock *Node)
static bool isIndirectBrTarget(BasicBlock *BB)
static bool annotateAllFunctions(const InstrumentationOptions &Opts, Module &M, StringRef ProfileFileName, StringRef ProfileRemappingFileName, vfs::FileSystem &FS, function_ref< TargetLibraryInfo &(Function &)> LookupTLI, function_ref< BranchProbabilityInfo *(Function &)> LookupBPI, function_ref< BlockFrequencyInfo *(Function &)> LookupBFI, function_ref< LoopInfo *(Function &)> LookupLI, ProfileSummaryInfo *PSI, bool IsCS)
static GlobalVariable * createIRLevelProfileFlagVar(const InstrumentationOptions &Opts, Module &M, PGOInstrumentationType InstrumentationType)
static void verifyFuncBFI(const InstrumentationOptions &Opts, PGOUseFunc &Func, CycleInfo &CI, BranchProbabilityInfo &NBPI, uint64_t HotCountThreshold, uint64_t ColdCountThreshold)
static bool canRenameComdat(const InstrumentationOptions &Opts, Function &F, std::unordered_multimap< Comdat *, GlobalValue * > &ComdatMembers)
static std::string getBranchCondString(Instruction *TI)
static const char * ValueProfKindDescr[]
This file provides the interface for IR based instrumentation passes ( (profile-gen,...
FunctionAnalysisManager FAM
ModuleAnalysisManager MAM
This file contains the declarations for profiling metadata utility functions.
const SmallVectorImpl< MachineOperand > & Cond
static cl::opt< RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode > Mode("regalloc-enable-advisor", cl::Hidden, cl::init(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default), cl::desc("Enable regalloc advisor mode"), cl::values(clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Default, "default", "Default"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Release, "release", "precompiled"), clEnumValN(RegAllocEvictionAdvisorAnalysisLegacy::AdvisorMode::Development, "development", "for training")))
static void visit(BasicBlock &Start, std::function< bool(BasicBlock *)> op)
std::pair< BasicBlock *, BasicBlock * > Edge
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)
StringSet - A set-like wrapper for the StringMap.
Defines the virtual file system interface vfs::FileSystem.
void printAsOperand(OutputBuffer &OB, Prec P=Prec::Default, bool StrictlyWorse=false) const
static const fltSemantics & IEEEdouble()
static constexpr roundingMode rmNearestTiesToEven
static APFloat getZero(const fltSemantics &Sem, bool Negative=false)
Factory for Positive and Negative Zero.
Class for arbitrary precision integers.
This templated class represents "all analyses that operate over <aparticular IR unit>" (e....
Represent a constant reference to an array (0 or more elements consecutively in memory),...
size_t size() const
Get the array size.
LLVM Basic Block Representation.
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
InstListType::iterator iterator
Instruction iterators...
LLVM_ABI const_iterator getFirstNonPHIOrDbgOrAlloca() const
Returns an iterator to the first instruction in this block that is not a PHINode, a debug intrinsic,...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction; assumes that the block is well-formed.
Analysis pass which computes BlockFrequencyInfo.
BlockFrequencyInfo pass uses BlockFrequencyInfoImpl implementation to estimate IR basic block frequen...
LLVM_ABI bool isIrrLoopHeader(const BasicBlock *BB)
Returns true if BB is an irreducible loop header block.
LLVM_ABI std::optional< uint64_t > getBlockProfileCount(const BasicBlock *BB) const
Returns the estimated profile count of BB.
Analysis pass which computes BranchProbabilityInfo.
Analysis providing branch probability information.
Edge & addEdge(BasicBlock *Src, BasicBlock *Dest, uint64_t W)
const std::vector< std::unique_ptr< Edge > > & allEdges() const
Predicate getPredicate() const
Return the predicate for this instruction.
LLVM_ABI StringRef getName() const
void setSelectionKind(SelectionKind Val)
SelectionKind getSelectionKind() const
Conditional Branch instruction.
Value * getCondition() const
static LLVM_ABI Constant * getPointerBitCastOrAddrSpaceCast(Constant *C, Type *Ty)
Create a BitCast or AddrSpaceCast for a pointer type depending on the address space.
This is the shared class of boolean and integer constants.
bool isMinusOne() const
This function will return true iff every bit in this constant is set to true.
bool isOne() const
This is just a convenience method to make client code smaller for a common case.
bool isZero() const
This is just a convenience method to make client code smaller for a common code.
static LLVM_ABI Constant * getIntegerValue(Type *Ty, const APInt &V)
Return the value for an integer or pointer constant, or a vector thereof, with the given scalar value...
iterator find(const_arg_type_t< KeyT > Val)
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Diagnostic information for the PGO profiler.
Base class for error info classes.
virtual std::string message() const
Return the error message as a string.
Lightweight error class with error context and mandatory checking.
void compute(FunctionT &F)
Compute the cycle info for a function.
static LLVM_ABI GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)
If a parent module is specified, the alias is automatically inserted into the end of the specified mo...
@ HiddenVisibility
The GV is hidden.
@ ExternalLinkage
Externally visible function.
@ WeakAnyLinkage
Keep one copy of named function when linking (weak)
@ AvailableExternallyLinkage
Available for inspection, not emission.
@ LinkOnceODRLinkage
Same, but only replaced by something equivalent.
This instruction compares its operands according to the predicate given to the constructor.
static Expected< std::unique_ptr< IndexedInstrProfReader > > create(const Twine &Path, vfs::FileSystem &FS, const Twine &RemappingPath="")
Factory method to create an indexed reader.
uint64_t getMaximumFunctionCount(bool UseCS)
Return the maximum of all known function counts.
Expected< NamedInstrProfRecord > getInstrProfRecord(StringRef FuncName, uint64_t FuncHash, StringRef DeprecatedFuncName="", uint64_t *MismatchedFuncSum=nullptr)
Return the NamedInstrProfRecord associated with FuncName and FuncHash.
Base class for instruction visitors.
static bool canInstrumentCallsite(const CallBase &CB)
instrprof_error get() const
std::string message() const override
Return the error message as a string.
LLVM_ABI unsigned getNumSuccessors() const LLVM_READONLY
Return the number of successors that this instruction has.
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 update(ArrayRef< uint8_t > Data)
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.
Analysis pass that exposes the LoopInfo for a function.
LLVM_ABI MDString * createString(StringRef Str)
Return the given string as metadata.
LLVM_ABI MDNode * createIrrLoopHeaderWeight(uint64_t Weight)
Return metadata containing an irreducible loop header weight.
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
static MDTuple * get(LLVMContext &Context, ArrayRef< Metadata * > MDs)
A Module instance is used to store all the information related to an LLVM module.
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
LLVM_ABI PGOInstrumentationUse(std::string Filename="", std::string RemappingFilename="", bool IsCS=false, IntrusiveRefCntPtr< vfs::FileSystem > FS=nullptr)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM)
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.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
PreservedAnalyses & preserve()
Mark an analysis as preserved.
An analysis pass based on the new PM to deliver ProfileSummaryInfo.
Analysis providing profile information.
LLVM_ABI uint64_t getOrCompColdCountThreshold() const
Returns ColdCountThreshold if set.
LLVM_ABI bool isColdCount(uint64_t C) const
Returns true if count C is considered cold.
LLVM_ABI void refresh(std::unique_ptr< ProfileSummary > &&Other=nullptr)
If a summary is provided as argument, use that.
LLVM_ABI bool isHotCount(uint64_t C) const
Returns true if count C is considered hot.
LLVM_ABI uint64_t getOrCompHotCountThreshold() const
Returns HotCountThreshold if set.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
reference emplace_back(ArgTypes &&... Args)
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 const char * data() const
Get a pointer to the start of the string (which may not be null terminated).
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
Triple - Helper class for working with autoconf configuration names.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
LLVM_ABI std::string str() const
Return the twine contents as a std::string.
The instances of the Type class are immutable: once they are created, they are never changed.
static LLVM_ABI IntegerType * getInt64Ty(LLVMContext &C)
LLVM_ABI void print(raw_ostream &O, bool IsForDebug=false, bool NoDetails=false) const
Print the current type.
Value * getOperand(unsigned i) const
std::vector< CandidateInfo > get(InstrProfValueKind Kind) const
returns a list of value profiling candidates of the given kind
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
An efficient, type-erasing, non-owning reference to a callable.
const ParentTy * getParent() const
A raw_ostream that writes to an std::string.
The virtual file system interface.
This provides a very simple, boring adaptor for a begin and end iterator into a range type.
This file contains the declaration of the Comdat class, which represents a single COMDAT in LLVM.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ BasicBlock
Various leaf nodes.
LLVM_ABI Function * getOrInsertDeclaration(Module *M, ID id, ArrayRef< Type * > OverloadTys={})
Look up the Function declaration of the intrinsic id in the Module M.
initializer< Ty > init(const Ty &Val)
uint64_t getFuncHash(const FuncRecordTy *Record)
Return the structural hash associated with the function.
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
NodeAddr< FuncNode * > Func
friend class Instruction
Iterator for Instructions in a `BasicBlock.
void write64le(void *P, uint64_t V)
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.
LLVM_ABI void setIrrLoopHeaderMetadata(Module *M, Instruction *TI, uint64_t Count)
LLVM_ABI void setProfMetadata(Instruction *TI, ArrayRef< uint64_t > EdgeCounts, uint64_t MaxCount)
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
LLVM_ABI std::string getPGOFuncName(const Function &F, bool InLTO=false, uint64_t Version=INSTR_PROF_INDEX_VERSION)
Please use getIRPGOObjectName for LLVM IR instrumentation.
LLVM_ABI unsigned GetSuccessorNumber(const BasicBlock *BB, const BasicBlock *Succ)
Search for the specified successor of basic block BB and return its position in the terminator instru...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
RelativeUniformCounterPtr ValuesPtrExpr NumValueSites[IPVK_Last+1]
auto successors(const MachineBasicBlock *BB)
LLVM_ABI void createProfileSamplingVar(Module &M)
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
constexpr from_range_t from_range
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LLVM_ABI bool SplitIndirectBrCriticalEdges(Function &F, bool IgnoreBlocksWithoutPHI, BranchProbabilityInfo *BPI=nullptr, BlockFrequencyInfo *BFI=nullptr, DomTreeUpdater *DTU=nullptr)
LLVM_ABI DenseMap< BasicBlock *, ColorVector > colorEHFunclets(Function &F)
If an EH funclet personality is in use (see isFuncletEHPersonality), this will recompute which blocks...
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
LLVM_ABI std::string getIRPGOObjectName(const GlobalObject &GO, bool InLTO=false)
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
cl::opt< unsigned > MaxNumVTableAnnotations("icp-max-num-vtables", cl::init(6), cl::Hidden, cl::desc("Max number of vtables annotated for a vtable load instruction."))
cl::opt< bool > EnableVTableProfileUse("enable-vtable-profile-use", cl::init(false), cl::desc("If ThinLTO and WPD is enabled and this option is true, vtable " "profiles will be used by ICP pass for more efficient indirect " "call sequence. If false, type profiles won't be used."))
bool isScopedEHPersonality(EHPersonality Pers)
Returns true if this personality uses scope-style EH IR instructions: catchswitch,...
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
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...
cl::opt< std::string > ViewBlockFreqFuncName("view-bfi-func-name", cl::Hidden, cl::desc("The option to specify " "the name of the function " "whose CFG will be displayed."))
LLVM_ABI GlobalVariable * createPGOFuncNameVar(Function &F, StringRef PGOFuncName)
Create and return the global variable for function name used in PGO instrumentation.
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...
auto reverse(ContainerTy &&C)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
IRBuilder(LLVMContext &, FolderTy, InserterTy) -> IRBuilder< FolderTy, InserterTy >
LLVM_ABI EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
cl::opt< bool > NoPGOWarnMismatch
RNSuccIterator< NodeRef, BlockT, RegionT > succ_begin(NodeRef Node)
cl::opt< PGOViewCountsType > PGOViewCounts("pgo-view-counts", cl::Hidden, cl::desc("A boolean option to show CFG dag or text with " "block profile counts and branch probabilities " "right after PGO profile annotation step. The " "profile counts are computed using branch " "probabilities from the runtime profile data and " "block frequency propagation algorithm. To view " "the raw counts from the profile, use option " "-pgo-view-raw-counts instead. To limit graph " "display to only one function, use filtering option " "-view-bfi-func-name."), cl::values(clEnumValN(PGOVCT_None, "none", "do not show."), clEnumValN(PGOVCT_Graph, "graph", "show a graph."), clEnumValN(PGOVCT_Text, "text", "show in text.")))
RNSuccIterator< NodeRef, BlockT, RegionT > succ_end(NodeRef Node)
OperandBundleDefT< Value * > OperandBundleDef
LLVM_ABI void appendToCompilerUsed(Module &M, ArrayRef< GlobalValue * > Values)
Adds global values to the llvm.compiler.used list.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
LLVM_ABI BasicBlock * SplitCriticalEdge(Instruction *TI, unsigned SuccNum, const CriticalEdgeSplittingOptions &Options=CriticalEdgeSplittingOptions(), const Twine &BBName="")
If this edge is a critical edge, insert a new node to split the critical edge.
void ViewGraph(const GraphType &G, const Twine &Name, bool ShortNames=false, const Twine &Title="", GraphProgram::Name Program=GraphProgram::DOT)
ViewGraph - Emit a dot graph, run 'dot', run gv on the postscript file, then cleanup.
LLVM_ABI bool isCriticalEdge(const Instruction *TI, unsigned SuccNum, bool AllowIdenticalEdges=false)
Return true if the specified edge is a critical edge.
LLVM_ABI bool canRenameComdatFunc(const Function &F, bool CheckAddressTaken=false)
Check if we can safely rename this Comdat function.
LLVM_ABI void createProfileFileNameVar(Module &M, StringRef InstrProfileOutput)
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
TinyPtrVector< BasicBlock * > ColorVector
LLVM_ABI bool extractBranchWeights(const MDNode *ProfileData, SmallVectorImpl< uint32_t > &Weights)
Extract branch weights from MD_prof metadata.
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
auto predecessors(const MachineBasicBlock *BB)
Instruction::const_succ_iterator const_succ_iterator
uint32_t scaleBranchCount(uint64_t Count, uint64_t Scale)
Scale an individual branch count.
constexpr bool valueOr(BoolOrDefault X, bool Default)
LLVM_ABI bool isGuaranteedNotToBePoison(const Value *V, AssumptionCache *AC=nullptr, const Instruction *CtxI=nullptr, const DominatorTree *DT=nullptr, unsigned Depth=0)
Returns true if V cannot be poison, but may be undef.
uint64_t calculateCountScale(uint64_t MaxCount)
Calculate what to divide by to scale counts.
LLVM_ABI SmallVector< uint32_t > downscaleWeights(ArrayRef< uint64_t > Weights, std::optional< uint64_t > KnownMaxCount=std::nullopt)
downscale the given weights preserving the ratio.
LLVM_ABI bool isGPUProfTarget(const Module &M)
Determines whether module targets a GPU eligable for PGO instrumentation.
cl::opt< bool > EnableVTableValueProfiling("enable-vtable-value-profiling", cl::init(false), cl::desc("If true, the virtual table address will be instrumented to know " "the types of a C++ pointer. The information is used in indirect " "call promotion to do selective vtable-based comparison."))
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
LLVM_ABI bool isPGOInstrumentColdFunctionOnly()
Return the value of -pgo-instrument-cold-function-only.
Implement std::hash so that hash_code can be used in STL containers.
DOTGraphTraits(bool isSimple=false)
static std::string getGraphName(const PGOUseFunc *G)
std::string getNodeLabel(const BasicBlock *Node, const PGOUseFunc *Graph)
DefaultDOTGraphTraits(bool simple=false)
static ChildIteratorType child_end(const NodeRef N)
static NodeRef getEntryNode(const PGOUseFunc *G)
static ChildIteratorType child_begin(const NodeRef N)
static nodes_iterator nodes_end(const PGOUseFunc *G)
const BasicBlock * NodeRef
static nodes_iterator nodes_begin(const PGOUseFunc *G)
pointer_iterator< Function::const_iterator > nodes_iterator
const_succ_iterator ChildIteratorType
bool isBlockUniform(unsigned BlockIdx) const
Check if a basic block is entered via a wave-uniform branch.
std::vector< uint64_t > Counts
CountPseudoKind getCountPseudoKind() const
uint32_t getNumValueSites(uint32_t ValueKind) const
Return the number of instrumented sites for ValueKind.
std::vector< uint8_t > UniformityBits
For AMDGPU offload profiling: 1 bit per basic block indicating whether the block is usually entered w...
static void setCSFlagInHash(uint64_t &FuncHash)
static constexpr uint64_t FUNC_HASH_MASK
Instruction * AnnotatedInst