diff options
author | ronryvchin <94285266+ronryvchin@users.noreply.github.com> | 2024-12-04 08:56:46 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-12-04 07:56:46 +0100 |
commit | ff281f7d37ead15bdbdbfccb4b82ea93013b1a00 (patch) | |
tree | 6e2845fbe9fd9ae58443e17a3376ae922268f730 /llvm/lib | |
parent | 92ed7e292443de1d89754a59a533ded160d544eb (diff) | |
download | llvm-ff281f7d37ead15bdbdbfccb4b82ea93013b1a00.zip llvm-ff281f7d37ead15bdbdbfccb4b82ea93013b1a00.tar.gz llvm-ff281f7d37ead15bdbdbfccb4b82ea93013b1a00.tar.bz2 |
[PGO] Add option to always instrumenting loop entries (#116789)
This patch extends the PGO infrastructure with an option to prefer the
instrumentation of loop entry blocks.
This option is a generalization of
https://github.com/llvm/llvm-project/commit/19fb5b467bb97f95eace1f3637d2d1041cebd3ce,
and helps to cover cases where the loop exit is never executed.
An example where this can occur are event handling loops.
Note that change does NOT change the default behavior.
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/ProfileData/InstrProfReader.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/ProfileData/InstrProfWriter.cpp | 7 | ||||
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp | 72 |
4 files changed, 65 insertions, 22 deletions
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp index 7663852..dad79b2 100644 --- a/llvm/lib/ProfileData/InstrProfReader.cpp +++ b/llvm/lib/ProfileData/InstrProfReader.cpp @@ -52,6 +52,9 @@ static InstrProfKind getProfileKindFromVersion(uint64_t Version) { if (Version & VARIANT_MASK_INSTR_ENTRY) { ProfileKind |= InstrProfKind::FunctionEntryInstrumentation; } + if (Version & VARIANT_MASK_INSTR_LOOP_ENTRIES) { + ProfileKind |= InstrProfKind::LoopEntriesInstrumentation; + } if (Version & VARIANT_MASK_BYTE_COVERAGE) { ProfileKind |= InstrProfKind::SingleByteCoverage; } @@ -262,6 +265,8 @@ Error TextInstrProfReader::readHeader() { ProfileKind |= InstrProfKind::FunctionEntryInstrumentation; else if (Str.equals_insensitive("not_entry_first")) ProfileKind &= ~InstrProfKind::FunctionEntryInstrumentation; + else if (Str.equals_insensitive("instrument_loop_entries")) + ProfileKind |= InstrProfKind::LoopEntriesInstrumentation; else if (Str.equals_insensitive("single_byte_coverage")) ProfileKind |= InstrProfKind::SingleByteCoverage; else if (Str.equals_insensitive("temporal_prof_traces")) { diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp index d8ab18d..64625de 100644 --- a/llvm/lib/ProfileData/InstrProfWriter.cpp +++ b/llvm/lib/ProfileData/InstrProfWriter.cpp @@ -877,6 +877,9 @@ Error InstrProfWriter::writeImpl(ProfOStream &OS) { if (static_cast<bool>(ProfileKind & InstrProfKind::FunctionEntryInstrumentation)) Header.Version |= VARIANT_MASK_INSTR_ENTRY; + if (static_cast<bool>(ProfileKind & + InstrProfKind::LoopEntriesInstrumentation)) + Header.Version |= VARIANT_MASK_INSTR_LOOP_ENTRIES; if (static_cast<bool>(ProfileKind & InstrProfKind::SingleByteCoverage)) Header.Version |= VARIANT_MASK_BYTE_COVERAGE; if (static_cast<bool>(ProfileKind & InstrProfKind::FunctionEntryOnly)) @@ -1120,6 +1123,10 @@ Error InstrProfWriter::writeText(raw_fd_ostream &OS) { if (static_cast<bool>(ProfileKind & InstrProfKind::FunctionEntryInstrumentation)) OS << "# Always instrument the function entry block\n:entry_first\n"; + if (static_cast<bool>(ProfileKind & + InstrProfKind::LoopEntriesInstrumentation)) + OS << "# Always instrument the loop entry " + "blocks\n:instrument_loop_entries\n"; if (static_cast<bool>(ProfileKind & InstrProfKind::SingleByteCoverage)) OS << "# Instrument block coverage\n:single_byte_coverage\n"; InstrProfSymtab Symtab; diff --git a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp index 2ea89be..f9be7f9 100644 --- a/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp +++ b/llvm/lib/Transforms/Instrumentation/GCOVProfiling.cpp @@ -820,7 +820,8 @@ bool GCOVProfiler::emitProfileNotes( SplitIndirectBrCriticalEdges(F, /*IgnoreBlocksWithoutPHI=*/false, BPI, BFI); - CFGMST<Edge, BBInfo> MST(F, /*InstrumentFuncEntry_=*/false, BPI, BFI); + CFGMST<Edge, BBInfo> MST(F, /*InstrumentFuncEntry=*/false, + /*InstrumentLoopEntries=*/false, BPI, BFI); // getInstrBB can split basic blocks and push elements to AllEdges. for (size_t I : llvm::seq<size_t>(0, MST.numEdges())) { diff --git a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp index 4d81414..471086c 100644 --- a/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp +++ b/llvm/lib/Transforms/Instrumentation/PGOInstrumentation.cpp @@ -259,6 +259,11 @@ static cl::opt<bool> PGOInstrumentEntry( "pgo-instrument-entry", cl::init(false), cl::Hidden, cl::desc("Force to instrument function entry basicblock.")); +static cl::opt<bool> + PGOInstrumentLoopEntries("pgo-instrument-loop-entries", cl::init(false), + cl::Hidden, + cl::desc("Force to instrument loop entries.")); + static cl::opt<bool> PGOFunctionEntryCoverage( "pgo-function-entry-coverage", cl::Hidden, cl::desc( @@ -359,6 +364,7 @@ class FunctionInstrumenter final { std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers; BranchProbabilityInfo *const BPI; BlockFrequencyInfo *const BFI; + LoopInfo *const LI; const PGOInstrumentationType InstrumentationType; @@ -376,14 +382,17 @@ class FunctionInstrumenter final { InstrumentationType == PGOInstrumentationType::CTXPROF; } + bool shouldInstrumentLoopEntries() const { return PGOInstrumentLoopEntries; } + public: FunctionInstrumenter( Module &M, Function &F, TargetLibraryInfo &TLI, std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers, BranchProbabilityInfo *BPI = nullptr, BlockFrequencyInfo *BFI = nullptr, + LoopInfo *LI = nullptr, PGOInstrumentationType InstrumentationType = PGOInstrumentationType::FDO) : M(M), F(F), TLI(TLI), ComdatMembers(ComdatMembers), BPI(BPI), BFI(BFI), - InstrumentationType(InstrumentationType) {} + LI(LI), InstrumentationType(InstrumentationType) {} void instrument(); }; @@ -439,6 +448,8 @@ createIRLevelProfileFlagVar(Module &M, if (PGOInstrumentEntry || InstrumentationType == PGOInstrumentationType::CTXPROF) ProfileVersion |= VARIANT_MASK_INSTR_ENTRY; + if (PGOInstrumentLoopEntries) + ProfileVersion |= VARIANT_MASK_INSTR_LOOP_ENTRIES; if (DebugInfoCorrelate || ProfileCorrelate == InstrProfCorrelator::DEBUG_INFO) ProfileVersion |= VARIANT_MASK_DBG_CORRELATE; if (PGOFunctionEntryCoverage) @@ -625,12 +636,13 @@ public: Function &Func, TargetLibraryInfo &TLI, std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers, bool CreateGlobalVar = false, BranchProbabilityInfo *BPI = nullptr, - BlockFrequencyInfo *BFI = nullptr, bool IsCS = false, - bool InstrumentFuncEntry = true, bool HasSingleByteCoverage = false) + BlockFrequencyInfo *BFI = nullptr, LoopInfo *LI = nullptr, + bool IsCS = false, bool InstrumentFuncEntry = true, + bool InstrumentLoopEntries = false, bool HasSingleByteCoverage = false) : F(Func), IsCS(IsCS), ComdatMembers(ComdatMembers), VPC(Func, TLI), TLI(TLI), ValueSites(IPVK_Last + 1), SIVisitor(Func, HasSingleByteCoverage), - MST(F, InstrumentFuncEntry, BPI, BFI), + MST(F, InstrumentFuncEntry, InstrumentLoopEntries, BPI, BFI, LI), BCI(constructBCI(Func, HasSingleByteCoverage, InstrumentFuncEntry)) { if (BCI && PGOViewBlockCoverageGraph) BCI->viewBlockCoverageGraph(); @@ -916,9 +928,10 @@ void FunctionInstrumenter::instrument() { const bool IsCtxProf = InstrumentationType == PGOInstrumentationType::CTXPROF; FuncPGOInstrumentation<PGOEdge, PGOBBInfo> FuncInfo( - F, TLI, ComdatMembers, /*CreateGlobalVar=*/!IsCtxProf, BPI, BFI, + F, TLI, ComdatMembers, /*CreateGlobalVar=*/!IsCtxProf, BPI, BFI, LI, InstrumentationType == PGOInstrumentationType::CSFDO, - shouldInstrumentEntryBB(), PGOBlockCoverage); + shouldInstrumentEntryBB(), shouldInstrumentLoopEntries(), + PGOBlockCoverage); auto *const Name = IsCtxProf ? cast<GlobalValue>(&F) : FuncInfo.FuncNameVar; auto *const CFGHash = @@ -1136,11 +1149,13 @@ public: PGOUseFunc(Function &Func, Module *Modu, TargetLibraryInfo &TLI, std::unordered_multimap<Comdat *, GlobalValue *> &ComdatMembers, BranchProbabilityInfo *BPI, BlockFrequencyInfo *BFIin, - ProfileSummaryInfo *PSI, bool IsCS, bool InstrumentFuncEntry, + LoopInfo *LI, ProfileSummaryInfo *PSI, bool IsCS, + bool InstrumentFuncEntry, bool InstrumentLoopEntries, bool HasSingleByteCoverage) : F(Func), M(Modu), BFI(BFIin), PSI(PSI), - FuncInfo(Func, TLI, ComdatMembers, false, BPI, BFIin, IsCS, - InstrumentFuncEntry, HasSingleByteCoverage), + FuncInfo(Func, TLI, ComdatMembers, false, BPI, BFIin, LI, IsCS, + InstrumentFuncEntry, InstrumentLoopEntries, + HasSingleByteCoverage), FreqAttr(FFA_Normal), IsCS(IsCS), VPC(Func, TLI) {} void handleInstrProfError(Error Err, uint64_t MismatchedFuncSum); @@ -1923,6 +1938,7 @@ static bool InstrumentAllFunctions( Module &M, function_ref<TargetLibraryInfo &(Function &)> LookupTLI, function_ref<BranchProbabilityInfo *(Function &)> LookupBPI, function_ref<BlockFrequencyInfo *(Function &)> LookupBFI, + function_ref<LoopInfo *(Function &)> LookupLI, PGOInstrumentationType InstrumentationType) { // For the context-sensitve instrumentation, we should have a separated pass // (before LTO/ThinLTO linking) to create these variables. @@ -1943,10 +1959,11 @@ static bool InstrumentAllFunctions( for (auto &F : M) { if (skipPGOGen(F)) continue; - auto &TLI = LookupTLI(F); - auto *BPI = LookupBPI(F); - auto *BFI = LookupBFI(F); - FunctionInstrumenter FI(M, F, TLI, ComdatMembers, BPI, BFI, + TargetLibraryInfo &TLI = LookupTLI(F); + BranchProbabilityInfo *BPI = LookupBPI(F); + BlockFrequencyInfo *BFI = LookupBFI(F); + LoopInfo *LI = LookupLI(F); + FunctionInstrumenter FI(M, F, TLI, ComdatMembers, BPI, BFI, LI, InstrumentationType); FI.instrument(); } @@ -1980,8 +1997,11 @@ PreservedAnalyses PGOInstrumentationGen::run(Module &M, auto LookupBFI = [&FAM](Function &F) { return &FAM.getResult<BlockFrequencyAnalysis>(F); }; + auto LookupLI = [&FAM](Function &F) { + return &FAM.getResult<LoopAnalysis>(F); + }; - if (!InstrumentAllFunctions(M, LookupTLI, LookupBPI, LookupBFI, + if (!InstrumentAllFunctions(M, LookupTLI, LookupBPI, LookupBFI, LookupLI, InstrumentationType)) return PreservedAnalyses::all(); @@ -2116,7 +2136,8 @@ static bool annotateAllFunctions( function_ref<TargetLibraryInfo &(Function &)> LookupTLI, function_ref<BranchProbabilityInfo *(Function &)> LookupBPI, function_ref<BlockFrequencyInfo *(Function &)> LookupBFI, - ProfileSummaryInfo *PSI, bool IsCS) { + function_ref<LoopInfo *(Function &)> LookupLI, ProfileSummaryInfo *PSI, + bool IsCS) { LLVM_DEBUG(dbgs() << "Read in profile counters: "); auto &Ctx = M.getContext(); // Read the counter array from file. @@ -2181,22 +2202,27 @@ static bool annotateAllFunctions( bool InstrumentFuncEntry = PGOReader->instrEntryBBEnabled(); if (PGOInstrumentEntry.getNumOccurrences() > 0) InstrumentFuncEntry = PGOInstrumentEntry; + bool InstrumentLoopEntries = PGOReader->instrLoopEntriesEnabled(); + if (PGOInstrumentLoopEntries.getNumOccurrences() > 0) + InstrumentLoopEntries = PGOInstrumentLoopEntries; bool HasSingleByteCoverage = PGOReader->hasSingleByteCoverage(); for (auto &F : M) { if (skipPGOUse(F)) continue; - auto &TLI = LookupTLI(F); - auto *BPI = LookupBPI(F); - auto *BFI = LookupBFI(F); + TargetLibraryInfo &TLI = LookupTLI(F); + BranchProbabilityInfo *BPI = LookupBPI(F); + BlockFrequencyInfo *BFI = LookupBFI(F); + LoopInfo *LI = LookupLI(F); if (!HasSingleByteCoverage) { // Split indirectbr critical edges here before computing the MST rather // than later in getInstrBB() to avoid invalidating it. SplitIndirectBrCriticalEdges(F, /*IgnoreBlocksWithoutPHI=*/false, BPI, BFI); } - PGOUseFunc Func(F, &M, TLI, ComdatMembers, BPI, BFI, PSI, IsCS, - InstrumentFuncEntry, HasSingleByteCoverage); + PGOUseFunc Func(F, &M, TLI, ComdatMembers, BPI, BFI, LI, PSI, IsCS, + InstrumentFuncEntry, InstrumentLoopEntries, + HasSingleByteCoverage); if (HasSingleByteCoverage) { Func.populateCoverage(PGOReader.get()); continue; @@ -2335,10 +2361,14 @@ PreservedAnalyses PGOInstrumentationUse::run(Module &M, auto LookupBFI = [&FAM](Function &F) { return &FAM.getResult<BlockFrequencyAnalysis>(F); }; + auto LookupLI = [&FAM](Function &F) { + return &FAM.getResult<LoopAnalysis>(F); + }; auto *PSI = &MAM.getResult<ProfileSummaryAnalysis>(M); if (!annotateAllFunctions(M, ProfileFileName, ProfileRemappingFileName, *FS, - LookupTLI, LookupBPI, LookupBFI, PSI, IsCS)) + LookupTLI, LookupBPI, LookupBFI, LookupLI, PSI, + IsCS)) return PreservedAnalyses::all(); return PreservedAnalyses::none(); |