ProfileSummaryInfo.h 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- llvm/Analysis/ProfileSummaryInfo.h - profile summary ---*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. // This file contains a pass that provides access to profile summary
  15. // information.
  16. //
  17. //===----------------------------------------------------------------------===//
  18. #ifndef LLVM_ANALYSIS_PROFILESUMMARYINFO_H
  19. #define LLVM_ANALYSIS_PROFILESUMMARYINFO_H
  20. #include "llvm/ADT/DenseMap.h"
  21. #include "llvm/IR/PassManager.h"
  22. #include "llvm/IR/ProfileSummary.h"
  23. #include "llvm/Pass.h"
  24. #include <memory>
  25. #include <optional>
  26. namespace llvm {
  27. class BasicBlock;
  28. class BlockFrequencyInfo;
  29. class CallBase;
  30. class Function;
  31. /// Analysis providing profile information.
  32. ///
  33. /// This is an immutable analysis pass that provides ability to query global
  34. /// (program-level) profile information. The main APIs are isHotCount and
  35. /// isColdCount that tells whether a given profile count is considered hot/cold
  36. /// based on the profile summary. This also provides convenience methods to
  37. /// check whether a function is hot or cold.
  38. // FIXME: Provide convenience methods to determine hotness/coldness of other IR
  39. // units. This would require making this depend on BFI.
  40. class ProfileSummaryInfo {
  41. private:
  42. const Module *M;
  43. std::unique_ptr<ProfileSummary> Summary;
  44. void computeThresholds();
  45. // Count thresholds to answer isHotCount and isColdCount queries.
  46. std::optional<uint64_t> HotCountThreshold, ColdCountThreshold;
  47. // True if the working set size of the code is considered huge,
  48. // because the number of profile counts required to reach the hot
  49. // percentile is above a huge threshold.
  50. std::optional<bool> HasHugeWorkingSetSize;
  51. // True if the working set size of the code is considered large,
  52. // because the number of profile counts required to reach the hot
  53. // percentile is above a large threshold.
  54. std::optional<bool> HasLargeWorkingSetSize;
  55. // Compute the threshold for a given cutoff.
  56. std::optional<uint64_t> computeThreshold(int PercentileCutoff) const;
  57. // The map that caches the threshold values. The keys are the percentile
  58. // cutoff values and the values are the corresponding threshold values.
  59. mutable DenseMap<int, uint64_t> ThresholdCache;
  60. public:
  61. ProfileSummaryInfo(const Module &M) : M(&M) { refresh(); }
  62. ProfileSummaryInfo(ProfileSummaryInfo &&Arg) = default;
  63. /// If no summary is present, attempt to refresh.
  64. void refresh();
  65. /// Returns true if profile summary is available.
  66. bool hasProfileSummary() const { return Summary != nullptr; }
  67. /// Returns true if module \c M has sample profile.
  68. bool hasSampleProfile() const {
  69. return hasProfileSummary() &&
  70. Summary->getKind() == ProfileSummary::PSK_Sample;
  71. }
  72. /// Returns true if module \c M has instrumentation profile.
  73. bool hasInstrumentationProfile() const {
  74. return hasProfileSummary() &&
  75. Summary->getKind() == ProfileSummary::PSK_Instr;
  76. }
  77. /// Returns true if module \c M has context sensitive instrumentation profile.
  78. bool hasCSInstrumentationProfile() const {
  79. return hasProfileSummary() &&
  80. Summary->getKind() == ProfileSummary::PSK_CSInstr;
  81. }
  82. /// Handle the invalidation of this information.
  83. ///
  84. /// When used as a result of \c ProfileSummaryAnalysis this method will be
  85. /// called when the module this was computed for changes. Since profile
  86. /// summary is immutable after it is annotated on the module, we return false
  87. /// here.
  88. bool invalidate(Module &, const PreservedAnalyses &,
  89. ModuleAnalysisManager::Invalidator &) {
  90. return false;
  91. }
  92. /// Returns the profile count for \p CallInst.
  93. std::optional<uint64_t> getProfileCount(const CallBase &CallInst,
  94. BlockFrequencyInfo *BFI,
  95. bool AllowSynthetic = false) const;
  96. /// Returns true if module \c M has partial-profile sample profile.
  97. bool hasPartialSampleProfile() const;
  98. /// Returns true if the working set size of the code is considered huge.
  99. bool hasHugeWorkingSetSize() const;
  100. /// Returns true if the working set size of the code is considered large.
  101. bool hasLargeWorkingSetSize() const;
  102. /// Returns true if \p F has hot function entry.
  103. bool isFunctionEntryHot(const Function *F) const;
  104. /// Returns true if \p F contains hot code.
  105. bool isFunctionHotInCallGraph(const Function *F,
  106. BlockFrequencyInfo &BFI) const;
  107. /// Returns true if \p F has cold function entry.
  108. bool isFunctionEntryCold(const Function *F) const;
  109. /// Returns true if \p F contains only cold code.
  110. bool isFunctionColdInCallGraph(const Function *F,
  111. BlockFrequencyInfo &BFI) const;
  112. /// Returns true if the hotness of \p F is unknown.
  113. bool isFunctionHotnessUnknown(const Function &F) const;
  114. /// Returns true if \p F contains hot code with regard to a given hot
  115. /// percentile cutoff value.
  116. bool isFunctionHotInCallGraphNthPercentile(int PercentileCutoff,
  117. const Function *F,
  118. BlockFrequencyInfo &BFI) const;
  119. /// Returns true if \p F contains cold code with regard to a given cold
  120. /// percentile cutoff value.
  121. bool isFunctionColdInCallGraphNthPercentile(int PercentileCutoff,
  122. const Function *F,
  123. BlockFrequencyInfo &BFI) const;
  124. /// Returns true if count \p C is considered hot.
  125. bool isHotCount(uint64_t C) const;
  126. /// Returns true if count \p C is considered cold.
  127. bool isColdCount(uint64_t C) const;
  128. /// Returns true if count \p C is considered hot with regard to a given
  129. /// hot percentile cutoff value.
  130. /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where
  131. /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile.
  132. bool isHotCountNthPercentile(int PercentileCutoff, uint64_t C) const;
  133. /// Returns true if count \p C is considered cold with regard to a given
  134. /// cold percentile cutoff value.
  135. /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where
  136. /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile.
  137. bool isColdCountNthPercentile(int PercentileCutoff, uint64_t C) const;
  138. /// Returns true if BasicBlock \p BB is considered hot.
  139. bool isHotBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI) const;
  140. /// Returns true if BasicBlock \p BB is considered cold.
  141. bool isColdBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI) const;
  142. /// Returns true if BasicBlock \p BB is considered hot with regard to a given
  143. /// hot percentile cutoff value.
  144. /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where
  145. /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile.
  146. bool isHotBlockNthPercentile(int PercentileCutoff, const BasicBlock *BB,
  147. BlockFrequencyInfo *BFI) const;
  148. /// Returns true if BasicBlock \p BB is considered cold with regard to a given
  149. /// cold percentile cutoff value.
  150. /// PercentileCutoff is encoded as a 6 digit decimal fixed point number, where
  151. /// the first two digits are the whole part. E.g. 995000 for 99.5 percentile.
  152. bool isColdBlockNthPercentile(int PercentileCutoff, const BasicBlock *BB,
  153. BlockFrequencyInfo *BFI) const;
  154. /// Returns true if the call site \p CB is considered hot.
  155. bool isHotCallSite(const CallBase &CB, BlockFrequencyInfo *BFI) const;
  156. /// Returns true if call site \p CB is considered cold.
  157. bool isColdCallSite(const CallBase &CB, BlockFrequencyInfo *BFI) const;
  158. /// Returns HotCountThreshold if set. Recompute HotCountThreshold
  159. /// if not set.
  160. uint64_t getOrCompHotCountThreshold() const;
  161. /// Returns ColdCountThreshold if set. Recompute HotCountThreshold
  162. /// if not set.
  163. uint64_t getOrCompColdCountThreshold() const;
  164. /// Returns HotCountThreshold if set.
  165. uint64_t getHotCountThreshold() const {
  166. return HotCountThreshold.value_or(0);
  167. }
  168. /// Returns ColdCountThreshold if set.
  169. uint64_t getColdCountThreshold() const {
  170. return ColdCountThreshold.value_or(0);
  171. }
  172. private:
  173. template <bool isHot>
  174. bool isFunctionHotOrColdInCallGraphNthPercentile(
  175. int PercentileCutoff, const Function *F, BlockFrequencyInfo &BFI) const;
  176. template <bool isHot>
  177. bool isHotOrColdCountNthPercentile(int PercentileCutoff, uint64_t C) const;
  178. template <bool isHot>
  179. bool isHotOrColdBlockNthPercentile(int PercentileCutoff,
  180. const BasicBlock *BB,
  181. BlockFrequencyInfo *BFI) const;
  182. };
  183. /// An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
  184. class ProfileSummaryInfoWrapperPass : public ImmutablePass {
  185. std::unique_ptr<ProfileSummaryInfo> PSI;
  186. public:
  187. static char ID;
  188. ProfileSummaryInfoWrapperPass();
  189. ProfileSummaryInfo &getPSI() { return *PSI; }
  190. const ProfileSummaryInfo &getPSI() const { return *PSI; }
  191. bool doInitialization(Module &M) override;
  192. bool doFinalization(Module &M) override;
  193. void getAnalysisUsage(AnalysisUsage &AU) const override {
  194. AU.setPreservesAll();
  195. }
  196. };
  197. /// An analysis pass based on the new PM to deliver ProfileSummaryInfo.
  198. class ProfileSummaryAnalysis
  199. : public AnalysisInfoMixin<ProfileSummaryAnalysis> {
  200. public:
  201. typedef ProfileSummaryInfo Result;
  202. Result run(Module &M, ModuleAnalysisManager &);
  203. private:
  204. friend AnalysisInfoMixin<ProfileSummaryAnalysis>;
  205. static AnalysisKey Key;
  206. };
  207. /// Printer pass that uses \c ProfileSummaryAnalysis.
  208. class ProfileSummaryPrinterPass
  209. : public PassInfoMixin<ProfileSummaryPrinterPass> {
  210. raw_ostream &OS;
  211. public:
  212. explicit ProfileSummaryPrinterPass(raw_ostream &OS) : OS(OS) {}
  213. PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
  214. };
  215. } // end namespace llvm
  216. #endif
  217. #ifdef __GNUC__
  218. #pragma GCC diagnostic pop
  219. #endif