Home | History | Annotate | Line # | Download | only in Analysis
      1 //===- llvm/Analysis/ProfileSummaryInfo.h - profile summary ---*- C++ -*-===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // This file contains a pass that provides access to profile summary
     10 // information.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 
     14 #ifndef LLVM_ANALYSIS_PROFILESUMMARYINFO_H
     15 #define LLVM_ANALYSIS_PROFILESUMMARYINFO_H
     16 
     17 #include "llvm/ADT/DenseMap.h"
     18 #include "llvm/IR/PassManager.h"
     19 #include "llvm/IR/ProfileSummary.h"
     20 #include "llvm/Pass.h"
     21 #include <memory>
     22 
     23 namespace llvm {
     24 class BasicBlock;
     25 class BlockFrequencyInfo;
     26 class CallBase;
     27 class Function;
     28 
     29 /// Analysis providing profile information.
     30 ///
     31 /// This is an immutable analysis pass that provides ability to query global
     32 /// (program-level) profile information. The main APIs are isHotCount and
     33 /// isColdCount that tells whether a given profile count is considered hot/cold
     34 /// based on the profile summary. This also provides convenience methods to
     35 /// check whether a function is hot or cold.
     36 
     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 
     60 public:
     61   ProfileSummaryInfo(const Module &M) : M(&M) { refresh(); }
     62   ProfileSummaryInfo(ProfileSummaryInfo &&Arg) = default;
     63 
     64   /// If no summary is present, attempt to refresh.
     65   void refresh();
     66 
     67   /// Returns true if profile summary is available.
     68   bool hasProfileSummary() const { return Summary != nullptr; }
     69 
     70   /// Returns true if module \c M has sample profile.
     71   bool hasSampleProfile() const {
     72     return hasProfileSummary() &&
     73            Summary->getKind() == ProfileSummary::PSK_Sample;
     74   }
     75 
     76   /// Returns true if module \c M has instrumentation profile.
     77   bool hasInstrumentationProfile() const {
     78     return hasProfileSummary() &&
     79            Summary->getKind() == ProfileSummary::PSK_Instr;
     80   }
     81 
     82   /// Returns true if module \c M has context sensitive instrumentation profile.
     83   bool hasCSInstrumentationProfile() const {
     84     return hasProfileSummary() &&
     85            Summary->getKind() == ProfileSummary::PSK_CSInstr;
     86   }
     87 
     88   /// Handle the invalidation of this information.
     89   ///
     90   /// When used as a result of \c ProfileSummaryAnalysis this method will be
     91   /// called when the module this was computed for changes. Since profile
     92   /// summary is immutable after it is annotated on the module, we return false
     93   /// here.
     94   bool invalidate(Module &, const PreservedAnalyses &,
     95                   ModuleAnalysisManager::Invalidator &) {
     96     return false;
     97   }
     98 
     99   /// Returns the profile count for \p CallInst.
    100   Optional<uint64_t> getProfileCount(const CallBase &CallInst,
    101                                      BlockFrequencyInfo *BFI,
    102                                      bool AllowSynthetic = false) const;
    103   /// Returns true if module \c M has partial-profile sample profile.
    104   bool hasPartialSampleProfile() const;
    105   /// Returns true if the working set size of the code is considered huge.
    106   bool hasHugeWorkingSetSize() const;
    107   /// Returns true if the working set size of the code is considered large.
    108   bool hasLargeWorkingSetSize() const;
    109   /// Returns true if \p F has hot function entry.
    110   bool isFunctionEntryHot(const Function *F) const;
    111   /// Returns true if \p F contains hot code.
    112   bool isFunctionHotInCallGraph(const Function *F,
    113                                 BlockFrequencyInfo &BFI) const;
    114   /// Returns true if \p F has cold function entry.
    115   bool isFunctionEntryCold(const Function *F) const;
    116   /// Returns true if \p F contains only cold code.
    117   bool isFunctionColdInCallGraph(const Function *F,
    118                                  BlockFrequencyInfo &BFI) const;
    119   /// Returns true if the hotness of \p F is unknown.
    120   bool isFunctionHotnessUnknown(const Function &F) const;
    121   /// Returns true if \p F contains hot code with regard to a given hot
    122   /// percentile cutoff value.
    123   bool isFunctionHotInCallGraphNthPercentile(int PercentileCutoff,
    124                                              const Function *F,
    125                                              BlockFrequencyInfo &BFI) const;
    126   /// Returns true if \p F contains cold code with regard to a given cold
    127   /// percentile cutoff value.
    128   bool isFunctionColdInCallGraphNthPercentile(int PercentileCutoff,
    129                                               const Function *F,
    130                                               BlockFrequencyInfo &BFI) const;
    131   /// Returns true if count \p C is considered hot.
    132   bool isHotCount(uint64_t C) const;
    133   /// Returns true if count \p C is considered cold.
    134   bool isColdCount(uint64_t C) const;
    135   /// Returns true if count \p C is considered hot with regard to a given
    136   /// hot percentile cutoff value.
    137   bool isHotCountNthPercentile(int PercentileCutoff, uint64_t C) const;
    138   /// Returns true if count \p C is considered cold with regard to a given
    139   /// cold percentile cutoff value.
    140   bool isColdCountNthPercentile(int PercentileCutoff, uint64_t C) const;
    141   /// Returns true if BasicBlock \p BB is considered hot.
    142   bool isHotBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI) const;
    143   /// Returns true if BasicBlock \p BB is considered cold.
    144   bool isColdBlock(const BasicBlock *BB, BlockFrequencyInfo *BFI) const;
    145   /// Returns true if BasicBlock \p BB is considered hot with regard to a given
    146   /// hot percentile cutoff value.
    147   bool isHotBlockNthPercentile(int PercentileCutoff, const BasicBlock *BB,
    148                                BlockFrequencyInfo *BFI) const;
    149   /// Returns true if BasicBlock \p BB is considered cold with regard to a given
    150   /// cold percentile cutoff value.
    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 ? HotCountThreshold.getValue() : 0;
    166   }
    167   /// Returns ColdCountThreshold if set.
    168   uint64_t getColdCountThreshold() const {
    169     return ColdCountThreshold ? ColdCountThreshold.getValue() : 0;
    170   }
    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 
    184 /// An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
    185 class ProfileSummaryInfoWrapperPass : public ImmutablePass {
    186   std::unique_ptr<ProfileSummaryInfo> PSI;
    187 
    188 public:
    189   static char ID;
    190   ProfileSummaryInfoWrapperPass();
    191 
    192   ProfileSummaryInfo &getPSI() { return *PSI; }
    193   const ProfileSummaryInfo &getPSI() const { return *PSI; }
    194 
    195   bool doInitialization(Module &M) override;
    196   bool doFinalization(Module &M) override;
    197   void getAnalysisUsage(AnalysisUsage &AU) const override {
    198     AU.setPreservesAll();
    199   }
    200 };
    201 
    202 /// An analysis pass based on the new PM to deliver ProfileSummaryInfo.
    203 class ProfileSummaryAnalysis
    204     : public AnalysisInfoMixin<ProfileSummaryAnalysis> {
    205 public:
    206   typedef ProfileSummaryInfo Result;
    207 
    208   Result run(Module &M, ModuleAnalysisManager &);
    209 
    210 private:
    211   friend AnalysisInfoMixin<ProfileSummaryAnalysis>;
    212   static AnalysisKey Key;
    213 };
    214 
    215 /// Printer pass that uses \c ProfileSummaryAnalysis.
    216 class ProfileSummaryPrinterPass
    217     : public PassInfoMixin<ProfileSummaryPrinterPass> {
    218   raw_ostream &OS;
    219 
    220 public:
    221   explicit ProfileSummaryPrinterPass(raw_ostream &OS) : OS(OS) {}
    222   PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
    223 };
    224 
    225 } // end namespace llvm
    226 
    227 #endif
    228