1*0a6a1f1dSLionel Sambuc //===--- CodeGenPGO.cpp - PGO Instrumentation for LLVM CodeGen --*- C++ -*-===//
2*0a6a1f1dSLionel Sambuc //
3*0a6a1f1dSLionel Sambuc // The LLVM Compiler Infrastructure
4*0a6a1f1dSLionel Sambuc //
5*0a6a1f1dSLionel Sambuc // This file is distributed under the University of Illinois Open Source
6*0a6a1f1dSLionel Sambuc // License. See LICENSE.TXT for details.
7*0a6a1f1dSLionel Sambuc //
8*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
9*0a6a1f1dSLionel Sambuc //
10*0a6a1f1dSLionel Sambuc // Instrumentation-based profile-guided optimization
11*0a6a1f1dSLionel Sambuc //
12*0a6a1f1dSLionel Sambuc //===----------------------------------------------------------------------===//
13*0a6a1f1dSLionel Sambuc
14*0a6a1f1dSLionel Sambuc #include "CodeGenPGO.h"
15*0a6a1f1dSLionel Sambuc #include "CodeGenFunction.h"
16*0a6a1f1dSLionel Sambuc #include "CoverageMappingGen.h"
17*0a6a1f1dSLionel Sambuc #include "clang/AST/RecursiveASTVisitor.h"
18*0a6a1f1dSLionel Sambuc #include "clang/AST/StmtVisitor.h"
19*0a6a1f1dSLionel Sambuc #include "llvm/IR/Intrinsics.h"
20*0a6a1f1dSLionel Sambuc #include "llvm/IR/MDBuilder.h"
21*0a6a1f1dSLionel Sambuc #include "llvm/ProfileData/InstrProfReader.h"
22*0a6a1f1dSLionel Sambuc #include "llvm/Support/Endian.h"
23*0a6a1f1dSLionel Sambuc #include "llvm/Support/FileSystem.h"
24*0a6a1f1dSLionel Sambuc #include "llvm/Support/MD5.h"
25*0a6a1f1dSLionel Sambuc
26*0a6a1f1dSLionel Sambuc using namespace clang;
27*0a6a1f1dSLionel Sambuc using namespace CodeGen;
28*0a6a1f1dSLionel Sambuc
setFuncName(StringRef Name,llvm::GlobalValue::LinkageTypes Linkage)29*0a6a1f1dSLionel Sambuc void CodeGenPGO::setFuncName(StringRef Name,
30*0a6a1f1dSLionel Sambuc llvm::GlobalValue::LinkageTypes Linkage) {
31*0a6a1f1dSLionel Sambuc StringRef RawFuncName = Name;
32*0a6a1f1dSLionel Sambuc
33*0a6a1f1dSLionel Sambuc // Function names may be prefixed with a binary '1' to indicate
34*0a6a1f1dSLionel Sambuc // that the backend should not modify the symbols due to any platform
35*0a6a1f1dSLionel Sambuc // naming convention. Do not include that '1' in the PGO profile name.
36*0a6a1f1dSLionel Sambuc if (RawFuncName[0] == '\1')
37*0a6a1f1dSLionel Sambuc RawFuncName = RawFuncName.substr(1);
38*0a6a1f1dSLionel Sambuc
39*0a6a1f1dSLionel Sambuc FuncName = RawFuncName;
40*0a6a1f1dSLionel Sambuc if (llvm::GlobalValue::isLocalLinkage(Linkage)) {
41*0a6a1f1dSLionel Sambuc // For local symbols, prepend the main file name to distinguish them.
42*0a6a1f1dSLionel Sambuc // Do not include the full path in the file name since there's no guarantee
43*0a6a1f1dSLionel Sambuc // that it will stay the same, e.g., if the files are checked out from
44*0a6a1f1dSLionel Sambuc // version control in different locations.
45*0a6a1f1dSLionel Sambuc if (CGM.getCodeGenOpts().MainFileName.empty())
46*0a6a1f1dSLionel Sambuc FuncName = FuncName.insert(0, "<unknown>:");
47*0a6a1f1dSLionel Sambuc else
48*0a6a1f1dSLionel Sambuc FuncName = FuncName.insert(0, CGM.getCodeGenOpts().MainFileName + ":");
49*0a6a1f1dSLionel Sambuc }
50*0a6a1f1dSLionel Sambuc
51*0a6a1f1dSLionel Sambuc // If we're generating a profile, create a variable for the name.
52*0a6a1f1dSLionel Sambuc if (CGM.getCodeGenOpts().ProfileInstrGenerate)
53*0a6a1f1dSLionel Sambuc createFuncNameVar(Linkage);
54*0a6a1f1dSLionel Sambuc }
55*0a6a1f1dSLionel Sambuc
setFuncName(llvm::Function * Fn)56*0a6a1f1dSLionel Sambuc void CodeGenPGO::setFuncName(llvm::Function *Fn) {
57*0a6a1f1dSLionel Sambuc setFuncName(Fn->getName(), Fn->getLinkage());
58*0a6a1f1dSLionel Sambuc }
59*0a6a1f1dSLionel Sambuc
createFuncNameVar(llvm::GlobalValue::LinkageTypes Linkage)60*0a6a1f1dSLionel Sambuc void CodeGenPGO::createFuncNameVar(llvm::GlobalValue::LinkageTypes Linkage) {
61*0a6a1f1dSLionel Sambuc // Usually, we want to match the function's linkage, but
62*0a6a1f1dSLionel Sambuc // available_externally and extern_weak both have the wrong semantics.
63*0a6a1f1dSLionel Sambuc if (Linkage == llvm::GlobalValue::ExternalWeakLinkage)
64*0a6a1f1dSLionel Sambuc Linkage = llvm::GlobalValue::LinkOnceAnyLinkage;
65*0a6a1f1dSLionel Sambuc else if (Linkage == llvm::GlobalValue::AvailableExternallyLinkage)
66*0a6a1f1dSLionel Sambuc Linkage = llvm::GlobalValue::LinkOnceODRLinkage;
67*0a6a1f1dSLionel Sambuc
68*0a6a1f1dSLionel Sambuc auto *Value =
69*0a6a1f1dSLionel Sambuc llvm::ConstantDataArray::getString(CGM.getLLVMContext(), FuncName, false);
70*0a6a1f1dSLionel Sambuc FuncNameVar =
71*0a6a1f1dSLionel Sambuc new llvm::GlobalVariable(CGM.getModule(), Value->getType(), true, Linkage,
72*0a6a1f1dSLionel Sambuc Value, "__llvm_profile_name_" + FuncName);
73*0a6a1f1dSLionel Sambuc
74*0a6a1f1dSLionel Sambuc // Hide the symbol so that we correctly get a copy for each executable.
75*0a6a1f1dSLionel Sambuc if (!llvm::GlobalValue::isLocalLinkage(FuncNameVar->getLinkage()))
76*0a6a1f1dSLionel Sambuc FuncNameVar->setVisibility(llvm::GlobalValue::HiddenVisibility);
77*0a6a1f1dSLionel Sambuc }
78*0a6a1f1dSLionel Sambuc
79*0a6a1f1dSLionel Sambuc namespace {
80*0a6a1f1dSLionel Sambuc /// \brief Stable hasher for PGO region counters.
81*0a6a1f1dSLionel Sambuc ///
82*0a6a1f1dSLionel Sambuc /// PGOHash produces a stable hash of a given function's control flow.
83*0a6a1f1dSLionel Sambuc ///
84*0a6a1f1dSLionel Sambuc /// Changing the output of this hash will invalidate all previously generated
85*0a6a1f1dSLionel Sambuc /// profiles -- i.e., don't do it.
86*0a6a1f1dSLionel Sambuc ///
87*0a6a1f1dSLionel Sambuc /// \note When this hash does eventually change (years?), we still need to
88*0a6a1f1dSLionel Sambuc /// support old hashes. We'll need to pull in the version number from the
89*0a6a1f1dSLionel Sambuc /// profile data format and use the matching hash function.
90*0a6a1f1dSLionel Sambuc class PGOHash {
91*0a6a1f1dSLionel Sambuc uint64_t Working;
92*0a6a1f1dSLionel Sambuc unsigned Count;
93*0a6a1f1dSLionel Sambuc llvm::MD5 MD5;
94*0a6a1f1dSLionel Sambuc
95*0a6a1f1dSLionel Sambuc static const int NumBitsPerType = 6;
96*0a6a1f1dSLionel Sambuc static const unsigned NumTypesPerWord = sizeof(uint64_t) * 8 / NumBitsPerType;
97*0a6a1f1dSLionel Sambuc static const unsigned TooBig = 1u << NumBitsPerType;
98*0a6a1f1dSLionel Sambuc
99*0a6a1f1dSLionel Sambuc public:
100*0a6a1f1dSLionel Sambuc /// \brief Hash values for AST nodes.
101*0a6a1f1dSLionel Sambuc ///
102*0a6a1f1dSLionel Sambuc /// Distinct values for AST nodes that have region counters attached.
103*0a6a1f1dSLionel Sambuc ///
104*0a6a1f1dSLionel Sambuc /// These values must be stable. All new members must be added at the end,
105*0a6a1f1dSLionel Sambuc /// and no members should be removed. Changing the enumeration value for an
106*0a6a1f1dSLionel Sambuc /// AST node will affect the hash of every function that contains that node.
107*0a6a1f1dSLionel Sambuc enum HashType : unsigned char {
108*0a6a1f1dSLionel Sambuc None = 0,
109*0a6a1f1dSLionel Sambuc LabelStmt = 1,
110*0a6a1f1dSLionel Sambuc WhileStmt,
111*0a6a1f1dSLionel Sambuc DoStmt,
112*0a6a1f1dSLionel Sambuc ForStmt,
113*0a6a1f1dSLionel Sambuc CXXForRangeStmt,
114*0a6a1f1dSLionel Sambuc ObjCForCollectionStmt,
115*0a6a1f1dSLionel Sambuc SwitchStmt,
116*0a6a1f1dSLionel Sambuc CaseStmt,
117*0a6a1f1dSLionel Sambuc DefaultStmt,
118*0a6a1f1dSLionel Sambuc IfStmt,
119*0a6a1f1dSLionel Sambuc CXXTryStmt,
120*0a6a1f1dSLionel Sambuc CXXCatchStmt,
121*0a6a1f1dSLionel Sambuc ConditionalOperator,
122*0a6a1f1dSLionel Sambuc BinaryOperatorLAnd,
123*0a6a1f1dSLionel Sambuc BinaryOperatorLOr,
124*0a6a1f1dSLionel Sambuc BinaryConditionalOperator,
125*0a6a1f1dSLionel Sambuc
126*0a6a1f1dSLionel Sambuc // Keep this last. It's for the static assert that follows.
127*0a6a1f1dSLionel Sambuc LastHashType
128*0a6a1f1dSLionel Sambuc };
129*0a6a1f1dSLionel Sambuc static_assert(LastHashType <= TooBig, "Too many types in HashType");
130*0a6a1f1dSLionel Sambuc
131*0a6a1f1dSLionel Sambuc // TODO: When this format changes, take in a version number here, and use the
132*0a6a1f1dSLionel Sambuc // old hash calculation for file formats that used the old hash.
PGOHash()133*0a6a1f1dSLionel Sambuc PGOHash() : Working(0), Count(0) {}
134*0a6a1f1dSLionel Sambuc void combine(HashType Type);
135*0a6a1f1dSLionel Sambuc uint64_t finalize();
136*0a6a1f1dSLionel Sambuc };
137*0a6a1f1dSLionel Sambuc const int PGOHash::NumBitsPerType;
138*0a6a1f1dSLionel Sambuc const unsigned PGOHash::NumTypesPerWord;
139*0a6a1f1dSLionel Sambuc const unsigned PGOHash::TooBig;
140*0a6a1f1dSLionel Sambuc
141*0a6a1f1dSLionel Sambuc /// A RecursiveASTVisitor that fills a map of statements to PGO counters.
142*0a6a1f1dSLionel Sambuc struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
143*0a6a1f1dSLionel Sambuc /// The next counter value to assign.
144*0a6a1f1dSLionel Sambuc unsigned NextCounter;
145*0a6a1f1dSLionel Sambuc /// The function hash.
146*0a6a1f1dSLionel Sambuc PGOHash Hash;
147*0a6a1f1dSLionel Sambuc /// The map of statements to counters.
148*0a6a1f1dSLionel Sambuc llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
149*0a6a1f1dSLionel Sambuc
MapRegionCounters__anon7f44950c0111::MapRegionCounters150*0a6a1f1dSLionel Sambuc MapRegionCounters(llvm::DenseMap<const Stmt *, unsigned> &CounterMap)
151*0a6a1f1dSLionel Sambuc : NextCounter(0), CounterMap(CounterMap) {}
152*0a6a1f1dSLionel Sambuc
153*0a6a1f1dSLionel Sambuc // Blocks and lambdas are handled as separate functions, so we need not
154*0a6a1f1dSLionel Sambuc // traverse them in the parent context.
TraverseBlockExpr__anon7f44950c0111::MapRegionCounters155*0a6a1f1dSLionel Sambuc bool TraverseBlockExpr(BlockExpr *BE) { return true; }
TraverseLambdaBody__anon7f44950c0111::MapRegionCounters156*0a6a1f1dSLionel Sambuc bool TraverseLambdaBody(LambdaExpr *LE) { return true; }
TraverseCapturedStmt__anon7f44950c0111::MapRegionCounters157*0a6a1f1dSLionel Sambuc bool TraverseCapturedStmt(CapturedStmt *CS) { return true; }
158*0a6a1f1dSLionel Sambuc
VisitDecl__anon7f44950c0111::MapRegionCounters159*0a6a1f1dSLionel Sambuc bool VisitDecl(const Decl *D) {
160*0a6a1f1dSLionel Sambuc switch (D->getKind()) {
161*0a6a1f1dSLionel Sambuc default:
162*0a6a1f1dSLionel Sambuc break;
163*0a6a1f1dSLionel Sambuc case Decl::Function:
164*0a6a1f1dSLionel Sambuc case Decl::CXXMethod:
165*0a6a1f1dSLionel Sambuc case Decl::CXXConstructor:
166*0a6a1f1dSLionel Sambuc case Decl::CXXDestructor:
167*0a6a1f1dSLionel Sambuc case Decl::CXXConversion:
168*0a6a1f1dSLionel Sambuc case Decl::ObjCMethod:
169*0a6a1f1dSLionel Sambuc case Decl::Block:
170*0a6a1f1dSLionel Sambuc case Decl::Captured:
171*0a6a1f1dSLionel Sambuc CounterMap[D->getBody()] = NextCounter++;
172*0a6a1f1dSLionel Sambuc break;
173*0a6a1f1dSLionel Sambuc }
174*0a6a1f1dSLionel Sambuc return true;
175*0a6a1f1dSLionel Sambuc }
176*0a6a1f1dSLionel Sambuc
VisitStmt__anon7f44950c0111::MapRegionCounters177*0a6a1f1dSLionel Sambuc bool VisitStmt(const Stmt *S) {
178*0a6a1f1dSLionel Sambuc auto Type = getHashType(S);
179*0a6a1f1dSLionel Sambuc if (Type == PGOHash::None)
180*0a6a1f1dSLionel Sambuc return true;
181*0a6a1f1dSLionel Sambuc
182*0a6a1f1dSLionel Sambuc CounterMap[S] = NextCounter++;
183*0a6a1f1dSLionel Sambuc Hash.combine(Type);
184*0a6a1f1dSLionel Sambuc return true;
185*0a6a1f1dSLionel Sambuc }
getHashType__anon7f44950c0111::MapRegionCounters186*0a6a1f1dSLionel Sambuc PGOHash::HashType getHashType(const Stmt *S) {
187*0a6a1f1dSLionel Sambuc switch (S->getStmtClass()) {
188*0a6a1f1dSLionel Sambuc default:
189*0a6a1f1dSLionel Sambuc break;
190*0a6a1f1dSLionel Sambuc case Stmt::LabelStmtClass:
191*0a6a1f1dSLionel Sambuc return PGOHash::LabelStmt;
192*0a6a1f1dSLionel Sambuc case Stmt::WhileStmtClass:
193*0a6a1f1dSLionel Sambuc return PGOHash::WhileStmt;
194*0a6a1f1dSLionel Sambuc case Stmt::DoStmtClass:
195*0a6a1f1dSLionel Sambuc return PGOHash::DoStmt;
196*0a6a1f1dSLionel Sambuc case Stmt::ForStmtClass:
197*0a6a1f1dSLionel Sambuc return PGOHash::ForStmt;
198*0a6a1f1dSLionel Sambuc case Stmt::CXXForRangeStmtClass:
199*0a6a1f1dSLionel Sambuc return PGOHash::CXXForRangeStmt;
200*0a6a1f1dSLionel Sambuc case Stmt::ObjCForCollectionStmtClass:
201*0a6a1f1dSLionel Sambuc return PGOHash::ObjCForCollectionStmt;
202*0a6a1f1dSLionel Sambuc case Stmt::SwitchStmtClass:
203*0a6a1f1dSLionel Sambuc return PGOHash::SwitchStmt;
204*0a6a1f1dSLionel Sambuc case Stmt::CaseStmtClass:
205*0a6a1f1dSLionel Sambuc return PGOHash::CaseStmt;
206*0a6a1f1dSLionel Sambuc case Stmt::DefaultStmtClass:
207*0a6a1f1dSLionel Sambuc return PGOHash::DefaultStmt;
208*0a6a1f1dSLionel Sambuc case Stmt::IfStmtClass:
209*0a6a1f1dSLionel Sambuc return PGOHash::IfStmt;
210*0a6a1f1dSLionel Sambuc case Stmt::CXXTryStmtClass:
211*0a6a1f1dSLionel Sambuc return PGOHash::CXXTryStmt;
212*0a6a1f1dSLionel Sambuc case Stmt::CXXCatchStmtClass:
213*0a6a1f1dSLionel Sambuc return PGOHash::CXXCatchStmt;
214*0a6a1f1dSLionel Sambuc case Stmt::ConditionalOperatorClass:
215*0a6a1f1dSLionel Sambuc return PGOHash::ConditionalOperator;
216*0a6a1f1dSLionel Sambuc case Stmt::BinaryConditionalOperatorClass:
217*0a6a1f1dSLionel Sambuc return PGOHash::BinaryConditionalOperator;
218*0a6a1f1dSLionel Sambuc case Stmt::BinaryOperatorClass: {
219*0a6a1f1dSLionel Sambuc const BinaryOperator *BO = cast<BinaryOperator>(S);
220*0a6a1f1dSLionel Sambuc if (BO->getOpcode() == BO_LAnd)
221*0a6a1f1dSLionel Sambuc return PGOHash::BinaryOperatorLAnd;
222*0a6a1f1dSLionel Sambuc if (BO->getOpcode() == BO_LOr)
223*0a6a1f1dSLionel Sambuc return PGOHash::BinaryOperatorLOr;
224*0a6a1f1dSLionel Sambuc break;
225*0a6a1f1dSLionel Sambuc }
226*0a6a1f1dSLionel Sambuc }
227*0a6a1f1dSLionel Sambuc return PGOHash::None;
228*0a6a1f1dSLionel Sambuc }
229*0a6a1f1dSLionel Sambuc };
230*0a6a1f1dSLionel Sambuc
231*0a6a1f1dSLionel Sambuc /// A StmtVisitor that propagates the raw counts through the AST and
232*0a6a1f1dSLionel Sambuc /// records the count at statements where the value may change.
233*0a6a1f1dSLionel Sambuc struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
234*0a6a1f1dSLionel Sambuc /// PGO state.
235*0a6a1f1dSLionel Sambuc CodeGenPGO &PGO;
236*0a6a1f1dSLionel Sambuc
237*0a6a1f1dSLionel Sambuc /// A flag that is set when the current count should be recorded on the
238*0a6a1f1dSLionel Sambuc /// next statement, such as at the exit of a loop.
239*0a6a1f1dSLionel Sambuc bool RecordNextStmtCount;
240*0a6a1f1dSLionel Sambuc
241*0a6a1f1dSLionel Sambuc /// The map of statements to count values.
242*0a6a1f1dSLionel Sambuc llvm::DenseMap<const Stmt *, uint64_t> &CountMap;
243*0a6a1f1dSLionel Sambuc
244*0a6a1f1dSLionel Sambuc /// BreakContinueStack - Keep counts of breaks and continues inside loops.
245*0a6a1f1dSLionel Sambuc struct BreakContinue {
246*0a6a1f1dSLionel Sambuc uint64_t BreakCount;
247*0a6a1f1dSLionel Sambuc uint64_t ContinueCount;
BreakContinue__anon7f44950c0111::ComputeRegionCounts::BreakContinue248*0a6a1f1dSLionel Sambuc BreakContinue() : BreakCount(0), ContinueCount(0) {}
249*0a6a1f1dSLionel Sambuc };
250*0a6a1f1dSLionel Sambuc SmallVector<BreakContinue, 8> BreakContinueStack;
251*0a6a1f1dSLionel Sambuc
ComputeRegionCounts__anon7f44950c0111::ComputeRegionCounts252*0a6a1f1dSLionel Sambuc ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &CountMap,
253*0a6a1f1dSLionel Sambuc CodeGenPGO &PGO)
254*0a6a1f1dSLionel Sambuc : PGO(PGO), RecordNextStmtCount(false), CountMap(CountMap) {}
255*0a6a1f1dSLionel Sambuc
RecordStmtCount__anon7f44950c0111::ComputeRegionCounts256*0a6a1f1dSLionel Sambuc void RecordStmtCount(const Stmt *S) {
257*0a6a1f1dSLionel Sambuc if (RecordNextStmtCount) {
258*0a6a1f1dSLionel Sambuc CountMap[S] = PGO.getCurrentRegionCount();
259*0a6a1f1dSLionel Sambuc RecordNextStmtCount = false;
260*0a6a1f1dSLionel Sambuc }
261*0a6a1f1dSLionel Sambuc }
262*0a6a1f1dSLionel Sambuc
VisitStmt__anon7f44950c0111::ComputeRegionCounts263*0a6a1f1dSLionel Sambuc void VisitStmt(const Stmt *S) {
264*0a6a1f1dSLionel Sambuc RecordStmtCount(S);
265*0a6a1f1dSLionel Sambuc for (Stmt::const_child_range I = S->children(); I; ++I) {
266*0a6a1f1dSLionel Sambuc if (*I)
267*0a6a1f1dSLionel Sambuc this->Visit(*I);
268*0a6a1f1dSLionel Sambuc }
269*0a6a1f1dSLionel Sambuc }
270*0a6a1f1dSLionel Sambuc
VisitFunctionDecl__anon7f44950c0111::ComputeRegionCounts271*0a6a1f1dSLionel Sambuc void VisitFunctionDecl(const FunctionDecl *D) {
272*0a6a1f1dSLionel Sambuc // Counter tracks entry to the function body.
273*0a6a1f1dSLionel Sambuc RegionCounter Cnt(PGO, D->getBody());
274*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
275*0a6a1f1dSLionel Sambuc CountMap[D->getBody()] = PGO.getCurrentRegionCount();
276*0a6a1f1dSLionel Sambuc Visit(D->getBody());
277*0a6a1f1dSLionel Sambuc }
278*0a6a1f1dSLionel Sambuc
279*0a6a1f1dSLionel Sambuc // Skip lambda expressions. We visit these as FunctionDecls when we're
280*0a6a1f1dSLionel Sambuc // generating them and aren't interested in the body when generating a
281*0a6a1f1dSLionel Sambuc // parent context.
VisitLambdaExpr__anon7f44950c0111::ComputeRegionCounts282*0a6a1f1dSLionel Sambuc void VisitLambdaExpr(const LambdaExpr *LE) {}
283*0a6a1f1dSLionel Sambuc
VisitCapturedDecl__anon7f44950c0111::ComputeRegionCounts284*0a6a1f1dSLionel Sambuc void VisitCapturedDecl(const CapturedDecl *D) {
285*0a6a1f1dSLionel Sambuc // Counter tracks entry to the capture body.
286*0a6a1f1dSLionel Sambuc RegionCounter Cnt(PGO, D->getBody());
287*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
288*0a6a1f1dSLionel Sambuc CountMap[D->getBody()] = PGO.getCurrentRegionCount();
289*0a6a1f1dSLionel Sambuc Visit(D->getBody());
290*0a6a1f1dSLionel Sambuc }
291*0a6a1f1dSLionel Sambuc
VisitObjCMethodDecl__anon7f44950c0111::ComputeRegionCounts292*0a6a1f1dSLionel Sambuc void VisitObjCMethodDecl(const ObjCMethodDecl *D) {
293*0a6a1f1dSLionel Sambuc // Counter tracks entry to the method body.
294*0a6a1f1dSLionel Sambuc RegionCounter Cnt(PGO, D->getBody());
295*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
296*0a6a1f1dSLionel Sambuc CountMap[D->getBody()] = PGO.getCurrentRegionCount();
297*0a6a1f1dSLionel Sambuc Visit(D->getBody());
298*0a6a1f1dSLionel Sambuc }
299*0a6a1f1dSLionel Sambuc
VisitBlockDecl__anon7f44950c0111::ComputeRegionCounts300*0a6a1f1dSLionel Sambuc void VisitBlockDecl(const BlockDecl *D) {
301*0a6a1f1dSLionel Sambuc // Counter tracks entry to the block body.
302*0a6a1f1dSLionel Sambuc RegionCounter Cnt(PGO, D->getBody());
303*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
304*0a6a1f1dSLionel Sambuc CountMap[D->getBody()] = PGO.getCurrentRegionCount();
305*0a6a1f1dSLionel Sambuc Visit(D->getBody());
306*0a6a1f1dSLionel Sambuc }
307*0a6a1f1dSLionel Sambuc
VisitReturnStmt__anon7f44950c0111::ComputeRegionCounts308*0a6a1f1dSLionel Sambuc void VisitReturnStmt(const ReturnStmt *S) {
309*0a6a1f1dSLionel Sambuc RecordStmtCount(S);
310*0a6a1f1dSLionel Sambuc if (S->getRetValue())
311*0a6a1f1dSLionel Sambuc Visit(S->getRetValue());
312*0a6a1f1dSLionel Sambuc PGO.setCurrentRegionUnreachable();
313*0a6a1f1dSLionel Sambuc RecordNextStmtCount = true;
314*0a6a1f1dSLionel Sambuc }
315*0a6a1f1dSLionel Sambuc
VisitGotoStmt__anon7f44950c0111::ComputeRegionCounts316*0a6a1f1dSLionel Sambuc void VisitGotoStmt(const GotoStmt *S) {
317*0a6a1f1dSLionel Sambuc RecordStmtCount(S);
318*0a6a1f1dSLionel Sambuc PGO.setCurrentRegionUnreachable();
319*0a6a1f1dSLionel Sambuc RecordNextStmtCount = true;
320*0a6a1f1dSLionel Sambuc }
321*0a6a1f1dSLionel Sambuc
VisitLabelStmt__anon7f44950c0111::ComputeRegionCounts322*0a6a1f1dSLionel Sambuc void VisitLabelStmt(const LabelStmt *S) {
323*0a6a1f1dSLionel Sambuc RecordNextStmtCount = false;
324*0a6a1f1dSLionel Sambuc // Counter tracks the block following the label.
325*0a6a1f1dSLionel Sambuc RegionCounter Cnt(PGO, S);
326*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
327*0a6a1f1dSLionel Sambuc CountMap[S] = PGO.getCurrentRegionCount();
328*0a6a1f1dSLionel Sambuc Visit(S->getSubStmt());
329*0a6a1f1dSLionel Sambuc }
330*0a6a1f1dSLionel Sambuc
VisitBreakStmt__anon7f44950c0111::ComputeRegionCounts331*0a6a1f1dSLionel Sambuc void VisitBreakStmt(const BreakStmt *S) {
332*0a6a1f1dSLionel Sambuc RecordStmtCount(S);
333*0a6a1f1dSLionel Sambuc assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
334*0a6a1f1dSLionel Sambuc BreakContinueStack.back().BreakCount += PGO.getCurrentRegionCount();
335*0a6a1f1dSLionel Sambuc PGO.setCurrentRegionUnreachable();
336*0a6a1f1dSLionel Sambuc RecordNextStmtCount = true;
337*0a6a1f1dSLionel Sambuc }
338*0a6a1f1dSLionel Sambuc
VisitContinueStmt__anon7f44950c0111::ComputeRegionCounts339*0a6a1f1dSLionel Sambuc void VisitContinueStmt(const ContinueStmt *S) {
340*0a6a1f1dSLionel Sambuc RecordStmtCount(S);
341*0a6a1f1dSLionel Sambuc assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
342*0a6a1f1dSLionel Sambuc BreakContinueStack.back().ContinueCount += PGO.getCurrentRegionCount();
343*0a6a1f1dSLionel Sambuc PGO.setCurrentRegionUnreachable();
344*0a6a1f1dSLionel Sambuc RecordNextStmtCount = true;
345*0a6a1f1dSLionel Sambuc }
346*0a6a1f1dSLionel Sambuc
VisitWhileStmt__anon7f44950c0111::ComputeRegionCounts347*0a6a1f1dSLionel Sambuc void VisitWhileStmt(const WhileStmt *S) {
348*0a6a1f1dSLionel Sambuc RecordStmtCount(S);
349*0a6a1f1dSLionel Sambuc // Counter tracks the body of the loop.
350*0a6a1f1dSLionel Sambuc RegionCounter Cnt(PGO, S);
351*0a6a1f1dSLionel Sambuc BreakContinueStack.push_back(BreakContinue());
352*0a6a1f1dSLionel Sambuc // Visit the body region first so the break/continue adjustments can be
353*0a6a1f1dSLionel Sambuc // included when visiting the condition.
354*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
355*0a6a1f1dSLionel Sambuc CountMap[S->getBody()] = PGO.getCurrentRegionCount();
356*0a6a1f1dSLionel Sambuc Visit(S->getBody());
357*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
358*0a6a1f1dSLionel Sambuc
359*0a6a1f1dSLionel Sambuc // ...then go back and propagate counts through the condition. The count
360*0a6a1f1dSLionel Sambuc // at the start of the condition is the sum of the incoming edges,
361*0a6a1f1dSLionel Sambuc // the backedge from the end of the loop body, and the edges from
362*0a6a1f1dSLionel Sambuc // continue statements.
363*0a6a1f1dSLionel Sambuc BreakContinue BC = BreakContinueStack.pop_back_val();
364*0a6a1f1dSLionel Sambuc Cnt.setCurrentRegionCount(Cnt.getParentCount() +
365*0a6a1f1dSLionel Sambuc Cnt.getAdjustedCount() + BC.ContinueCount);
366*0a6a1f1dSLionel Sambuc CountMap[S->getCond()] = PGO.getCurrentRegionCount();
367*0a6a1f1dSLionel Sambuc Visit(S->getCond());
368*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
369*0a6a1f1dSLionel Sambuc Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
370*0a6a1f1dSLionel Sambuc RecordNextStmtCount = true;
371*0a6a1f1dSLionel Sambuc }
372*0a6a1f1dSLionel Sambuc
VisitDoStmt__anon7f44950c0111::ComputeRegionCounts373*0a6a1f1dSLionel Sambuc void VisitDoStmt(const DoStmt *S) {
374*0a6a1f1dSLionel Sambuc RecordStmtCount(S);
375*0a6a1f1dSLionel Sambuc // Counter tracks the body of the loop.
376*0a6a1f1dSLionel Sambuc RegionCounter Cnt(PGO, S);
377*0a6a1f1dSLionel Sambuc BreakContinueStack.push_back(BreakContinue());
378*0a6a1f1dSLionel Sambuc Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
379*0a6a1f1dSLionel Sambuc CountMap[S->getBody()] = PGO.getCurrentRegionCount();
380*0a6a1f1dSLionel Sambuc Visit(S->getBody());
381*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
382*0a6a1f1dSLionel Sambuc
383*0a6a1f1dSLionel Sambuc BreakContinue BC = BreakContinueStack.pop_back_val();
384*0a6a1f1dSLionel Sambuc // The count at the start of the condition is equal to the count at the
385*0a6a1f1dSLionel Sambuc // end of the body. The adjusted count does not include either the
386*0a6a1f1dSLionel Sambuc // fall-through count coming into the loop or the continue count, so add
387*0a6a1f1dSLionel Sambuc // both of those separately. This is coincidentally the same equation as
388*0a6a1f1dSLionel Sambuc // with while loops but for different reasons.
389*0a6a1f1dSLionel Sambuc Cnt.setCurrentRegionCount(Cnt.getParentCount() +
390*0a6a1f1dSLionel Sambuc Cnt.getAdjustedCount() + BC.ContinueCount);
391*0a6a1f1dSLionel Sambuc CountMap[S->getCond()] = PGO.getCurrentRegionCount();
392*0a6a1f1dSLionel Sambuc Visit(S->getCond());
393*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
394*0a6a1f1dSLionel Sambuc Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
395*0a6a1f1dSLionel Sambuc RecordNextStmtCount = true;
396*0a6a1f1dSLionel Sambuc }
397*0a6a1f1dSLionel Sambuc
VisitForStmt__anon7f44950c0111::ComputeRegionCounts398*0a6a1f1dSLionel Sambuc void VisitForStmt(const ForStmt *S) {
399*0a6a1f1dSLionel Sambuc RecordStmtCount(S);
400*0a6a1f1dSLionel Sambuc if (S->getInit())
401*0a6a1f1dSLionel Sambuc Visit(S->getInit());
402*0a6a1f1dSLionel Sambuc // Counter tracks the body of the loop.
403*0a6a1f1dSLionel Sambuc RegionCounter Cnt(PGO, S);
404*0a6a1f1dSLionel Sambuc BreakContinueStack.push_back(BreakContinue());
405*0a6a1f1dSLionel Sambuc // Visit the body region first. (This is basically the same as a while
406*0a6a1f1dSLionel Sambuc // loop; see further comments in VisitWhileStmt.)
407*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
408*0a6a1f1dSLionel Sambuc CountMap[S->getBody()] = PGO.getCurrentRegionCount();
409*0a6a1f1dSLionel Sambuc Visit(S->getBody());
410*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
411*0a6a1f1dSLionel Sambuc
412*0a6a1f1dSLionel Sambuc // The increment is essentially part of the body but it needs to include
413*0a6a1f1dSLionel Sambuc // the count for all the continue statements.
414*0a6a1f1dSLionel Sambuc if (S->getInc()) {
415*0a6a1f1dSLionel Sambuc Cnt.setCurrentRegionCount(PGO.getCurrentRegionCount() +
416*0a6a1f1dSLionel Sambuc BreakContinueStack.back().ContinueCount);
417*0a6a1f1dSLionel Sambuc CountMap[S->getInc()] = PGO.getCurrentRegionCount();
418*0a6a1f1dSLionel Sambuc Visit(S->getInc());
419*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
420*0a6a1f1dSLionel Sambuc }
421*0a6a1f1dSLionel Sambuc
422*0a6a1f1dSLionel Sambuc BreakContinue BC = BreakContinueStack.pop_back_val();
423*0a6a1f1dSLionel Sambuc
424*0a6a1f1dSLionel Sambuc // ...then go back and propagate counts through the condition.
425*0a6a1f1dSLionel Sambuc if (S->getCond()) {
426*0a6a1f1dSLionel Sambuc Cnt.setCurrentRegionCount(Cnt.getParentCount() +
427*0a6a1f1dSLionel Sambuc Cnt.getAdjustedCount() +
428*0a6a1f1dSLionel Sambuc BC.ContinueCount);
429*0a6a1f1dSLionel Sambuc CountMap[S->getCond()] = PGO.getCurrentRegionCount();
430*0a6a1f1dSLionel Sambuc Visit(S->getCond());
431*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
432*0a6a1f1dSLionel Sambuc }
433*0a6a1f1dSLionel Sambuc Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
434*0a6a1f1dSLionel Sambuc RecordNextStmtCount = true;
435*0a6a1f1dSLionel Sambuc }
436*0a6a1f1dSLionel Sambuc
VisitCXXForRangeStmt__anon7f44950c0111::ComputeRegionCounts437*0a6a1f1dSLionel Sambuc void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
438*0a6a1f1dSLionel Sambuc RecordStmtCount(S);
439*0a6a1f1dSLionel Sambuc Visit(S->getRangeStmt());
440*0a6a1f1dSLionel Sambuc Visit(S->getBeginEndStmt());
441*0a6a1f1dSLionel Sambuc // Counter tracks the body of the loop.
442*0a6a1f1dSLionel Sambuc RegionCounter Cnt(PGO, S);
443*0a6a1f1dSLionel Sambuc BreakContinueStack.push_back(BreakContinue());
444*0a6a1f1dSLionel Sambuc // Visit the body region first. (This is basically the same as a while
445*0a6a1f1dSLionel Sambuc // loop; see further comments in VisitWhileStmt.)
446*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
447*0a6a1f1dSLionel Sambuc CountMap[S->getLoopVarStmt()] = PGO.getCurrentRegionCount();
448*0a6a1f1dSLionel Sambuc Visit(S->getLoopVarStmt());
449*0a6a1f1dSLionel Sambuc Visit(S->getBody());
450*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
451*0a6a1f1dSLionel Sambuc
452*0a6a1f1dSLionel Sambuc // The increment is essentially part of the body but it needs to include
453*0a6a1f1dSLionel Sambuc // the count for all the continue statements.
454*0a6a1f1dSLionel Sambuc Cnt.setCurrentRegionCount(PGO.getCurrentRegionCount() +
455*0a6a1f1dSLionel Sambuc BreakContinueStack.back().ContinueCount);
456*0a6a1f1dSLionel Sambuc CountMap[S->getInc()] = PGO.getCurrentRegionCount();
457*0a6a1f1dSLionel Sambuc Visit(S->getInc());
458*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
459*0a6a1f1dSLionel Sambuc
460*0a6a1f1dSLionel Sambuc BreakContinue BC = BreakContinueStack.pop_back_val();
461*0a6a1f1dSLionel Sambuc
462*0a6a1f1dSLionel Sambuc // ...then go back and propagate counts through the condition.
463*0a6a1f1dSLionel Sambuc Cnt.setCurrentRegionCount(Cnt.getParentCount() +
464*0a6a1f1dSLionel Sambuc Cnt.getAdjustedCount() +
465*0a6a1f1dSLionel Sambuc BC.ContinueCount);
466*0a6a1f1dSLionel Sambuc CountMap[S->getCond()] = PGO.getCurrentRegionCount();
467*0a6a1f1dSLionel Sambuc Visit(S->getCond());
468*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
469*0a6a1f1dSLionel Sambuc Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
470*0a6a1f1dSLionel Sambuc RecordNextStmtCount = true;
471*0a6a1f1dSLionel Sambuc }
472*0a6a1f1dSLionel Sambuc
VisitObjCForCollectionStmt__anon7f44950c0111::ComputeRegionCounts473*0a6a1f1dSLionel Sambuc void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
474*0a6a1f1dSLionel Sambuc RecordStmtCount(S);
475*0a6a1f1dSLionel Sambuc Visit(S->getElement());
476*0a6a1f1dSLionel Sambuc // Counter tracks the body of the loop.
477*0a6a1f1dSLionel Sambuc RegionCounter Cnt(PGO, S);
478*0a6a1f1dSLionel Sambuc BreakContinueStack.push_back(BreakContinue());
479*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
480*0a6a1f1dSLionel Sambuc CountMap[S->getBody()] = PGO.getCurrentRegionCount();
481*0a6a1f1dSLionel Sambuc Visit(S->getBody());
482*0a6a1f1dSLionel Sambuc BreakContinue BC = BreakContinueStack.pop_back_val();
483*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
484*0a6a1f1dSLionel Sambuc Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
485*0a6a1f1dSLionel Sambuc RecordNextStmtCount = true;
486*0a6a1f1dSLionel Sambuc }
487*0a6a1f1dSLionel Sambuc
VisitSwitchStmt__anon7f44950c0111::ComputeRegionCounts488*0a6a1f1dSLionel Sambuc void VisitSwitchStmt(const SwitchStmt *S) {
489*0a6a1f1dSLionel Sambuc RecordStmtCount(S);
490*0a6a1f1dSLionel Sambuc Visit(S->getCond());
491*0a6a1f1dSLionel Sambuc PGO.setCurrentRegionUnreachable();
492*0a6a1f1dSLionel Sambuc BreakContinueStack.push_back(BreakContinue());
493*0a6a1f1dSLionel Sambuc Visit(S->getBody());
494*0a6a1f1dSLionel Sambuc // If the switch is inside a loop, add the continue counts.
495*0a6a1f1dSLionel Sambuc BreakContinue BC = BreakContinueStack.pop_back_val();
496*0a6a1f1dSLionel Sambuc if (!BreakContinueStack.empty())
497*0a6a1f1dSLionel Sambuc BreakContinueStack.back().ContinueCount += BC.ContinueCount;
498*0a6a1f1dSLionel Sambuc // Counter tracks the exit block of the switch.
499*0a6a1f1dSLionel Sambuc RegionCounter ExitCnt(PGO, S);
500*0a6a1f1dSLionel Sambuc ExitCnt.beginRegion();
501*0a6a1f1dSLionel Sambuc RecordNextStmtCount = true;
502*0a6a1f1dSLionel Sambuc }
503*0a6a1f1dSLionel Sambuc
VisitCaseStmt__anon7f44950c0111::ComputeRegionCounts504*0a6a1f1dSLionel Sambuc void VisitCaseStmt(const CaseStmt *S) {
505*0a6a1f1dSLionel Sambuc RecordNextStmtCount = false;
506*0a6a1f1dSLionel Sambuc // Counter for this particular case. This counts only jumps from the
507*0a6a1f1dSLionel Sambuc // switch header and does not include fallthrough from the case before
508*0a6a1f1dSLionel Sambuc // this one.
509*0a6a1f1dSLionel Sambuc RegionCounter Cnt(PGO, S);
510*0a6a1f1dSLionel Sambuc Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
511*0a6a1f1dSLionel Sambuc CountMap[S] = Cnt.getCount();
512*0a6a1f1dSLionel Sambuc RecordNextStmtCount = true;
513*0a6a1f1dSLionel Sambuc Visit(S->getSubStmt());
514*0a6a1f1dSLionel Sambuc }
515*0a6a1f1dSLionel Sambuc
VisitDefaultStmt__anon7f44950c0111::ComputeRegionCounts516*0a6a1f1dSLionel Sambuc void VisitDefaultStmt(const DefaultStmt *S) {
517*0a6a1f1dSLionel Sambuc RecordNextStmtCount = false;
518*0a6a1f1dSLionel Sambuc // Counter for this default case. This does not include fallthrough from
519*0a6a1f1dSLionel Sambuc // the previous case.
520*0a6a1f1dSLionel Sambuc RegionCounter Cnt(PGO, S);
521*0a6a1f1dSLionel Sambuc Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
522*0a6a1f1dSLionel Sambuc CountMap[S] = Cnt.getCount();
523*0a6a1f1dSLionel Sambuc RecordNextStmtCount = true;
524*0a6a1f1dSLionel Sambuc Visit(S->getSubStmt());
525*0a6a1f1dSLionel Sambuc }
526*0a6a1f1dSLionel Sambuc
VisitIfStmt__anon7f44950c0111::ComputeRegionCounts527*0a6a1f1dSLionel Sambuc void VisitIfStmt(const IfStmt *S) {
528*0a6a1f1dSLionel Sambuc RecordStmtCount(S);
529*0a6a1f1dSLionel Sambuc // Counter tracks the "then" part of an if statement. The count for
530*0a6a1f1dSLionel Sambuc // the "else" part, if it exists, will be calculated from this counter.
531*0a6a1f1dSLionel Sambuc RegionCounter Cnt(PGO, S);
532*0a6a1f1dSLionel Sambuc Visit(S->getCond());
533*0a6a1f1dSLionel Sambuc
534*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
535*0a6a1f1dSLionel Sambuc CountMap[S->getThen()] = PGO.getCurrentRegionCount();
536*0a6a1f1dSLionel Sambuc Visit(S->getThen());
537*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
538*0a6a1f1dSLionel Sambuc
539*0a6a1f1dSLionel Sambuc if (S->getElse()) {
540*0a6a1f1dSLionel Sambuc Cnt.beginElseRegion();
541*0a6a1f1dSLionel Sambuc CountMap[S->getElse()] = PGO.getCurrentRegionCount();
542*0a6a1f1dSLionel Sambuc Visit(S->getElse());
543*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
544*0a6a1f1dSLionel Sambuc }
545*0a6a1f1dSLionel Sambuc Cnt.applyAdjustmentsToRegion(0);
546*0a6a1f1dSLionel Sambuc RecordNextStmtCount = true;
547*0a6a1f1dSLionel Sambuc }
548*0a6a1f1dSLionel Sambuc
VisitCXXTryStmt__anon7f44950c0111::ComputeRegionCounts549*0a6a1f1dSLionel Sambuc void VisitCXXTryStmt(const CXXTryStmt *S) {
550*0a6a1f1dSLionel Sambuc RecordStmtCount(S);
551*0a6a1f1dSLionel Sambuc Visit(S->getTryBlock());
552*0a6a1f1dSLionel Sambuc for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
553*0a6a1f1dSLionel Sambuc Visit(S->getHandler(I));
554*0a6a1f1dSLionel Sambuc // Counter tracks the continuation block of the try statement.
555*0a6a1f1dSLionel Sambuc RegionCounter Cnt(PGO, S);
556*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
557*0a6a1f1dSLionel Sambuc RecordNextStmtCount = true;
558*0a6a1f1dSLionel Sambuc }
559*0a6a1f1dSLionel Sambuc
VisitCXXCatchStmt__anon7f44950c0111::ComputeRegionCounts560*0a6a1f1dSLionel Sambuc void VisitCXXCatchStmt(const CXXCatchStmt *S) {
561*0a6a1f1dSLionel Sambuc RecordNextStmtCount = false;
562*0a6a1f1dSLionel Sambuc // Counter tracks the catch statement's handler block.
563*0a6a1f1dSLionel Sambuc RegionCounter Cnt(PGO, S);
564*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
565*0a6a1f1dSLionel Sambuc CountMap[S] = PGO.getCurrentRegionCount();
566*0a6a1f1dSLionel Sambuc Visit(S->getHandlerBlock());
567*0a6a1f1dSLionel Sambuc }
568*0a6a1f1dSLionel Sambuc
VisitAbstractConditionalOperator__anon7f44950c0111::ComputeRegionCounts569*0a6a1f1dSLionel Sambuc void VisitAbstractConditionalOperator(
570*0a6a1f1dSLionel Sambuc const AbstractConditionalOperator *E) {
571*0a6a1f1dSLionel Sambuc RecordStmtCount(E);
572*0a6a1f1dSLionel Sambuc // Counter tracks the "true" part of a conditional operator. The
573*0a6a1f1dSLionel Sambuc // count in the "false" part will be calculated from this counter.
574*0a6a1f1dSLionel Sambuc RegionCounter Cnt(PGO, E);
575*0a6a1f1dSLionel Sambuc Visit(E->getCond());
576*0a6a1f1dSLionel Sambuc
577*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
578*0a6a1f1dSLionel Sambuc CountMap[E->getTrueExpr()] = PGO.getCurrentRegionCount();
579*0a6a1f1dSLionel Sambuc Visit(E->getTrueExpr());
580*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
581*0a6a1f1dSLionel Sambuc
582*0a6a1f1dSLionel Sambuc Cnt.beginElseRegion();
583*0a6a1f1dSLionel Sambuc CountMap[E->getFalseExpr()] = PGO.getCurrentRegionCount();
584*0a6a1f1dSLionel Sambuc Visit(E->getFalseExpr());
585*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
586*0a6a1f1dSLionel Sambuc
587*0a6a1f1dSLionel Sambuc Cnt.applyAdjustmentsToRegion(0);
588*0a6a1f1dSLionel Sambuc RecordNextStmtCount = true;
589*0a6a1f1dSLionel Sambuc }
590*0a6a1f1dSLionel Sambuc
VisitBinLAnd__anon7f44950c0111::ComputeRegionCounts591*0a6a1f1dSLionel Sambuc void VisitBinLAnd(const BinaryOperator *E) {
592*0a6a1f1dSLionel Sambuc RecordStmtCount(E);
593*0a6a1f1dSLionel Sambuc // Counter tracks the right hand side of a logical and operator.
594*0a6a1f1dSLionel Sambuc RegionCounter Cnt(PGO, E);
595*0a6a1f1dSLionel Sambuc Visit(E->getLHS());
596*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
597*0a6a1f1dSLionel Sambuc CountMap[E->getRHS()] = PGO.getCurrentRegionCount();
598*0a6a1f1dSLionel Sambuc Visit(E->getRHS());
599*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
600*0a6a1f1dSLionel Sambuc Cnt.applyAdjustmentsToRegion(0);
601*0a6a1f1dSLionel Sambuc RecordNextStmtCount = true;
602*0a6a1f1dSLionel Sambuc }
603*0a6a1f1dSLionel Sambuc
VisitBinLOr__anon7f44950c0111::ComputeRegionCounts604*0a6a1f1dSLionel Sambuc void VisitBinLOr(const BinaryOperator *E) {
605*0a6a1f1dSLionel Sambuc RecordStmtCount(E);
606*0a6a1f1dSLionel Sambuc // Counter tracks the right hand side of a logical or operator.
607*0a6a1f1dSLionel Sambuc RegionCounter Cnt(PGO, E);
608*0a6a1f1dSLionel Sambuc Visit(E->getLHS());
609*0a6a1f1dSLionel Sambuc Cnt.beginRegion();
610*0a6a1f1dSLionel Sambuc CountMap[E->getRHS()] = PGO.getCurrentRegionCount();
611*0a6a1f1dSLionel Sambuc Visit(E->getRHS());
612*0a6a1f1dSLionel Sambuc Cnt.adjustForControlFlow();
613*0a6a1f1dSLionel Sambuc Cnt.applyAdjustmentsToRegion(0);
614*0a6a1f1dSLionel Sambuc RecordNextStmtCount = true;
615*0a6a1f1dSLionel Sambuc }
616*0a6a1f1dSLionel Sambuc };
617*0a6a1f1dSLionel Sambuc }
618*0a6a1f1dSLionel Sambuc
combine(HashType Type)619*0a6a1f1dSLionel Sambuc void PGOHash::combine(HashType Type) {
620*0a6a1f1dSLionel Sambuc // Check that we never combine 0 and only have six bits.
621*0a6a1f1dSLionel Sambuc assert(Type && "Hash is invalid: unexpected type 0");
622*0a6a1f1dSLionel Sambuc assert(unsigned(Type) < TooBig && "Hash is invalid: too many types");
623*0a6a1f1dSLionel Sambuc
624*0a6a1f1dSLionel Sambuc // Pass through MD5 if enough work has built up.
625*0a6a1f1dSLionel Sambuc if (Count && Count % NumTypesPerWord == 0) {
626*0a6a1f1dSLionel Sambuc using namespace llvm::support;
627*0a6a1f1dSLionel Sambuc uint64_t Swapped = endian::byte_swap<uint64_t, little>(Working);
628*0a6a1f1dSLionel Sambuc MD5.update(llvm::makeArrayRef((uint8_t *)&Swapped, sizeof(Swapped)));
629*0a6a1f1dSLionel Sambuc Working = 0;
630*0a6a1f1dSLionel Sambuc }
631*0a6a1f1dSLionel Sambuc
632*0a6a1f1dSLionel Sambuc // Accumulate the current type.
633*0a6a1f1dSLionel Sambuc ++Count;
634*0a6a1f1dSLionel Sambuc Working = Working << NumBitsPerType | Type;
635*0a6a1f1dSLionel Sambuc }
636*0a6a1f1dSLionel Sambuc
finalize()637*0a6a1f1dSLionel Sambuc uint64_t PGOHash::finalize() {
638*0a6a1f1dSLionel Sambuc // Use Working as the hash directly if we never used MD5.
639*0a6a1f1dSLionel Sambuc if (Count <= NumTypesPerWord)
640*0a6a1f1dSLionel Sambuc // No need to byte swap here, since none of the math was endian-dependent.
641*0a6a1f1dSLionel Sambuc // This number will be byte-swapped as required on endianness transitions,
642*0a6a1f1dSLionel Sambuc // so we will see the same value on the other side.
643*0a6a1f1dSLionel Sambuc return Working;
644*0a6a1f1dSLionel Sambuc
645*0a6a1f1dSLionel Sambuc // Check for remaining work in Working.
646*0a6a1f1dSLionel Sambuc if (Working)
647*0a6a1f1dSLionel Sambuc MD5.update(Working);
648*0a6a1f1dSLionel Sambuc
649*0a6a1f1dSLionel Sambuc // Finalize the MD5 and return the hash.
650*0a6a1f1dSLionel Sambuc llvm::MD5::MD5Result Result;
651*0a6a1f1dSLionel Sambuc MD5.final(Result);
652*0a6a1f1dSLionel Sambuc using namespace llvm::support;
653*0a6a1f1dSLionel Sambuc return endian::read<uint64_t, little, unaligned>(Result);
654*0a6a1f1dSLionel Sambuc }
655*0a6a1f1dSLionel Sambuc
checkGlobalDecl(GlobalDecl GD)656*0a6a1f1dSLionel Sambuc void CodeGenPGO::checkGlobalDecl(GlobalDecl GD) {
657*0a6a1f1dSLionel Sambuc // Make sure we only emit coverage mapping for one constructor/destructor.
658*0a6a1f1dSLionel Sambuc // Clang emits several functions for the constructor and the destructor of
659*0a6a1f1dSLionel Sambuc // a class. Every function is instrumented, but we only want to provide
660*0a6a1f1dSLionel Sambuc // coverage for one of them. Because of that we only emit the coverage mapping
661*0a6a1f1dSLionel Sambuc // for the base constructor/destructor.
662*0a6a1f1dSLionel Sambuc if ((isa<CXXConstructorDecl>(GD.getDecl()) &&
663*0a6a1f1dSLionel Sambuc GD.getCtorType() != Ctor_Base) ||
664*0a6a1f1dSLionel Sambuc (isa<CXXDestructorDecl>(GD.getDecl()) &&
665*0a6a1f1dSLionel Sambuc GD.getDtorType() != Dtor_Base)) {
666*0a6a1f1dSLionel Sambuc SkipCoverageMapping = true;
667*0a6a1f1dSLionel Sambuc }
668*0a6a1f1dSLionel Sambuc }
669*0a6a1f1dSLionel Sambuc
assignRegionCounters(const Decl * D,llvm::Function * Fn)670*0a6a1f1dSLionel Sambuc void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) {
671*0a6a1f1dSLionel Sambuc bool InstrumentRegions = CGM.getCodeGenOpts().ProfileInstrGenerate;
672*0a6a1f1dSLionel Sambuc llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
673*0a6a1f1dSLionel Sambuc if (!InstrumentRegions && !PGOReader)
674*0a6a1f1dSLionel Sambuc return;
675*0a6a1f1dSLionel Sambuc if (D->isImplicit())
676*0a6a1f1dSLionel Sambuc return;
677*0a6a1f1dSLionel Sambuc CGM.ClearUnusedCoverageMapping(D);
678*0a6a1f1dSLionel Sambuc setFuncName(Fn);
679*0a6a1f1dSLionel Sambuc
680*0a6a1f1dSLionel Sambuc mapRegionCounters(D);
681*0a6a1f1dSLionel Sambuc if (CGM.getCodeGenOpts().CoverageMapping)
682*0a6a1f1dSLionel Sambuc emitCounterRegionMapping(D);
683*0a6a1f1dSLionel Sambuc if (PGOReader) {
684*0a6a1f1dSLionel Sambuc SourceManager &SM = CGM.getContext().getSourceManager();
685*0a6a1f1dSLionel Sambuc loadRegionCounts(PGOReader, SM.isInMainFile(D->getLocation()));
686*0a6a1f1dSLionel Sambuc computeRegionCounts(D);
687*0a6a1f1dSLionel Sambuc applyFunctionAttributes(PGOReader, Fn);
688*0a6a1f1dSLionel Sambuc }
689*0a6a1f1dSLionel Sambuc }
690*0a6a1f1dSLionel Sambuc
mapRegionCounters(const Decl * D)691*0a6a1f1dSLionel Sambuc void CodeGenPGO::mapRegionCounters(const Decl *D) {
692*0a6a1f1dSLionel Sambuc RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>);
693*0a6a1f1dSLionel Sambuc MapRegionCounters Walker(*RegionCounterMap);
694*0a6a1f1dSLionel Sambuc if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
695*0a6a1f1dSLionel Sambuc Walker.TraverseDecl(const_cast<FunctionDecl *>(FD));
696*0a6a1f1dSLionel Sambuc else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
697*0a6a1f1dSLionel Sambuc Walker.TraverseDecl(const_cast<ObjCMethodDecl *>(MD));
698*0a6a1f1dSLionel Sambuc else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
699*0a6a1f1dSLionel Sambuc Walker.TraverseDecl(const_cast<BlockDecl *>(BD));
700*0a6a1f1dSLionel Sambuc else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
701*0a6a1f1dSLionel Sambuc Walker.TraverseDecl(const_cast<CapturedDecl *>(CD));
702*0a6a1f1dSLionel Sambuc assert(Walker.NextCounter > 0 && "no entry counter mapped for decl");
703*0a6a1f1dSLionel Sambuc NumRegionCounters = Walker.NextCounter;
704*0a6a1f1dSLionel Sambuc FunctionHash = Walker.Hash.finalize();
705*0a6a1f1dSLionel Sambuc }
706*0a6a1f1dSLionel Sambuc
emitCounterRegionMapping(const Decl * D)707*0a6a1f1dSLionel Sambuc void CodeGenPGO::emitCounterRegionMapping(const Decl *D) {
708*0a6a1f1dSLionel Sambuc if (SkipCoverageMapping)
709*0a6a1f1dSLionel Sambuc return;
710*0a6a1f1dSLionel Sambuc // Don't map the functions inside the system headers
711*0a6a1f1dSLionel Sambuc auto Loc = D->getBody()->getLocStart();
712*0a6a1f1dSLionel Sambuc if (CGM.getContext().getSourceManager().isInSystemHeader(Loc))
713*0a6a1f1dSLionel Sambuc return;
714*0a6a1f1dSLionel Sambuc
715*0a6a1f1dSLionel Sambuc std::string CoverageMapping;
716*0a6a1f1dSLionel Sambuc llvm::raw_string_ostream OS(CoverageMapping);
717*0a6a1f1dSLionel Sambuc CoverageMappingGen MappingGen(*CGM.getCoverageMapping(),
718*0a6a1f1dSLionel Sambuc CGM.getContext().getSourceManager(),
719*0a6a1f1dSLionel Sambuc CGM.getLangOpts(), RegionCounterMap.get());
720*0a6a1f1dSLionel Sambuc MappingGen.emitCounterMapping(D, OS);
721*0a6a1f1dSLionel Sambuc OS.flush();
722*0a6a1f1dSLionel Sambuc
723*0a6a1f1dSLionel Sambuc if (CoverageMapping.empty())
724*0a6a1f1dSLionel Sambuc return;
725*0a6a1f1dSLionel Sambuc
726*0a6a1f1dSLionel Sambuc CGM.getCoverageMapping()->addFunctionMappingRecord(
727*0a6a1f1dSLionel Sambuc FuncNameVar, FuncName, FunctionHash, CoverageMapping);
728*0a6a1f1dSLionel Sambuc }
729*0a6a1f1dSLionel Sambuc
730*0a6a1f1dSLionel Sambuc void
emitEmptyCounterMapping(const Decl * D,StringRef FuncName,llvm::GlobalValue::LinkageTypes Linkage)731*0a6a1f1dSLionel Sambuc CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef FuncName,
732*0a6a1f1dSLionel Sambuc llvm::GlobalValue::LinkageTypes Linkage) {
733*0a6a1f1dSLionel Sambuc if (SkipCoverageMapping)
734*0a6a1f1dSLionel Sambuc return;
735*0a6a1f1dSLionel Sambuc setFuncName(FuncName, Linkage);
736*0a6a1f1dSLionel Sambuc
737*0a6a1f1dSLionel Sambuc // Don't map the functions inside the system headers
738*0a6a1f1dSLionel Sambuc auto Loc = D->getBody()->getLocStart();
739*0a6a1f1dSLionel Sambuc if (CGM.getContext().getSourceManager().isInSystemHeader(Loc))
740*0a6a1f1dSLionel Sambuc return;
741*0a6a1f1dSLionel Sambuc
742*0a6a1f1dSLionel Sambuc std::string CoverageMapping;
743*0a6a1f1dSLionel Sambuc llvm::raw_string_ostream OS(CoverageMapping);
744*0a6a1f1dSLionel Sambuc CoverageMappingGen MappingGen(*CGM.getCoverageMapping(),
745*0a6a1f1dSLionel Sambuc CGM.getContext().getSourceManager(),
746*0a6a1f1dSLionel Sambuc CGM.getLangOpts());
747*0a6a1f1dSLionel Sambuc MappingGen.emitEmptyMapping(D, OS);
748*0a6a1f1dSLionel Sambuc OS.flush();
749*0a6a1f1dSLionel Sambuc
750*0a6a1f1dSLionel Sambuc if (CoverageMapping.empty())
751*0a6a1f1dSLionel Sambuc return;
752*0a6a1f1dSLionel Sambuc
753*0a6a1f1dSLionel Sambuc CGM.getCoverageMapping()->addFunctionMappingRecord(
754*0a6a1f1dSLionel Sambuc FuncNameVar, FuncName, FunctionHash, CoverageMapping);
755*0a6a1f1dSLionel Sambuc }
756*0a6a1f1dSLionel Sambuc
computeRegionCounts(const Decl * D)757*0a6a1f1dSLionel Sambuc void CodeGenPGO::computeRegionCounts(const Decl *D) {
758*0a6a1f1dSLionel Sambuc StmtCountMap.reset(new llvm::DenseMap<const Stmt *, uint64_t>);
759*0a6a1f1dSLionel Sambuc ComputeRegionCounts Walker(*StmtCountMap, *this);
760*0a6a1f1dSLionel Sambuc if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
761*0a6a1f1dSLionel Sambuc Walker.VisitFunctionDecl(FD);
762*0a6a1f1dSLionel Sambuc else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
763*0a6a1f1dSLionel Sambuc Walker.VisitObjCMethodDecl(MD);
764*0a6a1f1dSLionel Sambuc else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
765*0a6a1f1dSLionel Sambuc Walker.VisitBlockDecl(BD);
766*0a6a1f1dSLionel Sambuc else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
767*0a6a1f1dSLionel Sambuc Walker.VisitCapturedDecl(const_cast<CapturedDecl *>(CD));
768*0a6a1f1dSLionel Sambuc }
769*0a6a1f1dSLionel Sambuc
770*0a6a1f1dSLionel Sambuc void
applyFunctionAttributes(llvm::IndexedInstrProfReader * PGOReader,llvm::Function * Fn)771*0a6a1f1dSLionel Sambuc CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
772*0a6a1f1dSLionel Sambuc llvm::Function *Fn) {
773*0a6a1f1dSLionel Sambuc if (!haveRegionCounts())
774*0a6a1f1dSLionel Sambuc return;
775*0a6a1f1dSLionel Sambuc
776*0a6a1f1dSLionel Sambuc uint64_t MaxFunctionCount = PGOReader->getMaximumFunctionCount();
777*0a6a1f1dSLionel Sambuc uint64_t FunctionCount = getRegionCount(0);
778*0a6a1f1dSLionel Sambuc if (FunctionCount >= (uint64_t)(0.3 * (double)MaxFunctionCount))
779*0a6a1f1dSLionel Sambuc // Turn on InlineHint attribute for hot functions.
780*0a6a1f1dSLionel Sambuc // FIXME: 30% is from preliminary tuning on SPEC, it may not be optimal.
781*0a6a1f1dSLionel Sambuc Fn->addFnAttr(llvm::Attribute::InlineHint);
782*0a6a1f1dSLionel Sambuc else if (FunctionCount <= (uint64_t)(0.01 * (double)MaxFunctionCount))
783*0a6a1f1dSLionel Sambuc // Turn on Cold attribute for cold functions.
784*0a6a1f1dSLionel Sambuc // FIXME: 1% is from preliminary tuning on SPEC, it may not be optimal.
785*0a6a1f1dSLionel Sambuc Fn->addFnAttr(llvm::Attribute::Cold);
786*0a6a1f1dSLionel Sambuc }
787*0a6a1f1dSLionel Sambuc
emitCounterIncrement(CGBuilderTy & Builder,unsigned Counter)788*0a6a1f1dSLionel Sambuc void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, unsigned Counter) {
789*0a6a1f1dSLionel Sambuc if (!CGM.getCodeGenOpts().ProfileInstrGenerate || !RegionCounterMap)
790*0a6a1f1dSLionel Sambuc return;
791*0a6a1f1dSLionel Sambuc if (!Builder.GetInsertPoint())
792*0a6a1f1dSLionel Sambuc return;
793*0a6a1f1dSLionel Sambuc auto *I8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
794*0a6a1f1dSLionel Sambuc Builder.CreateCall4(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment),
795*0a6a1f1dSLionel Sambuc llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
796*0a6a1f1dSLionel Sambuc Builder.getInt64(FunctionHash),
797*0a6a1f1dSLionel Sambuc Builder.getInt32(NumRegionCounters),
798*0a6a1f1dSLionel Sambuc Builder.getInt32(Counter));
799*0a6a1f1dSLionel Sambuc }
800*0a6a1f1dSLionel Sambuc
loadRegionCounts(llvm::IndexedInstrProfReader * PGOReader,bool IsInMainFile)801*0a6a1f1dSLionel Sambuc void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
802*0a6a1f1dSLionel Sambuc bool IsInMainFile) {
803*0a6a1f1dSLionel Sambuc CGM.getPGOStats().addVisited(IsInMainFile);
804*0a6a1f1dSLionel Sambuc RegionCounts.clear();
805*0a6a1f1dSLionel Sambuc if (std::error_code EC =
806*0a6a1f1dSLionel Sambuc PGOReader->getFunctionCounts(FuncName, FunctionHash, RegionCounts)) {
807*0a6a1f1dSLionel Sambuc if (EC == llvm::instrprof_error::unknown_function)
808*0a6a1f1dSLionel Sambuc CGM.getPGOStats().addMissing(IsInMainFile);
809*0a6a1f1dSLionel Sambuc else if (EC == llvm::instrprof_error::hash_mismatch)
810*0a6a1f1dSLionel Sambuc CGM.getPGOStats().addMismatched(IsInMainFile);
811*0a6a1f1dSLionel Sambuc else if (EC == llvm::instrprof_error::malformed)
812*0a6a1f1dSLionel Sambuc // TODO: Consider a more specific warning for this case.
813*0a6a1f1dSLionel Sambuc CGM.getPGOStats().addMismatched(IsInMainFile);
814*0a6a1f1dSLionel Sambuc RegionCounts.clear();
815*0a6a1f1dSLionel Sambuc }
816*0a6a1f1dSLionel Sambuc }
817*0a6a1f1dSLionel Sambuc
818*0a6a1f1dSLionel Sambuc /// \brief Calculate what to divide by to scale weights.
819*0a6a1f1dSLionel Sambuc ///
820*0a6a1f1dSLionel Sambuc /// Given the maximum weight, calculate a divisor that will scale all the
821*0a6a1f1dSLionel Sambuc /// weights to strictly less than UINT32_MAX.
calculateWeightScale(uint64_t MaxWeight)822*0a6a1f1dSLionel Sambuc static uint64_t calculateWeightScale(uint64_t MaxWeight) {
823*0a6a1f1dSLionel Sambuc return MaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1;
824*0a6a1f1dSLionel Sambuc }
825*0a6a1f1dSLionel Sambuc
826*0a6a1f1dSLionel Sambuc /// \brief Scale an individual branch weight (and add 1).
827*0a6a1f1dSLionel Sambuc ///
828*0a6a1f1dSLionel Sambuc /// Scale a 64-bit weight down to 32-bits using \c Scale.
829*0a6a1f1dSLionel Sambuc ///
830*0a6a1f1dSLionel Sambuc /// According to Laplace's Rule of Succession, it is better to compute the
831*0a6a1f1dSLionel Sambuc /// weight based on the count plus 1, so universally add 1 to the value.
832*0a6a1f1dSLionel Sambuc ///
833*0a6a1f1dSLionel Sambuc /// \pre \c Scale was calculated by \a calculateWeightScale() with a weight no
834*0a6a1f1dSLionel Sambuc /// greater than \c Weight.
scaleBranchWeight(uint64_t Weight,uint64_t Scale)835*0a6a1f1dSLionel Sambuc static uint32_t scaleBranchWeight(uint64_t Weight, uint64_t Scale) {
836*0a6a1f1dSLionel Sambuc assert(Scale && "scale by 0?");
837*0a6a1f1dSLionel Sambuc uint64_t Scaled = Weight / Scale + 1;
838*0a6a1f1dSLionel Sambuc assert(Scaled <= UINT32_MAX && "overflow 32-bits");
839*0a6a1f1dSLionel Sambuc return Scaled;
840*0a6a1f1dSLionel Sambuc }
841*0a6a1f1dSLionel Sambuc
createBranchWeights(uint64_t TrueCount,uint64_t FalseCount)842*0a6a1f1dSLionel Sambuc llvm::MDNode *CodeGenPGO::createBranchWeights(uint64_t TrueCount,
843*0a6a1f1dSLionel Sambuc uint64_t FalseCount) {
844*0a6a1f1dSLionel Sambuc // Check for empty weights.
845*0a6a1f1dSLionel Sambuc if (!TrueCount && !FalseCount)
846*0a6a1f1dSLionel Sambuc return nullptr;
847*0a6a1f1dSLionel Sambuc
848*0a6a1f1dSLionel Sambuc // Calculate how to scale down to 32-bits.
849*0a6a1f1dSLionel Sambuc uint64_t Scale = calculateWeightScale(std::max(TrueCount, FalseCount));
850*0a6a1f1dSLionel Sambuc
851*0a6a1f1dSLionel Sambuc llvm::MDBuilder MDHelper(CGM.getLLVMContext());
852*0a6a1f1dSLionel Sambuc return MDHelper.createBranchWeights(scaleBranchWeight(TrueCount, Scale),
853*0a6a1f1dSLionel Sambuc scaleBranchWeight(FalseCount, Scale));
854*0a6a1f1dSLionel Sambuc }
855*0a6a1f1dSLionel Sambuc
createBranchWeights(ArrayRef<uint64_t> Weights)856*0a6a1f1dSLionel Sambuc llvm::MDNode *CodeGenPGO::createBranchWeights(ArrayRef<uint64_t> Weights) {
857*0a6a1f1dSLionel Sambuc // We need at least two elements to create meaningful weights.
858*0a6a1f1dSLionel Sambuc if (Weights.size() < 2)
859*0a6a1f1dSLionel Sambuc return nullptr;
860*0a6a1f1dSLionel Sambuc
861*0a6a1f1dSLionel Sambuc // Check for empty weights.
862*0a6a1f1dSLionel Sambuc uint64_t MaxWeight = *std::max_element(Weights.begin(), Weights.end());
863*0a6a1f1dSLionel Sambuc if (MaxWeight == 0)
864*0a6a1f1dSLionel Sambuc return nullptr;
865*0a6a1f1dSLionel Sambuc
866*0a6a1f1dSLionel Sambuc // Calculate how to scale down to 32-bits.
867*0a6a1f1dSLionel Sambuc uint64_t Scale = calculateWeightScale(MaxWeight);
868*0a6a1f1dSLionel Sambuc
869*0a6a1f1dSLionel Sambuc SmallVector<uint32_t, 16> ScaledWeights;
870*0a6a1f1dSLionel Sambuc ScaledWeights.reserve(Weights.size());
871*0a6a1f1dSLionel Sambuc for (uint64_t W : Weights)
872*0a6a1f1dSLionel Sambuc ScaledWeights.push_back(scaleBranchWeight(W, Scale));
873*0a6a1f1dSLionel Sambuc
874*0a6a1f1dSLionel Sambuc llvm::MDBuilder MDHelper(CGM.getLLVMContext());
875*0a6a1f1dSLionel Sambuc return MDHelper.createBranchWeights(ScaledWeights);
876*0a6a1f1dSLionel Sambuc }
877*0a6a1f1dSLionel Sambuc
createLoopWeights(const Stmt * Cond,RegionCounter & Cnt)878*0a6a1f1dSLionel Sambuc llvm::MDNode *CodeGenPGO::createLoopWeights(const Stmt *Cond,
879*0a6a1f1dSLionel Sambuc RegionCounter &Cnt) {
880*0a6a1f1dSLionel Sambuc if (!haveRegionCounts())
881*0a6a1f1dSLionel Sambuc return nullptr;
882*0a6a1f1dSLionel Sambuc uint64_t LoopCount = Cnt.getCount();
883*0a6a1f1dSLionel Sambuc uint64_t CondCount = 0;
884*0a6a1f1dSLionel Sambuc bool Found = getStmtCount(Cond, CondCount);
885*0a6a1f1dSLionel Sambuc assert(Found && "missing expected loop condition count");
886*0a6a1f1dSLionel Sambuc (void)Found;
887*0a6a1f1dSLionel Sambuc if (CondCount == 0)
888*0a6a1f1dSLionel Sambuc return nullptr;
889*0a6a1f1dSLionel Sambuc return createBranchWeights(LoopCount,
890*0a6a1f1dSLionel Sambuc std::max(CondCount, LoopCount) - LoopCount);
891*0a6a1f1dSLionel Sambuc }
892