129#include <unordered_map>
136#define DEBUG_TYPE "pgo-instrumentation"
138STATISTIC(NumOfPGOInstrument,
"Number of edges instrumented.");
139STATISTIC(NumOfPGOSelectInsts,
"Number of select instruction instrumented.");
140STATISTIC(NumOfPGOMemIntrinsics,
"Number of mem intrinsics instrumented.");
143STATISTIC(NumOfPGOSplit,
"Number of critical edge splits.");
144STATISTIC(NumOfPGOFunc,
"Number of functions having valid profile counts.");
145STATISTIC(NumOfPGOMismatch,
"Number of functions having mismatch profile.");
146STATISTIC(NumOfPGOMissing,
"Number of functions without profile.");
147STATISTIC(NumOfPGOICall,
"Number of indirect call value instrumentations.");
148STATISTIC(NumOfCSPGOInstrument,
"Number of edges instrumented in CSPGO.");
150 "Number of select instruction instrumented in CSPGO.");
152 "Number of mem intrinsics instrumented in CSPGO.");
154STATISTIC(NumOfCSPGOBB,
"Number of basic-blocks in CSPGO.");
155STATISTIC(NumOfCSPGOSplit,
"Number of critical edge splits in CSPGO.");
157 "Number of functions having valid profile counts in CSPGO.");
159 "Number of functions having mismatch profile in CSPGO.");
160STATISTIC(NumOfCSPGOMissing,
"Number of functions without profile in CSPGO.");
161STATISTIC(NumCoveredBlocks,
"Number of basic blocks that were executed");
169 cl::desc(
"Use this option to turn off/on "
170 "warnings about profile cfg mismatch."));
180 return LibraryOptions.
get<InstrumentationOptions>()
181 .pgo_instrument_cold_function_only;
185class FunctionInstrumenter final {
186 const InstrumentationOptions &Opts;
190 std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers;
201 bool isValueProfilingDisabled()
const {
208 return Opts.disable_vp ||
213 bool shouldInstrumentEntryBB()
const {
214 return valueOr(Opts.pgo_instrument_entry,
false) ||
215 InstrumentationType == PGOInstrumentationType::CTXPROF;
218 bool shouldInstrumentLoopEntries()
const {
219 return valueOr(Opts.pgo_instrument_loop_entries,
false);
223 FunctionInstrumenter(
225 TargetLibraryInfo &TLI,
226 std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers,
227 BranchProbabilityInfo *BPI =
nullptr, BlockFrequencyInfo *BFI =
nullptr,
228 LoopInfo *LI =
nullptr,
230 : Opts(Opts), M(M), F(F), TLI(TLI), ComdatMembers(ComdatMembers),
231 BPI(BPI), BFI(BFI), LI(LI), InstrumentationType(InstrumentationType) {}
242 return std::string();
247 return std::string();
259 else if (CV->
isOne())
270#define VALUE_PROF_KIND(Enumerator, Value, Descr) Descr,
284 if (
valueOr(Opts.pgo_instrument_entry,
false) ||
287 if (
valueOr(Opts.pgo_instrument_loop_entries,
false))
291 if (Opts.pgo_function_entry_coverage)
294 if (Opts.pgo_block_coverage)
296 if (Opts.pgo_temporal_instrumentation)
301 Triple TT(M.getTargetTriple());
302 IRLevelVersionVariable->setVisibility(TT.isGPU()
305 if (TT.supportsCOMDAT()) {
307 IRLevelVersionVariable->setComdat(M.getOrInsertComdat(VarName));
309 return IRLevelVersionVariable;
319enum VisitMode { VM_counting, VM_instrument, VM_annotate };
323struct SelectInstVisitor :
public InstVisitor<SelectInstVisitor> {
324 const InstrumentationOptions &Opts;
327 VisitMode Mode = VM_counting;
328 unsigned *CurCtrIdx =
nullptr;
329 unsigned TotalNumCtrs = 0;
330 GlobalValue *FuncNameVar =
nullptr;
332 PGOUseFunc *UseFunc =
nullptr;
333 bool HasSingleByteCoverage;
335 SelectInstVisitor(
const InstrumentationOptions &Opts,
Function &Func,
336 bool HasSingleByteCoverage)
337 : Opts(Opts), F(
Func), HasSingleByteCoverage(HasSingleByteCoverage) {}
339 void countSelects() {
349 void instrumentSelects(
unsigned *Ind,
unsigned TotalNC, GlobalValue *FNV,
351 Mode = VM_instrument;
353 TotalNumCtrs = TotalNC;
360 void annotateSelects(PGOUseFunc *UF,
unsigned *Ind) {
367 void instrumentOneSelectInst(SelectInst &SI);
368 void annotateOneSelectInst(SelectInst &SI);
371 void visitSelectInst(SelectInst &SI);
375 unsigned getNumOfSelectInsts()
const {
return NSIs; }
387 bool Removed =
false;
388 bool IsCritical =
false;
390 PGOEdge(BasicBlock *Src, BasicBlock *Dest,
uint64_t W = 1)
391 : SrcBB(Src), DestBB(Dest), Weight(
W) {}
394 std::string infoString()
const {
395 return (Twine(Removed ?
"-" :
" ") + (InMST ?
" " :
"*") +
396 (IsCritical ?
"c" :
" ") +
" W=" + Twine(Weight))
407 PGOBBInfo(
unsigned IX) : Group(this), Index(IX) {}
410 std::string infoString()
const {
411 return (Twine(
"Index=") + Twine(Index)).str();
416template <
class Edge,
class BBInfo>
class FuncPGOInstrumentation {
418 const InstrumentationOptions &Opts;
425 std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers;
427 ValueProfileCollector VPC;
429 void computeCFGHash();
430 void renameComdatFunction();
433 const TargetLibraryInfo &TLI;
434 std::vector<std::vector<VPCandidateInfo>> ValueSites;
435 SelectInstVisitor SIVisitor;
436 std::string FuncName;
437 std::string DeprecatedFuncName;
438 GlobalVariable *FuncNameVar;
444 CFGMST<Edge, BBInfo> MST;
446 const std::optional<BlockCoverageInference> BCI;
448 static std::optional<BlockCoverageInference>
449 constructBCI(
Function &Func,
bool HasSingleByteCoverage,
450 bool InstrumentFuncEntry) {
451 if (HasSingleByteCoverage)
452 return BlockCoverageInference(Func, InstrumentFuncEntry);
458 void getInstrumentBBs(std::vector<BasicBlock *> &InstrumentBBs);
465 BBInfo &getBBInfo(
const BasicBlock *BB)
const {
return MST.getBBInfo(BB); }
468 BBInfo *findBBInfo(
const BasicBlock *BB)
const {
return MST.findBBInfo(BB); }
471 void dumpInfo(StringRef Str =
"")
const {
472 MST.dumpEdges(
dbgs(), Twine(
"Dump Function ") + FuncName +
473 " Hash: " + Twine(FunctionHash) +
"\t" + Str);
476 FuncPGOInstrumentation(
477 const InstrumentationOptions &Opts,
Function &Func,
478 TargetLibraryInfo &TLI,
479 std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers,
480 bool CreateGlobalVar =
false, BranchProbabilityInfo *BPI =
nullptr,
481 BlockFrequencyInfo *BFI =
nullptr, LoopInfo *LI =
nullptr,
482 bool IsCS =
false,
bool InstrumentFuncEntry =
true,
483 bool InstrumentLoopEntries =
false,
bool HasSingleByteCoverage =
false)
484 : Opts(Opts), F(
Func), IsCS(IsCS), ComdatMembers(ComdatMembers),
485 VPC(
Func, TLI), TLI(TLI), ValueSites(IPVK_Last + 1),
486 SIVisitor(Opts,
Func, HasSingleByteCoverage),
487 MST(F, InstrumentFuncEntry, InstrumentLoopEntries, BPI, BFI, LI),
488 BCI(constructBCI(
Func, HasSingleByteCoverage, InstrumentFuncEntry)) {
489 if (BCI && Opts.pgo_view_block_coverage_graph)
490 BCI->viewBlockCoverageGraph();
492 SIVisitor.countSelects();
493 ValueSites[IPVK_MemOPSize] = VPC.get(IPVK_MemOPSize);
495 NumOfPGOSelectInsts += SIVisitor.getNumOfSelectInsts();
496 NumOfPGOMemIntrinsics += ValueSites[IPVK_MemOPSize].size();
497 NumOfPGOBB += MST.bbInfoSize();
498 ValueSites[IPVK_IndirectCallTarget] = VPC.get(IPVK_IndirectCallTarget);
500 ValueSites[IPVK_VTableTarget] = VPC.get(IPVK_VTableTarget);
502 NumOfCSPGOSelectInsts += SIVisitor.getNumOfSelectInsts();
503 NumOfCSPGOMemIntrinsics += ValueSites[IPVK_MemOPSize].size();
504 NumOfCSPGOBB += MST.bbInfoSize();
510 if (!ComdatMembers.empty())
511 renameComdatFunction();
514 for (
const auto &
E : MST.allEdges()) {
517 IsCS ? NumOfCSPGOEdge++ : NumOfPGOEdge++;
519 IsCS ? NumOfCSPGOInstrument++ : NumOfPGOInstrument++;
532template <
class Edge,
class BBInfo>
533void FuncPGOInstrumentation<Edge, BBInfo>::computeCFGHash() {
534 std::vector<uint8_t> Indexes;
538 auto BI = findBBInfo(Succ);
542 for (
int J = 0; J < 4; J++)
543 Indexes.push_back((
uint8_t)(Index >> (J * 8)));
550 auto updateJCH = [&JCH](
uint64_t Num) {
555 updateJCH((
uint64_t)SIVisitor.getNumOfSelectInsts());
556 updateJCH((
uint64_t)ValueSites[IPVK_IndirectCallTarget].
size());
559 updateJCH(BCI->getInstrumentedBlocksHash());
572 LLVM_DEBUG(
dbgs() <<
"Function Hash Computation for " <<
F.getName() <<
":\n"
573 <<
" CRC = " << JC.
getCRC()
574 <<
", Selects = " << SIVisitor.getNumOfSelectInsts()
575 <<
", Edges = " << MST.
numEdges() <<
", ICSites = "
576 << ValueSites[IPVK_IndirectCallTarget].size()
577 <<
", Memops = " << ValueSites[IPVK_MemOPSize].size()
578 <<
", High32 CRC = " << JCH.
getCRC()
579 <<
", Hash = " << FunctionHash <<
"\n";);
581 if (Opts.pgo_trace_func_hash !=
"-" &&
582 F.getName().contains(Opts.pgo_trace_func_hash))
583 dbgs() <<
"Funcname=" <<
F.getName() <<
", Hash=" << FunctionHash
584 <<
" in building " <<
F.getParent()->getSourceFileName() <<
"\n";
589 const InstrumentationOptions &Opts,
Function &
F,
590 std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers) {
602 for (
auto &&CM :
make_range(ComdatMembers.equal_range(
C))) {
612template <
class Edge,
class BBInfo>
613void FuncPGOInstrumentation<Edge, BBInfo>::renameComdatFunction() {
616 std::string OrigName =
F.getName().str();
617 std::string NewFuncName =
619 F.setName(
Twine(NewFuncName));
621 FuncName =
Twine(FuncName +
"." +
Twine(FunctionHash)).
str();
627 if (!
F.hasComdat()) {
629 NewComdat = M->getOrInsertComdat(
StringRef(NewFuncName));
631 F.setComdat(NewComdat);
636 Comdat *OrigComdat =
F.getComdat();
637 std::string NewComdatName =
639 NewComdat = M->getOrInsertComdat(
StringRef(NewComdatName));
642 for (
auto &&CM :
make_range(ComdatMembers.equal_range(OrigComdat))) {
650template <
class Edge,
class BBInfo>
651void FuncPGOInstrumentation<Edge, BBInfo>::getInstrumentBBs(
652 std::vector<BasicBlock *> &InstrumentBBs) {
655 if (BCI->shouldInstrumentBlock(BB))
656 InstrumentBBs.push_back(&BB);
661 std::vector<Edge *> EdgeList;
664 EdgeList.push_back(
E.get());
666 for (
auto &
E : EdgeList) {
669 InstrumentBBs.push_back(InstrBB);
675template <
class Edge,
class BBInfo>
676BasicBlock *FuncPGOInstrumentation<Edge, BBInfo>::getInstrBB(Edge *
E) {
677 if (
E->InMST ||
E->Removed)
683 if (SrcBB ==
nullptr)
685 if (DestBB ==
nullptr)
700 return canInstrument(SrcBB);
702 return canInstrument(DestBB);
711 dbgs() <<
"Fail to split critical edge: not instrument this edge.\n");
716 IsCS ? NumOfCSPGOSplit++ : NumOfPGOSplit++;
717 LLVM_DEBUG(
dbgs() <<
"Split critical edge: " << getBBInfo(SrcBB).Index
718 <<
" --> " << getBBInfo(DestBB).Index <<
"\n");
720 MST.
addEdge(SrcBB, InstrBB, 0);
722 Edge &NewEdge1 = MST.
addEdge(InstrBB, DestBB, 0);
723 NewEdge1.InMST =
true;
726 return canInstrument(InstrBB);
745 std::optional<OperandBundleUse> ParentFunclet =
753 if (!BlockColors.
empty()) {
754 const ColorVector &CV = BlockColors.
find(OrigCall->getParent())->second;
755 assert(CV.
size() == 1 &&
"non-unique color for block!");
757 if (EHPadIt->isEHPad())
765void FunctionInstrumenter::instrument() {
766 if (!Opts.pgo_block_coverage) {
772 const bool IsCtxProf = InstrumentationType == PGOInstrumentationType::CTXPROF;
773 FuncPGOInstrumentation<PGOEdge, PGOBBInfo> FuncInfo(
774 Opts,
F, TLI, ComdatMembers, !IsCtxProf, BPI, BFI, LI,
775 InstrumentationType == PGOInstrumentationType::CSFDO,
776 shouldInstrumentEntryBB(), shouldInstrumentLoopEntries(),
777 Opts.pgo_block_coverage);
780 auto *
const CFGHash =
781 ConstantInt::get(Type::getInt64Ty(
M.getContext()), FuncInfo.FunctionHash);
785 Name, PointerType::get(
M.getContext(), 0));
786 if (Opts.pgo_function_entry_coverage) {
787 auto &EntryBB =
F.getEntryBlock();
788 IRBuilder<> Builder(EntryBB.getFirstNonPHIOrAlloca());
791 Builder.CreateIntrinsic(
792 Intrinsic::instrprof_cover,
793 {NormalizedNamePtr, CFGHash, Builder.getInt32(1), Builder.getInt32(0)});
797 std::vector<BasicBlock *> InstrumentBBs;
798 FuncInfo.getInstrumentBBs(InstrumentBBs);
799 unsigned NumCounters =
800 InstrumentBBs.size() + FuncInfo.SIVisitor.getNumOfSelectInsts();
804 Opts.ctx_prof_skip_callsite_instr);
816 auto Visit = [&](llvm::function_ref<void(CallBase * CB)> Visitor) {
818 for (
auto &Instr : BB)
822 if (CS->getCalledFunction() &&
823 SkipCSInstr.contains(CS->getCalledFunction()->getName()))
829 uint32_t TotalNumCallsites = 0;
830 Visit([&TotalNumCallsites](
auto *) { ++TotalNumCallsites; });
834 Visit([&](
auto *CB) {
836 Builder.CreateCall(CSIntrinsic,
837 {
Name, CFGHash, Builder.getInt32(TotalNumCallsites),
839 CB->getCalledOperand()});
844 if (Opts.pgo_temporal_instrumentation) {
845 NumCounters += Opts.pgo_block_coverage ? 8 : 1;
846 auto &EntryBB =
F.getEntryBlock();
847 IRBuilder<> Builder(EntryBB.getFirstNonPHIOrAlloca());
850 Builder.CreateIntrinsic(Intrinsic::instrprof_timestamp,
851 {NormalizedNamePtr, CFGHash,
852 Builder.getInt32(NumCounters),
853 Builder.getInt32(
I)});
854 I += Opts.pgo_block_coverage ? 8 : 1;
857 for (
auto *InstrBB : InstrumentBBs) {
859 assert(Builder.GetInsertPoint() != InstrBB->
end() &&
860 "Cannot get the Instrumentation point");
863 Builder.CreateIntrinsic(
864 Opts.pgo_block_coverage ? Intrinsic::instrprof_cover
865 : Intrinsic::instrprof_increment,
866 {NormalizedNamePtr, CFGHash, Builder.getInt32(NumCounters),
867 Builder.getInt32(I++)});
871 FuncInfo.SIVisitor.instrumentSelects(&
I, NumCounters, Name,
872 FuncInfo.FunctionHash);
875 if (isValueProfilingDisabled())
878 NumOfPGOICall += FuncInfo.ValueSites[IPVK_IndirectCallTarget].size();
884 DenseMap<BasicBlock *, ColorVector> BlockColors;
885 if (
F.hasPersonalityFn() &&
890 for (uint32_t Kind = IPVK_First;
Kind <= IPVK_Last; ++
Kind) {
891 unsigned SiteIndex = 0;
892 if (Kind == IPVK_MemOPSize && !Opts.pgo_instr_memop)
897 <<
" site: CallSite Index = " << SiteIndex <<
"\n");
900 assert(Builder.GetInsertPoint() != Cand.InsertPt->getParent()->end() &&
901 "Cannot get the Instrumentation point");
903 Value *ToProfile =
nullptr;
904 if (Cand.V->getType()->isIntegerTy())
905 ToProfile = Builder.CreateZExtOrTrunc(Cand.V, Builder.getInt64Ty());
906 else if (Cand.V->getType()->isPointerTy())
907 ToProfile = Builder.CreatePtrToInt(Cand.V, Builder.getInt64Ty());
908 assert(ToProfile &&
"value profiling Value is of unexpected type");
911 Name, PointerType::get(
M.getContext(), 0));
917 Intrinsic::instrprof_value_profile),
918 {NormalizedNamePtr, Builder.getInt64(FuncInfo.FunctionHash),
919 ToProfile, Builder.getInt32(Kind), Builder.getInt32(SiteIndex++)},
928struct PGOUseEdge :
public PGOEdge {
929 using PGOEdge::PGOEdge;
931 std::optional<uint64_t>
Count;
937 std::string infoString()
const {
939 return PGOEdge::infoString();
940 return (Twine(PGOEdge::infoString()) +
" Count=" + Twine(*
Count)).str();
947struct PGOUseBBInfo :
public PGOBBInfo {
948 std::optional<uint64_t>
Count;
949 int32_t UnknownCountInEdge = 0;
950 int32_t UnknownCountOutEdge = 0;
952 DirectEdges OutEdges;
954 PGOUseBBInfo(
unsigned IX) : PGOBBInfo(IX) {}
960 std::string infoString()
const {
962 return PGOBBInfo::infoString();
963 return (Twine(PGOBBInfo::infoString()) +
" Count=" + Twine(*
Count)).str();
967 void addOutEdge(PGOUseEdge *
E) {
968 OutEdges.push_back(
E);
969 UnknownCountOutEdge++;
973 void addInEdge(PGOUseEdge *
E) {
974 InEdges.push_back(
E);
975 UnknownCountInEdge++;
984 for (
const auto &
E : Edges) {
997 PGOUseFunc(
const InstrumentationOptions &Opts,
Function &Func,
Module *Modu,
998 TargetLibraryInfo &TLI,
999 std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers,
1000 BranchProbabilityInfo *BPI, BlockFrequencyInfo *BFIin,
1001 LoopInfo *LI, ProfileSummaryInfo *PSI,
bool IsCS,
1002 bool InstrumentFuncEntry,
bool InstrumentLoopEntries,
1003 bool HasSingleByteCoverage)
1004 : Opts(Opts),
F(
Func),
M(Modu), BFI(BFIin), PSI(PSI),
1005 FuncInfo(Opts,
Func, TLI, ComdatMembers,
false, BPI, BFIin, LI, IsCS,
1006 InstrumentFuncEntry, InstrumentLoopEntries,
1007 HasSingleByteCoverage),
1008 FreqAttr(FFA_Normal), IsCS(IsCS), VPC(
Func, TLI) {}
1010 void handleInstrProfError(
Error Err,
uint64_t MismatchedFuncSum);
1015 bool getRecord(IndexedInstrProfReader *PGOReader);
1018 bool readCounters(
bool &AllZeros,
1022 void populateCounters();
1025 void populateCoverage();
1031 void annotateValueSites();
1034 void annotateValueSites(uint32_t Kind);
1037 void annotateIrrLoopHeaderWeights();
1040 void setBlockUniformityAttribute();
1043 enum FuncFreqAttr { FFA_Normal, FFA_Cold, FFA_Hot };
1046 FuncFreqAttr getFuncFreqAttr()
const {
return FreqAttr; }
1052 NamedInstrProfRecord &getProfileRecord() {
return ProfileRecord; }
1055 PGOUseBBInfo &getBBInfo(
const BasicBlock *BB)
const {
1056 return FuncInfo.getBBInfo(BB);
1060 PGOUseBBInfo *findBBInfo(
const BasicBlock *BB)
const {
1061 return FuncInfo.findBBInfo(BB);
1066 void dumpInfo(StringRef Str =
"")
const { FuncInfo.dumpInfo(Str); }
1068 uint64_t getProgramMaxCount()
const {
return ProgramMaxCount; }
1071 const InstrumentationOptions &Opts;
1074 BlockFrequencyInfo *BFI;
1075 ProfileSummaryInfo *PSI;
1078 FuncPGOInstrumentation<PGOUseEdge, PGOUseBBInfo> FuncInfo;
1085 uint32_t CountPosition = 0;
1088 uint32_t ProfileCountSize = 0;
1091 NamedInstrProfRecord ProfileRecord;
1094 FuncFreqAttr FreqAttr;
1099 ValueProfileCollector VPC;
1102 bool setInstrumentedCounts(
const std::vector<uint64_t> &CountFromProfile);
1115 FreqAttr = FFA_Cold;
1123 const FuncPGOInstrumentation<PGOUseEdge, PGOUseBBInfo> &FuncInfo) {
1127 for (
const auto &
E : FuncInfo.MST.allEdges()) {
1132 PGOUseBBInfo &SrcInfo = FuncInfo.getBBInfo(SrcBB);
1133 PGOUseBBInfo &DestInfo = FuncInfo.getBBInfo(DestBB);
1134 SrcInfo.addOutEdge(
E.get());
1135 DestInfo.addInEdge(
E.get());
1141bool PGOUseFunc::setInstrumentedCounts(
1142 const std::vector<uint64_t> &CountFromProfile) {
1144 std::vector<BasicBlock *> InstrumentBBs;
1145 FuncInfo.getInstrumentBBs(InstrumentBBs);
1149 unsigned NumInstrumentedBBs = InstrumentBBs.size();
1150 unsigned NumSelects = FuncInfo.SIVisitor.getNumOfSelectInsts();
1151 unsigned NumCounters = NumInstrumentedBBs + NumSelects;
1154 if (NumCounters != CountFromProfile.size()) {
1156 dbgs() <<
"PGO COUNTER MISMATCH for function " <<
F.getName() <<
":\n";
1157 dbgs() <<
" Expected counters: " << NumCounters <<
"\n";
1158 dbgs() <<
" - From instrumented edges: " << NumInstrumentedBBs <<
"\n";
1159 for (
size_t i = 0; i < InstrumentBBs.size(); ++i) {
1160 dbgs() <<
" " << i <<
": ";
1161 InstrumentBBs[i]->printAsOperand(
dbgs(),
false);
1164 dbgs() <<
" - From select instructions: " << NumSelects <<
"\n";
1165 dbgs() <<
" Actual counters from profile: " << CountFromProfile.size()
1170 auto *FuncEntry = &*
F.begin();
1174 for (BasicBlock *InstrBB : InstrumentBBs) {
1175 uint64_t CountValue = CountFromProfile[
I++];
1176 PGOUseBBInfo &
Info = getBBInfo(InstrBB);
1180 if (InstrBB == FuncEntry && CountValue == 0)
1182 Info.setBBInfoCount(CountValue);
1184 ProfileCountSize = CountFromProfile.size();
1188 auto setEdgeCount = [
this](PGOUseEdge *
E,
uint64_t Value) ->
void {
1190 this->getBBInfo(
E->SrcBB).UnknownCountOutEdge--;
1191 this->getBBInfo(
E->DestBB).UnknownCountInEdge--;
1197 for (
const auto &
E : FuncInfo.MST.allEdges()) {
1198 if (
E->Removed ||
E->InMST)
1201 PGOUseBBInfo &SrcInfo = getBBInfo(SrcBB);
1205 if (SrcInfo.Count && SrcInfo.OutEdges.size() == 1)
1206 setEdgeCount(
E.get(), *SrcInfo.Count);
1209 PGOUseBBInfo &DestInfo = getBBInfo(DestBB);
1212 if (DestInfo.Count && DestInfo.InEdges.size() == 1)
1213 setEdgeCount(
E.get(), *DestInfo.Count);
1219 setEdgeCount(
E.get(), 0);
1226void PGOUseFunc::setEdgeCount(DirectEdges &Edges,
uint64_t Value) {
1227 for (
auto &
E : Edges) {
1232 getBBInfo(
E->SrcBB).UnknownCountOutEdge--;
1233 getBBInfo(
E->DestBB).UnknownCountInEdge--;
1241 const char MetadataName[] =
"instr_prof_hash_mismatch";
1244 auto *Existing =
F.getMetadata(LLVMContext::MD_annotation);
1247 for (
const auto &
N : Tuple->operands()) {
1248 if (
N.equalsStr(MetadataName))
1257 F.setMetadata(LLVMContext::MD_annotation, MD);
1260void PGOUseFunc::handleInstrProfError(
Error Err,
uint64_t MismatchedFuncSum) {
1262 auto &Ctx =
M->getContext();
1263 auto Err = IPE.
get();
1264 bool SkipWarning =
false;
1266 << FuncInfo.FuncName <<
": ");
1267 if (Err == instrprof_error::unknown_function) {
1268 IsCS ? NumOfCSPGOMissing++ : NumOfPGOMissing++;
1269 SkipWarning = !Opts.pgo_warn_missing_function;
1271 }
else if (Err == instrprof_error::hash_mismatch ||
1272 Err == instrprof_error::malformed) {
1273 IsCS ? NumOfCSPGOMismatch++ : NumOfPGOMismatch++;
1276 (Opts.no_pgo_warn_mismatch_comdat_weak &&
1279 LLVM_DEBUG(
dbgs() <<
"hash mismatch (hash= " << FuncInfo.FunctionHash
1280 <<
" skip=" << SkipWarning <<
")");
1290 IPE.
message() + std::string(
" ") +
F.getName().str() +
1291 std::string(
" Hash = ") + std::to_string(FuncInfo.FunctionHash) +
1292 std::string(
" up to ") + std::to_string(MismatchedFuncSum) +
1293 std::string(
" count discarded");
1300bool PGOUseFunc::getRecord(IndexedInstrProfReader *PGOReader) {
1303 FuncInfo.FuncName, FuncInfo.FunctionHash, FuncInfo.DeprecatedFuncName,
1304 &MismatchedFuncSum);
1306 handleInstrProfError(std::move(
E), MismatchedFuncSum);
1309 ProfileRecord = std::move(
Result.get());
1317bool PGOUseFunc::readCounters(
bool &AllZeros,
1319 auto &Ctx =
M->getContext();
1324 std::vector<uint64_t> &CountFromProfile = ProfileRecord.
Counts;
1326 IsCS ? NumOfCSPGOFunc++ : NumOfPGOFunc++;
1330 for (
unsigned I = 0, S = CountFromProfile.size();
I < S;
I++) {
1332 ValueSum += CountFromProfile[
I];
1334 AllZeros = (ValueSum == 0);
1338 getBBInfo(
nullptr).UnknownCountOutEdge = 2;
1339 getBBInfo(
nullptr).UnknownCountInEdge = 2;
1341 if (!setInstrumentedCounts(CountFromProfile)) {
1343 dbgs() <<
"Inconsistent number of counts, skipping this function");
1344 Ctx.diagnose(DiagnosticInfoPGOProfile(
1345 M->getName().data(),
1346 Twine(
"Inconsistent number of counts in ") +
F.getName().str() +
1347 Twine(
": the profile may be stale or there is a function name "
1355void PGOUseFunc::populateCoverage() {
1356 IsCS ? NumOfCSPGOFunc++ : NumOfPGOFunc++;
1358 ArrayRef<uint64_t> CountsFromProfile = ProfileRecord.
Counts;
1359 DenseMap<const BasicBlock *, bool>
Coverage;
1362 if (FuncInfo.BCI->shouldInstrumentBlock(BB))
1367 DenseMap<const BasicBlock *, DenseSet<const BasicBlock *>>
1368 InverseDependencies;
1369 for (
auto &BB :
F) {
1370 for (
auto *Dep : FuncInfo.BCI->getDependencies(BB)) {
1372 InverseDependencies[Dep].
insert(&BB);
1377 std::stack<const BasicBlock *> CoveredBlocksToProcess;
1378 for (
auto &[BB, IsCovered] : Coverage)
1380 CoveredBlocksToProcess.push(BB);
1382 while (!CoveredBlocksToProcess.empty()) {
1383 auto *CoveredBlock = CoveredBlocksToProcess.top();
1384 assert(Coverage[CoveredBlock]);
1385 CoveredBlocksToProcess.pop();
1386 for (
auto *BB : InverseDependencies[CoveredBlock]) {
1392 CoveredBlocksToProcess.push(BB);
1397 MDBuilder MDB(
F.getContext());
1400 F.setEntryCount(Coverage[&
F.getEntryBlock()] ? 10000 : 0);
1401 for (
auto &BB :
F) {
1408 SmallVector<uint32_t, 4> Weights;
1410 Weights.
push_back((Coverage[Succ] || !Coverage[&BB]) ? 1 : 0);
1411 if (Weights.
size() >= 2)
1416 unsigned NumCorruptCoverage = 0;
1419 BranchProbabilityInfo BPI(
F, CI);
1420 BlockFrequencyInfo BFI(
F, BPI, CI);
1421 auto IsBlockDead = [&](
const BasicBlock &BB) -> std::optional<bool> {
1426 LLVM_DEBUG(
dbgs() <<
"Block Coverage: (Instrumented=*, Covered=X)\n");
1427 for (
auto &BB :
F) {
1428 LLVM_DEBUG(
dbgs() << (FuncInfo.BCI->shouldInstrumentBlock(BB) ?
"* " :
" ")
1429 << (Coverage[&BB] ?
"X " :
" ") <<
" " << BB.getName()
1436 if (Cov == IsBlockDead(BB).value_or(
false)) {
1438 dbgs() <<
"Found inconsistent block covearge for " << BB.getName()
1439 <<
": BCI=" << (Cov ?
"Covered" :
"Dead") <<
" BFI="
1440 << (IsBlockDead(BB).value() ?
"Dead" :
"Covered") <<
"\n");
1441 ++NumCorruptCoverage;
1446 if (Opts.pgo_verify_bfi && NumCorruptCoverage) {
1447 auto &Ctx =
M->getContext();
1448 Ctx.diagnose(DiagnosticInfoPGOProfile(
1449 M->getName().data(),
1450 Twine(
"Found inconsistent block coverage for function ") +
F.getName() +
1451 " in " + Twine(NumCorruptCoverage) +
" blocks.",
1454 if (Opts.pgo_view_block_coverage_graph)
1455 FuncInfo.BCI->viewBlockCoverageGraph(&Coverage);
1460void PGOUseFunc::populateCounters() {
1461 bool Changes =
true;
1462 unsigned NumPasses = 0;
1470 PGOUseBBInfo *UseBBInfo = findBBInfo(&BB);
1471 if (UseBBInfo ==
nullptr)
1473 if (!UseBBInfo->Count) {
1474 if (UseBBInfo->UnknownCountOutEdge == 0) {
1477 }
else if (UseBBInfo->UnknownCountInEdge == 0) {
1482 if (UseBBInfo->Count) {
1483 if (UseBBInfo->UnknownCountOutEdge == 1) {
1489 if (*UseBBInfo->Count > OutSum)
1490 Total = *UseBBInfo->Count - OutSum;
1491 setEdgeCount(UseBBInfo->OutEdges,
Total);
1494 if (UseBBInfo->UnknownCountInEdge == 1) {
1497 if (*UseBBInfo->Count > InSum)
1498 Total = *UseBBInfo->Count - InSum;
1499 setEdgeCount(UseBBInfo->InEdges,
Total);
1506 LLVM_DEBUG(
dbgs() <<
"Populate counts in " << NumPasses <<
" passes.\n");
1510 for (
auto &BB :
F) {
1511 auto BI = findBBInfo(&BB);
1514 assert(BI->Count &&
"BB count is not valid");
1518 FuncInfo.SIVisitor.annotateSelects(
this, &CountPosition);
1519 assert(CountPosition == ProfileCountSize);
1523 for (
auto &BB :
F) {
1524 auto BI = findBBInfo(&BB);
1527 FuncMaxCount = std::max(FuncMaxCount, *BI->Count);
1536 LLVM_DEBUG(FuncInfo.dumpInfo(
"after reading profile."));
1540void PGOUseFunc::setBranchWeights() {
1542 LLVM_DEBUG(
dbgs() <<
"\nSetting branch weights for func " <<
F.getName()
1543 <<
" IsCS=" << IsCS <<
"\n");
1544 for (
auto &BB :
F) {
1553 const PGOUseBBInfo &BBCountInfo = getBBInfo(&BB);
1554 if (!*BBCountInfo.Count)
1561 unsigned OutEdgesCount = BBCountInfo.OutEdges.size();
1562 unsigned SuccessorCount = BB.getTerminator()->getNumSuccessors();
1563 assert(OutEdgesCount <= SuccessorCount);
1567 for (
unsigned It = 0; It < OutEdgesCount; It++) {
1568 const PGOUseEdge *
E = BBCountInfo.OutEdges[It];
1571 if (DestBB ==
nullptr)
1575 if (EdgeCount > MaxCount)
1576 MaxCount = EdgeCount;
1577 EdgeCounts[SuccNum] = EdgeCount;
1586 auto &Ctx =
M->getContext();
1587 Ctx.diagnose(DiagnosticInfoPGOProfile(
1588 M->getName().data(),
1589 Twine(
"Profile in ") +
F.getName().str() +
1590 Twine(
" partially ignored") +
1591 Twine(
", possibly due to the lack of a return path."),
1605void PGOUseFunc::annotateIrrLoopHeaderWeights() {
1606 LLVM_DEBUG(
dbgs() <<
"\nAnnotating irreducible loop header weights.\n");
1608 for (
auto &BB :
F) {
1614 const PGOUseBBInfo &BBCountInfo = getBBInfo(&BB);
1620void PGOUseFunc::setBlockUniformityAttribute() {
1631 std::vector<BasicBlock *> InstrumentBBs;
1632 FuncInfo.getInstrumentBBs(InstrumentBBs);
1634 LLVMContext &Ctx =
F.getContext();
1635 Type *Int1Ty = Type::getInt1Ty(Ctx);
1637 for (
size_t I = 0,
E = InstrumentBBs.size();
I <
E; ++
I) {
1649 dbgs() <<
"PGO: Set block uniformity profile for " <<
F.getName() <<
": ";
1650 for (
size_t I = 0,
E = InstrumentBBs.size();
I <
E; ++
I)
1656void SelectInstVisitor::instrumentOneSelectInst(SelectInst &SI) {
1659 Type *Int64Ty = Builder.getInt64Ty();
1665 auto *Step = Builder.CreateZExt(
Cond, Int64Ty);
1666 auto *NormalizedFuncNameVarPtr =
1668 FuncNameVar, PointerType::get(
M->getContext(), 0));
1669 Builder.CreateIntrinsic(Intrinsic::instrprof_increment_step,
1670 {NormalizedFuncNameVarPtr, Builder.getInt64(
FuncHash),
1671 Builder.getInt32(TotalNumCtrs),
1672 Builder.getInt32(*CurCtrIdx), Step});
1676void SelectInstVisitor::annotateOneSelectInst(SelectInst &SI) {
1677 std::vector<uint64_t> &CountFromProfile = UseFunc->getProfileRecord().Counts;
1678 assert(*CurCtrIdx < CountFromProfile.size() &&
1679 "Out of bound access of counters");
1681 SCounts[0] = CountFromProfile[*CurCtrIdx];
1684 auto BI = UseFunc->findBBInfo(
SI.getParent());
1685 if (BI !=
nullptr) {
1686 TotalCount = *BI->Count;
1689 if (TotalCount < SCounts[0])
1690 BI->Count = SCounts[0];
1693 SCounts[1] = (TotalCount > SCounts[0] ? TotalCount - SCounts[0] : 0);
1694 uint64_t MaxCount = std::max(SCounts[0], SCounts[1]);
1699void SelectInstVisitor::visitSelectInst(SelectInst &SI) {
1700 if (!Opts.pgo_instr_select || Opts.pgo_function_entry_coverage ||
1701 HasSingleByteCoverage)
1704 if (
SI.getCondition()->getType()->isVectorTy())
1712 instrumentOneSelectInst(SI);
1715 annotateOneSelectInst(SI);
1725 if (ValueProfKind == IPVK_MemOPSize)
1726 return Opts.memop_max_annotations;
1727 if (ValueProfKind == llvm::IPVK_VTableTarget)
1729 return Opts.icp_max_annotations;
1733void PGOUseFunc::annotateValueSites() {
1734 if (Opts.disable_vp)
1737 for (uint32_t Kind = IPVK_First;
Kind <= IPVK_Last; ++
Kind)
1738 annotateValueSites(Kind);
1742void PGOUseFunc::annotateValueSites(uint32_t Kind) {
1743 assert(Kind <= IPVK_Last);
1744 unsigned ValueSiteIndex = 0;
1758 NumValueSites != FuncInfo.ValueSites[IPVK_VTableTarget].size() &&
1760 FuncInfo.ValueSites[IPVK_VTableTarget] = VPC.
get(IPVK_VTableTarget);
1761 auto &ValueSites = FuncInfo.ValueSites[
Kind];
1763 auto &Ctx =
M->getContext();
1764 Ctx.
diagnose(DiagnosticInfoPGOProfile(
1765 M->getName().data(),
1766 Twine(
"Inconsistent number of value sites for ") +
1769 Twine(
"\", possibly due to the use of a stale profile."),
1775 LLVM_DEBUG(
dbgs() <<
"Read one value site profile (kind = " << Kind
1776 <<
"): Index = " << ValueSiteIndex <<
" out of "
1779 *M, *
I.AnnotatedInst, ProfileRecord,
1790 const InstrumentationOptions &Opts,
Module &M,
1791 std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers) {
1792 if (!Opts.do_comdat_renaming)
1796 ComdatMembers.insert(std::make_pair(
C, &
F));
1798 if (
Comdat *
C = GV.getComdat())
1799 ComdatMembers.insert(std::make_pair(
C, &GV));
1801 if (
Comdat *
C = GA.getComdat())
1802 ComdatMembers.insert(std::make_pair(
C, &GA));
1807 if (
F.isDeclaration())
1812 unsigned NumCriticalEdges = 0;
1813 for (
auto &BB :
F) {
1820 if (NumCriticalEdges > Opts.pgo_critical_edge_threshold) {
1822 <<
", NumCriticalEdges=" << NumCriticalEdges
1823 <<
" exceed the threshold. Skip PGO.\n");
1833 if (
F.hasFnAttribute(llvm::Attribute::Naked))
1835 if (
F.hasFnAttribute(llvm::Attribute::NoProfile))
1837 if (
F.hasFnAttribute(llvm::Attribute::SkipProfile))
1839 if (
F.getInstructionCount() < Opts.pgo_function_size_threshold)
1841 if (Opts.pgo_instrument_cold_function_only) {
1842 if (
auto EntryCount =
F.getEntryCount())
1843 return *EntryCount > Opts.pgo_cold_instrument_entry_threshold;
1844 return !Opts.pgo_treat_unknown_as_cold;
1850 const InstrumentationOptions &Opts,
Module &M,
1861 Triple TT(M.getTargetTriple());
1866 Twine(
"VTable value profiling is presently not "
1867 "supported for non-ELF object formats"),
1869 std::unordered_multimap<Comdat *, GlobalValue *> ComdatMembers;
1879 FunctionInstrumenter FI(Opts, M,
F, TLI, ComdatMembers, BPI, BFI, LI,
1880 InstrumentationType);
1894 if (ProfileSampling)
1920 LookupLI, InstrumentationType))
1933 auto BFIEntryCount =
F.getEntryCount();
1934 assert(BFIEntryCount && (*BFIEntryCount > 0) &&
"Invalid BFI Entrycount");
1938 for (
auto &BBI :
F) {
1941 if (!Func.findBBInfo(&BBI))
1944 CountValue = *Func.getBBInfo(&BBI).Count;
1945 BFICountValue = *BFICount;
1949 if (SumCount.isZero())
1953 "Incorrect sum of BFI counts");
1956 double Scale = (SumCount / SumBFICount).convertToDouble();
1957 if (Scale < 1.001 && Scale > 0.999)
1962 if (NewEntryCount == 0)
1965 F.setEntryCount(NewEntryCount);
1968 << NewEntryCount <<
"\n");
1981 bool HotBBOnly = Opts.pgo_verify_hot_bfi;
1985 unsigned BBNum = 0, BBMisMatchNum = 0, NonZeroBBNum = 0;
1986 for (
auto &BBI :
F) {
1987 PGOUseBBInfo *BBInfo = Func.findBBInfo(&BBI);
1991 uint64_t CountValue = BBInfo->Count.value_or(CountValue);
1999 BFICountValue = *BFICount;
2002 bool rawIsHot = CountValue >= HotCountThreshold;
2003 bool BFIIsHot = BFICountValue >= HotCountThreshold;
2005 bool ShowCount =
false;
2006 if (rawIsHot && !BFIIsHot) {
2007 Msg =
"raw-Hot to BFI-nonHot";
2009 }
else if (rawIsCold && BFIIsHot) {
2010 Msg =
"raw-Cold to BFI-Hot";
2016 if ((CountValue < Opts.pgo_verify_bfi_cutoff) &&
2017 (BFICountValue < Opts.pgo_verify_bfi_cutoff))
2019 uint64_t Diff = (BFICountValue >= CountValue)
2020 ? BFICountValue - CountValue
2021 : CountValue - BFICountValue;
2022 if (Diff <= CountValue / 100 * Opts.pgo_verify_bfi_ratio)
2029 F.getSubprogram(), &BBI);
2031 <<
" Count=" <<
ore::NV(
"Count", CountValue)
2032 <<
" BFI_Count=" <<
ore::NV(
"Count", BFICountValue);
2041 F.getSubprogram(), &
F.getEntryBlock())
2042 <<
"In Func " <<
ore::NV(
"Function",
F.getName())
2043 <<
": Num_of_BB=" <<
ore::NV(
"Count", BBNum)
2044 <<
", Num_of_non_zerovalue_BB=" <<
ore::NV(
"Count", NonZeroBBNum)
2045 <<
", Num_of_mis_matching_BB=" <<
ore::NV(
"Count", BBMisMatchNum);
2050 const InstrumentationOptions &Opts,
Module &M,
StringRef ProfileFileName,
2058 auto &Ctx = M.getContext();
2061 ProfileRemappingFileName);
2062 if (
Error E = ReaderOrErr.takeError()) {
2070 std::unique_ptr<IndexedInstrProfReader> PGOReader =
2071 std::move(ReaderOrErr.get());
2077 if (!PGOReader->hasCSIRLevelProfile() && IsCS)
2081 if (!PGOReader->isIRLevelProfile()) {
2083 ProfileFileName.
data(),
"Not an IR level instrumentation profile"));
2086 if (PGOReader->functionEntryOnly()) {
2088 ProfileFileName.
data(),
2089 "Function entry profiles are not yet supported for optimization"));
2096 M.setProfileSummary(PGOReader->getSummary(IsCS).getMD(M.getContext()),
2101 std::unordered_multimap<Comdat *, GlobalValue *> ComdatMembers;
2103 std::vector<Function *> HotFunctions;
2104 std::vector<Function *> ColdFunctions;
2108 bool InstrumentFuncEntry =
2109 valueOr(Opts.pgo_instrument_entry, PGOReader->instrEntryBBEnabled());
2110 bool InstrumentLoopEntries =
valueOr(Opts.pgo_instrument_loop_entries,
2111 PGOReader->instrLoopEntriesEnabled());
2113 bool HasSingleByteCoverage = PGOReader->hasSingleByteCoverage();
2121 if (!HasSingleByteCoverage) {
2127 PGOUseFunc Func(Opts,
F, &M, TLI, ComdatMembers, BPI, BFI, LI, PSI, IsCS,
2128 InstrumentFuncEntry, InstrumentLoopEntries,
2129 HasSingleByteCoverage);
2130 if (!Func.getRecord(PGOReader.get()))
2132 if (HasSingleByteCoverage) {
2133 Func.populateCoverage();
2141 bool AllZeros =
false;
2142 if (!Func.readCounters(AllZeros, PseudoKind))
2146 if (Func.getProgramMaxCount() != 0)
2147 ColdFunctions.push_back(&
F);
2152 if (
F.hasFnAttribute(Attribute::Cold))
2153 F.removeFnAttr(Attribute::Cold);
2156 F.addFnAttr(Attribute::Hot);
2159 Func.populateCounters();
2160 Func.setBranchWeights();
2161 Func.annotateValueSites();
2162 Func.annotateIrrLoopHeaderWeights();
2163 Func.setBlockUniformityAttribute();
2164 PGOUseFunc::FuncFreqAttr FreqAttr = Func.getFuncFreqAttr();
2165 if (FreqAttr == PGOUseFunc::FFA_Cold)
2166 ColdFunctions.push_back(&
F);
2167 else if (FreqAttr == PGOUseFunc::FFA_Hot)
2168 HotFunctions.push_back(&
F);
2172 (ViewFuncName.
empty() ||
F.getName() == ViewFuncName)) {
2175 std::unique_ptr<BranchProbabilityInfo> NewBPI =
2176 std::make_unique<BranchProbabilityInfo>(
F, CI);
2177 std::unique_ptr<BlockFrequencyInfo> NewBFI =
2178 std::make_unique<BlockFrequencyInfo>(
F, *NewBPI, CI);
2182 dbgs() <<
"pgo-view-counts: " << Func.getFunc().getName() <<
"\n";
2183 NewBFI->print(
dbgs());
2187 (ViewFuncName.
empty() ||
F.getName() == ViewFuncName)) {
2189 if (ViewFuncName.
empty())
2192 ViewGraph(&Func,
Twine(
"PGORawCounts_") + Func.getFunc().getName());
2194 dbgs() <<
"pgo-view-raw-counts: " << Func.getFunc().getName() <<
"\n";
2199 if (Opts.pgo_verify_bfi || Opts.pgo_verify_hot_bfi ||
2200 Opts.pgo_fix_entry_count) {
2206 if (Opts.pgo_fix_entry_count)
2211 if (Opts.pgo_verify_hot_bfi) {
2224 for (
auto &
F : HotFunctions) {
2225 F->addFnAttr(Attribute::InlineHint);
2226 LLVM_DEBUG(
dbgs() <<
"Set inline attribute to function: " <<
F->getName()
2229 for (
auto &
F : ColdFunctions) {
2232 if (
F->hasFnAttribute(Attribute::Hot)) {
2233 auto &Ctx = M.getContext();
2234 std::string
Msg = std::string(
"Function ") +
F->getName().str() +
2235 std::string(
" is annotated as a hot function but"
2236 " the profile is cold");
2241 F->addFnAttr(Attribute::Cold);
2242 LLVM_DEBUG(
dbgs() <<
"Set cold attribute to function: " <<
F->getName()
2249 std::string
Filename, std::string RemappingFilename,
bool IsCS,
2252 ProfileRemappingFileName(
std::
move(RemappingFilename)), IsCS(IsCS),
2277 StringRef ProfileFile = ProfileFileName;
2278 if (!Opts.pgo_test_profile_file.empty())
2279 ProfileFile = Opts.pgo_test_profile_file;
2280 StringRef RemappingFile = ProfileRemappingFileName;
2281 if (!Opts.pgo_test_profile_remapping_file.empty())
2282 RemappingFile = Opts.pgo_test_profile_remapping_file;
2284 LookupBPI, LookupBFI, LookupLI, PSI, IsCS))
2291 if (!
Node->getName().empty())
2292 return Node->getName().str();
2294 std::string SimpleNodeName;
2297 return SimpleNodeName;
2301 uint64_t MaxCount) {
2304 LLVM_DEBUG(
dbgs() <<
"Weight is: ";
for (
const auto &W : Weights) {
2312 const InstrumentationOptions &Opts =
2314 if (Opts.pgo_emit_branch_prob) {
2316 if (BrCondStr.empty())
2320 std::accumulate(Weights.begin(), Weights.end(), (uint64_t)0,
2321 [](uint64_t w1, uint64_t w2) { return w1 + w2; });
2322 uint64_t TotalCount =
2323 std::accumulate(EdgeCounts.
begin(), EdgeCounts.
end(), (uint64_t)0,
2324 [](uint64_t c1, uint64_t c2) { return c1 + c2; });
2328 std::string BranchProbStr;
2331 OS <<
" (total count : " << TotalCount <<
")";
2336 << BrCondStr <<
" is true with probability : " << BranchProbStr;
2355 return &
G->getFunc().front();
2378 return std::string(
G->getFunc().getName());
2386 PGOUseBBInfo *BI =
Graph->findBBInfo(
Node);
2388 if (BI && BI->Count)
2389 OS << *BI->Count <<
"\\l";
2393 const InstrumentationOptions &Opts =
2395 if (!Opts.pgo_instr_select)
2402 OS <<
"SELECT : { T = ";
2406 OS <<
"Unknown, F = Unknown }\\l";
2408 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...
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)
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 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 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 uint32_t getMaxNumAnnotations(const InstrumentationOptions &Opts, const LLVMContext &C, InstrProfValueKind ValueProfKind)
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.
SmallVector< MachineOperand, 4 > 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 getFirstNonPHIOrAlloca() const
Returns an iterator to the first instruction in this block that is not a PHINode, a static alloca,...
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.
@ ProtectedVisibility
The GV is protected.
@ 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 const Function * getFunction() const
Return the function this instruction belongs to.
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 bool empty() const
Check if the string is empty.
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.
const InstrumentationOptions & getInstrumentationOptions(const LLVMContext &C)
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< 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...
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 PGOViewCountsType getPGOViewCounts(const LLVMContext &C)
Return -pgo-view-counts.
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)
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 unsigned getMaxNumVTableAnnotations(const LLVMContext &C)
Return -icp-max-num-vtables.
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.
LLVM_ABI StringRef getViewBlockFreqFuncName(const LLVMContext &C)
Return -view-bfi-func-name.
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."))
LLVM_ABI bool isPGOInstrumentColdFunctionOnly(const cl::LibraryOptionsContext &LibraryOptions)
Return the value of -pgo-instrument-cold-function-only in LibraryOptions.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
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