1ef512b99SJustin Bogner //===--- CodeGenPGO.cpp - PGO Instrumentation for LLVM CodeGen --*- C++ -*-===//
2ef512b99SJustin Bogner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ef512b99SJustin Bogner //
7ef512b99SJustin Bogner //===----------------------------------------------------------------------===//
8ef512b99SJustin Bogner //
9ef512b99SJustin Bogner // Instrumentation-based profile-guided optimization
10ef512b99SJustin Bogner //
11ef512b99SJustin Bogner //===----------------------------------------------------------------------===//
12ef512b99SJustin Bogner 
13ef512b99SJustin Bogner #include "CodeGenPGO.h"
14ef512b99SJustin Bogner #include "CodeGenFunction.h"
15ee02499aSAlex Lorenz #include "CoverageMappingGen.h"
16ef512b99SJustin Bogner #include "clang/AST/RecursiveASTVisitor.h"
17ef512b99SJustin Bogner #include "clang/AST/StmtVisitor.h"
18970ac605SJustin Bogner #include "llvm/IR/Intrinsics.h"
19ef512b99SJustin Bogner #include "llvm/IR/MDBuilder.h"
204c1a1d3cSReid Kleckner #include "llvm/Support/CommandLine.h"
214bc7731aSDuncan P. N. Exon Smith #include "llvm/Support/Endian.h"
22ef512b99SJustin Bogner #include "llvm/Support/FileSystem.h"
234bc7731aSDuncan P. N. Exon Smith #include "llvm/Support/MD5.h"
24ef512b99SJustin Bogner 
258065f0b9SZachary Turner static llvm::cl::opt<bool>
26*d86a206fSFangrui Song     EnableValueProfiling("enable-value-profiling",
278065f0b9SZachary Turner                          llvm::cl::desc("Enable value profiling"),
288065f0b9SZachary Turner                          llvm::cl::Hidden, llvm::cl::init(false));
29518276a5SBetul Buyukkurt 
30ef512b99SJustin Bogner using namespace clang;
31ef512b99SJustin Bogner using namespace CodeGen;
32ef512b99SJustin Bogner 
setFuncName(StringRef Name,llvm::GlobalValue::LinkageTypes Linkage)33ee02499aSAlex Lorenz void CodeGenPGO::setFuncName(StringRef Name,
34ee02499aSAlex Lorenz                              llvm::GlobalValue::LinkageTypes Linkage) {
35a569e24aSXinliang David Li   llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
36a569e24aSXinliang David Li   FuncName = llvm::getPGOFuncName(
37a569e24aSXinliang David Li       Name, Linkage, CGM.getCodeGenOpts().MainFileName,
38a569e24aSXinliang David Li       PGOReader ? PGOReader->getVersion() : llvm::IndexedInstrProf::Version);
39970ac605SJustin Bogner 
40970ac605SJustin Bogner   // If we're generating a profile, create a variable for the name.
419837ef56SRong Xu   if (CGM.getCodeGenOpts().hasProfileClangInstr())
422d7ec5a9SXinliang David Li     FuncNameVar = llvm::createPGOFuncNameVar(CGM.getModule(), Linkage, FuncName);
43da1ebedeSBob Wilson }
44da1ebedeSBob Wilson 
setFuncName(llvm::Function * Fn)45ee02499aSAlex Lorenz void CodeGenPGO::setFuncName(llvm::Function *Fn) {
46ee02499aSAlex Lorenz   setFuncName(Fn->getName(), Fn->getLinkage());
47f932f542SRong Xu   // Create PGOFuncName meta data.
48f932f542SRong Xu   llvm::createPGOFuncNameMetadata(*Fn, FuncName);
49ee02499aSAlex Lorenz }
50ee02499aSAlex Lorenz 
516186971aSVedant Kumar /// The version of the PGO hash algorithm.
526186971aSVedant Kumar enum PGOHashVersion : unsigned {
536186971aSVedant Kumar   PGO_HASH_V1,
546186971aSVedant Kumar   PGO_HASH_V2,
55de02a75eSserge-sans-paille   PGO_HASH_V3,
566186971aSVedant Kumar 
576186971aSVedant Kumar   // Keep this set to the latest hash version.
58de02a75eSserge-sans-paille   PGO_HASH_LATEST = PGO_HASH_V3
596186971aSVedant Kumar };
606186971aSVedant Kumar 
61ef512b99SJustin Bogner namespace {
629fc8faf9SAdrian Prantl /// Stable hasher for PGO region counters.
634bc7731aSDuncan P. N. Exon Smith ///
644bc7731aSDuncan P. N. Exon Smith /// PGOHash produces a stable hash of a given function's control flow.
654bc7731aSDuncan P. N. Exon Smith ///
664bc7731aSDuncan P. N. Exon Smith /// Changing the output of this hash will invalidate all previously generated
674bc7731aSDuncan P. N. Exon Smith /// profiles -- i.e., don't do it.
684bc7731aSDuncan P. N. Exon Smith ///
694bc7731aSDuncan P. N. Exon Smith /// \note  When this hash does eventually change (years?), we still need to
704bc7731aSDuncan P. N. Exon Smith /// support old hashes.  We'll need to pull in the version number from the
714bc7731aSDuncan P. N. Exon Smith /// profile data format and use the matching hash function.
724bc7731aSDuncan P. N. Exon Smith class PGOHash {
734bc7731aSDuncan P. N. Exon Smith   uint64_t Working;
744bc7731aSDuncan P. N. Exon Smith   unsigned Count;
756186971aSVedant Kumar   PGOHashVersion HashVersion;
764bc7731aSDuncan P. N. Exon Smith   llvm::MD5 MD5;
774bc7731aSDuncan P. N. Exon Smith 
784bc7731aSDuncan P. N. Exon Smith   static const int NumBitsPerType = 6;
794bc7731aSDuncan P. N. Exon Smith   static const unsigned NumTypesPerWord = sizeof(uint64_t) * 8 / NumBitsPerType;
804bc7731aSDuncan P. N. Exon Smith   static const unsigned TooBig = 1u << NumBitsPerType;
814bc7731aSDuncan P. N. Exon Smith 
824bc7731aSDuncan P. N. Exon Smith public:
839fc8faf9SAdrian Prantl   /// Hash values for AST nodes.
844bc7731aSDuncan P. N. Exon Smith   ///
854bc7731aSDuncan P. N. Exon Smith   /// Distinct values for AST nodes that have region counters attached.
864bc7731aSDuncan P. N. Exon Smith   ///
874bc7731aSDuncan P. N. Exon Smith   /// These values must be stable.  All new members must be added at the end,
884bc7731aSDuncan P. N. Exon Smith   /// and no members should be removed.  Changing the enumeration value for an
894bc7731aSDuncan P. N. Exon Smith   /// AST node will affect the hash of every function that contains that node.
904bc7731aSDuncan P. N. Exon Smith   enum HashType : unsigned char {
914bc7731aSDuncan P. N. Exon Smith     None = 0,
924bc7731aSDuncan P. N. Exon Smith     LabelStmt = 1,
934bc7731aSDuncan P. N. Exon Smith     WhileStmt,
944bc7731aSDuncan P. N. Exon Smith     DoStmt,
954bc7731aSDuncan P. N. Exon Smith     ForStmt,
964bc7731aSDuncan P. N. Exon Smith     CXXForRangeStmt,
974bc7731aSDuncan P. N. Exon Smith     ObjCForCollectionStmt,
984bc7731aSDuncan P. N. Exon Smith     SwitchStmt,
994bc7731aSDuncan P. N. Exon Smith     CaseStmt,
1004bc7731aSDuncan P. N. Exon Smith     DefaultStmt,
1014bc7731aSDuncan P. N. Exon Smith     IfStmt,
1024bc7731aSDuncan P. N. Exon Smith     CXXTryStmt,
1034bc7731aSDuncan P. N. Exon Smith     CXXCatchStmt,
1044bc7731aSDuncan P. N. Exon Smith     ConditionalOperator,
1054bc7731aSDuncan P. N. Exon Smith     BinaryOperatorLAnd,
1064bc7731aSDuncan P. N. Exon Smith     BinaryOperatorLOr,
1074bc7731aSDuncan P. N. Exon Smith     BinaryConditionalOperator,
1086186971aSVedant Kumar     // The preceding values are available with PGO_HASH_V1.
1096186971aSVedant Kumar 
1106186971aSVedant Kumar     EndOfScope,
1116186971aSVedant Kumar     IfThenBranch,
1126186971aSVedant Kumar     IfElseBranch,
1136186971aSVedant Kumar     GotoStmt,
1146186971aSVedant Kumar     IndirectGotoStmt,
1156186971aSVedant Kumar     BreakStmt,
1166186971aSVedant Kumar     ContinueStmt,
1176186971aSVedant Kumar     ReturnStmt,
1186186971aSVedant Kumar     ThrowExpr,
1196186971aSVedant Kumar     UnaryOperatorLNot,
1206186971aSVedant Kumar     BinaryOperatorLT,
1216186971aSVedant Kumar     BinaryOperatorGT,
1226186971aSVedant Kumar     BinaryOperatorLE,
1236186971aSVedant Kumar     BinaryOperatorGE,
1246186971aSVedant Kumar     BinaryOperatorEQ,
1256186971aSVedant Kumar     BinaryOperatorNE,
126de02a75eSserge-sans-paille     // The preceding values are available since PGO_HASH_V2.
1274bc7731aSDuncan P. N. Exon Smith 
1284bc7731aSDuncan P. N. Exon Smith     // Keep this last.  It's for the static assert that follows.
1294bc7731aSDuncan P. N. Exon Smith     LastHashType
1304bc7731aSDuncan P. N. Exon Smith   };
1314bc7731aSDuncan P. N. Exon Smith   static_assert(LastHashType <= TooBig, "Too many types in HashType");
1324bc7731aSDuncan P. N. Exon Smith 
PGOHash(PGOHashVersion HashVersion)1336186971aSVedant Kumar   PGOHash(PGOHashVersion HashVersion)
134d677a7cbSKazu Hirata       : Working(0), Count(0), HashVersion(HashVersion) {}
1354bc7731aSDuncan P. N. Exon Smith   void combine(HashType Type);
1364bc7731aSDuncan P. N. Exon Smith   uint64_t finalize();
getHashVersion() const1376186971aSVedant Kumar   PGOHashVersion getHashVersion() const { return HashVersion; }
1384bc7731aSDuncan P. N. Exon Smith };
1394bc7731aSDuncan P. N. Exon Smith const int PGOHash::NumBitsPerType;
1404bc7731aSDuncan P. N. Exon Smith const unsigned PGOHash::NumTypesPerWord;
1414bc7731aSDuncan P. N. Exon Smith const unsigned PGOHash::TooBig;
1424bc7731aSDuncan P. N. Exon Smith 
1436186971aSVedant Kumar /// Get the PGO hash version used in the given indexed profile.
getPGOHashVersion(llvm::IndexedInstrProfReader * PGOReader,CodeGenModule & CGM)1446186971aSVedant Kumar static PGOHashVersion getPGOHashVersion(llvm::IndexedInstrProfReader *PGOReader,
1456186971aSVedant Kumar                                         CodeGenModule &CGM) {
1466186971aSVedant Kumar   if (PGOReader->getVersion() <= 4)
1476186971aSVedant Kumar     return PGO_HASH_V1;
148de02a75eSserge-sans-paille   if (PGOReader->getVersion() <= 5)
1496186971aSVedant Kumar     return PGO_HASH_V2;
150de02a75eSserge-sans-paille   return PGO_HASH_V3;
1516186971aSVedant Kumar }
1526186971aSVedant Kumar 
153d8931425SBob Wilson /// A RecursiveASTVisitor that fills a map of statements to PGO counters.
154d8931425SBob Wilson struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
1556186971aSVedant Kumar   using Base = RecursiveASTVisitor<MapRegionCounters>;
1566186971aSVedant Kumar 
157ef512b99SJustin Bogner   /// The next counter value to assign.
158ef512b99SJustin Bogner   unsigned NextCounter;
1594bc7731aSDuncan P. N. Exon Smith   /// The function hash.
1604bc7731aSDuncan P. N. Exon Smith   PGOHash Hash;
161ef512b99SJustin Bogner   /// The map of statements to counters.
1623586be72SDuncan P. N. Exon Smith   llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
1639f2967bcSAlan Phipps   /// The profile version.
1649f2967bcSAlan Phipps   uint64_t ProfileVersion;
165ef512b99SJustin Bogner 
MapRegionCounters__anonc3cc86690111::MapRegionCounters1669f2967bcSAlan Phipps   MapRegionCounters(PGOHashVersion HashVersion, uint64_t ProfileVersion,
1676186971aSVedant Kumar                     llvm::DenseMap<const Stmt *, unsigned> &CounterMap)
1689f2967bcSAlan Phipps       : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap),
1699f2967bcSAlan Phipps         ProfileVersion(ProfileVersion) {}
170ef512b99SJustin Bogner 
171191ec63bSJustin Bogner   // Blocks and lambdas are handled as separate functions, so we need not
172191ec63bSJustin Bogner   // traverse them in the parent context.
TraverseBlockExpr__anonc3cc86690111::MapRegionCounters173191ec63bSJustin Bogner   bool TraverseBlockExpr(BlockExpr *BE) { return true; }
TraverseLambdaExpr__anonc3cc86690111::MapRegionCounters174e60151c9SSam McCall   bool TraverseLambdaExpr(LambdaExpr *LE) {
175e60151c9SSam McCall     // Traverse the captures, but not the body.
1768dc7b982SMark de Wever     for (auto C : zip(LE->captures(), LE->capture_inits()))
177e60151c9SSam McCall       TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C));
178e60151c9SSam McCall     return true;
179e60151c9SSam McCall   }
TraverseCapturedStmt__anonc3cc86690111::MapRegionCounters18081ab90f7SJustin Bogner   bool TraverseCapturedStmt(CapturedStmt *CS) { return true; }
181ef512b99SJustin Bogner 
VisitDecl__anonc3cc86690111::MapRegionCounters182d8931425SBob Wilson   bool VisitDecl(const Decl *D) {
183d8931425SBob Wilson     switch (D->getKind()) {
184d8931425SBob Wilson     default:
185d8931425SBob Wilson       break;
186d8931425SBob Wilson     case Decl::Function:
187d8931425SBob Wilson     case Decl::CXXMethod:
188d8931425SBob Wilson     case Decl::CXXConstructor:
189d8931425SBob Wilson     case Decl::CXXDestructor:
190d8931425SBob Wilson     case Decl::CXXConversion:
191d8931425SBob Wilson     case Decl::ObjCMethod:
192d8931425SBob Wilson     case Decl::Block:
19381ab90f7SJustin Bogner     case Decl::Captured:
1944a2f5ae8SDuncan P. N. Exon Smith       CounterMap[D->getBody()] = NextCounter++;
195d8931425SBob Wilson       break;
196ef512b99SJustin Bogner     }
197d8931425SBob Wilson     return true;
1985ec8fe19SBob Wilson   }
199d8931425SBob Wilson 
2006186971aSVedant Kumar   /// If \p S gets a fresh counter, update the counter mappings. Return the
2016186971aSVedant Kumar   /// V1 hash of \p S.
updateCounterMappings__anonc3cc86690111::MapRegionCounters2026186971aSVedant Kumar   PGOHash::HashType updateCounterMappings(Stmt *S) {
2036186971aSVedant Kumar     auto Type = getHashType(PGO_HASH_V1, S);
2046186971aSVedant Kumar     if (Type != PGOHash::None)
2054bc7731aSDuncan P. N. Exon Smith       CounterMap[S] = NextCounter++;
2066186971aSVedant Kumar     return Type;
2076186971aSVedant Kumar   }
2086186971aSVedant Kumar 
2099f2967bcSAlan Phipps   /// The RHS of all logical operators gets a fresh counter in order to count
2109f2967bcSAlan Phipps   /// how many times the RHS evaluates to true or false, depending on the
2119f2967bcSAlan Phipps   /// semantics of the operator. This is only valid for ">= v7" of the profile
2129f2967bcSAlan Phipps   /// version so that we facilitate backward compatibility.
VisitBinaryOperator__anonc3cc86690111::MapRegionCounters2139f2967bcSAlan Phipps   bool VisitBinaryOperator(BinaryOperator *S) {
2149f2967bcSAlan Phipps     if (ProfileVersion >= llvm::IndexedInstrProf::Version7)
2159f2967bcSAlan Phipps       if (S->isLogicalOp() &&
2169f2967bcSAlan Phipps           CodeGenFunction::isInstrumentedCondition(S->getRHS()))
2179f2967bcSAlan Phipps         CounterMap[S->getRHS()] = NextCounter++;
2189f2967bcSAlan Phipps     return Base::VisitBinaryOperator(S);
2199f2967bcSAlan Phipps   }
2209f2967bcSAlan Phipps 
2216186971aSVedant Kumar   /// Include \p S in the function hash.
VisitStmt__anonc3cc86690111::MapRegionCounters2226186971aSVedant Kumar   bool VisitStmt(Stmt *S) {
2236186971aSVedant Kumar     auto Type = updateCounterMappings(S);
2246186971aSVedant Kumar     if (Hash.getHashVersion() != PGO_HASH_V1)
2256186971aSVedant Kumar       Type = getHashType(Hash.getHashVersion(), S);
2266186971aSVedant Kumar     if (Type != PGOHash::None)
2274bc7731aSDuncan P. N. Exon Smith       Hash.combine(Type);
2284bc7731aSDuncan P. N. Exon Smith     return true;
2294bc7731aSDuncan P. N. Exon Smith   }
2306186971aSVedant Kumar 
TraverseIfStmt__anonc3cc86690111::MapRegionCounters2316186971aSVedant Kumar   bool TraverseIfStmt(IfStmt *If) {
2326186971aSVedant Kumar     // If we used the V1 hash, use the default traversal.
2336186971aSVedant Kumar     if (Hash.getHashVersion() == PGO_HASH_V1)
2346186971aSVedant Kumar       return Base::TraverseIfStmt(If);
2356186971aSVedant Kumar 
2366186971aSVedant Kumar     // Otherwise, keep track of which branch we're in while traversing.
2376186971aSVedant Kumar     VisitStmt(If);
2386186971aSVedant Kumar     for (Stmt *CS : If->children()) {
2396186971aSVedant Kumar       if (!CS)
2406186971aSVedant Kumar         continue;
2416186971aSVedant Kumar       if (CS == If->getThen())
2426186971aSVedant Kumar         Hash.combine(PGOHash::IfThenBranch);
2436186971aSVedant Kumar       else if (CS == If->getElse())
2446186971aSVedant Kumar         Hash.combine(PGOHash::IfElseBranch);
2456186971aSVedant Kumar       TraverseStmt(CS);
2466186971aSVedant Kumar     }
2476186971aSVedant Kumar     Hash.combine(PGOHash::EndOfScope);
2486186971aSVedant Kumar     return true;
2496186971aSVedant Kumar   }
2506186971aSVedant Kumar 
2516186971aSVedant Kumar // If the statement type \p N is nestable, and its nesting impacts profile
2526186971aSVedant Kumar // stability, define a custom traversal which tracks the end of the statement
2536186971aSVedant Kumar // in the hash (provided we're not using the V1 hash).
2546186971aSVedant Kumar #define DEFINE_NESTABLE_TRAVERSAL(N)                                           \
2556186971aSVedant Kumar   bool Traverse##N(N *S) {                                                     \
2566186971aSVedant Kumar     Base::Traverse##N(S);                                                      \
2576186971aSVedant Kumar     if (Hash.getHashVersion() != PGO_HASH_V1)                                  \
2586186971aSVedant Kumar       Hash.combine(PGOHash::EndOfScope);                                       \
2596186971aSVedant Kumar     return true;                                                               \
2606186971aSVedant Kumar   }
2616186971aSVedant Kumar 
2626186971aSVedant Kumar   DEFINE_NESTABLE_TRAVERSAL(WhileStmt)
DEFINE_NESTABLE_TRAVERSAL__anonc3cc86690111::MapRegionCounters2636186971aSVedant Kumar   DEFINE_NESTABLE_TRAVERSAL(DoStmt)
2646186971aSVedant Kumar   DEFINE_NESTABLE_TRAVERSAL(ForStmt)
2656186971aSVedant Kumar   DEFINE_NESTABLE_TRAVERSAL(CXXForRangeStmt)
2666186971aSVedant Kumar   DEFINE_NESTABLE_TRAVERSAL(ObjCForCollectionStmt)
2676186971aSVedant Kumar   DEFINE_NESTABLE_TRAVERSAL(CXXTryStmt)
2686186971aSVedant Kumar   DEFINE_NESTABLE_TRAVERSAL(CXXCatchStmt)
2696186971aSVedant Kumar 
2706186971aSVedant Kumar   /// Get version \p HashVersion of the PGO hash for \p S.
2716186971aSVedant Kumar   PGOHash::HashType getHashType(PGOHashVersion HashVersion, const Stmt *S) {
272d8931425SBob Wilson     switch (S->getStmtClass()) {
273d8931425SBob Wilson     default:
274d8931425SBob Wilson       break;
275d8931425SBob Wilson     case Stmt::LabelStmtClass:
2764bc7731aSDuncan P. N. Exon Smith       return PGOHash::LabelStmt;
277d8931425SBob Wilson     case Stmt::WhileStmtClass:
2784bc7731aSDuncan P. N. Exon Smith       return PGOHash::WhileStmt;
279d8931425SBob Wilson     case Stmt::DoStmtClass:
2804bc7731aSDuncan P. N. Exon Smith       return PGOHash::DoStmt;
281d8931425SBob Wilson     case Stmt::ForStmtClass:
2824bc7731aSDuncan P. N. Exon Smith       return PGOHash::ForStmt;
283d8931425SBob Wilson     case Stmt::CXXForRangeStmtClass:
2844bc7731aSDuncan P. N. Exon Smith       return PGOHash::CXXForRangeStmt;
285d8931425SBob Wilson     case Stmt::ObjCForCollectionStmtClass:
2864bc7731aSDuncan P. N. Exon Smith       return PGOHash::ObjCForCollectionStmt;
287d8931425SBob Wilson     case Stmt::SwitchStmtClass:
2884bc7731aSDuncan P. N. Exon Smith       return PGOHash::SwitchStmt;
289d8931425SBob Wilson     case Stmt::CaseStmtClass:
2904bc7731aSDuncan P. N. Exon Smith       return PGOHash::CaseStmt;
291d8931425SBob Wilson     case Stmt::DefaultStmtClass:
2924bc7731aSDuncan P. N. Exon Smith       return PGOHash::DefaultStmt;
293d8931425SBob Wilson     case Stmt::IfStmtClass:
2944bc7731aSDuncan P. N. Exon Smith       return PGOHash::IfStmt;
295d8931425SBob Wilson     case Stmt::CXXTryStmtClass:
2964bc7731aSDuncan P. N. Exon Smith       return PGOHash::CXXTryStmt;
297d8931425SBob Wilson     case Stmt::CXXCatchStmtClass:
2984bc7731aSDuncan P. N. Exon Smith       return PGOHash::CXXCatchStmt;
299d8931425SBob Wilson     case Stmt::ConditionalOperatorClass:
3004bc7731aSDuncan P. N. Exon Smith       return PGOHash::ConditionalOperator;
301d8931425SBob Wilson     case Stmt::BinaryConditionalOperatorClass:
3024bc7731aSDuncan P. N. Exon Smith       return PGOHash::BinaryConditionalOperator;
303d8931425SBob Wilson     case Stmt::BinaryOperatorClass: {
304d8931425SBob Wilson       const BinaryOperator *BO = cast<BinaryOperator>(S);
3054bc7731aSDuncan P. N. Exon Smith       if (BO->getOpcode() == BO_LAnd)
3064bc7731aSDuncan P. N. Exon Smith         return PGOHash::BinaryOperatorLAnd;
3074bc7731aSDuncan P. N. Exon Smith       if (BO->getOpcode() == BO_LOr)
3084bc7731aSDuncan P. N. Exon Smith         return PGOHash::BinaryOperatorLOr;
309de02a75eSserge-sans-paille       if (HashVersion >= PGO_HASH_V2) {
3106186971aSVedant Kumar         switch (BO->getOpcode()) {
3116186971aSVedant Kumar         default:
3126186971aSVedant Kumar           break;
3136186971aSVedant Kumar         case BO_LT:
3146186971aSVedant Kumar           return PGOHash::BinaryOperatorLT;
3156186971aSVedant Kumar         case BO_GT:
3166186971aSVedant Kumar           return PGOHash::BinaryOperatorGT;
3176186971aSVedant Kumar         case BO_LE:
3186186971aSVedant Kumar           return PGOHash::BinaryOperatorLE;
3196186971aSVedant Kumar         case BO_GE:
3206186971aSVedant Kumar           return PGOHash::BinaryOperatorGE;
3216186971aSVedant Kumar         case BO_EQ:
3226186971aSVedant Kumar           return PGOHash::BinaryOperatorEQ;
3236186971aSVedant Kumar         case BO_NE:
3246186971aSVedant Kumar           return PGOHash::BinaryOperatorNE;
3256186971aSVedant Kumar         }
3266186971aSVedant Kumar       }
327d8931425SBob Wilson       break;
328ef512b99SJustin Bogner     }
329ef512b99SJustin Bogner     }
3306186971aSVedant Kumar 
331de02a75eSserge-sans-paille     if (HashVersion >= PGO_HASH_V2) {
3326186971aSVedant Kumar       switch (S->getStmtClass()) {
3336186971aSVedant Kumar       default:
3346186971aSVedant Kumar         break;
3356186971aSVedant Kumar       case Stmt::GotoStmtClass:
3366186971aSVedant Kumar         return PGOHash::GotoStmt;
3376186971aSVedant Kumar       case Stmt::IndirectGotoStmtClass:
3386186971aSVedant Kumar         return PGOHash::IndirectGotoStmt;
3396186971aSVedant Kumar       case Stmt::BreakStmtClass:
3406186971aSVedant Kumar         return PGOHash::BreakStmt;
3416186971aSVedant Kumar       case Stmt::ContinueStmtClass:
3426186971aSVedant Kumar         return PGOHash::ContinueStmt;
3436186971aSVedant Kumar       case Stmt::ReturnStmtClass:
3446186971aSVedant Kumar         return PGOHash::ReturnStmt;
3456186971aSVedant Kumar       case Stmt::CXXThrowExprClass:
3466186971aSVedant Kumar         return PGOHash::ThrowExpr;
3476186971aSVedant Kumar       case Stmt::UnaryOperatorClass: {
3486186971aSVedant Kumar         const UnaryOperator *UO = cast<UnaryOperator>(S);
3496186971aSVedant Kumar         if (UO->getOpcode() == UO_LNot)
3506186971aSVedant Kumar           return PGOHash::UnaryOperatorLNot;
3516186971aSVedant Kumar         break;
3526186971aSVedant Kumar       }
3536186971aSVedant Kumar       }
3546186971aSVedant Kumar     }
3556186971aSVedant Kumar 
3564bc7731aSDuncan P. N. Exon Smith     return PGOHash::None;
357ef512b99SJustin Bogner   }
358ef512b99SJustin Bogner };
359bf854f0fSBob Wilson 
360bf854f0fSBob Wilson /// A StmtVisitor that propagates the raw counts through the AST and
361bf854f0fSBob Wilson /// records the count at statements where the value may change.
362bf854f0fSBob Wilson struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
363bf854f0fSBob Wilson   /// PGO state.
364bf854f0fSBob Wilson   CodeGenPGO &PGO;
365bf854f0fSBob Wilson 
366bf854f0fSBob Wilson   /// A flag that is set when the current count should be recorded on the
367bf854f0fSBob Wilson   /// next statement, such as at the exit of a loop.
368bf854f0fSBob Wilson   bool RecordNextStmtCount;
369bf854f0fSBob Wilson 
370a909abfdSJustin Bogner   /// The count at the current location in the traversal.
371a909abfdSJustin Bogner   uint64_t CurrentCount;
372a909abfdSJustin Bogner 
373bf854f0fSBob Wilson   /// The map of statements to count values.
3743586be72SDuncan P. N. Exon Smith   llvm::DenseMap<const Stmt *, uint64_t> &CountMap;
375bf854f0fSBob Wilson 
376bf854f0fSBob Wilson   /// BreakContinueStack - Keep counts of breaks and continues inside loops.
377bf854f0fSBob Wilson   struct BreakContinue {
378bf854f0fSBob Wilson     uint64_t BreakCount;
379bf854f0fSBob Wilson     uint64_t ContinueCount;
BreakContinue__anonc3cc86690111::ComputeRegionCounts::BreakContinue380bf854f0fSBob Wilson     BreakContinue() : BreakCount(0), ContinueCount(0) {}
381bf854f0fSBob Wilson   };
382bf854f0fSBob Wilson   SmallVector<BreakContinue, 8> BreakContinueStack;
383bf854f0fSBob Wilson 
ComputeRegionCounts__anonc3cc86690111::ComputeRegionCounts3843586be72SDuncan P. N. Exon Smith   ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &CountMap,
3853586be72SDuncan P. N. Exon Smith                       CodeGenPGO &PGO)
3863586be72SDuncan P. N. Exon Smith       : PGO(PGO), RecordNextStmtCount(false), CountMap(CountMap) {}
387bf854f0fSBob Wilson 
RecordStmtCount__anonc3cc86690111::ComputeRegionCounts388bf854f0fSBob Wilson   void RecordStmtCount(const Stmt *S) {
389bf854f0fSBob Wilson     if (RecordNextStmtCount) {
390a909abfdSJustin Bogner       CountMap[S] = CurrentCount;
391bf854f0fSBob Wilson       RecordNextStmtCount = false;
392bf854f0fSBob Wilson     }
393bf854f0fSBob Wilson   }
394bf854f0fSBob Wilson 
39507193cc8SJustin Bogner   /// Set and return the current count.
setCount__anonc3cc86690111::ComputeRegionCounts39607193cc8SJustin Bogner   uint64_t setCount(uint64_t Count) {
397a909abfdSJustin Bogner     CurrentCount = Count;
39807193cc8SJustin Bogner     return Count;
39907193cc8SJustin Bogner   }
40007193cc8SJustin Bogner 
VisitStmt__anonc3cc86690111::ComputeRegionCounts401bf854f0fSBob Wilson   void VisitStmt(const Stmt *S) {
402bf854f0fSBob Wilson     RecordStmtCount(S);
403642f173aSBenjamin Kramer     for (const Stmt *Child : S->children())
404642f173aSBenjamin Kramer       if (Child)
405642f173aSBenjamin Kramer         this->Visit(Child);
406bf854f0fSBob Wilson   }
407bf854f0fSBob Wilson 
VisitFunctionDecl__anonc3cc86690111::ComputeRegionCounts4084a2f5ae8SDuncan P. N. Exon Smith   void VisitFunctionDecl(const FunctionDecl *D) {
409d8931425SBob Wilson     // Counter tracks entry to the function body.
41007193cc8SJustin Bogner     uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
41107193cc8SJustin Bogner     CountMap[D->getBody()] = BodyCount;
4124a2f5ae8SDuncan P. N. Exon Smith     Visit(D->getBody());
413bf854f0fSBob Wilson   }
414bf854f0fSBob Wilson 
415191ec63bSJustin Bogner   // Skip lambda expressions. We visit these as FunctionDecls when we're
416191ec63bSJustin Bogner   // generating them and aren't interested in the body when generating a
417191ec63bSJustin Bogner   // parent context.
VisitLambdaExpr__anonc3cc86690111::ComputeRegionCounts418191ec63bSJustin Bogner   void VisitLambdaExpr(const LambdaExpr *LE) {}
419191ec63bSJustin Bogner 
VisitCapturedDecl__anonc3cc86690111::ComputeRegionCounts42081ab90f7SJustin Bogner   void VisitCapturedDecl(const CapturedDecl *D) {
42181ab90f7SJustin Bogner     // Counter tracks entry to the capture body.
42207193cc8SJustin Bogner     uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
42307193cc8SJustin Bogner     CountMap[D->getBody()] = BodyCount;
42481ab90f7SJustin Bogner     Visit(D->getBody());
42581ab90f7SJustin Bogner   }
42681ab90f7SJustin Bogner 
VisitObjCMethodDecl__anonc3cc86690111::ComputeRegionCounts4274a2f5ae8SDuncan P. N. Exon Smith   void VisitObjCMethodDecl(const ObjCMethodDecl *D) {
428d8931425SBob Wilson     // Counter tracks entry to the method body.
42907193cc8SJustin Bogner     uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
43007193cc8SJustin Bogner     CountMap[D->getBody()] = BodyCount;
4314a2f5ae8SDuncan P. N. Exon Smith     Visit(D->getBody());
4325ec8fe19SBob Wilson   }
4335ec8fe19SBob Wilson 
VisitBlockDecl__anonc3cc86690111::ComputeRegionCounts4344a2f5ae8SDuncan P. N. Exon Smith   void VisitBlockDecl(const BlockDecl *D) {
435d8931425SBob Wilson     // Counter tracks entry to the block body.
43607193cc8SJustin Bogner     uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
43707193cc8SJustin Bogner     CountMap[D->getBody()] = BodyCount;
4384a2f5ae8SDuncan P. N. Exon Smith     Visit(D->getBody());
439c845c00aSBob Wilson   }
440c845c00aSBob Wilson 
VisitReturnStmt__anonc3cc86690111::ComputeRegionCounts441bf854f0fSBob Wilson   void VisitReturnStmt(const ReturnStmt *S) {
442bf854f0fSBob Wilson     RecordStmtCount(S);
443bf854f0fSBob Wilson     if (S->getRetValue())
444bf854f0fSBob Wilson       Visit(S->getRetValue());
445a909abfdSJustin Bogner     CurrentCount = 0;
446bf854f0fSBob Wilson     RecordNextStmtCount = true;
447bf854f0fSBob Wilson   }
448bf854f0fSBob Wilson 
VisitCXXThrowExpr__anonc3cc86690111::ComputeRegionCounts449f959febfSJustin Bogner   void VisitCXXThrowExpr(const CXXThrowExpr *E) {
450f959febfSJustin Bogner     RecordStmtCount(E);
451f959febfSJustin Bogner     if (E->getSubExpr())
452f959febfSJustin Bogner       Visit(E->getSubExpr());
453a909abfdSJustin Bogner     CurrentCount = 0;
454f959febfSJustin Bogner     RecordNextStmtCount = true;
455f959febfSJustin Bogner   }
456f959febfSJustin Bogner 
VisitGotoStmt__anonc3cc86690111::ComputeRegionCounts457bf854f0fSBob Wilson   void VisitGotoStmt(const GotoStmt *S) {
458bf854f0fSBob Wilson     RecordStmtCount(S);
459a909abfdSJustin Bogner     CurrentCount = 0;
460bf854f0fSBob Wilson     RecordNextStmtCount = true;
461bf854f0fSBob Wilson   }
462bf854f0fSBob Wilson 
VisitLabelStmt__anonc3cc86690111::ComputeRegionCounts463bf854f0fSBob Wilson   void VisitLabelStmt(const LabelStmt *S) {
464bf854f0fSBob Wilson     RecordNextStmtCount = false;
465d8931425SBob Wilson     // Counter tracks the block following the label.
46607193cc8SJustin Bogner     uint64_t BlockCount = setCount(PGO.getRegionCount(S));
46707193cc8SJustin Bogner     CountMap[S] = BlockCount;
468bf854f0fSBob Wilson     Visit(S->getSubStmt());
469bf854f0fSBob Wilson   }
470bf854f0fSBob Wilson 
VisitBreakStmt__anonc3cc86690111::ComputeRegionCounts471bf854f0fSBob Wilson   void VisitBreakStmt(const BreakStmt *S) {
472bf854f0fSBob Wilson     RecordStmtCount(S);
473bf854f0fSBob Wilson     assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
474a909abfdSJustin Bogner     BreakContinueStack.back().BreakCount += CurrentCount;
475a909abfdSJustin Bogner     CurrentCount = 0;
476bf854f0fSBob Wilson     RecordNextStmtCount = true;
477bf854f0fSBob Wilson   }
478bf854f0fSBob Wilson 
VisitContinueStmt__anonc3cc86690111::ComputeRegionCounts479bf854f0fSBob Wilson   void VisitContinueStmt(const ContinueStmt *S) {
480bf854f0fSBob Wilson     RecordStmtCount(S);
481bf854f0fSBob Wilson     assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
482a909abfdSJustin Bogner     BreakContinueStack.back().ContinueCount += CurrentCount;
483a909abfdSJustin Bogner     CurrentCount = 0;
484bf854f0fSBob Wilson     RecordNextStmtCount = true;
485bf854f0fSBob Wilson   }
486bf854f0fSBob Wilson 
VisitWhileStmt__anonc3cc86690111::ComputeRegionCounts487bf854f0fSBob Wilson   void VisitWhileStmt(const WhileStmt *S) {
488bf854f0fSBob Wilson     RecordStmtCount(S);
489a909abfdSJustin Bogner     uint64_t ParentCount = CurrentCount;
49007193cc8SJustin Bogner 
491bf854f0fSBob Wilson     BreakContinueStack.push_back(BreakContinue());
492bf854f0fSBob Wilson     // Visit the body region first so the break/continue adjustments can be
493bf854f0fSBob Wilson     // included when visiting the condition.
49407193cc8SJustin Bogner     uint64_t BodyCount = setCount(PGO.getRegionCount(S));
495a909abfdSJustin Bogner     CountMap[S->getBody()] = CurrentCount;
496bf854f0fSBob Wilson     Visit(S->getBody());
497a909abfdSJustin Bogner     uint64_t BackedgeCount = CurrentCount;
498bf854f0fSBob Wilson 
499bf854f0fSBob Wilson     // ...then go back and propagate counts through the condition. The count
500bf854f0fSBob Wilson     // at the start of the condition is the sum of the incoming edges,
501bf854f0fSBob Wilson     // the backedge from the end of the loop body, and the edges from
502bf854f0fSBob Wilson     // continue statements.
503bf854f0fSBob Wilson     BreakContinue BC = BreakContinueStack.pop_back_val();
50407193cc8SJustin Bogner     uint64_t CondCount =
50507193cc8SJustin Bogner         setCount(ParentCount + BackedgeCount + BC.ContinueCount);
50607193cc8SJustin Bogner     CountMap[S->getCond()] = CondCount;
507bf854f0fSBob Wilson     Visit(S->getCond());
50807193cc8SJustin Bogner     setCount(BC.BreakCount + CondCount - BodyCount);
509bf854f0fSBob Wilson     RecordNextStmtCount = true;
510bf854f0fSBob Wilson   }
511bf854f0fSBob Wilson 
VisitDoStmt__anonc3cc86690111::ComputeRegionCounts512bf854f0fSBob Wilson   void VisitDoStmt(const DoStmt *S) {
513bf854f0fSBob Wilson     RecordStmtCount(S);
51407193cc8SJustin Bogner     uint64_t LoopCount = PGO.getRegionCount(S);
51507193cc8SJustin Bogner 
516bf854f0fSBob Wilson     BreakContinueStack.push_back(BreakContinue());
51707193cc8SJustin Bogner     // The count doesn't include the fallthrough from the parent scope. Add it.
518a909abfdSJustin Bogner     uint64_t BodyCount = setCount(LoopCount + CurrentCount);
51907193cc8SJustin Bogner     CountMap[S->getBody()] = BodyCount;
520bf854f0fSBob Wilson     Visit(S->getBody());
521a909abfdSJustin Bogner     uint64_t BackedgeCount = CurrentCount;
522bf854f0fSBob Wilson 
523bf854f0fSBob Wilson     BreakContinue BC = BreakContinueStack.pop_back_val();
524bf854f0fSBob Wilson     // The count at the start of the condition is equal to the count at the
52507193cc8SJustin Bogner     // end of the body, plus any continues.
52607193cc8SJustin Bogner     uint64_t CondCount = setCount(BackedgeCount + BC.ContinueCount);
52707193cc8SJustin Bogner     CountMap[S->getCond()] = CondCount;
528bf854f0fSBob Wilson     Visit(S->getCond());
52907193cc8SJustin Bogner     setCount(BC.BreakCount + CondCount - LoopCount);
530bf854f0fSBob Wilson     RecordNextStmtCount = true;
531bf854f0fSBob Wilson   }
532bf854f0fSBob Wilson 
VisitForStmt__anonc3cc86690111::ComputeRegionCounts533bf854f0fSBob Wilson   void VisitForStmt(const ForStmt *S) {
534bf854f0fSBob Wilson     RecordStmtCount(S);
535bf854f0fSBob Wilson     if (S->getInit())
536bf854f0fSBob Wilson       Visit(S->getInit());
53707193cc8SJustin Bogner 
538a909abfdSJustin Bogner     uint64_t ParentCount = CurrentCount;
53907193cc8SJustin Bogner 
540bf854f0fSBob Wilson     BreakContinueStack.push_back(BreakContinue());
541bf854f0fSBob Wilson     // Visit the body region first. (This is basically the same as a while
542bf854f0fSBob Wilson     // loop; see further comments in VisitWhileStmt.)
54307193cc8SJustin Bogner     uint64_t BodyCount = setCount(PGO.getRegionCount(S));
54407193cc8SJustin Bogner     CountMap[S->getBody()] = BodyCount;
545bf854f0fSBob Wilson     Visit(S->getBody());
546a909abfdSJustin Bogner     uint64_t BackedgeCount = CurrentCount;
54707193cc8SJustin Bogner     BreakContinue BC = BreakContinueStack.pop_back_val();
548bf854f0fSBob Wilson 
549bf854f0fSBob Wilson     // The increment is essentially part of the body but it needs to include
550bf854f0fSBob Wilson     // the count for all the continue statements.
551bf854f0fSBob Wilson     if (S->getInc()) {
55207193cc8SJustin Bogner       uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
55307193cc8SJustin Bogner       CountMap[S->getInc()] = IncCount;
554bf854f0fSBob Wilson       Visit(S->getInc());
555bf854f0fSBob Wilson     }
556bf854f0fSBob Wilson 
557bf854f0fSBob Wilson     // ...then go back and propagate counts through the condition.
55807193cc8SJustin Bogner     uint64_t CondCount =
55907193cc8SJustin Bogner         setCount(ParentCount + BackedgeCount + BC.ContinueCount);
560bf854f0fSBob Wilson     if (S->getCond()) {
56107193cc8SJustin Bogner       CountMap[S->getCond()] = CondCount;
562bf854f0fSBob Wilson       Visit(S->getCond());
563bf854f0fSBob Wilson     }
56407193cc8SJustin Bogner     setCount(BC.BreakCount + CondCount - BodyCount);
565bf854f0fSBob Wilson     RecordNextStmtCount = true;
566bf854f0fSBob Wilson   }
567bf854f0fSBob Wilson 
VisitCXXForRangeStmt__anonc3cc86690111::ComputeRegionCounts568bf854f0fSBob Wilson   void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
569bf854f0fSBob Wilson     RecordStmtCount(S);
5708baa5001SRichard Smith     if (S->getInit())
5718baa5001SRichard Smith       Visit(S->getInit());
5722e5d4845SJustin Bogner     Visit(S->getLoopVarStmt());
573bf854f0fSBob Wilson     Visit(S->getRangeStmt());
57401694c34SRichard Smith     Visit(S->getBeginStmt());
57501694c34SRichard Smith     Visit(S->getEndStmt());
57607193cc8SJustin Bogner 
577a909abfdSJustin Bogner     uint64_t ParentCount = CurrentCount;
578bf854f0fSBob Wilson     BreakContinueStack.push_back(BreakContinue());
579bf854f0fSBob Wilson     // Visit the body region first. (This is basically the same as a while
580bf854f0fSBob Wilson     // loop; see further comments in VisitWhileStmt.)
58107193cc8SJustin Bogner     uint64_t BodyCount = setCount(PGO.getRegionCount(S));
58207193cc8SJustin Bogner     CountMap[S->getBody()] = BodyCount;
583bf854f0fSBob Wilson     Visit(S->getBody());
584a909abfdSJustin Bogner     uint64_t BackedgeCount = CurrentCount;
58507193cc8SJustin Bogner     BreakContinue BC = BreakContinueStack.pop_back_val();
586bf854f0fSBob Wilson 
587bf854f0fSBob Wilson     // The increment is essentially part of the body but it needs to include
588bf854f0fSBob Wilson     // the count for all the continue statements.
58907193cc8SJustin Bogner     uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
59007193cc8SJustin Bogner     CountMap[S->getInc()] = IncCount;
591bf854f0fSBob Wilson     Visit(S->getInc());
592bf854f0fSBob Wilson 
593bf854f0fSBob Wilson     // ...then go back and propagate counts through the condition.
59407193cc8SJustin Bogner     uint64_t CondCount =
59507193cc8SJustin Bogner         setCount(ParentCount + BackedgeCount + BC.ContinueCount);
59607193cc8SJustin Bogner     CountMap[S->getCond()] = CondCount;
597bf854f0fSBob Wilson     Visit(S->getCond());
59807193cc8SJustin Bogner     setCount(BC.BreakCount + CondCount - BodyCount);
599bf854f0fSBob Wilson     RecordNextStmtCount = true;
600bf854f0fSBob Wilson   }
601bf854f0fSBob Wilson 
VisitObjCForCollectionStmt__anonc3cc86690111::ComputeRegionCounts602bf854f0fSBob Wilson   void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
603bf854f0fSBob Wilson     RecordStmtCount(S);
604bf854f0fSBob Wilson     Visit(S->getElement());
605a909abfdSJustin Bogner     uint64_t ParentCount = CurrentCount;
606bf854f0fSBob Wilson     BreakContinueStack.push_back(BreakContinue());
60707193cc8SJustin Bogner     // Counter tracks the body of the loop.
60807193cc8SJustin Bogner     uint64_t BodyCount = setCount(PGO.getRegionCount(S));
60907193cc8SJustin Bogner     CountMap[S->getBody()] = BodyCount;
610bf854f0fSBob Wilson     Visit(S->getBody());
611a909abfdSJustin Bogner     uint64_t BackedgeCount = CurrentCount;
612bf854f0fSBob Wilson     BreakContinue BC = BreakContinueStack.pop_back_val();
61307193cc8SJustin Bogner 
61407193cc8SJustin Bogner     setCount(BC.BreakCount + ParentCount + BackedgeCount + BC.ContinueCount -
61507193cc8SJustin Bogner              BodyCount);
616bf854f0fSBob Wilson     RecordNextStmtCount = true;
617bf854f0fSBob Wilson   }
618bf854f0fSBob Wilson 
VisitSwitchStmt__anonc3cc86690111::ComputeRegionCounts619bf854f0fSBob Wilson   void VisitSwitchStmt(const SwitchStmt *S) {
620bf854f0fSBob Wilson     RecordStmtCount(S);
621f2a6ec55SVedant Kumar     if (S->getInit())
622f2a6ec55SVedant Kumar       Visit(S->getInit());
623bf854f0fSBob Wilson     Visit(S->getCond());
624a909abfdSJustin Bogner     CurrentCount = 0;
625bf854f0fSBob Wilson     BreakContinueStack.push_back(BreakContinue());
626bf854f0fSBob Wilson     Visit(S->getBody());
627bf854f0fSBob Wilson     // If the switch is inside a loop, add the continue counts.
628bf854f0fSBob Wilson     BreakContinue BC = BreakContinueStack.pop_back_val();
629bf854f0fSBob Wilson     if (!BreakContinueStack.empty())
630bf854f0fSBob Wilson       BreakContinueStack.back().ContinueCount += BC.ContinueCount;
631d8931425SBob Wilson     // Counter tracks the exit block of the switch.
63207193cc8SJustin Bogner     setCount(PGO.getRegionCount(S));
633bf854f0fSBob Wilson     RecordNextStmtCount = true;
634bf854f0fSBob Wilson   }
635bf854f0fSBob Wilson 
VisitSwitchCase__anonc3cc86690111::ComputeRegionCounts63607193cc8SJustin Bogner   void VisitSwitchCase(const SwitchCase *S) {
637bf854f0fSBob Wilson     RecordNextStmtCount = false;
638d8931425SBob Wilson     // Counter for this particular case. This counts only jumps from the
639d8931425SBob Wilson     // switch header and does not include fallthrough from the case before
640d8931425SBob Wilson     // this one.
64107193cc8SJustin Bogner     uint64_t CaseCount = PGO.getRegionCount(S);
642a909abfdSJustin Bogner     setCount(CurrentCount + CaseCount);
64307193cc8SJustin Bogner     // We need the count without fallthrough in the mapping, so it's more useful
64407193cc8SJustin Bogner     // for branch probabilities.
64507193cc8SJustin Bogner     CountMap[S] = CaseCount;
646bf854f0fSBob Wilson     RecordNextStmtCount = true;
647bf854f0fSBob Wilson     Visit(S->getSubStmt());
648bf854f0fSBob Wilson   }
649bf854f0fSBob Wilson 
VisitIfStmt__anonc3cc86690111::ComputeRegionCounts650bf854f0fSBob Wilson   void VisitIfStmt(const IfStmt *S) {
651bf854f0fSBob Wilson     RecordStmtCount(S);
652424733c1SCorentin Jabot 
653424733c1SCorentin Jabot     if (S->isConsteval()) {
654424733c1SCorentin Jabot       const Stmt *Stm = S->isNegatedConsteval() ? S->getThen() : S->getElse();
655424733c1SCorentin Jabot       if (Stm)
656424733c1SCorentin Jabot         Visit(Stm);
657424733c1SCorentin Jabot       return;
658424733c1SCorentin Jabot     }
659424733c1SCorentin Jabot 
660a909abfdSJustin Bogner     uint64_t ParentCount = CurrentCount;
6619d2a16b9SVedant Kumar     if (S->getInit())
6629d2a16b9SVedant Kumar       Visit(S->getInit());
663bf854f0fSBob Wilson     Visit(S->getCond());
664bf854f0fSBob Wilson 
66507193cc8SJustin Bogner     // Counter tracks the "then" part of an if statement. The count for
66607193cc8SJustin Bogner     // the "else" part, if it exists, will be calculated from this counter.
66707193cc8SJustin Bogner     uint64_t ThenCount = setCount(PGO.getRegionCount(S));
66807193cc8SJustin Bogner     CountMap[S->getThen()] = ThenCount;
669bf854f0fSBob Wilson     Visit(S->getThen());
670a909abfdSJustin Bogner     uint64_t OutCount = CurrentCount;
671bf854f0fSBob Wilson 
67207193cc8SJustin Bogner     uint64_t ElseCount = ParentCount - ThenCount;
673bf854f0fSBob Wilson     if (S->getElse()) {
67407193cc8SJustin Bogner       setCount(ElseCount);
67507193cc8SJustin Bogner       CountMap[S->getElse()] = ElseCount;
676bf854f0fSBob Wilson       Visit(S->getElse());
677a909abfdSJustin Bogner       OutCount += CurrentCount;
67807193cc8SJustin Bogner     } else
67907193cc8SJustin Bogner       OutCount += ElseCount;
68007193cc8SJustin Bogner     setCount(OutCount);
681bf854f0fSBob Wilson     RecordNextStmtCount = true;
682bf854f0fSBob Wilson   }
683bf854f0fSBob Wilson 
VisitCXXTryStmt__anonc3cc86690111::ComputeRegionCounts684bf854f0fSBob Wilson   void VisitCXXTryStmt(const CXXTryStmt *S) {
685bf854f0fSBob Wilson     RecordStmtCount(S);
686bf854f0fSBob Wilson     Visit(S->getTryBlock());
687bf854f0fSBob Wilson     for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
688bf854f0fSBob Wilson       Visit(S->getHandler(I));
689d8931425SBob Wilson     // Counter tracks the continuation block of the try statement.
69007193cc8SJustin Bogner     setCount(PGO.getRegionCount(S));
691bf854f0fSBob Wilson     RecordNextStmtCount = true;
692bf854f0fSBob Wilson   }
693bf854f0fSBob Wilson 
VisitCXXCatchStmt__anonc3cc86690111::ComputeRegionCounts694bf854f0fSBob Wilson   void VisitCXXCatchStmt(const CXXCatchStmt *S) {
695bf854f0fSBob Wilson     RecordNextStmtCount = false;
696d8931425SBob Wilson     // Counter tracks the catch statement's handler block.
69707193cc8SJustin Bogner     uint64_t CatchCount = setCount(PGO.getRegionCount(S));
69807193cc8SJustin Bogner     CountMap[S] = CatchCount;
699bf854f0fSBob Wilson     Visit(S->getHandlerBlock());
700bf854f0fSBob Wilson   }
701bf854f0fSBob Wilson 
VisitAbstractConditionalOperator__anonc3cc86690111::ComputeRegionCounts702e4ca441aSJustin Bogner   void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
703bf854f0fSBob Wilson     RecordStmtCount(E);
704a909abfdSJustin Bogner     uint64_t ParentCount = CurrentCount;
705bf854f0fSBob Wilson     Visit(E->getCond());
706bf854f0fSBob Wilson 
70707193cc8SJustin Bogner     // Counter tracks the "true" part of a conditional operator. The
70807193cc8SJustin Bogner     // count in the "false" part will be calculated from this counter.
70907193cc8SJustin Bogner     uint64_t TrueCount = setCount(PGO.getRegionCount(E));
71007193cc8SJustin Bogner     CountMap[E->getTrueExpr()] = TrueCount;
711bf854f0fSBob Wilson     Visit(E->getTrueExpr());
712a909abfdSJustin Bogner     uint64_t OutCount = CurrentCount;
713bf854f0fSBob Wilson 
71407193cc8SJustin Bogner     uint64_t FalseCount = setCount(ParentCount - TrueCount);
71507193cc8SJustin Bogner     CountMap[E->getFalseExpr()] = FalseCount;
716bf854f0fSBob Wilson     Visit(E->getFalseExpr());
717a909abfdSJustin Bogner     OutCount += CurrentCount;
718bf854f0fSBob Wilson 
71907193cc8SJustin Bogner     setCount(OutCount);
720bf854f0fSBob Wilson     RecordNextStmtCount = true;
721bf854f0fSBob Wilson   }
722bf854f0fSBob Wilson 
VisitBinLAnd__anonc3cc86690111::ComputeRegionCounts723bf854f0fSBob Wilson   void VisitBinLAnd(const BinaryOperator *E) {
724bf854f0fSBob Wilson     RecordStmtCount(E);
725a909abfdSJustin Bogner     uint64_t ParentCount = CurrentCount;
726bf854f0fSBob Wilson     Visit(E->getLHS());
72707193cc8SJustin Bogner     // Counter tracks the right hand side of a logical and operator.
72807193cc8SJustin Bogner     uint64_t RHSCount = setCount(PGO.getRegionCount(E));
72907193cc8SJustin Bogner     CountMap[E->getRHS()] = RHSCount;
730bf854f0fSBob Wilson     Visit(E->getRHS());
731a909abfdSJustin Bogner     setCount(ParentCount + RHSCount - CurrentCount);
732bf854f0fSBob Wilson     RecordNextStmtCount = true;
733bf854f0fSBob Wilson   }
734bf854f0fSBob Wilson 
VisitBinLOr__anonc3cc86690111::ComputeRegionCounts735bf854f0fSBob Wilson   void VisitBinLOr(const BinaryOperator *E) {
736bf854f0fSBob Wilson     RecordStmtCount(E);
737a909abfdSJustin Bogner     uint64_t ParentCount = CurrentCount;
738bf854f0fSBob Wilson     Visit(E->getLHS());
73907193cc8SJustin Bogner     // Counter tracks the right hand side of a logical or operator.
74007193cc8SJustin Bogner     uint64_t RHSCount = setCount(PGO.getRegionCount(E));
74107193cc8SJustin Bogner     CountMap[E->getRHS()] = RHSCount;
742bf854f0fSBob Wilson     Visit(E->getRHS());
743a909abfdSJustin Bogner     setCount(ParentCount + RHSCount - CurrentCount);
744bf854f0fSBob Wilson     RecordNextStmtCount = true;
745bf854f0fSBob Wilson   }
746bf854f0fSBob Wilson };
747dcfba334SHans Wennborg } // end anonymous namespace
748ef512b99SJustin Bogner 
combine(HashType Type)7494bc7731aSDuncan P. N. Exon Smith void PGOHash::combine(HashType Type) {
7504bc7731aSDuncan P. N. Exon Smith   // Check that we never combine 0 and only have six bits.
7514bc7731aSDuncan P. N. Exon Smith   assert(Type && "Hash is invalid: unexpected type 0");
7524bc7731aSDuncan P. N. Exon Smith   assert(unsigned(Type) < TooBig && "Hash is invalid: too many types");
7534bc7731aSDuncan P. N. Exon Smith 
7544bc7731aSDuncan P. N. Exon Smith   // Pass through MD5 if enough work has built up.
7554bc7731aSDuncan P. N. Exon Smith   if (Count && Count % NumTypesPerWord == 0) {
7564bc7731aSDuncan P. N. Exon Smith     using namespace llvm::support;
7574bc7731aSDuncan P. N. Exon Smith     uint64_t Swapped = endian::byte_swap<uint64_t, little>(Working);
7584bc7731aSDuncan P. N. Exon Smith     MD5.update(llvm::makeArrayRef((uint8_t *)&Swapped, sizeof(Swapped)));
7594bc7731aSDuncan P. N. Exon Smith     Working = 0;
7604bc7731aSDuncan P. N. Exon Smith   }
7614bc7731aSDuncan P. N. Exon Smith 
7624bc7731aSDuncan P. N. Exon Smith   // Accumulate the current type.
7634bc7731aSDuncan P. N. Exon Smith   ++Count;
7644bc7731aSDuncan P. N. Exon Smith   Working = Working << NumBitsPerType | Type;
7654bc7731aSDuncan P. N. Exon Smith }
7664bc7731aSDuncan P. N. Exon Smith 
finalize()7674bc7731aSDuncan P. N. Exon Smith uint64_t PGOHash::finalize() {
7684bc7731aSDuncan P. N. Exon Smith   // Use Working as the hash directly if we never used MD5.
7694bc7731aSDuncan P. N. Exon Smith   if (Count <= NumTypesPerWord)
7704bc7731aSDuncan P. N. Exon Smith     // No need to byte swap here, since none of the math was endian-dependent.
7714bc7731aSDuncan P. N. Exon Smith     // This number will be byte-swapped as required on endianness transitions,
7724bc7731aSDuncan P. N. Exon Smith     // so we will see the same value on the other side.
7734bc7731aSDuncan P. N. Exon Smith     return Working;
7744bc7731aSDuncan P. N. Exon Smith 
7754bc7731aSDuncan P. N. Exon Smith   // Check for remaining work in Working.
776de02a75eSserge-sans-paille   if (Working) {
777de02a75eSserge-sans-paille     // Keep the buggy behavior from v1 and v2 for backward-compatibility. This
778de02a75eSserge-sans-paille     // is buggy because it converts a uint64_t into an array of uint8_t.
779de02a75eSserge-sans-paille     if (HashVersion < PGO_HASH_V3) {
780de02a75eSserge-sans-paille       MD5.update({(uint8_t)Working});
781de02a75eSserge-sans-paille     } else {
782de02a75eSserge-sans-paille       using namespace llvm::support;
783de02a75eSserge-sans-paille       uint64_t Swapped = endian::byte_swap<uint64_t, little>(Working);
784de02a75eSserge-sans-paille       MD5.update(llvm::makeArrayRef((uint8_t *)&Swapped, sizeof(Swapped)));
785de02a75eSserge-sans-paille     }
786de02a75eSserge-sans-paille   }
7874bc7731aSDuncan P. N. Exon Smith 
7884bc7731aSDuncan P. N. Exon Smith   // Finalize the MD5 and return the hash.
7894bc7731aSDuncan P. N. Exon Smith   llvm::MD5::MD5Result Result;
7904bc7731aSDuncan P. N. Exon Smith   MD5.final(Result);
79182a0c97bSZachary Turner   return Result.low();
7924bc7731aSDuncan P. N. Exon Smith }
7934bc7731aSDuncan P. N. Exon Smith 
assignRegionCounters(GlobalDecl GD,llvm::Function * Fn)7943a561459SSerge Pavlov void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) {
7953a561459SSerge Pavlov   const Decl *D = GD.getDecl();
79633d0a1ccSVedant Kumar   if (!D->hasBody())
79733d0a1ccSVedant Kumar     return;
79833d0a1ccSVedant Kumar 
799c7b683c1SMichael Liao   // Skip CUDA/HIP kernel launch stub functions.
800c7b683c1SMichael Liao   if (CGM.getLangOpts().CUDA && !CGM.getLangOpts().CUDAIsDevice &&
801c7b683c1SMichael Liao       D->hasAttr<CUDAGlobalAttr>())
802c7b683c1SMichael Liao     return;
803c7b683c1SMichael Liao 
8049837ef56SRong Xu   bool InstrumentRegions = CGM.getCodeGenOpts().hasProfileClangInstr();
805837a6f6fSJustin Bogner   llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
806837a6f6fSJustin Bogner   if (!InstrumentRegions && !PGOReader)
807ef512b99SJustin Bogner     return;
8083212b18bSJustin Bogner   if (D->isImplicit())
809ef512b99SJustin Bogner     return;
8103a561459SSerge Pavlov   // Constructors and destructors may be represented by several functions in IR.
8113a561459SSerge Pavlov   // If so, instrument only base variant, others are implemented by delegation
8123a561459SSerge Pavlov   // to the base one, it would be counted twice otherwise.
8137f809b2fSVedant Kumar   if (CGM.getTarget().getCXXABI().hasConstructorVariants()) {
8147f809b2fSVedant Kumar     if (const auto *CCD = dyn_cast<CXXConstructorDecl>(D))
8157f809b2fSVedant Kumar       if (GD.getCtorType() != Ctor_Base &&
8167f809b2fSVedant Kumar           CodeGenFunction::IsConstructorDelegationValid(CCD))
8173a561459SSerge Pavlov         return;
8183a561459SSerge Pavlov   }
819f9ef9f86SReid Kleckner   if (isa<CXXDestructorDecl>(D) && GD.getDtorType() != Dtor_Base)
820f9ef9f86SReid Kleckner     return;
821f9ef9f86SReid Kleckner 
8229fd9b5a9SPetr Hosek   CGM.ClearUnusedCoverageMapping(D);
823bb9eb198SPetr Hosek   if (Fn->hasFnAttribute(llvm::Attribute::NoProfile))
824bb9eb198SPetr Hosek     return;
825bb9eb198SPetr Hosek 
826da1ebedeSBob Wilson   setFuncName(Fn);
8277c41451bSDuncan P. N. Exon Smith 
828ef512b99SJustin Bogner   mapRegionCounters(D);
829ee02499aSAlex Lorenz   if (CGM.getCodeGenOpts().CoverageMapping)
830ee02499aSAlex Lorenz     emitCounterRegionMapping(D);
831837a6f6fSJustin Bogner   if (PGOReader) {
83240b8ba14SJustin Bogner     SourceManager &SM = CGM.getContext().getSourceManager();
83340b8ba14SJustin Bogner     loadRegionCounts(PGOReader, SM.isInMainFile(D->getLocation()));
834bf854f0fSBob Wilson     computeRegionCounts(D);
835837a6f6fSJustin Bogner     applyFunctionAttributes(PGOReader, Fn);
836bf854f0fSBob Wilson   }
837ef512b99SJustin Bogner }
838ef512b99SJustin Bogner 
mapRegionCounters(const Decl * D)839ef512b99SJustin Bogner void CodeGenPGO::mapRegionCounters(const Decl *D) {
8406186971aSVedant Kumar   // Use the latest hash version when inserting instrumentation, but use the
8416186971aSVedant Kumar   // version in the indexed profile if we're reading PGO data.
8426186971aSVedant Kumar   PGOHashVersion HashVersion = PGO_HASH_LATEST;
8439f2967bcSAlan Phipps   uint64_t ProfileVersion = llvm::IndexedInstrProf::Version;
8449f2967bcSAlan Phipps   if (auto *PGOReader = CGM.getPGOReader()) {
8456186971aSVedant Kumar     HashVersion = getPGOHashVersion(PGOReader, CGM);
8469f2967bcSAlan Phipps     ProfileVersion = PGOReader->getVersion();
8479f2967bcSAlan Phipps   }
8486186971aSVedant Kumar 
8491b67cfd4SDuncan P. N. Exon Smith   RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>);
8509f2967bcSAlan Phipps   MapRegionCounters Walker(HashVersion, ProfileVersion, *RegionCounterMap);
851ef512b99SJustin Bogner   if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
852d8931425SBob Wilson     Walker.TraverseDecl(const_cast<FunctionDecl *>(FD));
8535ec8fe19SBob Wilson   else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
854d8931425SBob Wilson     Walker.TraverseDecl(const_cast<ObjCMethodDecl *>(MD));
855c845c00aSBob Wilson   else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
856d8931425SBob Wilson     Walker.TraverseDecl(const_cast<BlockDecl *>(BD));
85781ab90f7SJustin Bogner   else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
85881ab90f7SJustin Bogner     Walker.TraverseDecl(const_cast<CapturedDecl *>(CD));
8593212b18bSJustin Bogner   assert(Walker.NextCounter > 0 && "no entry counter mapped for decl");
860ef512b99SJustin Bogner   NumRegionCounters = Walker.NextCounter;
8614bc7731aSDuncan P. N. Exon Smith   FunctionHash = Walker.Hash.finalize();
862ef512b99SJustin Bogner }
863ef512b99SJustin Bogner 
skipRegionMappingForDecl(const Decl * D)864c468bb8bSVedant Kumar bool CodeGenPGO::skipRegionMappingForDecl(const Decl *D) {
865bc370f0cSVedant Kumar   if (!D->getBody())
866bc370f0cSVedant Kumar     return true;
867bc370f0cSVedant Kumar 
868c7b683c1SMichael Liao   // Skip host-only functions in the CUDA device compilation and device-only
869c7b683c1SMichael Liao   // functions in the host compilation. Just roughly filter them out based on
870c7b683c1SMichael Liao   // the function attributes. If there are effectively host-only or device-only
871c7b683c1SMichael Liao   // ones, their coverage mapping may still be generated.
872c7b683c1SMichael Liao   if (CGM.getLangOpts().CUDA &&
873c7b683c1SMichael Liao       ((CGM.getLangOpts().CUDAIsDevice && !D->hasAttr<CUDADeviceAttr>() &&
874c7b683c1SMichael Liao         !D->hasAttr<CUDAGlobalAttr>()) ||
875c7b683c1SMichael Liao        (!CGM.getLangOpts().CUDAIsDevice &&
876c7b683c1SMichael Liao         (D->hasAttr<CUDAGlobalAttr>() ||
877c7b683c1SMichael Liao          (!D->hasAttr<CUDAHostAttr>() && D->hasAttr<CUDADeviceAttr>())))))
878c7b683c1SMichael Liao     return true;
879c7b683c1SMichael Liao 
880c468bb8bSVedant Kumar   // Don't map the functions in system headers.
881c468bb8bSVedant Kumar   const auto &SM = CGM.getContext().getSourceManager();
882f2ceec48SStephen Kelly   auto Loc = D->getBody()->getBeginLoc();
883c468bb8bSVedant Kumar   return SM.isInSystemHeader(Loc);
884c468bb8bSVedant Kumar }
885c468bb8bSVedant Kumar 
emitCounterRegionMapping(const Decl * D)886c468bb8bSVedant Kumar void CodeGenPGO::emitCounterRegionMapping(const Decl *D) {
887c468bb8bSVedant Kumar   if (skipRegionMappingForDecl(D))
888ee02499aSAlex Lorenz     return;
889ee02499aSAlex Lorenz 
890970ac605SJustin Bogner   std::string CoverageMapping;
891ee02499aSAlex Lorenz   llvm::raw_string_ostream OS(CoverageMapping);
892ee02499aSAlex Lorenz   CoverageMappingGen MappingGen(*CGM.getCoverageMapping(),
893ee02499aSAlex Lorenz                                 CGM.getContext().getSourceManager(),
894e5ee6c58SJustin Bogner                                 CGM.getLangOpts(), RegionCounterMap.get());
895ee02499aSAlex Lorenz   MappingGen.emitCounterMapping(D, OS);
896ee02499aSAlex Lorenz   OS.flush();
897970ac605SJustin Bogner 
898970ac605SJustin Bogner   if (CoverageMapping.empty())
899970ac605SJustin Bogner     return;
900970ac605SJustin Bogner 
901970ac605SJustin Bogner   CGM.getCoverageMapping()->addFunctionMappingRecord(
902970ac605SJustin Bogner       FuncNameVar, FuncName, FunctionHash, CoverageMapping);
903ee02499aSAlex Lorenz }
904ee02499aSAlex Lorenz 
905ee02499aSAlex Lorenz void
emitEmptyCounterMapping(const Decl * D,StringRef Name,llvm::GlobalValue::LinkageTypes Linkage)90660d852baSJustin Bogner CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef Name,
907ee02499aSAlex Lorenz                                     llvm::GlobalValue::LinkageTypes Linkage) {
908c468bb8bSVedant Kumar   if (skipRegionMappingForDecl(D))
909ee02499aSAlex Lorenz     return;
910ee02499aSAlex Lorenz 
911970ac605SJustin Bogner   std::string CoverageMapping;
912ee02499aSAlex Lorenz   llvm::raw_string_ostream OS(CoverageMapping);
913ee02499aSAlex Lorenz   CoverageMappingGen MappingGen(*CGM.getCoverageMapping(),
914ee02499aSAlex Lorenz                                 CGM.getContext().getSourceManager(),
915ee02499aSAlex Lorenz                                 CGM.getLangOpts());
916ee02499aSAlex Lorenz   MappingGen.emitEmptyMapping(D, OS);
917ee02499aSAlex Lorenz   OS.flush();
918970ac605SJustin Bogner 
919970ac605SJustin Bogner   if (CoverageMapping.empty())
920970ac605SJustin Bogner     return;
921970ac605SJustin Bogner 
92260d852baSJustin Bogner   setFuncName(Name, Linkage);
923970ac605SJustin Bogner   CGM.getCoverageMapping()->addFunctionMappingRecord(
9242129ae53SXinliang David Li       FuncNameVar, FuncName, FunctionHash, CoverageMapping, false);
925ee02499aSAlex Lorenz }
926ee02499aSAlex Lorenz 
computeRegionCounts(const Decl * D)927bf854f0fSBob Wilson void CodeGenPGO::computeRegionCounts(const Decl *D) {
9281b67cfd4SDuncan P. N. Exon Smith   StmtCountMap.reset(new llvm::DenseMap<const Stmt *, uint64_t>);
9293586be72SDuncan P. N. Exon Smith   ComputeRegionCounts Walker(*StmtCountMap, *this);
930bf854f0fSBob Wilson   if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
931bf854f0fSBob Wilson     Walker.VisitFunctionDecl(FD);
9325ec8fe19SBob Wilson   else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
9335ec8fe19SBob Wilson     Walker.VisitObjCMethodDecl(MD);
934c845c00aSBob Wilson   else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
935c845c00aSBob Wilson     Walker.VisitBlockDecl(BD);
93681ab90f7SJustin Bogner   else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
93781ab90f7SJustin Bogner     Walker.VisitCapturedDecl(const_cast<CapturedDecl *>(CD));
938bf854f0fSBob Wilson }
939bf854f0fSBob Wilson 
940837a6f6fSJustin Bogner void
applyFunctionAttributes(llvm::IndexedInstrProfReader * PGOReader,llvm::Function * Fn)941837a6f6fSJustin Bogner CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
9424c9c45c0SJustin Bogner                                     llvm::Function *Fn) {
9434c9c45c0SJustin Bogner   if (!haveRegionCounts())
9444c9c45c0SJustin Bogner     return;
9454c9c45c0SJustin Bogner 
946dcfba334SHans Wennborg   uint64_t FunctionCount = getRegionCount(nullptr);
947aa8b1cb8SDiego Novillo   Fn->setEntryCount(FunctionCount);
9484c9c45c0SJustin Bogner }
9494c9c45c0SJustin Bogner 
emitCounterIncrement(CGBuilderTy & Builder,const Stmt * S,llvm::Value * StepV)950502bbfafSVedant Kumar void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S,
951502bbfafSVedant Kumar                                       llvm::Value *StepV) {
9529837ef56SRong Xu   if (!CGM.getCodeGenOpts().hasProfileClangInstr() || !RegionCounterMap)
953ef512b99SJustin Bogner     return;
9549f5260abSDuncan P. N. Exon Smith   if (!Builder.GetInsertBlock())
955203f91e3SJustin Bogner     return;
95666242d6cSJustin Bogner 
95766242d6cSJustin Bogner   unsigned Counter = (*RegionCounterMap)[S];
958970ac605SJustin Bogner   auto *I8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
959502bbfafSVedant Kumar 
960502bbfafSVedant Kumar   llvm::Value *Args[] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
961a45f315eSVedant Kumar                          Builder.getInt64(FunctionHash),
962a45f315eSVedant Kumar                          Builder.getInt32(NumRegionCounters),
963502bbfafSVedant Kumar                          Builder.getInt32(Counter), StepV};
964502bbfafSVedant Kumar   if (!StepV)
965502bbfafSVedant Kumar     Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment),
966502bbfafSVedant Kumar                        makeArrayRef(Args, 4));
967502bbfafSVedant Kumar   else
968502bbfafSVedant Kumar     Builder.CreateCall(
969502bbfafSVedant Kumar         CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment_step),
970502bbfafSVedant Kumar         makeArrayRef(Args));
971ef512b99SJustin Bogner }
972ef512b99SJustin Bogner 
setValueProfilingFlag(llvm::Module & M)9738f20ac95SReid Kleckner void CodeGenPGO::setValueProfilingFlag(llvm::Module &M) {
9748f20ac95SReid Kleckner   if (CGM.getCodeGenOpts().hasProfileClangInstr())
9758f20ac95SReid Kleckner     M.addModuleFlag(llvm::Module::Warning, "EnableValueProfiling",
9768f20ac95SReid Kleckner                     uint32_t(EnableValueProfiling));
9778f20ac95SReid Kleckner }
9788f20ac95SReid Kleckner 
979518276a5SBetul Buyukkurt // This method either inserts a call to the profile run-time during
980518276a5SBetul Buyukkurt // instrumentation or puts profile data into metadata for PGO use.
valueProfile(CGBuilderTy & Builder,uint32_t ValueKind,llvm::Instruction * ValueSite,llvm::Value * ValuePtr)981518276a5SBetul Buyukkurt void CodeGenPGO::valueProfile(CGBuilderTy &Builder, uint32_t ValueKind,
982518276a5SBetul Buyukkurt     llvm::Instruction *ValueSite, llvm::Value *ValuePtr) {
983518276a5SBetul Buyukkurt 
984518276a5SBetul Buyukkurt   if (!EnableValueProfiling)
985518276a5SBetul Buyukkurt     return;
986518276a5SBetul Buyukkurt 
987518276a5SBetul Buyukkurt   if (!ValuePtr || !ValueSite || !Builder.GetInsertBlock())
988518276a5SBetul Buyukkurt     return;
989518276a5SBetul Buyukkurt 
9903da993c4SBetul Buyukkurt   if (isa<llvm::Constant>(ValuePtr))
9913da993c4SBetul Buyukkurt     return;
9923da993c4SBetul Buyukkurt 
9939837ef56SRong Xu   bool InstrumentValueSites = CGM.getCodeGenOpts().hasProfileClangInstr();
994518276a5SBetul Buyukkurt   if (InstrumentValueSites && RegionCounterMap) {
995cb6f5f16SBetul Buyukkurt     auto BuilderInsertPoint = Builder.saveIP();
996cb6f5f16SBetul Buyukkurt     Builder.SetInsertPoint(ValueSite);
997518276a5SBetul Buyukkurt     llvm::Value *Args[5] = {
998cb6f5f16SBetul Buyukkurt         llvm::ConstantExpr::getBitCast(FuncNameVar, Builder.getInt8PtrTy()),
999518276a5SBetul Buyukkurt         Builder.getInt64(FunctionHash),
1000518276a5SBetul Buyukkurt         Builder.CreatePtrToInt(ValuePtr, Builder.getInt64Ty()),
1001518276a5SBetul Buyukkurt         Builder.getInt32(ValueKind),
1002518276a5SBetul Buyukkurt         Builder.getInt32(NumValueSites[ValueKind]++)
1003518276a5SBetul Buyukkurt     };
1004518276a5SBetul Buyukkurt     Builder.CreateCall(
1005518276a5SBetul Buyukkurt         CGM.getIntrinsic(llvm::Intrinsic::instrprof_value_profile), Args);
1006cb6f5f16SBetul Buyukkurt     Builder.restoreIP(BuilderInsertPoint);
1007518276a5SBetul Buyukkurt     return;
1008518276a5SBetul Buyukkurt   }
1009518276a5SBetul Buyukkurt 
1010518276a5SBetul Buyukkurt   llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
1011518276a5SBetul Buyukkurt   if (PGOReader && haveRegionCounts()) {
1012518276a5SBetul Buyukkurt     // We record the top most called three functions at each call site.
1013518276a5SBetul Buyukkurt     // Profile metadata contains "VP" string identifying this metadata
1014518276a5SBetul Buyukkurt     // as value profiling data, then a uint32_t value for the value profiling
1015518276a5SBetul Buyukkurt     // kind, a uint64_t value for the total number of times the call is
1016518276a5SBetul Buyukkurt     // executed, followed by the function hash and execution count (uint64_t)
1017518276a5SBetul Buyukkurt     // pairs for each function.
1018518276a5SBetul Buyukkurt     if (NumValueSites[ValueKind] >= ProfRecord->getNumValueSites(ValueKind))
1019518276a5SBetul Buyukkurt       return;
10205527a9ddSXinliang David Li 
10215527a9ddSXinliang David Li     llvm::annotateValueSite(CGM.getModule(), *ValueSite, *ProfRecord,
10225527a9ddSXinliang David Li                             (llvm::InstrProfValueKind)ValueKind,
1023518276a5SBetul Buyukkurt                             NumValueSites[ValueKind]);
1024518276a5SBetul Buyukkurt 
1025518276a5SBetul Buyukkurt     NumValueSites[ValueKind]++;
1026518276a5SBetul Buyukkurt   }
1027518276a5SBetul Buyukkurt }
1028518276a5SBetul Buyukkurt 
loadRegionCounts(llvm::IndexedInstrProfReader * PGOReader,bool IsInMainFile)102940b8ba14SJustin Bogner void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
103040b8ba14SJustin Bogner                                   bool IsInMainFile) {
103140b8ba14SJustin Bogner   CGM.getPGOStats().addVisited(IsInMainFile);
10327f8cf5bfSJustin Bogner   RegionCounts.clear();
1033fa2d5955SVedant Kumar   llvm::Expected<llvm::InstrProfRecord> RecordExpected =
1034518276a5SBetul Buyukkurt       PGOReader->getInstrProfRecord(FuncName, FunctionHash);
1035fa2d5955SVedant Kumar   if (auto E = RecordExpected.takeError()) {
1036fa2d5955SVedant Kumar     auto IPE = llvm::InstrProfError::take(std::move(E));
1037fa2d5955SVedant Kumar     if (IPE == llvm::instrprof_error::unknown_function)
103840b8ba14SJustin Bogner       CGM.getPGOStats().addMissing(IsInMainFile);
1039fa2d5955SVedant Kumar     else if (IPE == llvm::instrprof_error::hash_mismatch)
10409c6818efSJustin Bogner       CGM.getPGOStats().addMismatched(IsInMainFile);
1041fa2d5955SVedant Kumar     else if (IPE == llvm::instrprof_error::malformed)
10429c6818efSJustin Bogner       // TODO: Consider a more specific warning for this case.
104340b8ba14SJustin Bogner       CGM.getPGOStats().addMismatched(IsInMainFile);
1044518276a5SBetul Buyukkurt     return;
1045e2ef2a09SJustin Bogner   }
1046518276a5SBetul Buyukkurt   ProfRecord =
10472b3d49b6SJonas Devlieghere       std::make_unique<llvm::InstrProfRecord>(std::move(RecordExpected.get()));
1048518276a5SBetul Buyukkurt   RegionCounts = ProfRecord->Counts;
1049ef512b99SJustin Bogner }
1050ef512b99SJustin Bogner 
10515c31b8b9SArthur Eubanks /// Calculate what to divide by to scale weights.
10525c31b8b9SArthur Eubanks ///
10535c31b8b9SArthur Eubanks /// Given the maximum weight, calculate a divisor that will scale all the
10545c31b8b9SArthur Eubanks /// weights to strictly less than UINT32_MAX.
calculateWeightScale(uint64_t MaxWeight)10555c31b8b9SArthur Eubanks static uint64_t calculateWeightScale(uint64_t MaxWeight) {
10565c31b8b9SArthur Eubanks   return MaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1;
10575c31b8b9SArthur Eubanks }
10585c31b8b9SArthur Eubanks 
10595c31b8b9SArthur Eubanks /// Scale an individual branch weight (and add 1).
10605c31b8b9SArthur Eubanks ///
10615c31b8b9SArthur Eubanks /// Scale a 64-bit weight down to 32-bits using \c Scale.
106238402dc9SDuncan P. N. Exon Smith ///
106338402dc9SDuncan P. N. Exon Smith /// According to Laplace's Rule of Succession, it is better to compute the
106438402dc9SDuncan P. N. Exon Smith /// weight based on the count plus 1, so universally add 1 to the value.
10655c31b8b9SArthur Eubanks ///
10665c31b8b9SArthur Eubanks /// \pre \c Scale was calculated by \a calculateWeightScale() with a weight no
10675c31b8b9SArthur Eubanks /// greater than \c Weight.
scaleBranchWeight(uint64_t Weight,uint64_t Scale)10685c31b8b9SArthur Eubanks static uint32_t scaleBranchWeight(uint64_t Weight, uint64_t Scale) {
10695c31b8b9SArthur Eubanks   assert(Scale && "scale by 0?");
10705c31b8b9SArthur Eubanks   uint64_t Scaled = Weight / Scale + 1;
10715c31b8b9SArthur Eubanks   assert(Scaled <= UINT32_MAX && "overflow 32-bits");
10725c31b8b9SArthur Eubanks   return Scaled;
10735c31b8b9SArthur Eubanks }
107438402dc9SDuncan P. N. Exon Smith 
createProfileWeights(uint64_t TrueCount,uint64_t FalseCount) const107565512647SJustin Bogner llvm::MDNode *CodeGenFunction::createProfileWeights(uint64_t TrueCount,
1076389c8d5bSMark de Wever                                                     uint64_t FalseCount) const {
107738402dc9SDuncan P. N. Exon Smith   // Check for empty weights.
1078ef512b99SJustin Bogner   if (!TrueCount && !FalseCount)
1079a5f804a7SDuncan P. N. Exon Smith     return nullptr;
1080ef512b99SJustin Bogner 
10815c31b8b9SArthur Eubanks   // Calculate how to scale down to 32-bits.
10825c31b8b9SArthur Eubanks   uint64_t Scale = calculateWeightScale(std::max(TrueCount, FalseCount));
10835c31b8b9SArthur Eubanks 
1084ef512b99SJustin Bogner   llvm::MDBuilder MDHelper(CGM.getLLVMContext());
10855c31b8b9SArthur Eubanks   return MDHelper.createBranchWeights(scaleBranchWeight(TrueCount, Scale),
10865c31b8b9SArthur Eubanks                                       scaleBranchWeight(FalseCount, Scale));
1087ef512b99SJustin Bogner }
1088ef512b99SJustin Bogner 
108965512647SJustin Bogner llvm::MDNode *
createProfileWeights(ArrayRef<uint64_t> Weights) const1090389c8d5bSMark de Wever CodeGenFunction::createProfileWeights(ArrayRef<uint64_t> Weights) const {
109138402dc9SDuncan P. N. Exon Smith   // We need at least two elements to create meaningful weights.
109238402dc9SDuncan P. N. Exon Smith   if (Weights.size() < 2)
1093a5f804a7SDuncan P. N. Exon Smith     return nullptr;
109438402dc9SDuncan P. N. Exon Smith 
1095f3aefca7SJustin Bogner   // Check for empty weights.
1096f3aefca7SJustin Bogner   uint64_t MaxWeight = *std::max_element(Weights.begin(), Weights.end());
1097f3aefca7SJustin Bogner   if (MaxWeight == 0)
1098f3aefca7SJustin Bogner     return nullptr;
1099f3aefca7SJustin Bogner 
11005c31b8b9SArthur Eubanks   // Calculate how to scale down to 32-bits.
11015c31b8b9SArthur Eubanks   uint64_t Scale = calculateWeightScale(MaxWeight);
11025c31b8b9SArthur Eubanks 
11035c31b8b9SArthur Eubanks   SmallVector<uint32_t, 16> ScaledWeights;
1104ef512b99SJustin Bogner   ScaledWeights.reserve(Weights.size());
110538402dc9SDuncan P. N. Exon Smith   for (uint64_t W : Weights)
11065c31b8b9SArthur Eubanks     ScaledWeights.push_back(scaleBranchWeight(W, Scale));
110738402dc9SDuncan P. N. Exon Smith 
110838402dc9SDuncan P. N. Exon Smith   llvm::MDBuilder MDHelper(CGM.getLLVMContext());
1109ef512b99SJustin Bogner   return MDHelper.createBranchWeights(ScaledWeights);
1110ef512b99SJustin Bogner }
1111bf854f0fSBob Wilson 
1112389c8d5bSMark de Wever llvm::MDNode *
createProfileWeightsForLoop(const Stmt * Cond,uint64_t LoopCount) const1113389c8d5bSMark de Wever CodeGenFunction::createProfileWeightsForLoop(const Stmt *Cond,
1114389c8d5bSMark de Wever                                              uint64_t LoopCount) const {
111565512647SJustin Bogner   if (!PGO.haveRegionCounts())
1116a5f804a7SDuncan P. N. Exon Smith     return nullptr;
111765512647SJustin Bogner   Optional<uint64_t> CondCount = PGO.getStmtCount(Cond);
111855b9b11fSHans Wennborg   if (!CondCount || *CondCount == 0)
1119a5f804a7SDuncan P. N. Exon Smith     return nullptr;
112065512647SJustin Bogner   return createProfileWeights(LoopCount,
11211c21c28bSJustin Bogner                               std::max(*CondCount, LoopCount) - LoopCount);
1122bf854f0fSBob Wilson }
1123