blob: 58b67e74ba5130074615e02d903167d4cc59613b [file] [log] [blame]
Andrew Scull5e1ddfa2018-08-14 10:06:54 +01001//===- llvm/Analysis/ProfileSummaryInfo.h - profile summary ---*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file contains a pass that provides access to profile summary
11// information.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLVM_ANALYSIS_PROFILE_SUMMARY_INFO_H
16#define LLVM_ANALYSIS_PROFILE_SUMMARY_INFO_H
17
18#include "llvm/ADT/ArrayRef.h"
19#include "llvm/ADT/DenseMap.h"
20#include "llvm/ADT/SmallSet.h"
21#include "llvm/IR/Function.h"
22#include "llvm/IR/Instructions.h"
23#include "llvm/IR/PassManager.h"
24#include "llvm/IR/ProfileSummary.h"
25#include "llvm/IR/ValueHandle.h"
26#include "llvm/Pass.h"
27#include <memory>
28
29namespace llvm {
30class BasicBlock;
31class BlockFrequencyInfo;
32class CallSite;
33class ProfileSummary;
Andrew Scullcdfcccc2018-10-05 20:58:37 +010034/// Analysis providing profile information.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010035///
36/// This is an immutable analysis pass that provides ability to query global
37/// (program-level) profile information. The main APIs are isHotCount and
38/// isColdCount that tells whether a given profile count is considered hot/cold
39/// based on the profile summary. This also provides convenience methods to
40/// check whether a function is hot or cold.
41
42// FIXME: Provide convenience methods to determine hotness/coldness of other IR
43// units. This would require making this depend on BFI.
44class ProfileSummaryInfo {
45private:
46 Module &M;
47 std::unique_ptr<ProfileSummary> Summary;
48 bool computeSummary();
49 void computeThresholds();
50 // Count thresholds to answer isHotCount and isColdCount queries.
51 Optional<uint64_t> HotCountThreshold, ColdCountThreshold;
52 // True if the working set size of the code is considered huge,
53 // because the number of profile counts required to reach the hot
54 // percentile is above a huge threshold.
55 Optional<bool> HasHugeWorkingSetSize;
56
57public:
58 ProfileSummaryInfo(Module &M) : M(M) {}
59 ProfileSummaryInfo(ProfileSummaryInfo &&Arg)
60 : M(Arg.M), Summary(std::move(Arg.Summary)) {}
61
Andrew Scullcdfcccc2018-10-05 20:58:37 +010062 /// Returns true if profile summary is available.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010063 bool hasProfileSummary() { return computeSummary(); }
64
Andrew Scullcdfcccc2018-10-05 20:58:37 +010065 /// Returns true if module \c M has sample profile.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010066 bool hasSampleProfile() {
67 return hasProfileSummary() &&
68 Summary->getKind() == ProfileSummary::PSK_Sample;
69 }
70
Andrew Scullcdfcccc2018-10-05 20:58:37 +010071 /// Returns true if module \c M has instrumentation profile.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010072 bool hasInstrumentationProfile() {
73 return hasProfileSummary() &&
74 Summary->getKind() == ProfileSummary::PSK_Instr;
75 }
76
77 /// Handle the invalidation of this information.
78 ///
79 /// When used as a result of \c ProfileSummaryAnalysis this method will be
80 /// called when the module this was computed for changes. Since profile
81 /// summary is immutable after it is annotated on the module, we return false
82 /// here.
83 bool invalidate(Module &, const PreservedAnalyses &,
84 ModuleAnalysisManager::Invalidator &) {
85 return false;
86 }
87
88 /// Returns the profile count for \p CallInst.
89 Optional<uint64_t> getProfileCount(const Instruction *CallInst,
90 BlockFrequencyInfo *BFI);
91 /// Returns true if the working set size of the code is considered huge.
92 bool hasHugeWorkingSetSize();
Andrew Scullcdfcccc2018-10-05 20:58:37 +010093 /// Returns true if \p F has hot function entry.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010094 bool isFunctionEntryHot(const Function *F);
95 /// Returns true if \p F contains hot code.
96 bool isFunctionHotInCallGraph(const Function *F, BlockFrequencyInfo &BFI);
Andrew Scullcdfcccc2018-10-05 20:58:37 +010097 /// Returns true if \p F has cold function entry.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +010098 bool isFunctionEntryCold(const Function *F);
99 /// Returns true if \p F contains only cold code.
100 bool isFunctionColdInCallGraph(const Function *F, BlockFrequencyInfo &BFI);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100101 /// Returns true if \p F is a hot function.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100102 bool isHotCount(uint64_t C);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100103 /// Returns true if count \p C is considered cold.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100104 bool isColdCount(uint64_t C);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100105 /// Returns true if BasicBlock \p B is considered hot.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100106 bool isHotBB(const BasicBlock *B, BlockFrequencyInfo *BFI);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100107 /// Returns true if BasicBlock \p B is considered cold.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100108 bool isColdBB(const BasicBlock *B, BlockFrequencyInfo *BFI);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100109 /// Returns true if CallSite \p CS is considered hot.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100110 bool isHotCallSite(const CallSite &CS, BlockFrequencyInfo *BFI);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100111 /// Returns true if Callsite \p CS is considered cold.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100112 bool isColdCallSite(const CallSite &CS, BlockFrequencyInfo *BFI);
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100113 /// Returns HotCountThreshold if set. Recompute HotCountThreshold
114 /// if not set.
115 uint64_t getOrCompHotCountThreshold();
116 /// Returns ColdCountThreshold if set. Recompute HotCountThreshold
117 /// if not set.
118 uint64_t getOrCompColdCountThreshold();
119 /// Returns HotCountThreshold if set.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100120 uint64_t getHotCountThreshold() {
121 return HotCountThreshold ? HotCountThreshold.getValue() : 0;
122 }
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100123 /// Returns ColdCountThreshold if set.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100124 uint64_t getColdCountThreshold() {
125 return ColdCountThreshold ? ColdCountThreshold.getValue() : 0;
126 }
127};
128
129/// An analysis pass based on legacy pass manager to deliver ProfileSummaryInfo.
130class ProfileSummaryInfoWrapperPass : public ImmutablePass {
131 std::unique_ptr<ProfileSummaryInfo> PSI;
132
133public:
134 static char ID;
135 ProfileSummaryInfoWrapperPass();
136
137 ProfileSummaryInfo *getPSI() {
138 return &*PSI;
139 }
140
141 bool doInitialization(Module &M) override;
142 bool doFinalization(Module &M) override;
143 void getAnalysisUsage(AnalysisUsage &AU) const override {
144 AU.setPreservesAll();
145 }
146};
147
148/// An analysis pass based on the new PM to deliver ProfileSummaryInfo.
149class ProfileSummaryAnalysis
150 : public AnalysisInfoMixin<ProfileSummaryAnalysis> {
151public:
152 typedef ProfileSummaryInfo Result;
153
154 Result run(Module &M, ModuleAnalysisManager &);
155
156private:
157 friend AnalysisInfoMixin<ProfileSummaryAnalysis>;
158 static AnalysisKey Key;
159};
160
Andrew Scullcdfcccc2018-10-05 20:58:37 +0100161/// Printer pass that uses \c ProfileSummaryAnalysis.
Andrew Scull5e1ddfa2018-08-14 10:06:54 +0100162class ProfileSummaryPrinterPass
163 : public PassInfoMixin<ProfileSummaryPrinterPass> {
164 raw_ostream &OS;
165
166public:
167 explicit ProfileSummaryPrinterPass(raw_ostream &OS) : OS(OS) {}
168 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
169};
170
171} // end namespace llvm
172
173#endif