annotate clang/lib/CodeGen/CodeGenPGO.cpp @ 152:e8a9b4f4d755

pull from 146
author anatofuz
date Wed, 11 Mar 2020 18:29:16 +0900
parents 1d019706d866
children 0572611fdcc8
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===--- CodeGenPGO.cpp - PGO Instrumentation for LLVM CodeGen --*- C++ -*-===//
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
8 //
anatofuz
parents:
diff changeset
9 // Instrumentation-based profile-guided optimization
anatofuz
parents:
diff changeset
10 //
anatofuz
parents:
diff changeset
11 //===----------------------------------------------------------------------===//
anatofuz
parents:
diff changeset
12
anatofuz
parents:
diff changeset
13 #include "CodeGenPGO.h"
anatofuz
parents:
diff changeset
14 #include "CodeGenFunction.h"
anatofuz
parents:
diff changeset
15 #include "CoverageMappingGen.h"
anatofuz
parents:
diff changeset
16 #include "clang/AST/RecursiveASTVisitor.h"
anatofuz
parents:
diff changeset
17 #include "clang/AST/StmtVisitor.h"
anatofuz
parents:
diff changeset
18 #include "llvm/IR/Intrinsics.h"
anatofuz
parents:
diff changeset
19 #include "llvm/IR/MDBuilder.h"
anatofuz
parents:
diff changeset
20 #include "llvm/Support/CommandLine.h"
anatofuz
parents:
diff changeset
21 #include "llvm/Support/Endian.h"
anatofuz
parents:
diff changeset
22 #include "llvm/Support/FileSystem.h"
anatofuz
parents:
diff changeset
23 #include "llvm/Support/MD5.h"
anatofuz
parents:
diff changeset
24
anatofuz
parents:
diff changeset
25 static llvm::cl::opt<bool>
anatofuz
parents:
diff changeset
26 EnableValueProfiling("enable-value-profiling", llvm::cl::ZeroOrMore,
anatofuz
parents:
diff changeset
27 llvm::cl::desc("Enable value profiling"),
anatofuz
parents:
diff changeset
28 llvm::cl::Hidden, llvm::cl::init(false));
anatofuz
parents:
diff changeset
29
anatofuz
parents:
diff changeset
30 using namespace clang;
anatofuz
parents:
diff changeset
31 using namespace CodeGen;
anatofuz
parents:
diff changeset
32
anatofuz
parents:
diff changeset
33 void CodeGenPGO::setFuncName(StringRef Name,
anatofuz
parents:
diff changeset
34 llvm::GlobalValue::LinkageTypes Linkage) {
anatofuz
parents:
diff changeset
35 llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
anatofuz
parents:
diff changeset
36 FuncName = llvm::getPGOFuncName(
anatofuz
parents:
diff changeset
37 Name, Linkage, CGM.getCodeGenOpts().MainFileName,
anatofuz
parents:
diff changeset
38 PGOReader ? PGOReader->getVersion() : llvm::IndexedInstrProf::Version);
anatofuz
parents:
diff changeset
39
anatofuz
parents:
diff changeset
40 // If we're generating a profile, create a variable for the name.
anatofuz
parents:
diff changeset
41 if (CGM.getCodeGenOpts().hasProfileClangInstr())
anatofuz
parents:
diff changeset
42 FuncNameVar = llvm::createPGOFuncNameVar(CGM.getModule(), Linkage, FuncName);
anatofuz
parents:
diff changeset
43 }
anatofuz
parents:
diff changeset
44
anatofuz
parents:
diff changeset
45 void CodeGenPGO::setFuncName(llvm::Function *Fn) {
anatofuz
parents:
diff changeset
46 setFuncName(Fn->getName(), Fn->getLinkage());
anatofuz
parents:
diff changeset
47 // Create PGOFuncName meta data.
anatofuz
parents:
diff changeset
48 llvm::createPGOFuncNameMetadata(*Fn, FuncName);
anatofuz
parents:
diff changeset
49 }
anatofuz
parents:
diff changeset
50
anatofuz
parents:
diff changeset
51 /// The version of the PGO hash algorithm.
anatofuz
parents:
diff changeset
52 enum PGOHashVersion : unsigned {
anatofuz
parents:
diff changeset
53 PGO_HASH_V1,
anatofuz
parents:
diff changeset
54 PGO_HASH_V2,
anatofuz
parents:
diff changeset
55
anatofuz
parents:
diff changeset
56 // Keep this set to the latest hash version.
anatofuz
parents:
diff changeset
57 PGO_HASH_LATEST = PGO_HASH_V2
anatofuz
parents:
diff changeset
58 };
anatofuz
parents:
diff changeset
59
anatofuz
parents:
diff changeset
60 namespace {
anatofuz
parents:
diff changeset
61 /// Stable hasher for PGO region counters.
anatofuz
parents:
diff changeset
62 ///
anatofuz
parents:
diff changeset
63 /// PGOHash produces a stable hash of a given function's control flow.
anatofuz
parents:
diff changeset
64 ///
anatofuz
parents:
diff changeset
65 /// Changing the output of this hash will invalidate all previously generated
anatofuz
parents:
diff changeset
66 /// profiles -- i.e., don't do it.
anatofuz
parents:
diff changeset
67 ///
anatofuz
parents:
diff changeset
68 /// \note When this hash does eventually change (years?), we still need to
anatofuz
parents:
diff changeset
69 /// support old hashes. We'll need to pull in the version number from the
anatofuz
parents:
diff changeset
70 /// profile data format and use the matching hash function.
anatofuz
parents:
diff changeset
71 class PGOHash {
anatofuz
parents:
diff changeset
72 uint64_t Working;
anatofuz
parents:
diff changeset
73 unsigned Count;
anatofuz
parents:
diff changeset
74 PGOHashVersion HashVersion;
anatofuz
parents:
diff changeset
75 llvm::MD5 MD5;
anatofuz
parents:
diff changeset
76
anatofuz
parents:
diff changeset
77 static const int NumBitsPerType = 6;
anatofuz
parents:
diff changeset
78 static const unsigned NumTypesPerWord = sizeof(uint64_t) * 8 / NumBitsPerType;
anatofuz
parents:
diff changeset
79 static const unsigned TooBig = 1u << NumBitsPerType;
anatofuz
parents:
diff changeset
80
anatofuz
parents:
diff changeset
81 public:
anatofuz
parents:
diff changeset
82 /// Hash values for AST nodes.
anatofuz
parents:
diff changeset
83 ///
anatofuz
parents:
diff changeset
84 /// Distinct values for AST nodes that have region counters attached.
anatofuz
parents:
diff changeset
85 ///
anatofuz
parents:
diff changeset
86 /// These values must be stable. All new members must be added at the end,
anatofuz
parents:
diff changeset
87 /// and no members should be removed. Changing the enumeration value for an
anatofuz
parents:
diff changeset
88 /// AST node will affect the hash of every function that contains that node.
anatofuz
parents:
diff changeset
89 enum HashType : unsigned char {
anatofuz
parents:
diff changeset
90 None = 0,
anatofuz
parents:
diff changeset
91 LabelStmt = 1,
anatofuz
parents:
diff changeset
92 WhileStmt,
anatofuz
parents:
diff changeset
93 DoStmt,
anatofuz
parents:
diff changeset
94 ForStmt,
anatofuz
parents:
diff changeset
95 CXXForRangeStmt,
anatofuz
parents:
diff changeset
96 ObjCForCollectionStmt,
anatofuz
parents:
diff changeset
97 SwitchStmt,
anatofuz
parents:
diff changeset
98 CaseStmt,
anatofuz
parents:
diff changeset
99 DefaultStmt,
anatofuz
parents:
diff changeset
100 IfStmt,
anatofuz
parents:
diff changeset
101 CXXTryStmt,
anatofuz
parents:
diff changeset
102 CXXCatchStmt,
anatofuz
parents:
diff changeset
103 ConditionalOperator,
anatofuz
parents:
diff changeset
104 BinaryOperatorLAnd,
anatofuz
parents:
diff changeset
105 BinaryOperatorLOr,
anatofuz
parents:
diff changeset
106 BinaryConditionalOperator,
anatofuz
parents:
diff changeset
107 // The preceding values are available with PGO_HASH_V1.
anatofuz
parents:
diff changeset
108
anatofuz
parents:
diff changeset
109 EndOfScope,
anatofuz
parents:
diff changeset
110 IfThenBranch,
anatofuz
parents:
diff changeset
111 IfElseBranch,
anatofuz
parents:
diff changeset
112 GotoStmt,
anatofuz
parents:
diff changeset
113 IndirectGotoStmt,
anatofuz
parents:
diff changeset
114 BreakStmt,
anatofuz
parents:
diff changeset
115 ContinueStmt,
anatofuz
parents:
diff changeset
116 ReturnStmt,
anatofuz
parents:
diff changeset
117 ThrowExpr,
anatofuz
parents:
diff changeset
118 UnaryOperatorLNot,
anatofuz
parents:
diff changeset
119 BinaryOperatorLT,
anatofuz
parents:
diff changeset
120 BinaryOperatorGT,
anatofuz
parents:
diff changeset
121 BinaryOperatorLE,
anatofuz
parents:
diff changeset
122 BinaryOperatorGE,
anatofuz
parents:
diff changeset
123 BinaryOperatorEQ,
anatofuz
parents:
diff changeset
124 BinaryOperatorNE,
anatofuz
parents:
diff changeset
125 // The preceding values are available with PGO_HASH_V2.
anatofuz
parents:
diff changeset
126
anatofuz
parents:
diff changeset
127 // Keep this last. It's for the static assert that follows.
anatofuz
parents:
diff changeset
128 LastHashType
anatofuz
parents:
diff changeset
129 };
anatofuz
parents:
diff changeset
130 static_assert(LastHashType <= TooBig, "Too many types in HashType");
anatofuz
parents:
diff changeset
131
anatofuz
parents:
diff changeset
132 PGOHash(PGOHashVersion HashVersion)
anatofuz
parents:
diff changeset
133 : Working(0), Count(0), HashVersion(HashVersion), MD5() {}
anatofuz
parents:
diff changeset
134 void combine(HashType Type);
anatofuz
parents:
diff changeset
135 uint64_t finalize();
anatofuz
parents:
diff changeset
136 PGOHashVersion getHashVersion() const { return HashVersion; }
anatofuz
parents:
diff changeset
137 };
anatofuz
parents:
diff changeset
138 const int PGOHash::NumBitsPerType;
anatofuz
parents:
diff changeset
139 const unsigned PGOHash::NumTypesPerWord;
anatofuz
parents:
diff changeset
140 const unsigned PGOHash::TooBig;
anatofuz
parents:
diff changeset
141
anatofuz
parents:
diff changeset
142 /// Get the PGO hash version used in the given indexed profile.
anatofuz
parents:
diff changeset
143 static PGOHashVersion getPGOHashVersion(llvm::IndexedInstrProfReader *PGOReader,
anatofuz
parents:
diff changeset
144 CodeGenModule &CGM) {
anatofuz
parents:
diff changeset
145 if (PGOReader->getVersion() <= 4)
anatofuz
parents:
diff changeset
146 return PGO_HASH_V1;
anatofuz
parents:
diff changeset
147 return PGO_HASH_V2;
anatofuz
parents:
diff changeset
148 }
anatofuz
parents:
diff changeset
149
anatofuz
parents:
diff changeset
150 /// A RecursiveASTVisitor that fills a map of statements to PGO counters.
anatofuz
parents:
diff changeset
151 struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
anatofuz
parents:
diff changeset
152 using Base = RecursiveASTVisitor<MapRegionCounters>;
anatofuz
parents:
diff changeset
153
anatofuz
parents:
diff changeset
154 /// The next counter value to assign.
anatofuz
parents:
diff changeset
155 unsigned NextCounter;
anatofuz
parents:
diff changeset
156 /// The function hash.
anatofuz
parents:
diff changeset
157 PGOHash Hash;
anatofuz
parents:
diff changeset
158 /// The map of statements to counters.
anatofuz
parents:
diff changeset
159 llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
anatofuz
parents:
diff changeset
160
anatofuz
parents:
diff changeset
161 MapRegionCounters(PGOHashVersion HashVersion,
anatofuz
parents:
diff changeset
162 llvm::DenseMap<const Stmt *, unsigned> &CounterMap)
anatofuz
parents:
diff changeset
163 : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap) {}
anatofuz
parents:
diff changeset
164
anatofuz
parents:
diff changeset
165 // Blocks and lambdas are handled as separate functions, so we need not
anatofuz
parents:
diff changeset
166 // traverse them in the parent context.
anatofuz
parents:
diff changeset
167 bool TraverseBlockExpr(BlockExpr *BE) { return true; }
anatofuz
parents:
diff changeset
168 bool TraverseLambdaExpr(LambdaExpr *LE) {
anatofuz
parents:
diff changeset
169 // Traverse the captures, but not the body.
anatofuz
parents:
diff changeset
170 for (auto C : zip(LE->captures(), LE->capture_inits()))
anatofuz
parents:
diff changeset
171 TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C));
anatofuz
parents:
diff changeset
172 return true;
anatofuz
parents:
diff changeset
173 }
anatofuz
parents:
diff changeset
174 bool TraverseCapturedStmt(CapturedStmt *CS) { return true; }
anatofuz
parents:
diff changeset
175
anatofuz
parents:
diff changeset
176 bool VisitDecl(const Decl *D) {
anatofuz
parents:
diff changeset
177 switch (D->getKind()) {
anatofuz
parents:
diff changeset
178 default:
anatofuz
parents:
diff changeset
179 break;
anatofuz
parents:
diff changeset
180 case Decl::Function:
anatofuz
parents:
diff changeset
181 case Decl::CXXMethod:
anatofuz
parents:
diff changeset
182 case Decl::CXXConstructor:
anatofuz
parents:
diff changeset
183 case Decl::CXXDestructor:
anatofuz
parents:
diff changeset
184 case Decl::CXXConversion:
anatofuz
parents:
diff changeset
185 case Decl::ObjCMethod:
anatofuz
parents:
diff changeset
186 case Decl::Block:
anatofuz
parents:
diff changeset
187 case Decl::Captured:
anatofuz
parents:
diff changeset
188 CounterMap[D->getBody()] = NextCounter++;
anatofuz
parents:
diff changeset
189 break;
anatofuz
parents:
diff changeset
190 }
anatofuz
parents:
diff changeset
191 return true;
anatofuz
parents:
diff changeset
192 }
anatofuz
parents:
diff changeset
193
anatofuz
parents:
diff changeset
194 /// If \p S gets a fresh counter, update the counter mappings. Return the
anatofuz
parents:
diff changeset
195 /// V1 hash of \p S.
anatofuz
parents:
diff changeset
196 PGOHash::HashType updateCounterMappings(Stmt *S) {
anatofuz
parents:
diff changeset
197 auto Type = getHashType(PGO_HASH_V1, S);
anatofuz
parents:
diff changeset
198 if (Type != PGOHash::None)
anatofuz
parents:
diff changeset
199 CounterMap[S] = NextCounter++;
anatofuz
parents:
diff changeset
200 return Type;
anatofuz
parents:
diff changeset
201 }
anatofuz
parents:
diff changeset
202
anatofuz
parents:
diff changeset
203 /// Include \p S in the function hash.
anatofuz
parents:
diff changeset
204 bool VisitStmt(Stmt *S) {
anatofuz
parents:
diff changeset
205 auto Type = updateCounterMappings(S);
anatofuz
parents:
diff changeset
206 if (Hash.getHashVersion() != PGO_HASH_V1)
anatofuz
parents:
diff changeset
207 Type = getHashType(Hash.getHashVersion(), S);
anatofuz
parents:
diff changeset
208 if (Type != PGOHash::None)
anatofuz
parents:
diff changeset
209 Hash.combine(Type);
anatofuz
parents:
diff changeset
210 return true;
anatofuz
parents:
diff changeset
211 }
anatofuz
parents:
diff changeset
212
anatofuz
parents:
diff changeset
213 bool TraverseIfStmt(IfStmt *If) {
anatofuz
parents:
diff changeset
214 // If we used the V1 hash, use the default traversal.
anatofuz
parents:
diff changeset
215 if (Hash.getHashVersion() == PGO_HASH_V1)
anatofuz
parents:
diff changeset
216 return Base::TraverseIfStmt(If);
anatofuz
parents:
diff changeset
217
anatofuz
parents:
diff changeset
218 // Otherwise, keep track of which branch we're in while traversing.
anatofuz
parents:
diff changeset
219 VisitStmt(If);
anatofuz
parents:
diff changeset
220 for (Stmt *CS : If->children()) {
anatofuz
parents:
diff changeset
221 if (!CS)
anatofuz
parents:
diff changeset
222 continue;
anatofuz
parents:
diff changeset
223 if (CS == If->getThen())
anatofuz
parents:
diff changeset
224 Hash.combine(PGOHash::IfThenBranch);
anatofuz
parents:
diff changeset
225 else if (CS == If->getElse())
anatofuz
parents:
diff changeset
226 Hash.combine(PGOHash::IfElseBranch);
anatofuz
parents:
diff changeset
227 TraverseStmt(CS);
anatofuz
parents:
diff changeset
228 }
anatofuz
parents:
diff changeset
229 Hash.combine(PGOHash::EndOfScope);
anatofuz
parents:
diff changeset
230 return true;
anatofuz
parents:
diff changeset
231 }
anatofuz
parents:
diff changeset
232
anatofuz
parents:
diff changeset
233 // If the statement type \p N is nestable, and its nesting impacts profile
anatofuz
parents:
diff changeset
234 // stability, define a custom traversal which tracks the end of the statement
anatofuz
parents:
diff changeset
235 // in the hash (provided we're not using the V1 hash).
anatofuz
parents:
diff changeset
236 #define DEFINE_NESTABLE_TRAVERSAL(N) \
anatofuz
parents:
diff changeset
237 bool Traverse##N(N *S) { \
anatofuz
parents:
diff changeset
238 Base::Traverse##N(S); \
anatofuz
parents:
diff changeset
239 if (Hash.getHashVersion() != PGO_HASH_V1) \
anatofuz
parents:
diff changeset
240 Hash.combine(PGOHash::EndOfScope); \
anatofuz
parents:
diff changeset
241 return true; \
anatofuz
parents:
diff changeset
242 }
anatofuz
parents:
diff changeset
243
anatofuz
parents:
diff changeset
244 DEFINE_NESTABLE_TRAVERSAL(WhileStmt)
anatofuz
parents:
diff changeset
245 DEFINE_NESTABLE_TRAVERSAL(DoStmt)
anatofuz
parents:
diff changeset
246 DEFINE_NESTABLE_TRAVERSAL(ForStmt)
anatofuz
parents:
diff changeset
247 DEFINE_NESTABLE_TRAVERSAL(CXXForRangeStmt)
anatofuz
parents:
diff changeset
248 DEFINE_NESTABLE_TRAVERSAL(ObjCForCollectionStmt)
anatofuz
parents:
diff changeset
249 DEFINE_NESTABLE_TRAVERSAL(CXXTryStmt)
anatofuz
parents:
diff changeset
250 DEFINE_NESTABLE_TRAVERSAL(CXXCatchStmt)
anatofuz
parents:
diff changeset
251
anatofuz
parents:
diff changeset
252 /// Get version \p HashVersion of the PGO hash for \p S.
anatofuz
parents:
diff changeset
253 PGOHash::HashType getHashType(PGOHashVersion HashVersion, const Stmt *S) {
anatofuz
parents:
diff changeset
254 switch (S->getStmtClass()) {
anatofuz
parents:
diff changeset
255 default:
anatofuz
parents:
diff changeset
256 break;
anatofuz
parents:
diff changeset
257 case Stmt::LabelStmtClass:
anatofuz
parents:
diff changeset
258 return PGOHash::LabelStmt;
anatofuz
parents:
diff changeset
259 case Stmt::WhileStmtClass:
anatofuz
parents:
diff changeset
260 return PGOHash::WhileStmt;
anatofuz
parents:
diff changeset
261 case Stmt::DoStmtClass:
anatofuz
parents:
diff changeset
262 return PGOHash::DoStmt;
anatofuz
parents:
diff changeset
263 case Stmt::ForStmtClass:
anatofuz
parents:
diff changeset
264 return PGOHash::ForStmt;
anatofuz
parents:
diff changeset
265 case Stmt::CXXForRangeStmtClass:
anatofuz
parents:
diff changeset
266 return PGOHash::CXXForRangeStmt;
anatofuz
parents:
diff changeset
267 case Stmt::ObjCForCollectionStmtClass:
anatofuz
parents:
diff changeset
268 return PGOHash::ObjCForCollectionStmt;
anatofuz
parents:
diff changeset
269 case Stmt::SwitchStmtClass:
anatofuz
parents:
diff changeset
270 return PGOHash::SwitchStmt;
anatofuz
parents:
diff changeset
271 case Stmt::CaseStmtClass:
anatofuz
parents:
diff changeset
272 return PGOHash::CaseStmt;
anatofuz
parents:
diff changeset
273 case Stmt::DefaultStmtClass:
anatofuz
parents:
diff changeset
274 return PGOHash::DefaultStmt;
anatofuz
parents:
diff changeset
275 case Stmt::IfStmtClass:
anatofuz
parents:
diff changeset
276 return PGOHash::IfStmt;
anatofuz
parents:
diff changeset
277 case Stmt::CXXTryStmtClass:
anatofuz
parents:
diff changeset
278 return PGOHash::CXXTryStmt;
anatofuz
parents:
diff changeset
279 case Stmt::CXXCatchStmtClass:
anatofuz
parents:
diff changeset
280 return PGOHash::CXXCatchStmt;
anatofuz
parents:
diff changeset
281 case Stmt::ConditionalOperatorClass:
anatofuz
parents:
diff changeset
282 return PGOHash::ConditionalOperator;
anatofuz
parents:
diff changeset
283 case Stmt::BinaryConditionalOperatorClass:
anatofuz
parents:
diff changeset
284 return PGOHash::BinaryConditionalOperator;
anatofuz
parents:
diff changeset
285 case Stmt::BinaryOperatorClass: {
anatofuz
parents:
diff changeset
286 const BinaryOperator *BO = cast<BinaryOperator>(S);
anatofuz
parents:
diff changeset
287 if (BO->getOpcode() == BO_LAnd)
anatofuz
parents:
diff changeset
288 return PGOHash::BinaryOperatorLAnd;
anatofuz
parents:
diff changeset
289 if (BO->getOpcode() == BO_LOr)
anatofuz
parents:
diff changeset
290 return PGOHash::BinaryOperatorLOr;
anatofuz
parents:
diff changeset
291 if (HashVersion == PGO_HASH_V2) {
anatofuz
parents:
diff changeset
292 switch (BO->getOpcode()) {
anatofuz
parents:
diff changeset
293 default:
anatofuz
parents:
diff changeset
294 break;
anatofuz
parents:
diff changeset
295 case BO_LT:
anatofuz
parents:
diff changeset
296 return PGOHash::BinaryOperatorLT;
anatofuz
parents:
diff changeset
297 case BO_GT:
anatofuz
parents:
diff changeset
298 return PGOHash::BinaryOperatorGT;
anatofuz
parents:
diff changeset
299 case BO_LE:
anatofuz
parents:
diff changeset
300 return PGOHash::BinaryOperatorLE;
anatofuz
parents:
diff changeset
301 case BO_GE:
anatofuz
parents:
diff changeset
302 return PGOHash::BinaryOperatorGE;
anatofuz
parents:
diff changeset
303 case BO_EQ:
anatofuz
parents:
diff changeset
304 return PGOHash::BinaryOperatorEQ;
anatofuz
parents:
diff changeset
305 case BO_NE:
anatofuz
parents:
diff changeset
306 return PGOHash::BinaryOperatorNE;
anatofuz
parents:
diff changeset
307 }
anatofuz
parents:
diff changeset
308 }
anatofuz
parents:
diff changeset
309 break;
anatofuz
parents:
diff changeset
310 }
anatofuz
parents:
diff changeset
311 }
anatofuz
parents:
diff changeset
312
anatofuz
parents:
diff changeset
313 if (HashVersion == PGO_HASH_V2) {
anatofuz
parents:
diff changeset
314 switch (S->getStmtClass()) {
anatofuz
parents:
diff changeset
315 default:
anatofuz
parents:
diff changeset
316 break;
anatofuz
parents:
diff changeset
317 case Stmt::GotoStmtClass:
anatofuz
parents:
diff changeset
318 return PGOHash::GotoStmt;
anatofuz
parents:
diff changeset
319 case Stmt::IndirectGotoStmtClass:
anatofuz
parents:
diff changeset
320 return PGOHash::IndirectGotoStmt;
anatofuz
parents:
diff changeset
321 case Stmt::BreakStmtClass:
anatofuz
parents:
diff changeset
322 return PGOHash::BreakStmt;
anatofuz
parents:
diff changeset
323 case Stmt::ContinueStmtClass:
anatofuz
parents:
diff changeset
324 return PGOHash::ContinueStmt;
anatofuz
parents:
diff changeset
325 case Stmt::ReturnStmtClass:
anatofuz
parents:
diff changeset
326 return PGOHash::ReturnStmt;
anatofuz
parents:
diff changeset
327 case Stmt::CXXThrowExprClass:
anatofuz
parents:
diff changeset
328 return PGOHash::ThrowExpr;
anatofuz
parents:
diff changeset
329 case Stmt::UnaryOperatorClass: {
anatofuz
parents:
diff changeset
330 const UnaryOperator *UO = cast<UnaryOperator>(S);
anatofuz
parents:
diff changeset
331 if (UO->getOpcode() == UO_LNot)
anatofuz
parents:
diff changeset
332 return PGOHash::UnaryOperatorLNot;
anatofuz
parents:
diff changeset
333 break;
anatofuz
parents:
diff changeset
334 }
anatofuz
parents:
diff changeset
335 }
anatofuz
parents:
diff changeset
336 }
anatofuz
parents:
diff changeset
337
anatofuz
parents:
diff changeset
338 return PGOHash::None;
anatofuz
parents:
diff changeset
339 }
anatofuz
parents:
diff changeset
340 };
anatofuz
parents:
diff changeset
341
anatofuz
parents:
diff changeset
342 /// A StmtVisitor that propagates the raw counts through the AST and
anatofuz
parents:
diff changeset
343 /// records the count at statements where the value may change.
anatofuz
parents:
diff changeset
344 struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
anatofuz
parents:
diff changeset
345 /// PGO state.
anatofuz
parents:
diff changeset
346 CodeGenPGO &PGO;
anatofuz
parents:
diff changeset
347
anatofuz
parents:
diff changeset
348 /// A flag that is set when the current count should be recorded on the
anatofuz
parents:
diff changeset
349 /// next statement, such as at the exit of a loop.
anatofuz
parents:
diff changeset
350 bool RecordNextStmtCount;
anatofuz
parents:
diff changeset
351
anatofuz
parents:
diff changeset
352 /// The count at the current location in the traversal.
anatofuz
parents:
diff changeset
353 uint64_t CurrentCount;
anatofuz
parents:
diff changeset
354
anatofuz
parents:
diff changeset
355 /// The map of statements to count values.
anatofuz
parents:
diff changeset
356 llvm::DenseMap<const Stmt *, uint64_t> &CountMap;
anatofuz
parents:
diff changeset
357
anatofuz
parents:
diff changeset
358 /// BreakContinueStack - Keep counts of breaks and continues inside loops.
anatofuz
parents:
diff changeset
359 struct BreakContinue {
anatofuz
parents:
diff changeset
360 uint64_t BreakCount;
anatofuz
parents:
diff changeset
361 uint64_t ContinueCount;
anatofuz
parents:
diff changeset
362 BreakContinue() : BreakCount(0), ContinueCount(0) {}
anatofuz
parents:
diff changeset
363 };
anatofuz
parents:
diff changeset
364 SmallVector<BreakContinue, 8> BreakContinueStack;
anatofuz
parents:
diff changeset
365
anatofuz
parents:
diff changeset
366 ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &CountMap,
anatofuz
parents:
diff changeset
367 CodeGenPGO &PGO)
anatofuz
parents:
diff changeset
368 : PGO(PGO), RecordNextStmtCount(false), CountMap(CountMap) {}
anatofuz
parents:
diff changeset
369
anatofuz
parents:
diff changeset
370 void RecordStmtCount(const Stmt *S) {
anatofuz
parents:
diff changeset
371 if (RecordNextStmtCount) {
anatofuz
parents:
diff changeset
372 CountMap[S] = CurrentCount;
anatofuz
parents:
diff changeset
373 RecordNextStmtCount = false;
anatofuz
parents:
diff changeset
374 }
anatofuz
parents:
diff changeset
375 }
anatofuz
parents:
diff changeset
376
anatofuz
parents:
diff changeset
377 /// Set and return the current count.
anatofuz
parents:
diff changeset
378 uint64_t setCount(uint64_t Count) {
anatofuz
parents:
diff changeset
379 CurrentCount = Count;
anatofuz
parents:
diff changeset
380 return Count;
anatofuz
parents:
diff changeset
381 }
anatofuz
parents:
diff changeset
382
anatofuz
parents:
diff changeset
383 void VisitStmt(const Stmt *S) {
anatofuz
parents:
diff changeset
384 RecordStmtCount(S);
anatofuz
parents:
diff changeset
385 for (const Stmt *Child : S->children())
anatofuz
parents:
diff changeset
386 if (Child)
anatofuz
parents:
diff changeset
387 this->Visit(Child);
anatofuz
parents:
diff changeset
388 }
anatofuz
parents:
diff changeset
389
anatofuz
parents:
diff changeset
390 void VisitFunctionDecl(const FunctionDecl *D) {
anatofuz
parents:
diff changeset
391 // Counter tracks entry to the function body.
anatofuz
parents:
diff changeset
392 uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
anatofuz
parents:
diff changeset
393 CountMap[D->getBody()] = BodyCount;
anatofuz
parents:
diff changeset
394 Visit(D->getBody());
anatofuz
parents:
diff changeset
395 }
anatofuz
parents:
diff changeset
396
anatofuz
parents:
diff changeset
397 // Skip lambda expressions. We visit these as FunctionDecls when we're
anatofuz
parents:
diff changeset
398 // generating them and aren't interested in the body when generating a
anatofuz
parents:
diff changeset
399 // parent context.
anatofuz
parents:
diff changeset
400 void VisitLambdaExpr(const LambdaExpr *LE) {}
anatofuz
parents:
diff changeset
401
anatofuz
parents:
diff changeset
402 void VisitCapturedDecl(const CapturedDecl *D) {
anatofuz
parents:
diff changeset
403 // Counter tracks entry to the capture body.
anatofuz
parents:
diff changeset
404 uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
anatofuz
parents:
diff changeset
405 CountMap[D->getBody()] = BodyCount;
anatofuz
parents:
diff changeset
406 Visit(D->getBody());
anatofuz
parents:
diff changeset
407 }
anatofuz
parents:
diff changeset
408
anatofuz
parents:
diff changeset
409 void VisitObjCMethodDecl(const ObjCMethodDecl *D) {
anatofuz
parents:
diff changeset
410 // Counter tracks entry to the method body.
anatofuz
parents:
diff changeset
411 uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
anatofuz
parents:
diff changeset
412 CountMap[D->getBody()] = BodyCount;
anatofuz
parents:
diff changeset
413 Visit(D->getBody());
anatofuz
parents:
diff changeset
414 }
anatofuz
parents:
diff changeset
415
anatofuz
parents:
diff changeset
416 void VisitBlockDecl(const BlockDecl *D) {
anatofuz
parents:
diff changeset
417 // Counter tracks entry to the block body.
anatofuz
parents:
diff changeset
418 uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
anatofuz
parents:
diff changeset
419 CountMap[D->getBody()] = BodyCount;
anatofuz
parents:
diff changeset
420 Visit(D->getBody());
anatofuz
parents:
diff changeset
421 }
anatofuz
parents:
diff changeset
422
anatofuz
parents:
diff changeset
423 void VisitReturnStmt(const ReturnStmt *S) {
anatofuz
parents:
diff changeset
424 RecordStmtCount(S);
anatofuz
parents:
diff changeset
425 if (S->getRetValue())
anatofuz
parents:
diff changeset
426 Visit(S->getRetValue());
anatofuz
parents:
diff changeset
427 CurrentCount = 0;
anatofuz
parents:
diff changeset
428 RecordNextStmtCount = true;
anatofuz
parents:
diff changeset
429 }
anatofuz
parents:
diff changeset
430
anatofuz
parents:
diff changeset
431 void VisitCXXThrowExpr(const CXXThrowExpr *E) {
anatofuz
parents:
diff changeset
432 RecordStmtCount(E);
anatofuz
parents:
diff changeset
433 if (E->getSubExpr())
anatofuz
parents:
diff changeset
434 Visit(E->getSubExpr());
anatofuz
parents:
diff changeset
435 CurrentCount = 0;
anatofuz
parents:
diff changeset
436 RecordNextStmtCount = true;
anatofuz
parents:
diff changeset
437 }
anatofuz
parents:
diff changeset
438
anatofuz
parents:
diff changeset
439 void VisitGotoStmt(const GotoStmt *S) {
anatofuz
parents:
diff changeset
440 RecordStmtCount(S);
anatofuz
parents:
diff changeset
441 CurrentCount = 0;
anatofuz
parents:
diff changeset
442 RecordNextStmtCount = true;
anatofuz
parents:
diff changeset
443 }
anatofuz
parents:
diff changeset
444
anatofuz
parents:
diff changeset
445 void VisitLabelStmt(const LabelStmt *S) {
anatofuz
parents:
diff changeset
446 RecordNextStmtCount = false;
anatofuz
parents:
diff changeset
447 // Counter tracks the block following the label.
anatofuz
parents:
diff changeset
448 uint64_t BlockCount = setCount(PGO.getRegionCount(S));
anatofuz
parents:
diff changeset
449 CountMap[S] = BlockCount;
anatofuz
parents:
diff changeset
450 Visit(S->getSubStmt());
anatofuz
parents:
diff changeset
451 }
anatofuz
parents:
diff changeset
452
anatofuz
parents:
diff changeset
453 void VisitBreakStmt(const BreakStmt *S) {
anatofuz
parents:
diff changeset
454 RecordStmtCount(S);
anatofuz
parents:
diff changeset
455 assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
anatofuz
parents:
diff changeset
456 BreakContinueStack.back().BreakCount += CurrentCount;
anatofuz
parents:
diff changeset
457 CurrentCount = 0;
anatofuz
parents:
diff changeset
458 RecordNextStmtCount = true;
anatofuz
parents:
diff changeset
459 }
anatofuz
parents:
diff changeset
460
anatofuz
parents:
diff changeset
461 void VisitContinueStmt(const ContinueStmt *S) {
anatofuz
parents:
diff changeset
462 RecordStmtCount(S);
anatofuz
parents:
diff changeset
463 assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
anatofuz
parents:
diff changeset
464 BreakContinueStack.back().ContinueCount += CurrentCount;
anatofuz
parents:
diff changeset
465 CurrentCount = 0;
anatofuz
parents:
diff changeset
466 RecordNextStmtCount = true;
anatofuz
parents:
diff changeset
467 }
anatofuz
parents:
diff changeset
468
anatofuz
parents:
diff changeset
469 void VisitWhileStmt(const WhileStmt *S) {
anatofuz
parents:
diff changeset
470 RecordStmtCount(S);
anatofuz
parents:
diff changeset
471 uint64_t ParentCount = CurrentCount;
anatofuz
parents:
diff changeset
472
anatofuz
parents:
diff changeset
473 BreakContinueStack.push_back(BreakContinue());
anatofuz
parents:
diff changeset
474 // Visit the body region first so the break/continue adjustments can be
anatofuz
parents:
diff changeset
475 // included when visiting the condition.
anatofuz
parents:
diff changeset
476 uint64_t BodyCount = setCount(PGO.getRegionCount(S));
anatofuz
parents:
diff changeset
477 CountMap[S->getBody()] = CurrentCount;
anatofuz
parents:
diff changeset
478 Visit(S->getBody());
anatofuz
parents:
diff changeset
479 uint64_t BackedgeCount = CurrentCount;
anatofuz
parents:
diff changeset
480
anatofuz
parents:
diff changeset
481 // ...then go back and propagate counts through the condition. The count
anatofuz
parents:
diff changeset
482 // at the start of the condition is the sum of the incoming edges,
anatofuz
parents:
diff changeset
483 // the backedge from the end of the loop body, and the edges from
anatofuz
parents:
diff changeset
484 // continue statements.
anatofuz
parents:
diff changeset
485 BreakContinue BC = BreakContinueStack.pop_back_val();
anatofuz
parents:
diff changeset
486 uint64_t CondCount =
anatofuz
parents:
diff changeset
487 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
anatofuz
parents:
diff changeset
488 CountMap[S->getCond()] = CondCount;
anatofuz
parents:
diff changeset
489 Visit(S->getCond());
anatofuz
parents:
diff changeset
490 setCount(BC.BreakCount + CondCount - BodyCount);
anatofuz
parents:
diff changeset
491 RecordNextStmtCount = true;
anatofuz
parents:
diff changeset
492 }
anatofuz
parents:
diff changeset
493
anatofuz
parents:
diff changeset
494 void VisitDoStmt(const DoStmt *S) {
anatofuz
parents:
diff changeset
495 RecordStmtCount(S);
anatofuz
parents:
diff changeset
496 uint64_t LoopCount = PGO.getRegionCount(S);
anatofuz
parents:
diff changeset
497
anatofuz
parents:
diff changeset
498 BreakContinueStack.push_back(BreakContinue());
anatofuz
parents:
diff changeset
499 // The count doesn't include the fallthrough from the parent scope. Add it.
anatofuz
parents:
diff changeset
500 uint64_t BodyCount = setCount(LoopCount + CurrentCount);
anatofuz
parents:
diff changeset
501 CountMap[S->getBody()] = BodyCount;
anatofuz
parents:
diff changeset
502 Visit(S->getBody());
anatofuz
parents:
diff changeset
503 uint64_t BackedgeCount = CurrentCount;
anatofuz
parents:
diff changeset
504
anatofuz
parents:
diff changeset
505 BreakContinue BC = BreakContinueStack.pop_back_val();
anatofuz
parents:
diff changeset
506 // The count at the start of the condition is equal to the count at the
anatofuz
parents:
diff changeset
507 // end of the body, plus any continues.
anatofuz
parents:
diff changeset
508 uint64_t CondCount = setCount(BackedgeCount + BC.ContinueCount);
anatofuz
parents:
diff changeset
509 CountMap[S->getCond()] = CondCount;
anatofuz
parents:
diff changeset
510 Visit(S->getCond());
anatofuz
parents:
diff changeset
511 setCount(BC.BreakCount + CondCount - LoopCount);
anatofuz
parents:
diff changeset
512 RecordNextStmtCount = true;
anatofuz
parents:
diff changeset
513 }
anatofuz
parents:
diff changeset
514
anatofuz
parents:
diff changeset
515 void VisitForStmt(const ForStmt *S) {
anatofuz
parents:
diff changeset
516 RecordStmtCount(S);
anatofuz
parents:
diff changeset
517 if (S->getInit())
anatofuz
parents:
diff changeset
518 Visit(S->getInit());
anatofuz
parents:
diff changeset
519
anatofuz
parents:
diff changeset
520 uint64_t ParentCount = CurrentCount;
anatofuz
parents:
diff changeset
521
anatofuz
parents:
diff changeset
522 BreakContinueStack.push_back(BreakContinue());
anatofuz
parents:
diff changeset
523 // Visit the body region first. (This is basically the same as a while
anatofuz
parents:
diff changeset
524 // loop; see further comments in VisitWhileStmt.)
anatofuz
parents:
diff changeset
525 uint64_t BodyCount = setCount(PGO.getRegionCount(S));
anatofuz
parents:
diff changeset
526 CountMap[S->getBody()] = BodyCount;
anatofuz
parents:
diff changeset
527 Visit(S->getBody());
anatofuz
parents:
diff changeset
528 uint64_t BackedgeCount = CurrentCount;
anatofuz
parents:
diff changeset
529 BreakContinue BC = BreakContinueStack.pop_back_val();
anatofuz
parents:
diff changeset
530
anatofuz
parents:
diff changeset
531 // The increment is essentially part of the body but it needs to include
anatofuz
parents:
diff changeset
532 // the count for all the continue statements.
anatofuz
parents:
diff changeset
533 if (S->getInc()) {
anatofuz
parents:
diff changeset
534 uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
anatofuz
parents:
diff changeset
535 CountMap[S->getInc()] = IncCount;
anatofuz
parents:
diff changeset
536 Visit(S->getInc());
anatofuz
parents:
diff changeset
537 }
anatofuz
parents:
diff changeset
538
anatofuz
parents:
diff changeset
539 // ...then go back and propagate counts through the condition.
anatofuz
parents:
diff changeset
540 uint64_t CondCount =
anatofuz
parents:
diff changeset
541 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
anatofuz
parents:
diff changeset
542 if (S->getCond()) {
anatofuz
parents:
diff changeset
543 CountMap[S->getCond()] = CondCount;
anatofuz
parents:
diff changeset
544 Visit(S->getCond());
anatofuz
parents:
diff changeset
545 }
anatofuz
parents:
diff changeset
546 setCount(BC.BreakCount + CondCount - BodyCount);
anatofuz
parents:
diff changeset
547 RecordNextStmtCount = true;
anatofuz
parents:
diff changeset
548 }
anatofuz
parents:
diff changeset
549
anatofuz
parents:
diff changeset
550 void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
anatofuz
parents:
diff changeset
551 RecordStmtCount(S);
anatofuz
parents:
diff changeset
552 if (S->getInit())
anatofuz
parents:
diff changeset
553 Visit(S->getInit());
anatofuz
parents:
diff changeset
554 Visit(S->getLoopVarStmt());
anatofuz
parents:
diff changeset
555 Visit(S->getRangeStmt());
anatofuz
parents:
diff changeset
556 Visit(S->getBeginStmt());
anatofuz
parents:
diff changeset
557 Visit(S->getEndStmt());
anatofuz
parents:
diff changeset
558
anatofuz
parents:
diff changeset
559 uint64_t ParentCount = CurrentCount;
anatofuz
parents:
diff changeset
560 BreakContinueStack.push_back(BreakContinue());
anatofuz
parents:
diff changeset
561 // Visit the body region first. (This is basically the same as a while
anatofuz
parents:
diff changeset
562 // loop; see further comments in VisitWhileStmt.)
anatofuz
parents:
diff changeset
563 uint64_t BodyCount = setCount(PGO.getRegionCount(S));
anatofuz
parents:
diff changeset
564 CountMap[S->getBody()] = BodyCount;
anatofuz
parents:
diff changeset
565 Visit(S->getBody());
anatofuz
parents:
diff changeset
566 uint64_t BackedgeCount = CurrentCount;
anatofuz
parents:
diff changeset
567 BreakContinue BC = BreakContinueStack.pop_back_val();
anatofuz
parents:
diff changeset
568
anatofuz
parents:
diff changeset
569 // The increment is essentially part of the body but it needs to include
anatofuz
parents:
diff changeset
570 // the count for all the continue statements.
anatofuz
parents:
diff changeset
571 uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
anatofuz
parents:
diff changeset
572 CountMap[S->getInc()] = IncCount;
anatofuz
parents:
diff changeset
573 Visit(S->getInc());
anatofuz
parents:
diff changeset
574
anatofuz
parents:
diff changeset
575 // ...then go back and propagate counts through the condition.
anatofuz
parents:
diff changeset
576 uint64_t CondCount =
anatofuz
parents:
diff changeset
577 setCount(ParentCount + BackedgeCount + BC.ContinueCount);
anatofuz
parents:
diff changeset
578 CountMap[S->getCond()] = CondCount;
anatofuz
parents:
diff changeset
579 Visit(S->getCond());
anatofuz
parents:
diff changeset
580 setCount(BC.BreakCount + CondCount - BodyCount);
anatofuz
parents:
diff changeset
581 RecordNextStmtCount = true;
anatofuz
parents:
diff changeset
582 }
anatofuz
parents:
diff changeset
583
anatofuz
parents:
diff changeset
584 void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
anatofuz
parents:
diff changeset
585 RecordStmtCount(S);
anatofuz
parents:
diff changeset
586 Visit(S->getElement());
anatofuz
parents:
diff changeset
587 uint64_t ParentCount = CurrentCount;
anatofuz
parents:
diff changeset
588 BreakContinueStack.push_back(BreakContinue());
anatofuz
parents:
diff changeset
589 // Counter tracks the body of the loop.
anatofuz
parents:
diff changeset
590 uint64_t BodyCount = setCount(PGO.getRegionCount(S));
anatofuz
parents:
diff changeset
591 CountMap[S->getBody()] = BodyCount;
anatofuz
parents:
diff changeset
592 Visit(S->getBody());
anatofuz
parents:
diff changeset
593 uint64_t BackedgeCount = CurrentCount;
anatofuz
parents:
diff changeset
594 BreakContinue BC = BreakContinueStack.pop_back_val();
anatofuz
parents:
diff changeset
595
anatofuz
parents:
diff changeset
596 setCount(BC.BreakCount + ParentCount + BackedgeCount + BC.ContinueCount -
anatofuz
parents:
diff changeset
597 BodyCount);
anatofuz
parents:
diff changeset
598 RecordNextStmtCount = true;
anatofuz
parents:
diff changeset
599 }
anatofuz
parents:
diff changeset
600
anatofuz
parents:
diff changeset
601 void VisitSwitchStmt(const SwitchStmt *S) {
anatofuz
parents:
diff changeset
602 RecordStmtCount(S);
anatofuz
parents:
diff changeset
603 if (S->getInit())
anatofuz
parents:
diff changeset
604 Visit(S->getInit());
anatofuz
parents:
diff changeset
605 Visit(S->getCond());
anatofuz
parents:
diff changeset
606 CurrentCount = 0;
anatofuz
parents:
diff changeset
607 BreakContinueStack.push_back(BreakContinue());
anatofuz
parents:
diff changeset
608 Visit(S->getBody());
anatofuz
parents:
diff changeset
609 // If the switch is inside a loop, add the continue counts.
anatofuz
parents:
diff changeset
610 BreakContinue BC = BreakContinueStack.pop_back_val();
anatofuz
parents:
diff changeset
611 if (!BreakContinueStack.empty())
anatofuz
parents:
diff changeset
612 BreakContinueStack.back().ContinueCount += BC.ContinueCount;
anatofuz
parents:
diff changeset
613 // Counter tracks the exit block of the switch.
anatofuz
parents:
diff changeset
614 setCount(PGO.getRegionCount(S));
anatofuz
parents:
diff changeset
615 RecordNextStmtCount = true;
anatofuz
parents:
diff changeset
616 }
anatofuz
parents:
diff changeset
617
anatofuz
parents:
diff changeset
618 void VisitSwitchCase(const SwitchCase *S) {
anatofuz
parents:
diff changeset
619 RecordNextStmtCount = false;
anatofuz
parents:
diff changeset
620 // Counter for this particular case. This counts only jumps from the
anatofuz
parents:
diff changeset
621 // switch header and does not include fallthrough from the case before
anatofuz
parents:
diff changeset
622 // this one.
anatofuz
parents:
diff changeset
623 uint64_t CaseCount = PGO.getRegionCount(S);
anatofuz
parents:
diff changeset
624 setCount(CurrentCount + CaseCount);
anatofuz
parents:
diff changeset
625 // We need the count without fallthrough in the mapping, so it's more useful
anatofuz
parents:
diff changeset
626 // for branch probabilities.
anatofuz
parents:
diff changeset
627 CountMap[S] = CaseCount;
anatofuz
parents:
diff changeset
628 RecordNextStmtCount = true;
anatofuz
parents:
diff changeset
629 Visit(S->getSubStmt());
anatofuz
parents:
diff changeset
630 }
anatofuz
parents:
diff changeset
631
anatofuz
parents:
diff changeset
632 void VisitIfStmt(const IfStmt *S) {
anatofuz
parents:
diff changeset
633 RecordStmtCount(S);
anatofuz
parents:
diff changeset
634 uint64_t ParentCount = CurrentCount;
anatofuz
parents:
diff changeset
635 if (S->getInit())
anatofuz
parents:
diff changeset
636 Visit(S->getInit());
anatofuz
parents:
diff changeset
637 Visit(S->getCond());
anatofuz
parents:
diff changeset
638
anatofuz
parents:
diff changeset
639 // Counter tracks the "then" part of an if statement. The count for
anatofuz
parents:
diff changeset
640 // the "else" part, if it exists, will be calculated from this counter.
anatofuz
parents:
diff changeset
641 uint64_t ThenCount = setCount(PGO.getRegionCount(S));
anatofuz
parents:
diff changeset
642 CountMap[S->getThen()] = ThenCount;
anatofuz
parents:
diff changeset
643 Visit(S->getThen());
anatofuz
parents:
diff changeset
644 uint64_t OutCount = CurrentCount;
anatofuz
parents:
diff changeset
645
anatofuz
parents:
diff changeset
646 uint64_t ElseCount = ParentCount - ThenCount;
anatofuz
parents:
diff changeset
647 if (S->getElse()) {
anatofuz
parents:
diff changeset
648 setCount(ElseCount);
anatofuz
parents:
diff changeset
649 CountMap[S->getElse()] = ElseCount;
anatofuz
parents:
diff changeset
650 Visit(S->getElse());
anatofuz
parents:
diff changeset
651 OutCount += CurrentCount;
anatofuz
parents:
diff changeset
652 } else
anatofuz
parents:
diff changeset
653 OutCount += ElseCount;
anatofuz
parents:
diff changeset
654 setCount(OutCount);
anatofuz
parents:
diff changeset
655 RecordNextStmtCount = true;
anatofuz
parents:
diff changeset
656 }
anatofuz
parents:
diff changeset
657
anatofuz
parents:
diff changeset
658 void VisitCXXTryStmt(const CXXTryStmt *S) {
anatofuz
parents:
diff changeset
659 RecordStmtCount(S);
anatofuz
parents:
diff changeset
660 Visit(S->getTryBlock());
anatofuz
parents:
diff changeset
661 for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
anatofuz
parents:
diff changeset
662 Visit(S->getHandler(I));
anatofuz
parents:
diff changeset
663 // Counter tracks the continuation block of the try statement.
anatofuz
parents:
diff changeset
664 setCount(PGO.getRegionCount(S));
anatofuz
parents:
diff changeset
665 RecordNextStmtCount = true;
anatofuz
parents:
diff changeset
666 }
anatofuz
parents:
diff changeset
667
anatofuz
parents:
diff changeset
668 void VisitCXXCatchStmt(const CXXCatchStmt *S) {
anatofuz
parents:
diff changeset
669 RecordNextStmtCount = false;
anatofuz
parents:
diff changeset
670 // Counter tracks the catch statement's handler block.
anatofuz
parents:
diff changeset
671 uint64_t CatchCount = setCount(PGO.getRegionCount(S));
anatofuz
parents:
diff changeset
672 CountMap[S] = CatchCount;
anatofuz
parents:
diff changeset
673 Visit(S->getHandlerBlock());
anatofuz
parents:
diff changeset
674 }
anatofuz
parents:
diff changeset
675
anatofuz
parents:
diff changeset
676 void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
anatofuz
parents:
diff changeset
677 RecordStmtCount(E);
anatofuz
parents:
diff changeset
678 uint64_t ParentCount = CurrentCount;
anatofuz
parents:
diff changeset
679 Visit(E->getCond());
anatofuz
parents:
diff changeset
680
anatofuz
parents:
diff changeset
681 // Counter tracks the "true" part of a conditional operator. The
anatofuz
parents:
diff changeset
682 // count in the "false" part will be calculated from this counter.
anatofuz
parents:
diff changeset
683 uint64_t TrueCount = setCount(PGO.getRegionCount(E));
anatofuz
parents:
diff changeset
684 CountMap[E->getTrueExpr()] = TrueCount;
anatofuz
parents:
diff changeset
685 Visit(E->getTrueExpr());
anatofuz
parents:
diff changeset
686 uint64_t OutCount = CurrentCount;
anatofuz
parents:
diff changeset
687
anatofuz
parents:
diff changeset
688 uint64_t FalseCount = setCount(ParentCount - TrueCount);
anatofuz
parents:
diff changeset
689 CountMap[E->getFalseExpr()] = FalseCount;
anatofuz
parents:
diff changeset
690 Visit(E->getFalseExpr());
anatofuz
parents:
diff changeset
691 OutCount += CurrentCount;
anatofuz
parents:
diff changeset
692
anatofuz
parents:
diff changeset
693 setCount(OutCount);
anatofuz
parents:
diff changeset
694 RecordNextStmtCount = true;
anatofuz
parents:
diff changeset
695 }
anatofuz
parents:
diff changeset
696
anatofuz
parents:
diff changeset
697 void VisitBinLAnd(const BinaryOperator *E) {
anatofuz
parents:
diff changeset
698 RecordStmtCount(E);
anatofuz
parents:
diff changeset
699 uint64_t ParentCount = CurrentCount;
anatofuz
parents:
diff changeset
700 Visit(E->getLHS());
anatofuz
parents:
diff changeset
701 // Counter tracks the right hand side of a logical and operator.
anatofuz
parents:
diff changeset
702 uint64_t RHSCount = setCount(PGO.getRegionCount(E));
anatofuz
parents:
diff changeset
703 CountMap[E->getRHS()] = RHSCount;
anatofuz
parents:
diff changeset
704 Visit(E->getRHS());
anatofuz
parents:
diff changeset
705 setCount(ParentCount + RHSCount - CurrentCount);
anatofuz
parents:
diff changeset
706 RecordNextStmtCount = true;
anatofuz
parents:
diff changeset
707 }
anatofuz
parents:
diff changeset
708
anatofuz
parents:
diff changeset
709 void VisitBinLOr(const BinaryOperator *E) {
anatofuz
parents:
diff changeset
710 RecordStmtCount(E);
anatofuz
parents:
diff changeset
711 uint64_t ParentCount = CurrentCount;
anatofuz
parents:
diff changeset
712 Visit(E->getLHS());
anatofuz
parents:
diff changeset
713 // Counter tracks the right hand side of a logical or operator.
anatofuz
parents:
diff changeset
714 uint64_t RHSCount = setCount(PGO.getRegionCount(E));
anatofuz
parents:
diff changeset
715 CountMap[E->getRHS()] = RHSCount;
anatofuz
parents:
diff changeset
716 Visit(E->getRHS());
anatofuz
parents:
diff changeset
717 setCount(ParentCount + RHSCount - CurrentCount);
anatofuz
parents:
diff changeset
718 RecordNextStmtCount = true;
anatofuz
parents:
diff changeset
719 }
anatofuz
parents:
diff changeset
720 };
anatofuz
parents:
diff changeset
721 } // end anonymous namespace
anatofuz
parents:
diff changeset
722
anatofuz
parents:
diff changeset
723 void PGOHash::combine(HashType Type) {
anatofuz
parents:
diff changeset
724 // Check that we never combine 0 and only have six bits.
anatofuz
parents:
diff changeset
725 assert(Type && "Hash is invalid: unexpected type 0");
anatofuz
parents:
diff changeset
726 assert(unsigned(Type) < TooBig && "Hash is invalid: too many types");
anatofuz
parents:
diff changeset
727
anatofuz
parents:
diff changeset
728 // Pass through MD5 if enough work has built up.
anatofuz
parents:
diff changeset
729 if (Count && Count % NumTypesPerWord == 0) {
anatofuz
parents:
diff changeset
730 using namespace llvm::support;
anatofuz
parents:
diff changeset
731 uint64_t Swapped = endian::byte_swap<uint64_t, little>(Working);
anatofuz
parents:
diff changeset
732 MD5.update(llvm::makeArrayRef((uint8_t *)&Swapped, sizeof(Swapped)));
anatofuz
parents:
diff changeset
733 Working = 0;
anatofuz
parents:
diff changeset
734 }
anatofuz
parents:
diff changeset
735
anatofuz
parents:
diff changeset
736 // Accumulate the current type.
anatofuz
parents:
diff changeset
737 ++Count;
anatofuz
parents:
diff changeset
738 Working = Working << NumBitsPerType | Type;
anatofuz
parents:
diff changeset
739 }
anatofuz
parents:
diff changeset
740
anatofuz
parents:
diff changeset
741 uint64_t PGOHash::finalize() {
anatofuz
parents:
diff changeset
742 // Use Working as the hash directly if we never used MD5.
anatofuz
parents:
diff changeset
743 if (Count <= NumTypesPerWord)
anatofuz
parents:
diff changeset
744 // No need to byte swap here, since none of the math was endian-dependent.
anatofuz
parents:
diff changeset
745 // This number will be byte-swapped as required on endianness transitions,
anatofuz
parents:
diff changeset
746 // so we will see the same value on the other side.
anatofuz
parents:
diff changeset
747 return Working;
anatofuz
parents:
diff changeset
748
anatofuz
parents:
diff changeset
749 // Check for remaining work in Working.
anatofuz
parents:
diff changeset
750 if (Working)
anatofuz
parents:
diff changeset
751 MD5.update(Working);
anatofuz
parents:
diff changeset
752
anatofuz
parents:
diff changeset
753 // Finalize the MD5 and return the hash.
anatofuz
parents:
diff changeset
754 llvm::MD5::MD5Result Result;
anatofuz
parents:
diff changeset
755 MD5.final(Result);
anatofuz
parents:
diff changeset
756 using namespace llvm::support;
anatofuz
parents:
diff changeset
757 return Result.low();
anatofuz
parents:
diff changeset
758 }
anatofuz
parents:
diff changeset
759
anatofuz
parents:
diff changeset
760 void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) {
anatofuz
parents:
diff changeset
761 const Decl *D = GD.getDecl();
anatofuz
parents:
diff changeset
762 if (!D->hasBody())
anatofuz
parents:
diff changeset
763 return;
anatofuz
parents:
diff changeset
764
anatofuz
parents:
diff changeset
765 bool InstrumentRegions = CGM.getCodeGenOpts().hasProfileClangInstr();
anatofuz
parents:
diff changeset
766 llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
anatofuz
parents:
diff changeset
767 if (!InstrumentRegions && !PGOReader)
anatofuz
parents:
diff changeset
768 return;
anatofuz
parents:
diff changeset
769 if (D->isImplicit())
anatofuz
parents:
diff changeset
770 return;
anatofuz
parents:
diff changeset
771 // Constructors and destructors may be represented by several functions in IR.
anatofuz
parents:
diff changeset
772 // If so, instrument only base variant, others are implemented by delegation
anatofuz
parents:
diff changeset
773 // to the base one, it would be counted twice otherwise.
anatofuz
parents:
diff changeset
774 if (CGM.getTarget().getCXXABI().hasConstructorVariants()) {
anatofuz
parents:
diff changeset
775 if (const auto *CCD = dyn_cast<CXXConstructorDecl>(D))
anatofuz
parents:
diff changeset
776 if (GD.getCtorType() != Ctor_Base &&
anatofuz
parents:
diff changeset
777 CodeGenFunction::IsConstructorDelegationValid(CCD))
anatofuz
parents:
diff changeset
778 return;
anatofuz
parents:
diff changeset
779 }
anatofuz
parents:
diff changeset
780 if (isa<CXXDestructorDecl>(D) && GD.getDtorType() != Dtor_Base)
anatofuz
parents:
diff changeset
781 return;
anatofuz
parents:
diff changeset
782
anatofuz
parents:
diff changeset
783 CGM.ClearUnusedCoverageMapping(D);
anatofuz
parents:
diff changeset
784 setFuncName(Fn);
anatofuz
parents:
diff changeset
785
anatofuz
parents:
diff changeset
786 mapRegionCounters(D);
anatofuz
parents:
diff changeset
787 if (CGM.getCodeGenOpts().CoverageMapping)
anatofuz
parents:
diff changeset
788 emitCounterRegionMapping(D);
anatofuz
parents:
diff changeset
789 if (PGOReader) {
anatofuz
parents:
diff changeset
790 SourceManager &SM = CGM.getContext().getSourceManager();
anatofuz
parents:
diff changeset
791 loadRegionCounts(PGOReader, SM.isInMainFile(D->getLocation()));
anatofuz
parents:
diff changeset
792 computeRegionCounts(D);
anatofuz
parents:
diff changeset
793 applyFunctionAttributes(PGOReader, Fn);
anatofuz
parents:
diff changeset
794 }
anatofuz
parents:
diff changeset
795 }
anatofuz
parents:
diff changeset
796
anatofuz
parents:
diff changeset
797 void CodeGenPGO::mapRegionCounters(const Decl *D) {
anatofuz
parents:
diff changeset
798 // Use the latest hash version when inserting instrumentation, but use the
anatofuz
parents:
diff changeset
799 // version in the indexed profile if we're reading PGO data.
anatofuz
parents:
diff changeset
800 PGOHashVersion HashVersion = PGO_HASH_LATEST;
anatofuz
parents:
diff changeset
801 if (auto *PGOReader = CGM.getPGOReader())
anatofuz
parents:
diff changeset
802 HashVersion = getPGOHashVersion(PGOReader, CGM);
anatofuz
parents:
diff changeset
803
anatofuz
parents:
diff changeset
804 RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>);
anatofuz
parents:
diff changeset
805 MapRegionCounters Walker(HashVersion, *RegionCounterMap);
anatofuz
parents:
diff changeset
806 if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
anatofuz
parents:
diff changeset
807 Walker.TraverseDecl(const_cast<FunctionDecl *>(FD));
anatofuz
parents:
diff changeset
808 else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
anatofuz
parents:
diff changeset
809 Walker.TraverseDecl(const_cast<ObjCMethodDecl *>(MD));
anatofuz
parents:
diff changeset
810 else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
anatofuz
parents:
diff changeset
811 Walker.TraverseDecl(const_cast<BlockDecl *>(BD));
anatofuz
parents:
diff changeset
812 else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
anatofuz
parents:
diff changeset
813 Walker.TraverseDecl(const_cast<CapturedDecl *>(CD));
anatofuz
parents:
diff changeset
814 assert(Walker.NextCounter > 0 && "no entry counter mapped for decl");
anatofuz
parents:
diff changeset
815 NumRegionCounters = Walker.NextCounter;
anatofuz
parents:
diff changeset
816 FunctionHash = Walker.Hash.finalize();
anatofuz
parents:
diff changeset
817 }
anatofuz
parents:
diff changeset
818
anatofuz
parents:
diff changeset
819 bool CodeGenPGO::skipRegionMappingForDecl(const Decl *D) {
anatofuz
parents:
diff changeset
820 if (!D->getBody())
anatofuz
parents:
diff changeset
821 return true;
anatofuz
parents:
diff changeset
822
anatofuz
parents:
diff changeset
823 // Don't map the functions in system headers.
anatofuz
parents:
diff changeset
824 const auto &SM = CGM.getContext().getSourceManager();
anatofuz
parents:
diff changeset
825 auto Loc = D->getBody()->getBeginLoc();
anatofuz
parents:
diff changeset
826 return SM.isInSystemHeader(Loc);
anatofuz
parents:
diff changeset
827 }
anatofuz
parents:
diff changeset
828
anatofuz
parents:
diff changeset
829 void CodeGenPGO::emitCounterRegionMapping(const Decl *D) {
anatofuz
parents:
diff changeset
830 if (skipRegionMappingForDecl(D))
anatofuz
parents:
diff changeset
831 return;
anatofuz
parents:
diff changeset
832
anatofuz
parents:
diff changeset
833 std::string CoverageMapping;
anatofuz
parents:
diff changeset
834 llvm::raw_string_ostream OS(CoverageMapping);
anatofuz
parents:
diff changeset
835 CoverageMappingGen MappingGen(*CGM.getCoverageMapping(),
anatofuz
parents:
diff changeset
836 CGM.getContext().getSourceManager(),
anatofuz
parents:
diff changeset
837 CGM.getLangOpts(), RegionCounterMap.get());
anatofuz
parents:
diff changeset
838 MappingGen.emitCounterMapping(D, OS);
anatofuz
parents:
diff changeset
839 OS.flush();
anatofuz
parents:
diff changeset
840
anatofuz
parents:
diff changeset
841 if (CoverageMapping.empty())
anatofuz
parents:
diff changeset
842 return;
anatofuz
parents:
diff changeset
843
anatofuz
parents:
diff changeset
844 CGM.getCoverageMapping()->addFunctionMappingRecord(
anatofuz
parents:
diff changeset
845 FuncNameVar, FuncName, FunctionHash, CoverageMapping);
anatofuz
parents:
diff changeset
846 }
anatofuz
parents:
diff changeset
847
anatofuz
parents:
diff changeset
848 void
anatofuz
parents:
diff changeset
849 CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef Name,
anatofuz
parents:
diff changeset
850 llvm::GlobalValue::LinkageTypes Linkage) {
anatofuz
parents:
diff changeset
851 if (skipRegionMappingForDecl(D))
anatofuz
parents:
diff changeset
852 return;
anatofuz
parents:
diff changeset
853
anatofuz
parents:
diff changeset
854 std::string CoverageMapping;
anatofuz
parents:
diff changeset
855 llvm::raw_string_ostream OS(CoverageMapping);
anatofuz
parents:
diff changeset
856 CoverageMappingGen MappingGen(*CGM.getCoverageMapping(),
anatofuz
parents:
diff changeset
857 CGM.getContext().getSourceManager(),
anatofuz
parents:
diff changeset
858 CGM.getLangOpts());
anatofuz
parents:
diff changeset
859 MappingGen.emitEmptyMapping(D, OS);
anatofuz
parents:
diff changeset
860 OS.flush();
anatofuz
parents:
diff changeset
861
anatofuz
parents:
diff changeset
862 if (CoverageMapping.empty())
anatofuz
parents:
diff changeset
863 return;
anatofuz
parents:
diff changeset
864
anatofuz
parents:
diff changeset
865 setFuncName(Name, Linkage);
anatofuz
parents:
diff changeset
866 CGM.getCoverageMapping()->addFunctionMappingRecord(
anatofuz
parents:
diff changeset
867 FuncNameVar, FuncName, FunctionHash, CoverageMapping, false);
anatofuz
parents:
diff changeset
868 }
anatofuz
parents:
diff changeset
869
anatofuz
parents:
diff changeset
870 void CodeGenPGO::computeRegionCounts(const Decl *D) {
anatofuz
parents:
diff changeset
871 StmtCountMap.reset(new llvm::DenseMap<const Stmt *, uint64_t>);
anatofuz
parents:
diff changeset
872 ComputeRegionCounts Walker(*StmtCountMap, *this);
anatofuz
parents:
diff changeset
873 if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
anatofuz
parents:
diff changeset
874 Walker.VisitFunctionDecl(FD);
anatofuz
parents:
diff changeset
875 else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
anatofuz
parents:
diff changeset
876 Walker.VisitObjCMethodDecl(MD);
anatofuz
parents:
diff changeset
877 else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
anatofuz
parents:
diff changeset
878 Walker.VisitBlockDecl(BD);
anatofuz
parents:
diff changeset
879 else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
anatofuz
parents:
diff changeset
880 Walker.VisitCapturedDecl(const_cast<CapturedDecl *>(CD));
anatofuz
parents:
diff changeset
881 }
anatofuz
parents:
diff changeset
882
anatofuz
parents:
diff changeset
883 void
anatofuz
parents:
diff changeset
884 CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
anatofuz
parents:
diff changeset
885 llvm::Function *Fn) {
anatofuz
parents:
diff changeset
886 if (!haveRegionCounts())
anatofuz
parents:
diff changeset
887 return;
anatofuz
parents:
diff changeset
888
anatofuz
parents:
diff changeset
889 uint64_t FunctionCount = getRegionCount(nullptr);
anatofuz
parents:
diff changeset
890 Fn->setEntryCount(FunctionCount);
anatofuz
parents:
diff changeset
891 }
anatofuz
parents:
diff changeset
892
anatofuz
parents:
diff changeset
893 void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S,
anatofuz
parents:
diff changeset
894 llvm::Value *StepV) {
anatofuz
parents:
diff changeset
895 if (!CGM.getCodeGenOpts().hasProfileClangInstr() || !RegionCounterMap)
anatofuz
parents:
diff changeset
896 return;
anatofuz
parents:
diff changeset
897 if (!Builder.GetInsertBlock())
anatofuz
parents:
diff changeset
898 return;
anatofuz
parents:
diff changeset
899
anatofuz
parents:
diff changeset
900 unsigned Counter = (*RegionCounterMap)[S];
anatofuz
parents:
diff changeset
901 auto *I8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
anatofuz
parents:
diff changeset
902
anatofuz
parents:
diff changeset
903 llvm::Value *Args[] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
anatofuz
parents:
diff changeset
904 Builder.getInt64(FunctionHash),
anatofuz
parents:
diff changeset
905 Builder.getInt32(NumRegionCounters),
anatofuz
parents:
diff changeset
906 Builder.getInt32(Counter), StepV};
anatofuz
parents:
diff changeset
907 if (!StepV)
anatofuz
parents:
diff changeset
908 Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment),
anatofuz
parents:
diff changeset
909 makeArrayRef(Args, 4));
anatofuz
parents:
diff changeset
910 else
anatofuz
parents:
diff changeset
911 Builder.CreateCall(
anatofuz
parents:
diff changeset
912 CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment_step),
anatofuz
parents:
diff changeset
913 makeArrayRef(Args));
anatofuz
parents:
diff changeset
914 }
anatofuz
parents:
diff changeset
915
anatofuz
parents:
diff changeset
916 // This method either inserts a call to the profile run-time during
anatofuz
parents:
diff changeset
917 // instrumentation or puts profile data into metadata for PGO use.
anatofuz
parents:
diff changeset
918 void CodeGenPGO::valueProfile(CGBuilderTy &Builder, uint32_t ValueKind,
anatofuz
parents:
diff changeset
919 llvm::Instruction *ValueSite, llvm::Value *ValuePtr) {
anatofuz
parents:
diff changeset
920
anatofuz
parents:
diff changeset
921 if (!EnableValueProfiling)
anatofuz
parents:
diff changeset
922 return;
anatofuz
parents:
diff changeset
923
anatofuz
parents:
diff changeset
924 if (!ValuePtr || !ValueSite || !Builder.GetInsertBlock())
anatofuz
parents:
diff changeset
925 return;
anatofuz
parents:
diff changeset
926
anatofuz
parents:
diff changeset
927 if (isa<llvm::Constant>(ValuePtr))
anatofuz
parents:
diff changeset
928 return;
anatofuz
parents:
diff changeset
929
anatofuz
parents:
diff changeset
930 bool InstrumentValueSites = CGM.getCodeGenOpts().hasProfileClangInstr();
anatofuz
parents:
diff changeset
931 if (InstrumentValueSites && RegionCounterMap) {
anatofuz
parents:
diff changeset
932 auto BuilderInsertPoint = Builder.saveIP();
anatofuz
parents:
diff changeset
933 Builder.SetInsertPoint(ValueSite);
anatofuz
parents:
diff changeset
934 llvm::Value *Args[5] = {
anatofuz
parents:
diff changeset
935 llvm::ConstantExpr::getBitCast(FuncNameVar, Builder.getInt8PtrTy()),
anatofuz
parents:
diff changeset
936 Builder.getInt64(FunctionHash),
anatofuz
parents:
diff changeset
937 Builder.CreatePtrToInt(ValuePtr, Builder.getInt64Ty()),
anatofuz
parents:
diff changeset
938 Builder.getInt32(ValueKind),
anatofuz
parents:
diff changeset
939 Builder.getInt32(NumValueSites[ValueKind]++)
anatofuz
parents:
diff changeset
940 };
anatofuz
parents:
diff changeset
941 Builder.CreateCall(
anatofuz
parents:
diff changeset
942 CGM.getIntrinsic(llvm::Intrinsic::instrprof_value_profile), Args);
anatofuz
parents:
diff changeset
943 Builder.restoreIP(BuilderInsertPoint);
anatofuz
parents:
diff changeset
944 return;
anatofuz
parents:
diff changeset
945 }
anatofuz
parents:
diff changeset
946
anatofuz
parents:
diff changeset
947 llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
anatofuz
parents:
diff changeset
948 if (PGOReader && haveRegionCounts()) {
anatofuz
parents:
diff changeset
949 // We record the top most called three functions at each call site.
anatofuz
parents:
diff changeset
950 // Profile metadata contains "VP" string identifying this metadata
anatofuz
parents:
diff changeset
951 // as value profiling data, then a uint32_t value for the value profiling
anatofuz
parents:
diff changeset
952 // kind, a uint64_t value for the total number of times the call is
anatofuz
parents:
diff changeset
953 // executed, followed by the function hash and execution count (uint64_t)
anatofuz
parents:
diff changeset
954 // pairs for each function.
anatofuz
parents:
diff changeset
955 if (NumValueSites[ValueKind] >= ProfRecord->getNumValueSites(ValueKind))
anatofuz
parents:
diff changeset
956 return;
anatofuz
parents:
diff changeset
957
anatofuz
parents:
diff changeset
958 llvm::annotateValueSite(CGM.getModule(), *ValueSite, *ProfRecord,
anatofuz
parents:
diff changeset
959 (llvm::InstrProfValueKind)ValueKind,
anatofuz
parents:
diff changeset
960 NumValueSites[ValueKind]);
anatofuz
parents:
diff changeset
961
anatofuz
parents:
diff changeset
962 NumValueSites[ValueKind]++;
anatofuz
parents:
diff changeset
963 }
anatofuz
parents:
diff changeset
964 }
anatofuz
parents:
diff changeset
965
anatofuz
parents:
diff changeset
966 void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
anatofuz
parents:
diff changeset
967 bool IsInMainFile) {
anatofuz
parents:
diff changeset
968 CGM.getPGOStats().addVisited(IsInMainFile);
anatofuz
parents:
diff changeset
969 RegionCounts.clear();
anatofuz
parents:
diff changeset
970 llvm::Expected<llvm::InstrProfRecord> RecordExpected =
anatofuz
parents:
diff changeset
971 PGOReader->getInstrProfRecord(FuncName, FunctionHash);
anatofuz
parents:
diff changeset
972 if (auto E = RecordExpected.takeError()) {
anatofuz
parents:
diff changeset
973 auto IPE = llvm::InstrProfError::take(std::move(E));
anatofuz
parents:
diff changeset
974 if (IPE == llvm::instrprof_error::unknown_function)
anatofuz
parents:
diff changeset
975 CGM.getPGOStats().addMissing(IsInMainFile);
anatofuz
parents:
diff changeset
976 else if (IPE == llvm::instrprof_error::hash_mismatch)
anatofuz
parents:
diff changeset
977 CGM.getPGOStats().addMismatched(IsInMainFile);
anatofuz
parents:
diff changeset
978 else if (IPE == llvm::instrprof_error::malformed)
anatofuz
parents:
diff changeset
979 // TODO: Consider a more specific warning for this case.
anatofuz
parents:
diff changeset
980 CGM.getPGOStats().addMismatched(IsInMainFile);
anatofuz
parents:
diff changeset
981 return;
anatofuz
parents:
diff changeset
982 }
anatofuz
parents:
diff changeset
983 ProfRecord =
anatofuz
parents:
diff changeset
984 std::make_unique<llvm::InstrProfRecord>(std::move(RecordExpected.get()));
anatofuz
parents:
diff changeset
985 RegionCounts = ProfRecord->Counts;
anatofuz
parents:
diff changeset
986 }
anatofuz
parents:
diff changeset
987
anatofuz
parents:
diff changeset
988 /// Calculate what to divide by to scale weights.
anatofuz
parents:
diff changeset
989 ///
anatofuz
parents:
diff changeset
990 /// Given the maximum weight, calculate a divisor that will scale all the
anatofuz
parents:
diff changeset
991 /// weights to strictly less than UINT32_MAX.
anatofuz
parents:
diff changeset
992 static uint64_t calculateWeightScale(uint64_t MaxWeight) {
anatofuz
parents:
diff changeset
993 return MaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1;
anatofuz
parents:
diff changeset
994 }
anatofuz
parents:
diff changeset
995
anatofuz
parents:
diff changeset
996 /// Scale an individual branch weight (and add 1).
anatofuz
parents:
diff changeset
997 ///
anatofuz
parents:
diff changeset
998 /// Scale a 64-bit weight down to 32-bits using \c Scale.
anatofuz
parents:
diff changeset
999 ///
anatofuz
parents:
diff changeset
1000 /// According to Laplace's Rule of Succession, it is better to compute the
anatofuz
parents:
diff changeset
1001 /// weight based on the count plus 1, so universally add 1 to the value.
anatofuz
parents:
diff changeset
1002 ///
anatofuz
parents:
diff changeset
1003 /// \pre \c Scale was calculated by \a calculateWeightScale() with a weight no
anatofuz
parents:
diff changeset
1004 /// greater than \c Weight.
anatofuz
parents:
diff changeset
1005 static uint32_t scaleBranchWeight(uint64_t Weight, uint64_t Scale) {
anatofuz
parents:
diff changeset
1006 assert(Scale && "scale by 0?");
anatofuz
parents:
diff changeset
1007 uint64_t Scaled = Weight / Scale + 1;
anatofuz
parents:
diff changeset
1008 assert(Scaled <= UINT32_MAX && "overflow 32-bits");
anatofuz
parents:
diff changeset
1009 return Scaled;
anatofuz
parents:
diff changeset
1010 }
anatofuz
parents:
diff changeset
1011
anatofuz
parents:
diff changeset
1012 llvm::MDNode *CodeGenFunction::createProfileWeights(uint64_t TrueCount,
anatofuz
parents:
diff changeset
1013 uint64_t FalseCount) {
anatofuz
parents:
diff changeset
1014 // Check for empty weights.
anatofuz
parents:
diff changeset
1015 if (!TrueCount && !FalseCount)
anatofuz
parents:
diff changeset
1016 return nullptr;
anatofuz
parents:
diff changeset
1017
anatofuz
parents:
diff changeset
1018 // Calculate how to scale down to 32-bits.
anatofuz
parents:
diff changeset
1019 uint64_t Scale = calculateWeightScale(std::max(TrueCount, FalseCount));
anatofuz
parents:
diff changeset
1020
anatofuz
parents:
diff changeset
1021 llvm::MDBuilder MDHelper(CGM.getLLVMContext());
anatofuz
parents:
diff changeset
1022 return MDHelper.createBranchWeights(scaleBranchWeight(TrueCount, Scale),
anatofuz
parents:
diff changeset
1023 scaleBranchWeight(FalseCount, Scale));
anatofuz
parents:
diff changeset
1024 }
anatofuz
parents:
diff changeset
1025
anatofuz
parents:
diff changeset
1026 llvm::MDNode *
anatofuz
parents:
diff changeset
1027 CodeGenFunction::createProfileWeights(ArrayRef<uint64_t> Weights) {
anatofuz
parents:
diff changeset
1028 // We need at least two elements to create meaningful weights.
anatofuz
parents:
diff changeset
1029 if (Weights.size() < 2)
anatofuz
parents:
diff changeset
1030 return nullptr;
anatofuz
parents:
diff changeset
1031
anatofuz
parents:
diff changeset
1032 // Check for empty weights.
anatofuz
parents:
diff changeset
1033 uint64_t MaxWeight = *std::max_element(Weights.begin(), Weights.end());
anatofuz
parents:
diff changeset
1034 if (MaxWeight == 0)
anatofuz
parents:
diff changeset
1035 return nullptr;
anatofuz
parents:
diff changeset
1036
anatofuz
parents:
diff changeset
1037 // Calculate how to scale down to 32-bits.
anatofuz
parents:
diff changeset
1038 uint64_t Scale = calculateWeightScale(MaxWeight);
anatofuz
parents:
diff changeset
1039
anatofuz
parents:
diff changeset
1040 SmallVector<uint32_t, 16> ScaledWeights;
anatofuz
parents:
diff changeset
1041 ScaledWeights.reserve(Weights.size());
anatofuz
parents:
diff changeset
1042 for (uint64_t W : Weights)
anatofuz
parents:
diff changeset
1043 ScaledWeights.push_back(scaleBranchWeight(W, Scale));
anatofuz
parents:
diff changeset
1044
anatofuz
parents:
diff changeset
1045 llvm::MDBuilder MDHelper(CGM.getLLVMContext());
anatofuz
parents:
diff changeset
1046 return MDHelper.createBranchWeights(ScaledWeights);
anatofuz
parents:
diff changeset
1047 }
anatofuz
parents:
diff changeset
1048
anatofuz
parents:
diff changeset
1049 llvm::MDNode *CodeGenFunction::createProfileWeightsForLoop(const Stmt *Cond,
anatofuz
parents:
diff changeset
1050 uint64_t LoopCount) {
anatofuz
parents:
diff changeset
1051 if (!PGO.haveRegionCounts())
anatofuz
parents:
diff changeset
1052 return nullptr;
anatofuz
parents:
diff changeset
1053 Optional<uint64_t> CondCount = PGO.getStmtCount(Cond);
anatofuz
parents:
diff changeset
1054 assert(CondCount.hasValue() && "missing expected loop condition count");
anatofuz
parents:
diff changeset
1055 if (*CondCount == 0)
anatofuz
parents:
diff changeset
1056 return nullptr;
anatofuz
parents:
diff changeset
1057 return createProfileWeights(LoopCount,
anatofuz
parents:
diff changeset
1058 std::max(*CondCount, LoopCount) - LoopCount);
anatofuz
parents:
diff changeset
1059 }