ProfileSummaryInfo.h 10 KB

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