File indexing completed on 2026-05-10 08:43:16
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_ANALYSIS_PROFILESUMMARYINFO_H
0015 #define LLVM_ANALYSIS_PROFILESUMMARYINFO_H
0016
0017 #include "llvm/ADT/DenseMap.h"
0018 #include "llvm/IR/Function.h"
0019 #include "llvm/IR/Instructions.h"
0020 #include "llvm/IR/PassManager.h"
0021 #include "llvm/IR/ProfileSummary.h"
0022 #include "llvm/Pass.h"
0023 #include "llvm/Support/BlockFrequency.h"
0024 #include <memory>
0025 #include <optional>
0026
0027 namespace llvm {
0028 class BlockFrequencyInfo;
0029 class MachineFunction;
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041 class ProfileSummaryInfo {
0042 private:
0043 const Module *M;
0044 std::unique_ptr<ProfileSummary> Summary;
0045 void computeThresholds();
0046
0047 std::optional<uint64_t> HotCountThreshold, ColdCountThreshold;
0048
0049
0050
0051 std::optional<bool> HasHugeWorkingSetSize;
0052
0053
0054
0055 std::optional<bool> HasLargeWorkingSetSize;
0056
0057 std::optional<uint64_t> computeThreshold(int PercentileCutoff) const;
0058
0059
0060 mutable DenseMap<int, uint64_t> ThresholdCache;
0061
0062 public:
0063 ProfileSummaryInfo(const Module &M) : M(&M) { refresh(); }
0064 ProfileSummaryInfo(ProfileSummaryInfo &&Arg) = default;
0065
0066
0067 void refresh();
0068
0069
0070 bool hasProfileSummary() const { return Summary != nullptr; }
0071
0072
0073 bool hasSampleProfile() const {
0074 return hasProfileSummary() &&
0075 Summary->getKind() == ProfileSummary::PSK_Sample;
0076 }
0077
0078
0079 bool hasInstrumentationProfile() const {
0080 return hasProfileSummary() &&
0081 Summary->getKind() == ProfileSummary::PSK_Instr;
0082 }
0083
0084
0085 bool hasCSInstrumentationProfile() const {
0086 return hasProfileSummary() &&
0087 Summary->getKind() == ProfileSummary::PSK_CSInstr;
0088 }
0089
0090
0091
0092
0093
0094
0095
0096 bool invalidate(Module &, const PreservedAnalyses &,
0097 ModuleAnalysisManager::Invalidator &) {
0098 return false;
0099 }
0100
0101
0102 std::optional<uint64_t> getProfileCount(const CallBase &CallInst,
0103 BlockFrequencyInfo *BFI,
0104 bool AllowSynthetic = false) const;
0105
0106 bool hasPartialSampleProfile() const;
0107
0108 bool hasHugeWorkingSetSize() const;
0109
0110 bool hasLargeWorkingSetSize() const;
0111
0112
0113
0114 template <typename FuncT> bool isFunctionEntryHot(const FuncT *F) const {
0115 if (!F || !hasProfileSummary())
0116 return false;
0117 std::optional<Function::ProfileCount> FunctionCount = getEntryCount(F);
0118
0119
0120
0121 return FunctionCount && isHotCount(FunctionCount->getCount());
0122 }
0123
0124
0125 template <typename FuncT, typename BFIT>
0126 bool isFunctionHotInCallGraph(const FuncT *F, BFIT &BFI) const {
0127 if (!F || !hasProfileSummary())
0128 return false;
0129 if (auto FunctionCount = getEntryCount(F))
0130 if (isHotCount(FunctionCount->getCount()))
0131 return true;
0132
0133 if (auto TotalCallCount = getTotalCallCount(F))
0134 if (isHotCount(*TotalCallCount))
0135 return true;
0136
0137 for (const auto &BB : *F)
0138 if (isHotBlock(&BB, &BFI))
0139 return true;
0140 return false;
0141 }
0142
0143 bool isFunctionEntryCold(const Function *F) const;
0144
0145 template <typename FuncT, typename BFIT>
0146 bool isFunctionColdInCallGraph(const FuncT *F, BFIT &BFI) const {
0147 if (!F || !hasProfileSummary())
0148 return false;
0149 if (auto FunctionCount = getEntryCount(F))
0150 if (!isColdCount(FunctionCount->getCount()))
0151 return false;
0152
0153 if (auto TotalCallCount = getTotalCallCount(F))
0154 if (!isColdCount(*TotalCallCount))
0155 return false;
0156
0157 for (const auto &BB : *F)
0158 if (!isColdBlock(&BB, &BFI))
0159 return false;
0160 return true;
0161 }
0162
0163 bool isFunctionHotnessUnknown(const Function &F) const;
0164
0165
0166 template <typename FuncT, typename BFIT>
0167 bool isFunctionHotInCallGraphNthPercentile(int PercentileCutoff,
0168 const FuncT *F, BFIT &BFI) const {
0169 return isFunctionHotOrColdInCallGraphNthPercentile<true, FuncT, BFIT>(
0170 PercentileCutoff, F, BFI);
0171 }
0172
0173
0174 template <typename FuncT, typename BFIT>
0175 bool isFunctionColdInCallGraphNthPercentile(int PercentileCutoff,
0176 const FuncT *F, BFIT &BFI) const {
0177 return isFunctionHotOrColdInCallGraphNthPercentile<false, FuncT, BFIT>(
0178 PercentileCutoff, F, BFI);
0179 }
0180
0181 bool isHotCount(uint64_t C) const;
0182
0183 bool isColdCount(uint64_t C) const;
0184
0185
0186
0187
0188 bool isHotCountNthPercentile(int PercentileCutoff, uint64_t C) const;
0189
0190
0191
0192
0193 bool isColdCountNthPercentile(int PercentileCutoff, uint64_t C) const;
0194
0195
0196 template <typename BBType, typename BFIT>
0197 bool isHotBlock(const BBType *BB, BFIT *BFI) const {
0198 auto Count = BFI->getBlockProfileCount(BB);
0199 return Count && isHotCount(*Count);
0200 }
0201
0202
0203 template <typename BBType, typename BFIT>
0204 bool isColdBlock(const BBType *BB, BFIT *BFI) const {
0205 auto Count = BFI->getBlockProfileCount(BB);
0206 return Count && isColdCount(*Count);
0207 }
0208
0209 template <typename BFIT>
0210 bool isColdBlock(BlockFrequency BlockFreq, const BFIT *BFI) const {
0211 auto Count = BFI->getProfileCountFromFreq(BlockFreq);
0212 return Count && isColdCount(*Count);
0213 }
0214
0215 template <typename BBType, typename BFIT>
0216 bool isHotBlockNthPercentile(int PercentileCutoff, const BBType *BB,
0217 BFIT *BFI) const {
0218 return isHotOrColdBlockNthPercentile<true, BBType, BFIT>(PercentileCutoff,
0219 BB, BFI);
0220 }
0221
0222 template <typename BFIT>
0223 bool isHotBlockNthPercentile(int PercentileCutoff, BlockFrequency BlockFreq,
0224 BFIT *BFI) const {
0225 return isHotOrColdBlockNthPercentile<true, BFIT>(PercentileCutoff,
0226 BlockFreq, BFI);
0227 }
0228
0229
0230
0231
0232
0233 template <typename BBType, typename BFIT>
0234 bool isColdBlockNthPercentile(int PercentileCutoff, const BBType *BB,
0235 BFIT *BFI) const {
0236 return isHotOrColdBlockNthPercentile<false, BBType, BFIT>(PercentileCutoff,
0237 BB, BFI);
0238 }
0239 template <typename BFIT>
0240 bool isColdBlockNthPercentile(int PercentileCutoff, BlockFrequency BlockFreq,
0241 BFIT *BFI) const {
0242 return isHotOrColdBlockNthPercentile<false, BFIT>(PercentileCutoff,
0243 BlockFreq, BFI);
0244 }
0245
0246 bool isHotCallSite(const CallBase &CB, BlockFrequencyInfo *BFI) const;
0247
0248 bool isColdCallSite(const CallBase &CB, BlockFrequencyInfo *BFI) const;
0249
0250
0251 uint64_t getOrCompHotCountThreshold() const;
0252
0253
0254 uint64_t getOrCompColdCountThreshold() const;
0255
0256 uint64_t getHotCountThreshold() const {
0257 return HotCountThreshold.value_or(0);
0258 }
0259
0260 uint64_t getColdCountThreshold() const {
0261 return ColdCountThreshold.value_or(0);
0262 }
0263
0264 private:
0265 template <typename FuncT>
0266 std::optional<uint64_t> getTotalCallCount(const FuncT *F) const {
0267 return std::nullopt;
0268 }
0269
0270 template <bool isHot, typename FuncT, typename BFIT>
0271 bool isFunctionHotOrColdInCallGraphNthPercentile(int PercentileCutoff,
0272 const FuncT *F,
0273 BFIT &FI) const {
0274 if (!F || !hasProfileSummary())
0275 return false;
0276 if (auto FunctionCount = getEntryCount(F)) {
0277 if (isHot &&
0278 isHotCountNthPercentile(PercentileCutoff, FunctionCount->getCount()))
0279 return true;
0280 if (!isHot && !isColdCountNthPercentile(PercentileCutoff,
0281 FunctionCount->getCount()))
0282 return false;
0283 }
0284 if (auto TotalCallCount = getTotalCallCount(F)) {
0285 if (isHot && isHotCountNthPercentile(PercentileCutoff, *TotalCallCount))
0286 return true;
0287 if (!isHot &&
0288 !isColdCountNthPercentile(PercentileCutoff, *TotalCallCount))
0289 return false;
0290 }
0291 for (const auto &BB : *F) {
0292 if (isHot && isHotBlockNthPercentile(PercentileCutoff, &BB, &FI))
0293 return true;
0294 if (!isHot && !isColdBlockNthPercentile(PercentileCutoff, &BB, &FI))
0295 return false;
0296 }
0297 return !isHot;
0298 }
0299
0300 template <bool isHot>
0301 bool isHotOrColdCountNthPercentile(int PercentileCutoff, uint64_t C) const;
0302
0303 template <bool isHot, typename BBType, typename BFIT>
0304 bool isHotOrColdBlockNthPercentile(int PercentileCutoff, const BBType *BB,
0305 BFIT *BFI) const {
0306 auto Count = BFI->getBlockProfileCount(BB);
0307 if (isHot)
0308 return Count && isHotCountNthPercentile(PercentileCutoff, *Count);
0309 else
0310 return Count && isColdCountNthPercentile(PercentileCutoff, *Count);
0311 }
0312
0313 template <bool isHot, typename BFIT>
0314 bool isHotOrColdBlockNthPercentile(int PercentileCutoff,
0315 BlockFrequency BlockFreq,
0316 BFIT *BFI) const {
0317 auto Count = BFI->getProfileCountFromFreq(BlockFreq);
0318 if (isHot)
0319 return Count && isHotCountNthPercentile(PercentileCutoff, *Count);
0320 else
0321 return Count && isColdCountNthPercentile(PercentileCutoff, *Count);
0322 }
0323
0324 template <typename FuncT>
0325 std::optional<Function::ProfileCount> getEntryCount(const FuncT *F) const {
0326 return F->getEntryCount();
0327 }
0328 };
0329
0330 template <>
0331 inline std::optional<uint64_t>
0332 ProfileSummaryInfo::getTotalCallCount<Function>(const Function *F) const {
0333 if (!hasSampleProfile())
0334 return std::nullopt;
0335 uint64_t TotalCallCount = 0;
0336 for (const auto &BB : *F)
0337 for (const auto &I : BB)
0338 if (isa<CallInst>(I) || isa<InvokeInst>(I))
0339 if (auto CallCount = getProfileCount(cast<CallBase>(I), nullptr))
0340 TotalCallCount += *CallCount;
0341 return TotalCallCount;
0342 }
0343
0344
0345
0346
0347 template <>
0348 std::optional<Function::ProfileCount>
0349 ProfileSummaryInfo::getEntryCount<MachineFunction>(
0350 const MachineFunction *F) const;
0351
0352
0353 class ProfileSummaryInfoWrapperPass : public ImmutablePass {
0354 std::unique_ptr<ProfileSummaryInfo> PSI;
0355
0356 public:
0357 static char ID;
0358 ProfileSummaryInfoWrapperPass();
0359
0360 ProfileSummaryInfo &getPSI() { return *PSI; }
0361 const ProfileSummaryInfo &getPSI() const { return *PSI; }
0362
0363 bool doInitialization(Module &M) override;
0364 bool doFinalization(Module &M) override;
0365 void getAnalysisUsage(AnalysisUsage &AU) const override {
0366 AU.setPreservesAll();
0367 }
0368 };
0369
0370
0371 class ProfileSummaryAnalysis
0372 : public AnalysisInfoMixin<ProfileSummaryAnalysis> {
0373 public:
0374 typedef ProfileSummaryInfo Result;
0375
0376 Result run(Module &M, ModuleAnalysisManager &);
0377
0378 private:
0379 friend AnalysisInfoMixin<ProfileSummaryAnalysis>;
0380 static AnalysisKey Key;
0381 };
0382
0383
0384 class ProfileSummaryPrinterPass
0385 : public PassInfoMixin<ProfileSummaryPrinterPass> {
0386 raw_ostream &OS;
0387
0388 public:
0389 explicit ProfileSummaryPrinterPass(raw_ostream &OS) : OS(OS) {}
0390 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
0391 static bool isRequired() { return true; }
0392 };
0393
0394 }
0395
0396 #endif