ProfileSummaryInfo.h 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  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_PROFILE_SUMMARY_INFO_H
  19. #define LLVM_ANALYSIS_PROFILE_SUMMARY_INFO_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. bool isHotCountNthPercentile(int PercentileCutoff, uint64_t C) const;
  130. /// Returns true if count \p C is considered cold with regard to a given
  131. /// cold percentile cutoff value.
  132. bool isColdCountNthPercentile(int PercentileCutoff, uint64_t C) const;
  133. /// Returns true if BasicBlock \p BB is considered hot.
  134. bool isHotBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI) const;
  135. /// Returns true if BasicBlock \p BB is considered cold.
  136. bool isColdBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI) const;
  137. /// Returns true if BasicBlock \p BB is considered hot with regard to a given
  138. /// hot percentile cutoff value.
  139. bool isHotBlockNthPercentile(int PercentileCutoff, const BasicBlock *BB,
  140. BlockFrequencyInfo *BFI) const;
  141. /// Returns true if BasicBlock \p BB is considered cold with regard to a given
  142. /// cold percentile cutoff value.
  143. bool isColdBlockNthPercentile(int PercentileCutoff, const BasicBlock *BB,
  144. BlockFrequencyInfo *BFI) const;
  145. /// Returns true if the call site \p CB is considered hot.
  146. bool isHotCallSite(const CallBase &CB, BlockFrequencyInfo *BFI) const;
  147. /// Returns true if call site \p CB is considered cold.
  148. bool isColdCallSite(const CallBase &CB, BlockFrequencyInfo *BFI) const;
  149. /// Returns HotCountThreshold if set. Recompute HotCountThreshold
  150. /// if not set.
  151. uint64_t getOrCompHotCountThreshold() const;
  152. /// Returns ColdCountThreshold if set. Recompute HotCountThreshold
  153. /// if not set.
  154. uint64_t getOrCompColdCountThreshold() const;
  155. /// Returns HotCountThreshold if set.
  156. uint64_t getHotCountThreshold() const {
  157. return HotCountThreshold ? HotCountThreshold.getValue() : 0;
  158. }
  159. /// Returns ColdCountThreshold if set.
  160. uint64_t getColdCountThreshold() const {
  161. return ColdCountThreshold ? ColdCountThreshold.getValue() : 0;
  162. }
  163. private:
  164. template <bool isHot>
  165. bool isFunctionHotOrColdInCallGraphNthPercentile(
  166. int PercentileCutoff, const Function *F, BlockFrequencyInfo &BFI) const;
  167. template <bool isHot>
  168. bool isHotOrColdCountNthPercentile(int PercentileCutoff, uint64_t C) const;
  169. template <bool isHot>
  170. bool isHotOrColdBlockNthPercentile(int PercentileCutoff,
  171. const BasicBlock *BB,
  172. BlockFrequencyInfo *BFI) const;
  173. };
  174. /// An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
  175. class ProfileSummaryInfoWrapperPass : public ImmutablePass {
  176. std::unique_ptr<ProfileSummaryInfo> PSI;
  177. public:
  178. static char ID;
  179. ProfileSummaryInfoWrapperPass();
  180. ProfileSummaryInfo &getPSI() { return *PSI; }
  181. const ProfileSummaryInfo &getPSI() const { return *PSI; }
  182. bool doInitialization(Module &M) override;
  183. bool doFinalization(Module &M) override;
  184. void getAnalysisUsage(AnalysisUsage &AU) const override {
  185. AU.setPreservesAll();
  186. }
  187. };
  188. /// An analysis pass based on the new PM to deliver ProfileSummaryInfo.
  189. class ProfileSummaryAnalysis
  190. : public AnalysisInfoMixin<ProfileSummaryAnalysis> {
  191. public:
  192. typedef ProfileSummaryInfo Result;
  193. Result run(Module &M, ModuleAnalysisManager &);
  194. private:
  195. friend AnalysisInfoMixin<ProfileSummaryAnalysis>;
  196. static AnalysisKey Key;
  197. };
  198. /// Printer pass that uses \c ProfileSummaryAnalysis.
  199. class ProfileSummaryPrinterPass
  200. : public PassInfoMixin<ProfileSummaryPrinterPass> {
  201. raw_ostream &OS;
  202. public:
  203. explicit ProfileSummaryPrinterPass(raw_ostream &OS) : OS(OS) {}
  204. PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
  205. };
  206. } // end namespace llvm
  207. #endif
  208. #ifdef __GNUC__
  209. #pragma GCC diagnostic pop
  210. #endif