blob: 51d59cf9a9b1c2856deb6606e11dcb52e5902ddc [file] [log] [blame]
Justin Bogneref512b92014-01-06 22:27:43 +00001//===--- CodeGenPGO.h - PGO Instrumentation for LLVM CodeGen ----*- 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// Instrumentation-based profile-guided optimization
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef CLANG_CODEGEN_CODEGENPGO_H
15#define CLANG_CODEGEN_CODEGENPGO_H
16
17#include "CGBuilder.h"
18#include "CodeGenModule.h"
19#include "CodeGenTypes.h"
20#include "clang/Frontend/CodeGenOptions.h"
Justin Bogneref512b92014-01-06 22:27:43 +000021#include "llvm/ADT/StringMap.h"
22#include "llvm/Support/MemoryBuffer.h"
Ahmed Charlesdfca6f92014-03-09 11:36:40 +000023#include <memory>
Justin Bogneref512b92014-01-06 22:27:43 +000024
25namespace clang {
26namespace CodeGen {
27class RegionCounter;
28
Justin Bognerd66a17d2014-03-12 21:06:31 +000029/// The raw counter data from an instrumented PGO binary
30class PGOProfileData {
31private:
32 /// The PGO data
33 std::unique_ptr<llvm::MemoryBuffer> DataBuffer;
34 /// Offsets into DataBuffer for each function's counters
35 llvm::StringMap<unsigned> DataOffsets;
36 /// Execution counts for each function.
37 llvm::StringMap<uint64_t> FunctionCounts;
38 /// The maximal execution count among all functions.
39 uint64_t MaxFunctionCount;
40 CodeGenModule &CGM;
41public:
42 PGOProfileData(CodeGenModule &CGM, std::string Path);
43 /// Fill Counts with the profile data for the given function name. Returns
44 /// false on success.
45 bool getFunctionCounts(StringRef FuncName, std::vector<uint64_t> &Counts);
46 /// Return the maximum of all known function counts.
47 uint64_t getMaximumFunctionCount() { return MaxFunctionCount; }
48};
49
Justin Bogneref512b92014-01-06 22:27:43 +000050/// Per-function PGO state. This class should generally not be used directly,
51/// but instead through the CodeGenFunction and RegionCounter types.
52class CodeGenPGO {
53private:
54 CodeGenModule &CGM;
Bob Wilsonda1ebed2014-03-06 04:55:41 +000055 std::string *FuncName;
Justin Bogneref512b92014-01-06 22:27:43 +000056
57 unsigned NumRegionCounters;
58 llvm::GlobalVariable *RegionCounters;
59 llvm::DenseMap<const Stmt*, unsigned> *RegionCounterMap;
Bob Wilsonbf854f02014-02-17 19:21:09 +000060 llvm::DenseMap<const Stmt*, uint64_t> *StmtCountMap;
Justin Bogneref512b92014-01-06 22:27:43 +000061 std::vector<uint64_t> *RegionCounts;
62 uint64_t CurrentRegionCount;
63
64public:
65 CodeGenPGO(CodeGenModule &CGM)
Bob Wilsonda1ebed2014-03-06 04:55:41 +000066 : CGM(CGM), FuncName(0), NumRegionCounters(0), RegionCounters(0),
67 RegionCounterMap(0), StmtCountMap(0), RegionCounts(0),
68 CurrentRegionCount(0) {}
69 ~CodeGenPGO() {
70 if (FuncName) delete FuncName;
71 }
Justin Bogneref512b92014-01-06 22:27:43 +000072
73 /// Whether or not we have PGO region data for the current function. This is
74 /// false both when we have no data at all and when our data has been
75 /// discarded.
76 bool haveRegionCounts() const { return RegionCounts != 0; }
77
Bob Wilsonda1ebed2014-03-06 04:55:41 +000078 /// Get the string used to identify this function in the profile data.
79 /// For functions with local linkage, this includes the main file name.
80 const StringRef getFuncName() const { return StringRef(*FuncName); }
81
Justin Bogneref512b92014-01-06 22:27:43 +000082 /// Return the counter value of the current region.
83 uint64_t getCurrentRegionCount() const { return CurrentRegionCount; }
Bob Wilsonbf854f02014-02-17 19:21:09 +000084
Justin Bogneref512b92014-01-06 22:27:43 +000085 /// Set the counter value for the current region. This is used to keep track
86 /// of changes to the most recent counter from control flow and non-local
87 /// exits.
88 void setCurrentRegionCount(uint64_t Count) { CurrentRegionCount = Count; }
Bob Wilsonbf854f02014-02-17 19:21:09 +000089
Justin Bogner06bd6d02014-01-13 21:24:18 +000090 /// Indicate that the current region is never reached, and thus should have a
91 /// counter value of zero. This is important so that subsequent regions can
92 /// correctly track their parent counts.
93 void setCurrentRegionUnreachable() { setCurrentRegionCount(0); }
Justin Bogneref512b92014-01-06 22:27:43 +000094
Bob Wilsonbf854f02014-02-17 19:21:09 +000095 /// Check if an execution count is known for a given statement. If so, return
96 /// true and put the value in Count; else return false.
97 bool getStmtCount(const Stmt *S, uint64_t &Count) {
98 if (!StmtCountMap)
99 return false;
100 llvm::DenseMap<const Stmt*, uint64_t>::const_iterator
101 I = StmtCountMap->find(S);
102 if (I == StmtCountMap->end())
103 return false;
104 Count = I->second;
105 return true;
106 }
107
108 /// If the execution count for the current statement is known, record that
109 /// as the current count.
110 void setCurrentStmt(const Stmt *S) {
111 uint64_t Count;
112 if (getStmtCount(S, Count))
113 setCurrentRegionCount(Count);
114 }
115
Justin Bogneref512b92014-01-06 22:27:43 +0000116 /// Calculate branch weights appropriate for PGO data
117 llvm::MDNode *createBranchWeights(uint64_t TrueCount, uint64_t FalseCount);
118 llvm::MDNode *createBranchWeights(ArrayRef<uint64_t> Weights);
Bob Wilsonbf854f02014-02-17 19:21:09 +0000119 llvm::MDNode *createLoopWeights(const Stmt *Cond, RegionCounter &Cnt);
Justin Bogneref512b92014-01-06 22:27:43 +0000120
121 /// Assign counters to regions and configure them for PGO of a given
122 /// function. Does nothing if instrumentation is not enabled and either
123 /// generates global variables or associates PGO data with each of the
124 /// counters depending on whether we are generating or using instrumentation.
Bob Wilsonda1ebed2014-03-06 04:55:41 +0000125 void assignRegionCounters(const Decl *D, llvm::Function *Fn);
Justin Bogneref512b92014-01-06 22:27:43 +0000126 /// Emit code to write counts for a given function to disk, if necessary.
Bob Wilsonda1ebed2014-03-06 04:55:41 +0000127 void emitWriteoutFunction();
Justin Bogneref512b92014-01-06 22:27:43 +0000128 /// Clean up region counter state. Must be called if assignRegionCounters is
129 /// used.
130 void destroyRegionCounters();
131 /// Emit the logic to register region counter write out functions. Returns a
132 /// function that implements this logic.
133 static llvm::Function *emitInitialization(CodeGenModule &CGM);
134
135private:
Bob Wilsonda1ebed2014-03-06 04:55:41 +0000136 void setFuncName(llvm::Function *Fn);
Justin Bogneref512b92014-01-06 22:27:43 +0000137 void mapRegionCounters(const Decl *D);
Bob Wilsonbf854f02014-02-17 19:21:09 +0000138 void computeRegionCounts(const Decl *D);
Justin Bognerd66a17d2014-03-12 21:06:31 +0000139 void applyFunctionAttributes(PGOProfileData *PGOData, llvm::Function *Fn);
140 void loadRegionCounts(PGOProfileData *PGOData);
Justin Bogneref512b92014-01-06 22:27:43 +0000141 void emitCounterVariables();
142
143 /// Emit code to increment the counter at the given index
144 void emitCounterIncrement(CGBuilderTy &Builder, unsigned Counter);
145
146 /// Return the region counter for the given statement. This should only be
147 /// called on statements that have a dedicated counter.
148 unsigned getRegionCounter(const Stmt *S) {
149 if (RegionCounterMap == 0)
150 return 0;
151 return (*RegionCounterMap)[S];
152 }
153
154 /// Return the region count for the counter at the given index.
155 uint64_t getRegionCount(unsigned Counter) {
156 if (!haveRegionCounts())
157 return 0;
158 return (*RegionCounts)[Counter];
159 }
160
161 friend class RegionCounter;
162};
163
164/// A counter for a particular region. This is the primary interface through
165/// which clients manage PGO counters and their values.
166class RegionCounter {
167 CodeGenPGO *PGO;
168 unsigned Counter;
169 uint64_t Count;
170 uint64_t ParentCount;
171 uint64_t RegionCount;
172 int64_t Adjust;
173
174 RegionCounter(CodeGenPGO &PGO, unsigned CounterIndex)
175 : PGO(&PGO), Counter(CounterIndex), Count(PGO.getRegionCount(Counter)),
176 ParentCount(PGO.getCurrentRegionCount()), Adjust(0) {}
177
178public:
179 RegionCounter(CodeGenPGO &PGO, const Stmt *S)
180 : PGO(&PGO), Counter(PGO.getRegionCounter(S)),
181 Count(PGO.getRegionCount(Counter)),
182 ParentCount(PGO.getCurrentRegionCount()), Adjust(0) {}
183
184 /// Get the value of the counter. In most cases this is the number of times
185 /// the region of the counter was entered, but for switch labels it's the
186 /// number of direct jumps to that label.
187 uint64_t getCount() const { return Count; }
Bob Wilsonbf854f02014-02-17 19:21:09 +0000188
Justin Bogneref512b92014-01-06 22:27:43 +0000189 /// Get the value of the counter with adjustments applied. Adjustments occur
Bob Wilsona7b16e02014-02-17 19:21:03 +0000190 /// when control enters or leaves the region abnormally; i.e., if there is a
Justin Bogneref512b92014-01-06 22:27:43 +0000191 /// jump to a label within the region, or if the function can return from
192 /// within the region. The adjusted count, then, is the value of the counter
193 /// at the end of the region.
194 uint64_t getAdjustedCount() const {
Justin Bogneref512b92014-01-06 22:27:43 +0000195 return Count + Adjust;
196 }
Bob Wilsonbf854f02014-02-17 19:21:09 +0000197
Bob Wilsona7b16e02014-02-17 19:21:03 +0000198 /// Get the value of the counter in this region's parent, i.e., the region
199 /// that was active when this region began. This is useful for deriving
200 /// counts in implicitly counted regions, like the false case of a condition
201 /// or the normal exits of a loop.
Justin Bogneref512b92014-01-06 22:27:43 +0000202 uint64_t getParentCount() const { return ParentCount; }
203
Justin Bogneref512b92014-01-06 22:27:43 +0000204 /// Activate the counter by emitting an increment and starting to track
205 /// adjustments. If AddIncomingFallThrough is true, the current region count
206 /// will be added to the counter for the purposes of tracking the region.
207 void beginRegion(CGBuilderTy &Builder, bool AddIncomingFallThrough=false) {
Bob Wilsonbf854f02014-02-17 19:21:09 +0000208 beginRegion(AddIncomingFallThrough);
209 PGO->emitCounterIncrement(Builder, Counter);
210 }
211 void beginRegion(bool AddIncomingFallThrough=false) {
Justin Bogneref512b92014-01-06 22:27:43 +0000212 RegionCount = Count;
213 if (AddIncomingFallThrough)
214 RegionCount += PGO->getCurrentRegionCount();
215 PGO->setCurrentRegionCount(RegionCount);
Justin Bogneref512b92014-01-06 22:27:43 +0000216 }
Bob Wilsonbf854f02014-02-17 19:21:09 +0000217
Justin Bogneref512b92014-01-06 22:27:43 +0000218 /// For counters on boolean branches, begins tracking adjustments for the
219 /// uncounted path.
220 void beginElseRegion() {
221 RegionCount = ParentCount - Count;
222 PGO->setCurrentRegionCount(RegionCount);
223 }
224
Bob Wilsonbf854f02014-02-17 19:21:09 +0000225 /// Reset the current region count.
226 void setCurrentRegionCount(uint64_t CurrentCount) {
227 RegionCount = CurrentCount;
228 PGO->setCurrentRegionCount(RegionCount);
229 }
230
Justin Bogner0718a3a2014-01-13 21:24:22 +0000231 /// Adjust for non-local control flow after emitting a subexpression or
232 /// substatement. This must be called to account for constructs such as gotos,
233 /// labels, and returns, so that we can ensure that our region's count is
234 /// correct in the code that follows.
235 void adjustForControlFlow() {
Justin Bogneref512b92014-01-06 22:27:43 +0000236 Adjust += PGO->getCurrentRegionCount() - RegionCount;
Bob Wilsonbf854f02014-02-17 19:21:09 +0000237 // Reset the region count in case this is called again later.
238 RegionCount = PGO->getCurrentRegionCount();
Justin Bogneref512b92014-01-06 22:27:43 +0000239 }
Bob Wilsonbf854f02014-02-17 19:21:09 +0000240
241 /// Commit all adjustments to the current region. If the region is a loop,
242 /// the LoopAdjust value should be the count of all the breaks and continues
243 /// from the loop, to compensate for those counts being deducted from the
244 /// adjustments for the body of the loop.
245 void applyAdjustmentsToRegion(uint64_t LoopAdjust) {
246 PGO->setCurrentRegionCount(ParentCount + Adjust + LoopAdjust);
Justin Bogneref512b92014-01-06 22:27:43 +0000247 }
248};
249
250} // end namespace CodeGen
251} // end namespace clang
252
253#endif