159d1ed5bSDimitry Andric //===--- CodeGenPGO.cpp - PGO Instrumentation for LLVM CodeGen --*- C++ -*-===//
259d1ed5bSDimitry Andric //
359d1ed5bSDimitry Andric // The LLVM Compiler Infrastructure
459d1ed5bSDimitry Andric //
559d1ed5bSDimitry Andric // This file is distributed under the University of Illinois Open Source
659d1ed5bSDimitry Andric // License. See LICENSE.TXT for details.
759d1ed5bSDimitry Andric //
859d1ed5bSDimitry Andric //===----------------------------------------------------------------------===//
959d1ed5bSDimitry Andric //
1059d1ed5bSDimitry Andric // Instrumentation-based profile-guided optimization
1159d1ed5bSDimitry Andric //
1259d1ed5bSDimitry Andric //===----------------------------------------------------------------------===//
1359d1ed5bSDimitry Andric
1459d1ed5bSDimitry Andric #include "CodeGenPGO.h"
1559d1ed5bSDimitry Andric #include "CodeGenFunction.h"
1639d628a0SDimitry Andric #include "CoverageMappingGen.h"
1759d1ed5bSDimitry Andric #include "clang/AST/RecursiveASTVisitor.h"
1859d1ed5bSDimitry Andric #include "clang/AST/StmtVisitor.h"
1939d628a0SDimitry Andric #include "llvm/IR/Intrinsics.h"
2059d1ed5bSDimitry Andric #include "llvm/IR/MDBuilder.h"
2159d1ed5bSDimitry Andric #include "llvm/Support/Endian.h"
2259d1ed5bSDimitry Andric #include "llvm/Support/FileSystem.h"
2359d1ed5bSDimitry Andric #include "llvm/Support/MD5.h"
2459d1ed5bSDimitry Andric
259a199699SDimitry Andric static llvm::cl::opt<bool>
269a199699SDimitry Andric EnableValueProfiling("enable-value-profiling", llvm::cl::ZeroOrMore,
279a199699SDimitry Andric llvm::cl::desc("Enable value profiling"),
289a199699SDimitry Andric llvm::cl::Hidden, llvm::cl::init(false));
29e7145dcbSDimitry Andric
3059d1ed5bSDimitry Andric using namespace clang;
3159d1ed5bSDimitry Andric using namespace CodeGen;
3259d1ed5bSDimitry Andric
setFuncName(StringRef Name,llvm::GlobalValue::LinkageTypes Linkage)3339d628a0SDimitry Andric void CodeGenPGO::setFuncName(StringRef Name,
3439d628a0SDimitry Andric llvm::GlobalValue::LinkageTypes Linkage) {
350623d748SDimitry Andric llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
360623d748SDimitry Andric FuncName = llvm::getPGOFuncName(
370623d748SDimitry Andric Name, Linkage, CGM.getCodeGenOpts().MainFileName,
380623d748SDimitry Andric PGOReader ? PGOReader->getVersion() : llvm::IndexedInstrProf::Version);
3959d1ed5bSDimitry Andric
4039d628a0SDimitry Andric // If we're generating a profile, create a variable for the name.
41e7145dcbSDimitry Andric if (CGM.getCodeGenOpts().hasProfileClangInstr())
420623d748SDimitry Andric FuncNameVar = llvm::createPGOFuncNameVar(CGM.getModule(), Linkage, FuncName);
4359d1ed5bSDimitry Andric }
4459d1ed5bSDimitry Andric
setFuncName(llvm::Function * Fn)4539d628a0SDimitry Andric void CodeGenPGO::setFuncName(llvm::Function *Fn) {
4639d628a0SDimitry Andric setFuncName(Fn->getName(), Fn->getLinkage());
47e7145dcbSDimitry Andric // Create PGOFuncName meta data.
48e7145dcbSDimitry Andric llvm::createPGOFuncNameMetadata(*Fn, FuncName);
4959d1ed5bSDimitry Andric }
5059d1ed5bSDimitry Andric
519a199699SDimitry Andric /// The version of the PGO hash algorithm.
529a199699SDimitry Andric enum PGOHashVersion : unsigned {
539a199699SDimitry Andric PGO_HASH_V1,
549a199699SDimitry Andric PGO_HASH_V2,
559a199699SDimitry Andric
569a199699SDimitry Andric // Keep this set to the latest hash version.
579a199699SDimitry Andric PGO_HASH_LATEST = PGO_HASH_V2
589a199699SDimitry Andric };
599a199699SDimitry Andric
6059d1ed5bSDimitry Andric namespace {
614ba319b5SDimitry Andric /// Stable hasher for PGO region counters.
6259d1ed5bSDimitry Andric ///
6359d1ed5bSDimitry Andric /// PGOHash produces a stable hash of a given function's control flow.
6459d1ed5bSDimitry Andric ///
6559d1ed5bSDimitry Andric /// Changing the output of this hash will invalidate all previously generated
6659d1ed5bSDimitry Andric /// profiles -- i.e., don't do it.
6759d1ed5bSDimitry Andric ///
6859d1ed5bSDimitry Andric /// \note When this hash does eventually change (years?), we still need to
6959d1ed5bSDimitry Andric /// support old hashes. We'll need to pull in the version number from the
7059d1ed5bSDimitry Andric /// profile data format and use the matching hash function.
7159d1ed5bSDimitry Andric class PGOHash {
7259d1ed5bSDimitry Andric uint64_t Working;
7359d1ed5bSDimitry Andric unsigned Count;
749a199699SDimitry Andric PGOHashVersion HashVersion;
7559d1ed5bSDimitry Andric llvm::MD5 MD5;
7659d1ed5bSDimitry Andric
7759d1ed5bSDimitry Andric static const int NumBitsPerType = 6;
7859d1ed5bSDimitry Andric static const unsigned NumTypesPerWord = sizeof(uint64_t) * 8 / NumBitsPerType;
7959d1ed5bSDimitry Andric static const unsigned TooBig = 1u << NumBitsPerType;
8059d1ed5bSDimitry Andric
8159d1ed5bSDimitry Andric public:
824ba319b5SDimitry Andric /// Hash values for AST nodes.
8359d1ed5bSDimitry Andric ///
8459d1ed5bSDimitry Andric /// Distinct values for AST nodes that have region counters attached.
8559d1ed5bSDimitry Andric ///
8659d1ed5bSDimitry Andric /// These values must be stable. All new members must be added at the end,
8759d1ed5bSDimitry Andric /// and no members should be removed. Changing the enumeration value for an
8859d1ed5bSDimitry Andric /// AST node will affect the hash of every function that contains that node.
8959d1ed5bSDimitry Andric enum HashType : unsigned char {
9059d1ed5bSDimitry Andric None = 0,
9159d1ed5bSDimitry Andric LabelStmt = 1,
9259d1ed5bSDimitry Andric WhileStmt,
9359d1ed5bSDimitry Andric DoStmt,
9459d1ed5bSDimitry Andric ForStmt,
9559d1ed5bSDimitry Andric CXXForRangeStmt,
9659d1ed5bSDimitry Andric ObjCForCollectionStmt,
9759d1ed5bSDimitry Andric SwitchStmt,
9859d1ed5bSDimitry Andric CaseStmt,
9959d1ed5bSDimitry Andric DefaultStmt,
10059d1ed5bSDimitry Andric IfStmt,
10159d1ed5bSDimitry Andric CXXTryStmt,
10259d1ed5bSDimitry Andric CXXCatchStmt,
10359d1ed5bSDimitry Andric ConditionalOperator,
10459d1ed5bSDimitry Andric BinaryOperatorLAnd,
10559d1ed5bSDimitry Andric BinaryOperatorLOr,
10659d1ed5bSDimitry Andric BinaryConditionalOperator,
1079a199699SDimitry Andric // The preceding values are available with PGO_HASH_V1.
1089a199699SDimitry Andric
1099a199699SDimitry Andric EndOfScope,
1109a199699SDimitry Andric IfThenBranch,
1119a199699SDimitry Andric IfElseBranch,
1129a199699SDimitry Andric GotoStmt,
1139a199699SDimitry Andric IndirectGotoStmt,
1149a199699SDimitry Andric BreakStmt,
1159a199699SDimitry Andric ContinueStmt,
1169a199699SDimitry Andric ReturnStmt,
1179a199699SDimitry Andric ThrowExpr,
1189a199699SDimitry Andric UnaryOperatorLNot,
1199a199699SDimitry Andric BinaryOperatorLT,
1209a199699SDimitry Andric BinaryOperatorGT,
1219a199699SDimitry Andric BinaryOperatorLE,
1229a199699SDimitry Andric BinaryOperatorGE,
1239a199699SDimitry Andric BinaryOperatorEQ,
1249a199699SDimitry Andric BinaryOperatorNE,
1259a199699SDimitry Andric // The preceding values are available with PGO_HASH_V2.
12659d1ed5bSDimitry Andric
12759d1ed5bSDimitry Andric // Keep this last. It's for the static assert that follows.
12859d1ed5bSDimitry Andric LastHashType
12959d1ed5bSDimitry Andric };
13059d1ed5bSDimitry Andric static_assert(LastHashType <= TooBig, "Too many types in HashType");
13159d1ed5bSDimitry Andric
PGOHash(PGOHashVersion HashVersion)1329a199699SDimitry Andric PGOHash(PGOHashVersion HashVersion)
1339a199699SDimitry Andric : Working(0), Count(0), HashVersion(HashVersion), MD5() {}
13459d1ed5bSDimitry Andric void combine(HashType Type);
13559d1ed5bSDimitry Andric uint64_t finalize();
getHashVersion() const1369a199699SDimitry Andric PGOHashVersion getHashVersion() const { return HashVersion; }
13759d1ed5bSDimitry Andric };
13859d1ed5bSDimitry Andric const int PGOHash::NumBitsPerType;
13959d1ed5bSDimitry Andric const unsigned PGOHash::NumTypesPerWord;
14059d1ed5bSDimitry Andric const unsigned PGOHash::TooBig;
14159d1ed5bSDimitry Andric
1429a199699SDimitry Andric /// Get the PGO hash version used in the given indexed profile.
getPGOHashVersion(llvm::IndexedInstrProfReader * PGOReader,CodeGenModule & CGM)1439a199699SDimitry Andric static PGOHashVersion getPGOHashVersion(llvm::IndexedInstrProfReader *PGOReader,
1449a199699SDimitry Andric CodeGenModule &CGM) {
1459a199699SDimitry Andric if (PGOReader->getVersion() <= 4)
1469a199699SDimitry Andric return PGO_HASH_V1;
1479a199699SDimitry Andric return PGO_HASH_V2;
1489a199699SDimitry Andric }
1499a199699SDimitry Andric
15059d1ed5bSDimitry Andric /// A RecursiveASTVisitor that fills a map of statements to PGO counters.
15159d1ed5bSDimitry Andric struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
1529a199699SDimitry Andric using Base = RecursiveASTVisitor<MapRegionCounters>;
1539a199699SDimitry Andric
15459d1ed5bSDimitry Andric /// The next counter value to assign.
15559d1ed5bSDimitry Andric unsigned NextCounter;
15659d1ed5bSDimitry Andric /// The function hash.
15759d1ed5bSDimitry Andric PGOHash Hash;
15859d1ed5bSDimitry Andric /// The map of statements to counters.
15959d1ed5bSDimitry Andric llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
16059d1ed5bSDimitry Andric
MapRegionCounters__anon67ae45280111::MapRegionCounters1619a199699SDimitry Andric MapRegionCounters(PGOHashVersion HashVersion,
1629a199699SDimitry Andric llvm::DenseMap<const Stmt *, unsigned> &CounterMap)
1639a199699SDimitry Andric : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap) {}
16459d1ed5bSDimitry Andric
16559d1ed5bSDimitry Andric // Blocks and lambdas are handled as separate functions, so we need not
16659d1ed5bSDimitry Andric // traverse them in the parent context.
TraverseBlockExpr__anon67ae45280111::MapRegionCounters16759d1ed5bSDimitry Andric bool TraverseBlockExpr(BlockExpr *BE) { return true; }
TraverseLambdaExpr__anon67ae45280111::MapRegionCounters168*b5893f02SDimitry Andric bool TraverseLambdaExpr(LambdaExpr *LE) {
169*b5893f02SDimitry Andric // Traverse the captures, but not the body.
170*b5893f02SDimitry Andric for (const auto &C : zip(LE->captures(), LE->capture_inits()))
171*b5893f02SDimitry Andric TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C));
172*b5893f02SDimitry Andric return true;
173*b5893f02SDimitry Andric }
TraverseCapturedStmt__anon67ae45280111::MapRegionCounters17459d1ed5bSDimitry Andric bool TraverseCapturedStmt(CapturedStmt *CS) { return true; }
17559d1ed5bSDimitry Andric
VisitDecl__anon67ae45280111::MapRegionCounters17659d1ed5bSDimitry Andric bool VisitDecl(const Decl *D) {
17759d1ed5bSDimitry Andric switch (D->getKind()) {
17859d1ed5bSDimitry Andric default:
17959d1ed5bSDimitry Andric break;
18059d1ed5bSDimitry Andric case Decl::Function:
18159d1ed5bSDimitry Andric case Decl::CXXMethod:
18259d1ed5bSDimitry Andric case Decl::CXXConstructor:
18359d1ed5bSDimitry Andric case Decl::CXXDestructor:
18459d1ed5bSDimitry Andric case Decl::CXXConversion:
18559d1ed5bSDimitry Andric case Decl::ObjCMethod:
18659d1ed5bSDimitry Andric case Decl::Block:
18759d1ed5bSDimitry Andric case Decl::Captured:
18859d1ed5bSDimitry Andric CounterMap[D->getBody()] = NextCounter++;
18959d1ed5bSDimitry Andric break;
19059d1ed5bSDimitry Andric }
19159d1ed5bSDimitry Andric return true;
19259d1ed5bSDimitry Andric }
19359d1ed5bSDimitry Andric
1949a199699SDimitry Andric /// If \p S gets a fresh counter, update the counter mappings. Return the
1959a199699SDimitry Andric /// V1 hash of \p S.
updateCounterMappings__anon67ae45280111::MapRegionCounters1969a199699SDimitry Andric PGOHash::HashType updateCounterMappings(Stmt *S) {
1979a199699SDimitry Andric auto Type = getHashType(PGO_HASH_V1, S);
1989a199699SDimitry Andric if (Type != PGOHash::None)
19959d1ed5bSDimitry Andric CounterMap[S] = NextCounter++;
2009a199699SDimitry Andric return Type;
2019a199699SDimitry Andric }
2029a199699SDimitry Andric
2039a199699SDimitry Andric /// Include \p S in the function hash.
VisitStmt__anon67ae45280111::MapRegionCounters2049a199699SDimitry Andric bool VisitStmt(Stmt *S) {
2059a199699SDimitry Andric auto Type = updateCounterMappings(S);
2069a199699SDimitry Andric if (Hash.getHashVersion() != PGO_HASH_V1)
2079a199699SDimitry Andric Type = getHashType(Hash.getHashVersion(), S);
2089a199699SDimitry Andric if (Type != PGOHash::None)
20959d1ed5bSDimitry Andric Hash.combine(Type);
21059d1ed5bSDimitry Andric return true;
21159d1ed5bSDimitry Andric }
2129a199699SDimitry Andric
TraverseIfStmt__anon67ae45280111::MapRegionCounters2139a199699SDimitry Andric bool TraverseIfStmt(IfStmt *If) {
2149a199699SDimitry Andric // If we used the V1 hash, use the default traversal.
2159a199699SDimitry Andric if (Hash.getHashVersion() == PGO_HASH_V1)
2169a199699SDimitry Andric return Base::TraverseIfStmt(If);
2179a199699SDimitry Andric
2189a199699SDimitry Andric // Otherwise, keep track of which branch we're in while traversing.
2199a199699SDimitry Andric VisitStmt(If);
2209a199699SDimitry Andric for (Stmt *CS : If->children()) {
2219a199699SDimitry Andric if (!CS)
2229a199699SDimitry Andric continue;
2239a199699SDimitry Andric if (CS == If->getThen())
2249a199699SDimitry Andric Hash.combine(PGOHash::IfThenBranch);
2259a199699SDimitry Andric else if (CS == If->getElse())
2269a199699SDimitry Andric Hash.combine(PGOHash::IfElseBranch);
2279a199699SDimitry Andric TraverseStmt(CS);
2289a199699SDimitry Andric }
2299a199699SDimitry Andric Hash.combine(PGOHash::EndOfScope);
2309a199699SDimitry Andric return true;
2319a199699SDimitry Andric }
2329a199699SDimitry Andric
2339a199699SDimitry Andric // If the statement type \p N is nestable, and its nesting impacts profile
2349a199699SDimitry Andric // stability, define a custom traversal which tracks the end of the statement
2359a199699SDimitry Andric // in the hash (provided we're not using the V1 hash).
2369a199699SDimitry Andric #define DEFINE_NESTABLE_TRAVERSAL(N) \
2379a199699SDimitry Andric bool Traverse##N(N *S) { \
2389a199699SDimitry Andric Base::Traverse##N(S); \
2399a199699SDimitry Andric if (Hash.getHashVersion() != PGO_HASH_V1) \
2409a199699SDimitry Andric Hash.combine(PGOHash::EndOfScope); \
2419a199699SDimitry Andric return true; \
2429a199699SDimitry Andric }
2439a199699SDimitry Andric
2449a199699SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(WhileStmt)
DEFINE_NESTABLE_TRAVERSAL__anon67ae45280111::MapRegionCounters2459a199699SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(DoStmt)
2469a199699SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(ForStmt)
2479a199699SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(CXXForRangeStmt)
2489a199699SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(ObjCForCollectionStmt)
2499a199699SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(CXXTryStmt)
2509a199699SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(CXXCatchStmt)
2519a199699SDimitry Andric
2529a199699SDimitry Andric /// Get version \p HashVersion of the PGO hash for \p S.
2539a199699SDimitry Andric PGOHash::HashType getHashType(PGOHashVersion HashVersion, const Stmt *S) {
25459d1ed5bSDimitry Andric switch (S->getStmtClass()) {
25559d1ed5bSDimitry Andric default:
25659d1ed5bSDimitry Andric break;
25759d1ed5bSDimitry Andric case Stmt::LabelStmtClass:
25859d1ed5bSDimitry Andric return PGOHash::LabelStmt;
25959d1ed5bSDimitry Andric case Stmt::WhileStmtClass:
26059d1ed5bSDimitry Andric return PGOHash::WhileStmt;
26159d1ed5bSDimitry Andric case Stmt::DoStmtClass:
26259d1ed5bSDimitry Andric return PGOHash::DoStmt;
26359d1ed5bSDimitry Andric case Stmt::ForStmtClass:
26459d1ed5bSDimitry Andric return PGOHash::ForStmt;
26559d1ed5bSDimitry Andric case Stmt::CXXForRangeStmtClass:
26659d1ed5bSDimitry Andric return PGOHash::CXXForRangeStmt;
26759d1ed5bSDimitry Andric case Stmt::ObjCForCollectionStmtClass:
26859d1ed5bSDimitry Andric return PGOHash::ObjCForCollectionStmt;
26959d1ed5bSDimitry Andric case Stmt::SwitchStmtClass:
27059d1ed5bSDimitry Andric return PGOHash::SwitchStmt;
27159d1ed5bSDimitry Andric case Stmt::CaseStmtClass:
27259d1ed5bSDimitry Andric return PGOHash::CaseStmt;
27359d1ed5bSDimitry Andric case Stmt::DefaultStmtClass:
27459d1ed5bSDimitry Andric return PGOHash::DefaultStmt;
27559d1ed5bSDimitry Andric case Stmt::IfStmtClass:
27659d1ed5bSDimitry Andric return PGOHash::IfStmt;
27759d1ed5bSDimitry Andric case Stmt::CXXTryStmtClass:
27859d1ed5bSDimitry Andric return PGOHash::CXXTryStmt;
27959d1ed5bSDimitry Andric case Stmt::CXXCatchStmtClass:
28059d1ed5bSDimitry Andric return PGOHash::CXXCatchStmt;
28159d1ed5bSDimitry Andric case Stmt::ConditionalOperatorClass:
28259d1ed5bSDimitry Andric return PGOHash::ConditionalOperator;
28359d1ed5bSDimitry Andric case Stmt::BinaryConditionalOperatorClass:
28459d1ed5bSDimitry Andric return PGOHash::BinaryConditionalOperator;
28559d1ed5bSDimitry Andric case Stmt::BinaryOperatorClass: {
28659d1ed5bSDimitry Andric const BinaryOperator *BO = cast<BinaryOperator>(S);
28759d1ed5bSDimitry Andric if (BO->getOpcode() == BO_LAnd)
28859d1ed5bSDimitry Andric return PGOHash::BinaryOperatorLAnd;
28959d1ed5bSDimitry Andric if (BO->getOpcode() == BO_LOr)
29059d1ed5bSDimitry Andric return PGOHash::BinaryOperatorLOr;
2919a199699SDimitry Andric if (HashVersion == PGO_HASH_V2) {
2929a199699SDimitry Andric switch (BO->getOpcode()) {
2939a199699SDimitry Andric default:
2949a199699SDimitry Andric break;
2959a199699SDimitry Andric case BO_LT:
2969a199699SDimitry Andric return PGOHash::BinaryOperatorLT;
2979a199699SDimitry Andric case BO_GT:
2989a199699SDimitry Andric return PGOHash::BinaryOperatorGT;
2999a199699SDimitry Andric case BO_LE:
3009a199699SDimitry Andric return PGOHash::BinaryOperatorLE;
3019a199699SDimitry Andric case BO_GE:
3029a199699SDimitry Andric return PGOHash::BinaryOperatorGE;
3039a199699SDimitry Andric case BO_EQ:
3049a199699SDimitry Andric return PGOHash::BinaryOperatorEQ;
3059a199699SDimitry Andric case BO_NE:
3069a199699SDimitry Andric return PGOHash::BinaryOperatorNE;
3079a199699SDimitry Andric }
3089a199699SDimitry Andric }
30959d1ed5bSDimitry Andric break;
31059d1ed5bSDimitry Andric }
31159d1ed5bSDimitry Andric }
3129a199699SDimitry Andric
3139a199699SDimitry Andric if (HashVersion == PGO_HASH_V2) {
3149a199699SDimitry Andric switch (S->getStmtClass()) {
3159a199699SDimitry Andric default:
3169a199699SDimitry Andric break;
3179a199699SDimitry Andric case Stmt::GotoStmtClass:
3189a199699SDimitry Andric return PGOHash::GotoStmt;
3199a199699SDimitry Andric case Stmt::IndirectGotoStmtClass:
3209a199699SDimitry Andric return PGOHash::IndirectGotoStmt;
3219a199699SDimitry Andric case Stmt::BreakStmtClass:
3229a199699SDimitry Andric return PGOHash::BreakStmt;
3239a199699SDimitry Andric case Stmt::ContinueStmtClass:
3249a199699SDimitry Andric return PGOHash::ContinueStmt;
3259a199699SDimitry Andric case Stmt::ReturnStmtClass:
3269a199699SDimitry Andric return PGOHash::ReturnStmt;
3279a199699SDimitry Andric case Stmt::CXXThrowExprClass:
3289a199699SDimitry Andric return PGOHash::ThrowExpr;
3299a199699SDimitry Andric case Stmt::UnaryOperatorClass: {
3309a199699SDimitry Andric const UnaryOperator *UO = cast<UnaryOperator>(S);
3319a199699SDimitry Andric if (UO->getOpcode() == UO_LNot)
3329a199699SDimitry Andric return PGOHash::UnaryOperatorLNot;
3339a199699SDimitry Andric break;
3349a199699SDimitry Andric }
3359a199699SDimitry Andric }
3369a199699SDimitry Andric }
3379a199699SDimitry Andric
33859d1ed5bSDimitry Andric return PGOHash::None;
33959d1ed5bSDimitry Andric }
34059d1ed5bSDimitry Andric };
34159d1ed5bSDimitry Andric
34259d1ed5bSDimitry Andric /// A StmtVisitor that propagates the raw counts through the AST and
34359d1ed5bSDimitry Andric /// records the count at statements where the value may change.
34459d1ed5bSDimitry Andric struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
34559d1ed5bSDimitry Andric /// PGO state.
34659d1ed5bSDimitry Andric CodeGenPGO &PGO;
34759d1ed5bSDimitry Andric
34859d1ed5bSDimitry Andric /// A flag that is set when the current count should be recorded on the
34959d1ed5bSDimitry Andric /// next statement, such as at the exit of a loop.
35059d1ed5bSDimitry Andric bool RecordNextStmtCount;
35159d1ed5bSDimitry Andric
35233956c43SDimitry Andric /// The count at the current location in the traversal.
35333956c43SDimitry Andric uint64_t CurrentCount;
35433956c43SDimitry Andric
35559d1ed5bSDimitry Andric /// The map of statements to count values.
35659d1ed5bSDimitry Andric llvm::DenseMap<const Stmt *, uint64_t> &CountMap;
35759d1ed5bSDimitry Andric
35859d1ed5bSDimitry Andric /// BreakContinueStack - Keep counts of breaks and continues inside loops.
35959d1ed5bSDimitry Andric struct BreakContinue {
36059d1ed5bSDimitry Andric uint64_t BreakCount;
36159d1ed5bSDimitry Andric uint64_t ContinueCount;
BreakContinue__anon67ae45280111::ComputeRegionCounts::BreakContinue36259d1ed5bSDimitry Andric BreakContinue() : BreakCount(0), ContinueCount(0) {}
36359d1ed5bSDimitry Andric };
36459d1ed5bSDimitry Andric SmallVector<BreakContinue, 8> BreakContinueStack;
36559d1ed5bSDimitry Andric
ComputeRegionCounts__anon67ae45280111::ComputeRegionCounts36659d1ed5bSDimitry Andric ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &CountMap,
36759d1ed5bSDimitry Andric CodeGenPGO &PGO)
36859d1ed5bSDimitry Andric : PGO(PGO), RecordNextStmtCount(false), CountMap(CountMap) {}
36959d1ed5bSDimitry Andric
RecordStmtCount__anon67ae45280111::ComputeRegionCounts37059d1ed5bSDimitry Andric void RecordStmtCount(const Stmt *S) {
37159d1ed5bSDimitry Andric if (RecordNextStmtCount) {
37233956c43SDimitry Andric CountMap[S] = CurrentCount;
37359d1ed5bSDimitry Andric RecordNextStmtCount = false;
37459d1ed5bSDimitry Andric }
37559d1ed5bSDimitry Andric }
37659d1ed5bSDimitry Andric
37733956c43SDimitry Andric /// Set and return the current count.
setCount__anon67ae45280111::ComputeRegionCounts37833956c43SDimitry Andric uint64_t setCount(uint64_t Count) {
37933956c43SDimitry Andric CurrentCount = Count;
38033956c43SDimitry Andric return Count;
38133956c43SDimitry Andric }
38233956c43SDimitry Andric
VisitStmt__anon67ae45280111::ComputeRegionCounts38359d1ed5bSDimitry Andric void VisitStmt(const Stmt *S) {
38459d1ed5bSDimitry Andric RecordStmtCount(S);
3853dac3a9bSDimitry Andric for (const Stmt *Child : S->children())
3863dac3a9bSDimitry Andric if (Child)
3873dac3a9bSDimitry Andric this->Visit(Child);
38859d1ed5bSDimitry Andric }
38959d1ed5bSDimitry Andric
VisitFunctionDecl__anon67ae45280111::ComputeRegionCounts39059d1ed5bSDimitry Andric void VisitFunctionDecl(const FunctionDecl *D) {
39159d1ed5bSDimitry Andric // Counter tracks entry to the function body.
39233956c43SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
39333956c43SDimitry Andric CountMap[D->getBody()] = BodyCount;
39459d1ed5bSDimitry Andric Visit(D->getBody());
39559d1ed5bSDimitry Andric }
39659d1ed5bSDimitry Andric
39759d1ed5bSDimitry Andric // Skip lambda expressions. We visit these as FunctionDecls when we're
39859d1ed5bSDimitry Andric // generating them and aren't interested in the body when generating a
39959d1ed5bSDimitry Andric // parent context.
VisitLambdaExpr__anon67ae45280111::ComputeRegionCounts40059d1ed5bSDimitry Andric void VisitLambdaExpr(const LambdaExpr *LE) {}
40159d1ed5bSDimitry Andric
VisitCapturedDecl__anon67ae45280111::ComputeRegionCounts40259d1ed5bSDimitry Andric void VisitCapturedDecl(const CapturedDecl *D) {
40359d1ed5bSDimitry Andric // Counter tracks entry to the capture body.
40433956c43SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
40533956c43SDimitry Andric CountMap[D->getBody()] = BodyCount;
40659d1ed5bSDimitry Andric Visit(D->getBody());
40759d1ed5bSDimitry Andric }
40859d1ed5bSDimitry Andric
VisitObjCMethodDecl__anon67ae45280111::ComputeRegionCounts40959d1ed5bSDimitry Andric void VisitObjCMethodDecl(const ObjCMethodDecl *D) {
41059d1ed5bSDimitry Andric // Counter tracks entry to the method body.
41133956c43SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
41233956c43SDimitry Andric CountMap[D->getBody()] = BodyCount;
41359d1ed5bSDimitry Andric Visit(D->getBody());
41459d1ed5bSDimitry Andric }
41559d1ed5bSDimitry Andric
VisitBlockDecl__anon67ae45280111::ComputeRegionCounts41659d1ed5bSDimitry Andric void VisitBlockDecl(const BlockDecl *D) {
41759d1ed5bSDimitry Andric // Counter tracks entry to the block body.
41833956c43SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
41933956c43SDimitry Andric CountMap[D->getBody()] = BodyCount;
42059d1ed5bSDimitry Andric Visit(D->getBody());
42159d1ed5bSDimitry Andric }
42259d1ed5bSDimitry Andric
VisitReturnStmt__anon67ae45280111::ComputeRegionCounts42359d1ed5bSDimitry Andric void VisitReturnStmt(const ReturnStmt *S) {
42459d1ed5bSDimitry Andric RecordStmtCount(S);
42559d1ed5bSDimitry Andric if (S->getRetValue())
42659d1ed5bSDimitry Andric Visit(S->getRetValue());
42733956c43SDimitry Andric CurrentCount = 0;
42833956c43SDimitry Andric RecordNextStmtCount = true;
42933956c43SDimitry Andric }
43033956c43SDimitry Andric
VisitCXXThrowExpr__anon67ae45280111::ComputeRegionCounts43133956c43SDimitry Andric void VisitCXXThrowExpr(const CXXThrowExpr *E) {
43233956c43SDimitry Andric RecordStmtCount(E);
43333956c43SDimitry Andric if (E->getSubExpr())
43433956c43SDimitry Andric Visit(E->getSubExpr());
43533956c43SDimitry Andric CurrentCount = 0;
43659d1ed5bSDimitry Andric RecordNextStmtCount = true;
43759d1ed5bSDimitry Andric }
43859d1ed5bSDimitry Andric
VisitGotoStmt__anon67ae45280111::ComputeRegionCounts43959d1ed5bSDimitry Andric void VisitGotoStmt(const GotoStmt *S) {
44059d1ed5bSDimitry Andric RecordStmtCount(S);
44133956c43SDimitry Andric CurrentCount = 0;
44259d1ed5bSDimitry Andric RecordNextStmtCount = true;
44359d1ed5bSDimitry Andric }
44459d1ed5bSDimitry Andric
VisitLabelStmt__anon67ae45280111::ComputeRegionCounts44559d1ed5bSDimitry Andric void VisitLabelStmt(const LabelStmt *S) {
44659d1ed5bSDimitry Andric RecordNextStmtCount = false;
44759d1ed5bSDimitry Andric // Counter tracks the block following the label.
44833956c43SDimitry Andric uint64_t BlockCount = setCount(PGO.getRegionCount(S));
44933956c43SDimitry Andric CountMap[S] = BlockCount;
45059d1ed5bSDimitry Andric Visit(S->getSubStmt());
45159d1ed5bSDimitry Andric }
45259d1ed5bSDimitry Andric
VisitBreakStmt__anon67ae45280111::ComputeRegionCounts45359d1ed5bSDimitry Andric void VisitBreakStmt(const BreakStmt *S) {
45459d1ed5bSDimitry Andric RecordStmtCount(S);
45559d1ed5bSDimitry Andric assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
45633956c43SDimitry Andric BreakContinueStack.back().BreakCount += CurrentCount;
45733956c43SDimitry Andric CurrentCount = 0;
45859d1ed5bSDimitry Andric RecordNextStmtCount = true;
45959d1ed5bSDimitry Andric }
46059d1ed5bSDimitry Andric
VisitContinueStmt__anon67ae45280111::ComputeRegionCounts46159d1ed5bSDimitry Andric void VisitContinueStmt(const ContinueStmt *S) {
46259d1ed5bSDimitry Andric RecordStmtCount(S);
46359d1ed5bSDimitry Andric assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
46433956c43SDimitry Andric BreakContinueStack.back().ContinueCount += CurrentCount;
46533956c43SDimitry Andric CurrentCount = 0;
46659d1ed5bSDimitry Andric RecordNextStmtCount = true;
46759d1ed5bSDimitry Andric }
46859d1ed5bSDimitry Andric
VisitWhileStmt__anon67ae45280111::ComputeRegionCounts46959d1ed5bSDimitry Andric void VisitWhileStmt(const WhileStmt *S) {
47059d1ed5bSDimitry Andric RecordStmtCount(S);
47133956c43SDimitry Andric uint64_t ParentCount = CurrentCount;
47233956c43SDimitry Andric
47359d1ed5bSDimitry Andric BreakContinueStack.push_back(BreakContinue());
47459d1ed5bSDimitry Andric // Visit the body region first so the break/continue adjustments can be
47559d1ed5bSDimitry Andric // included when visiting the condition.
47633956c43SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(S));
47733956c43SDimitry Andric CountMap[S->getBody()] = CurrentCount;
47859d1ed5bSDimitry Andric Visit(S->getBody());
47933956c43SDimitry Andric uint64_t BackedgeCount = CurrentCount;
48059d1ed5bSDimitry Andric
48159d1ed5bSDimitry Andric // ...then go back and propagate counts through the condition. The count
48259d1ed5bSDimitry Andric // at the start of the condition is the sum of the incoming edges,
48359d1ed5bSDimitry Andric // the backedge from the end of the loop body, and the edges from
48459d1ed5bSDimitry Andric // continue statements.
48559d1ed5bSDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val();
48633956c43SDimitry Andric uint64_t CondCount =
48733956c43SDimitry Andric setCount(ParentCount + BackedgeCount + BC.ContinueCount);
48833956c43SDimitry Andric CountMap[S->getCond()] = CondCount;
48959d1ed5bSDimitry Andric Visit(S->getCond());
49033956c43SDimitry Andric setCount(BC.BreakCount + CondCount - BodyCount);
49159d1ed5bSDimitry Andric RecordNextStmtCount = true;
49259d1ed5bSDimitry Andric }
49359d1ed5bSDimitry Andric
VisitDoStmt__anon67ae45280111::ComputeRegionCounts49459d1ed5bSDimitry Andric void VisitDoStmt(const DoStmt *S) {
49559d1ed5bSDimitry Andric RecordStmtCount(S);
49633956c43SDimitry Andric uint64_t LoopCount = PGO.getRegionCount(S);
49733956c43SDimitry Andric
49859d1ed5bSDimitry Andric BreakContinueStack.push_back(BreakContinue());
49933956c43SDimitry Andric // The count doesn't include the fallthrough from the parent scope. Add it.
50033956c43SDimitry Andric uint64_t BodyCount = setCount(LoopCount + CurrentCount);
50133956c43SDimitry Andric CountMap[S->getBody()] = BodyCount;
50259d1ed5bSDimitry Andric Visit(S->getBody());
50333956c43SDimitry Andric uint64_t BackedgeCount = CurrentCount;
50459d1ed5bSDimitry Andric
50559d1ed5bSDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val();
50659d1ed5bSDimitry Andric // The count at the start of the condition is equal to the count at the
50733956c43SDimitry Andric // end of the body, plus any continues.
50833956c43SDimitry Andric uint64_t CondCount = setCount(BackedgeCount + BC.ContinueCount);
50933956c43SDimitry Andric CountMap[S->getCond()] = CondCount;
51059d1ed5bSDimitry Andric Visit(S->getCond());
51133956c43SDimitry Andric setCount(BC.BreakCount + CondCount - LoopCount);
51259d1ed5bSDimitry Andric RecordNextStmtCount = true;
51359d1ed5bSDimitry Andric }
51459d1ed5bSDimitry Andric
VisitForStmt__anon67ae45280111::ComputeRegionCounts51559d1ed5bSDimitry Andric void VisitForStmt(const ForStmt *S) {
51659d1ed5bSDimitry Andric RecordStmtCount(S);
51759d1ed5bSDimitry Andric if (S->getInit())
51859d1ed5bSDimitry Andric Visit(S->getInit());
51933956c43SDimitry Andric
52033956c43SDimitry Andric uint64_t ParentCount = CurrentCount;
52133956c43SDimitry Andric
52259d1ed5bSDimitry Andric BreakContinueStack.push_back(BreakContinue());
52359d1ed5bSDimitry Andric // Visit the body region first. (This is basically the same as a while
52459d1ed5bSDimitry Andric // loop; see further comments in VisitWhileStmt.)
52533956c43SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(S));
52633956c43SDimitry Andric CountMap[S->getBody()] = BodyCount;
52759d1ed5bSDimitry Andric Visit(S->getBody());
52833956c43SDimitry Andric uint64_t BackedgeCount = CurrentCount;
52933956c43SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val();
53059d1ed5bSDimitry Andric
53159d1ed5bSDimitry Andric // The increment is essentially part of the body but it needs to include
53259d1ed5bSDimitry Andric // the count for all the continue statements.
53359d1ed5bSDimitry Andric if (S->getInc()) {
53433956c43SDimitry Andric uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
53533956c43SDimitry Andric CountMap[S->getInc()] = IncCount;
53659d1ed5bSDimitry Andric Visit(S->getInc());
53759d1ed5bSDimitry Andric }
53859d1ed5bSDimitry Andric
53959d1ed5bSDimitry Andric // ...then go back and propagate counts through the condition.
54033956c43SDimitry Andric uint64_t CondCount =
54133956c43SDimitry Andric setCount(ParentCount + BackedgeCount + BC.ContinueCount);
54259d1ed5bSDimitry Andric if (S->getCond()) {
54333956c43SDimitry Andric CountMap[S->getCond()] = CondCount;
54459d1ed5bSDimitry Andric Visit(S->getCond());
54559d1ed5bSDimitry Andric }
54633956c43SDimitry Andric setCount(BC.BreakCount + CondCount - BodyCount);
54759d1ed5bSDimitry Andric RecordNextStmtCount = true;
54859d1ed5bSDimitry Andric }
54959d1ed5bSDimitry Andric
VisitCXXForRangeStmt__anon67ae45280111::ComputeRegionCounts55059d1ed5bSDimitry Andric void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
55159d1ed5bSDimitry Andric RecordStmtCount(S);
552*b5893f02SDimitry Andric if (S->getInit())
553*b5893f02SDimitry Andric Visit(S->getInit());
55433956c43SDimitry Andric Visit(S->getLoopVarStmt());
55559d1ed5bSDimitry Andric Visit(S->getRangeStmt());
556e7145dcbSDimitry Andric Visit(S->getBeginStmt());
557e7145dcbSDimitry Andric Visit(S->getEndStmt());
55833956c43SDimitry Andric
55933956c43SDimitry Andric uint64_t ParentCount = CurrentCount;
56059d1ed5bSDimitry Andric BreakContinueStack.push_back(BreakContinue());
56159d1ed5bSDimitry Andric // Visit the body region first. (This is basically the same as a while
56259d1ed5bSDimitry Andric // loop; see further comments in VisitWhileStmt.)
56333956c43SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(S));
56433956c43SDimitry Andric CountMap[S->getBody()] = BodyCount;
56559d1ed5bSDimitry Andric Visit(S->getBody());
56633956c43SDimitry Andric uint64_t BackedgeCount = CurrentCount;
56733956c43SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val();
56859d1ed5bSDimitry Andric
56959d1ed5bSDimitry Andric // The increment is essentially part of the body but it needs to include
57059d1ed5bSDimitry Andric // the count for all the continue statements.
57133956c43SDimitry Andric uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
57233956c43SDimitry Andric CountMap[S->getInc()] = IncCount;
57359d1ed5bSDimitry Andric Visit(S->getInc());
57459d1ed5bSDimitry Andric
57559d1ed5bSDimitry Andric // ...then go back and propagate counts through the condition.
57633956c43SDimitry Andric uint64_t CondCount =
57733956c43SDimitry Andric setCount(ParentCount + BackedgeCount + BC.ContinueCount);
57833956c43SDimitry Andric CountMap[S->getCond()] = CondCount;
57959d1ed5bSDimitry Andric Visit(S->getCond());
58033956c43SDimitry Andric setCount(BC.BreakCount + CondCount - BodyCount);
58159d1ed5bSDimitry Andric RecordNextStmtCount = true;
58259d1ed5bSDimitry Andric }
58359d1ed5bSDimitry Andric
VisitObjCForCollectionStmt__anon67ae45280111::ComputeRegionCounts58459d1ed5bSDimitry Andric void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
58559d1ed5bSDimitry Andric RecordStmtCount(S);
58659d1ed5bSDimitry Andric Visit(S->getElement());
58733956c43SDimitry Andric uint64_t ParentCount = CurrentCount;
58859d1ed5bSDimitry Andric BreakContinueStack.push_back(BreakContinue());
58933956c43SDimitry Andric // Counter tracks the body of the loop.
59033956c43SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(S));
59133956c43SDimitry Andric CountMap[S->getBody()] = BodyCount;
59259d1ed5bSDimitry Andric Visit(S->getBody());
59333956c43SDimitry Andric uint64_t BackedgeCount = CurrentCount;
59459d1ed5bSDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val();
59533956c43SDimitry Andric
59633956c43SDimitry Andric setCount(BC.BreakCount + ParentCount + BackedgeCount + BC.ContinueCount -
59733956c43SDimitry Andric BodyCount);
59859d1ed5bSDimitry Andric RecordNextStmtCount = true;
59959d1ed5bSDimitry Andric }
60059d1ed5bSDimitry Andric
VisitSwitchStmt__anon67ae45280111::ComputeRegionCounts60159d1ed5bSDimitry Andric void VisitSwitchStmt(const SwitchStmt *S) {
60259d1ed5bSDimitry Andric RecordStmtCount(S);
60344290647SDimitry Andric if (S->getInit())
60444290647SDimitry Andric Visit(S->getInit());
60559d1ed5bSDimitry Andric Visit(S->getCond());
60633956c43SDimitry Andric CurrentCount = 0;
60759d1ed5bSDimitry Andric BreakContinueStack.push_back(BreakContinue());
60859d1ed5bSDimitry Andric Visit(S->getBody());
60959d1ed5bSDimitry Andric // If the switch is inside a loop, add the continue counts.
61059d1ed5bSDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val();
61159d1ed5bSDimitry Andric if (!BreakContinueStack.empty())
61259d1ed5bSDimitry Andric BreakContinueStack.back().ContinueCount += BC.ContinueCount;
61359d1ed5bSDimitry Andric // Counter tracks the exit block of the switch.
61433956c43SDimitry Andric setCount(PGO.getRegionCount(S));
61559d1ed5bSDimitry Andric RecordNextStmtCount = true;
61659d1ed5bSDimitry Andric }
61759d1ed5bSDimitry Andric
VisitSwitchCase__anon67ae45280111::ComputeRegionCounts61833956c43SDimitry Andric void VisitSwitchCase(const SwitchCase *S) {
61959d1ed5bSDimitry Andric RecordNextStmtCount = false;
62059d1ed5bSDimitry Andric // Counter for this particular case. This counts only jumps from the
62159d1ed5bSDimitry Andric // switch header and does not include fallthrough from the case before
62259d1ed5bSDimitry Andric // this one.
62333956c43SDimitry Andric uint64_t CaseCount = PGO.getRegionCount(S);
62433956c43SDimitry Andric setCount(CurrentCount + CaseCount);
62533956c43SDimitry Andric // We need the count without fallthrough in the mapping, so it's more useful
62633956c43SDimitry Andric // for branch probabilities.
62733956c43SDimitry Andric CountMap[S] = CaseCount;
62859d1ed5bSDimitry Andric RecordNextStmtCount = true;
62959d1ed5bSDimitry Andric Visit(S->getSubStmt());
63059d1ed5bSDimitry Andric }
63159d1ed5bSDimitry Andric
VisitIfStmt__anon67ae45280111::ComputeRegionCounts63259d1ed5bSDimitry Andric void VisitIfStmt(const IfStmt *S) {
63359d1ed5bSDimitry Andric RecordStmtCount(S);
63433956c43SDimitry Andric uint64_t ParentCount = CurrentCount;
63544290647SDimitry Andric if (S->getInit())
63644290647SDimitry Andric Visit(S->getInit());
63759d1ed5bSDimitry Andric Visit(S->getCond());
63859d1ed5bSDimitry Andric
63933956c43SDimitry Andric // Counter tracks the "then" part of an if statement. The count for
64033956c43SDimitry Andric // the "else" part, if it exists, will be calculated from this counter.
64133956c43SDimitry Andric uint64_t ThenCount = setCount(PGO.getRegionCount(S));
64233956c43SDimitry Andric CountMap[S->getThen()] = ThenCount;
64359d1ed5bSDimitry Andric Visit(S->getThen());
64433956c43SDimitry Andric uint64_t OutCount = CurrentCount;
64559d1ed5bSDimitry Andric
64633956c43SDimitry Andric uint64_t ElseCount = ParentCount - ThenCount;
64759d1ed5bSDimitry Andric if (S->getElse()) {
64833956c43SDimitry Andric setCount(ElseCount);
64933956c43SDimitry Andric CountMap[S->getElse()] = ElseCount;
65059d1ed5bSDimitry Andric Visit(S->getElse());
65133956c43SDimitry Andric OutCount += CurrentCount;
65233956c43SDimitry Andric } else
65333956c43SDimitry Andric OutCount += ElseCount;
65433956c43SDimitry Andric setCount(OutCount);
65559d1ed5bSDimitry Andric RecordNextStmtCount = true;
65659d1ed5bSDimitry Andric }
65759d1ed5bSDimitry Andric
VisitCXXTryStmt__anon67ae45280111::ComputeRegionCounts65859d1ed5bSDimitry Andric void VisitCXXTryStmt(const CXXTryStmt *S) {
65959d1ed5bSDimitry Andric RecordStmtCount(S);
66059d1ed5bSDimitry Andric Visit(S->getTryBlock());
66159d1ed5bSDimitry Andric for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
66259d1ed5bSDimitry Andric Visit(S->getHandler(I));
66359d1ed5bSDimitry Andric // Counter tracks the continuation block of the try statement.
66433956c43SDimitry Andric setCount(PGO.getRegionCount(S));
66559d1ed5bSDimitry Andric RecordNextStmtCount = true;
66659d1ed5bSDimitry Andric }
66759d1ed5bSDimitry Andric
VisitCXXCatchStmt__anon67ae45280111::ComputeRegionCounts66859d1ed5bSDimitry Andric void VisitCXXCatchStmt(const CXXCatchStmt *S) {
66959d1ed5bSDimitry Andric RecordNextStmtCount = false;
67059d1ed5bSDimitry Andric // Counter tracks the catch statement's handler block.
67133956c43SDimitry Andric uint64_t CatchCount = setCount(PGO.getRegionCount(S));
67233956c43SDimitry Andric CountMap[S] = CatchCount;
67359d1ed5bSDimitry Andric Visit(S->getHandlerBlock());
67459d1ed5bSDimitry Andric }
67559d1ed5bSDimitry Andric
VisitAbstractConditionalOperator__anon67ae45280111::ComputeRegionCounts67633956c43SDimitry Andric void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
67759d1ed5bSDimitry Andric RecordStmtCount(E);
67833956c43SDimitry Andric uint64_t ParentCount = CurrentCount;
67959d1ed5bSDimitry Andric Visit(E->getCond());
68059d1ed5bSDimitry Andric
68133956c43SDimitry Andric // Counter tracks the "true" part of a conditional operator. The
68233956c43SDimitry Andric // count in the "false" part will be calculated from this counter.
68333956c43SDimitry Andric uint64_t TrueCount = setCount(PGO.getRegionCount(E));
68433956c43SDimitry Andric CountMap[E->getTrueExpr()] = TrueCount;
68559d1ed5bSDimitry Andric Visit(E->getTrueExpr());
68633956c43SDimitry Andric uint64_t OutCount = CurrentCount;
68759d1ed5bSDimitry Andric
68833956c43SDimitry Andric uint64_t FalseCount = setCount(ParentCount - TrueCount);
68933956c43SDimitry Andric CountMap[E->getFalseExpr()] = FalseCount;
69059d1ed5bSDimitry Andric Visit(E->getFalseExpr());
69133956c43SDimitry Andric OutCount += CurrentCount;
69259d1ed5bSDimitry Andric
69333956c43SDimitry Andric setCount(OutCount);
69459d1ed5bSDimitry Andric RecordNextStmtCount = true;
69559d1ed5bSDimitry Andric }
69659d1ed5bSDimitry Andric
VisitBinLAnd__anon67ae45280111::ComputeRegionCounts69759d1ed5bSDimitry Andric void VisitBinLAnd(const BinaryOperator *E) {
69859d1ed5bSDimitry Andric RecordStmtCount(E);
69933956c43SDimitry Andric uint64_t ParentCount = CurrentCount;
70059d1ed5bSDimitry Andric Visit(E->getLHS());
70133956c43SDimitry Andric // Counter tracks the right hand side of a logical and operator.
70233956c43SDimitry Andric uint64_t RHSCount = setCount(PGO.getRegionCount(E));
70333956c43SDimitry Andric CountMap[E->getRHS()] = RHSCount;
70459d1ed5bSDimitry Andric Visit(E->getRHS());
70533956c43SDimitry Andric setCount(ParentCount + RHSCount - CurrentCount);
70659d1ed5bSDimitry Andric RecordNextStmtCount = true;
70759d1ed5bSDimitry Andric }
70859d1ed5bSDimitry Andric
VisitBinLOr__anon67ae45280111::ComputeRegionCounts70959d1ed5bSDimitry Andric void VisitBinLOr(const BinaryOperator *E) {
71059d1ed5bSDimitry Andric RecordStmtCount(E);
71133956c43SDimitry Andric uint64_t ParentCount = CurrentCount;
71259d1ed5bSDimitry Andric Visit(E->getLHS());
71333956c43SDimitry Andric // Counter tracks the right hand side of a logical or operator.
71433956c43SDimitry Andric uint64_t RHSCount = setCount(PGO.getRegionCount(E));
71533956c43SDimitry Andric CountMap[E->getRHS()] = RHSCount;
71659d1ed5bSDimitry Andric Visit(E->getRHS());
71733956c43SDimitry Andric setCount(ParentCount + RHSCount - CurrentCount);
71859d1ed5bSDimitry Andric RecordNextStmtCount = true;
71959d1ed5bSDimitry Andric }
72059d1ed5bSDimitry Andric };
7210623d748SDimitry Andric } // end anonymous namespace
72259d1ed5bSDimitry Andric
combine(HashType Type)72359d1ed5bSDimitry Andric void PGOHash::combine(HashType Type) {
72459d1ed5bSDimitry Andric // Check that we never combine 0 and only have six bits.
72559d1ed5bSDimitry Andric assert(Type && "Hash is invalid: unexpected type 0");
72659d1ed5bSDimitry Andric assert(unsigned(Type) < TooBig && "Hash is invalid: too many types");
72759d1ed5bSDimitry Andric
72859d1ed5bSDimitry Andric // Pass through MD5 if enough work has built up.
72959d1ed5bSDimitry Andric if (Count && Count % NumTypesPerWord == 0) {
73059d1ed5bSDimitry Andric using namespace llvm::support;
73159d1ed5bSDimitry Andric uint64_t Swapped = endian::byte_swap<uint64_t, little>(Working);
73259d1ed5bSDimitry Andric MD5.update(llvm::makeArrayRef((uint8_t *)&Swapped, sizeof(Swapped)));
73359d1ed5bSDimitry Andric Working = 0;
73459d1ed5bSDimitry Andric }
73559d1ed5bSDimitry Andric
73659d1ed5bSDimitry Andric // Accumulate the current type.
73759d1ed5bSDimitry Andric ++Count;
73859d1ed5bSDimitry Andric Working = Working << NumBitsPerType | Type;
73959d1ed5bSDimitry Andric }
74059d1ed5bSDimitry Andric
finalize()74159d1ed5bSDimitry Andric uint64_t PGOHash::finalize() {
74259d1ed5bSDimitry Andric // Use Working as the hash directly if we never used MD5.
74359d1ed5bSDimitry Andric if (Count <= NumTypesPerWord)
74459d1ed5bSDimitry Andric // No need to byte swap here, since none of the math was endian-dependent.
74559d1ed5bSDimitry Andric // This number will be byte-swapped as required on endianness transitions,
74659d1ed5bSDimitry Andric // so we will see the same value on the other side.
74759d1ed5bSDimitry Andric return Working;
74859d1ed5bSDimitry Andric
74959d1ed5bSDimitry Andric // Check for remaining work in Working.
75059d1ed5bSDimitry Andric if (Working)
75159d1ed5bSDimitry Andric MD5.update(Working);
75259d1ed5bSDimitry Andric
75359d1ed5bSDimitry Andric // Finalize the MD5 and return the hash.
75459d1ed5bSDimitry Andric llvm::MD5::MD5Result Result;
75559d1ed5bSDimitry Andric MD5.final(Result);
75659d1ed5bSDimitry Andric using namespace llvm::support;
75720e90f04SDimitry Andric return Result.low();
75859d1ed5bSDimitry Andric }
75959d1ed5bSDimitry Andric
assignRegionCounters(GlobalDecl GD,llvm::Function * Fn)7600623d748SDimitry Andric void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) {
7610623d748SDimitry Andric const Decl *D = GD.getDecl();
762a580b014SDimitry Andric if (!D->hasBody())
763a580b014SDimitry Andric return;
764a580b014SDimitry Andric
765e7145dcbSDimitry Andric bool InstrumentRegions = CGM.getCodeGenOpts().hasProfileClangInstr();
76659d1ed5bSDimitry Andric llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
76759d1ed5bSDimitry Andric if (!InstrumentRegions && !PGOReader)
76859d1ed5bSDimitry Andric return;
76959d1ed5bSDimitry Andric if (D->isImplicit())
77059d1ed5bSDimitry Andric return;
7710623d748SDimitry Andric // Constructors and destructors may be represented by several functions in IR.
7720623d748SDimitry Andric // If so, instrument only base variant, others are implemented by delegation
7730623d748SDimitry Andric // to the base one, it would be counted twice otherwise.
77420e90f04SDimitry Andric if (CGM.getTarget().getCXXABI().hasConstructorVariants()) {
77520e90f04SDimitry Andric if (isa<CXXDestructorDecl>(D) && GD.getDtorType() != Dtor_Base)
77620e90f04SDimitry Andric return;
77720e90f04SDimitry Andric
77820e90f04SDimitry Andric if (const auto *CCD = dyn_cast<CXXConstructorDecl>(D))
77920e90f04SDimitry Andric if (GD.getCtorType() != Ctor_Base &&
78020e90f04SDimitry Andric CodeGenFunction::IsConstructorDelegationValid(CCD))
7810623d748SDimitry Andric return;
7820623d748SDimitry Andric }
78339d628a0SDimitry Andric CGM.ClearUnusedCoverageMapping(D);
78459d1ed5bSDimitry Andric setFuncName(Fn);
78559d1ed5bSDimitry Andric
78659d1ed5bSDimitry Andric mapRegionCounters(D);
78739d628a0SDimitry Andric if (CGM.getCodeGenOpts().CoverageMapping)
78839d628a0SDimitry Andric emitCounterRegionMapping(D);
78959d1ed5bSDimitry Andric if (PGOReader) {
79059d1ed5bSDimitry Andric SourceManager &SM = CGM.getContext().getSourceManager();
79159d1ed5bSDimitry Andric loadRegionCounts(PGOReader, SM.isInMainFile(D->getLocation()));
79259d1ed5bSDimitry Andric computeRegionCounts(D);
79359d1ed5bSDimitry Andric applyFunctionAttributes(PGOReader, Fn);
79459d1ed5bSDimitry Andric }
79559d1ed5bSDimitry Andric }
79659d1ed5bSDimitry Andric
mapRegionCounters(const Decl * D)79759d1ed5bSDimitry Andric void CodeGenPGO::mapRegionCounters(const Decl *D) {
7989a199699SDimitry Andric // Use the latest hash version when inserting instrumentation, but use the
7999a199699SDimitry Andric // version in the indexed profile if we're reading PGO data.
8009a199699SDimitry Andric PGOHashVersion HashVersion = PGO_HASH_LATEST;
8019a199699SDimitry Andric if (auto *PGOReader = CGM.getPGOReader())
8029a199699SDimitry Andric HashVersion = getPGOHashVersion(PGOReader, CGM);
8039a199699SDimitry Andric
80459d1ed5bSDimitry Andric RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>);
8059a199699SDimitry Andric MapRegionCounters Walker(HashVersion, *RegionCounterMap);
80659d1ed5bSDimitry Andric if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
80759d1ed5bSDimitry Andric Walker.TraverseDecl(const_cast<FunctionDecl *>(FD));
80859d1ed5bSDimitry Andric else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
80959d1ed5bSDimitry Andric Walker.TraverseDecl(const_cast<ObjCMethodDecl *>(MD));
81059d1ed5bSDimitry Andric else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
81159d1ed5bSDimitry Andric Walker.TraverseDecl(const_cast<BlockDecl *>(BD));
81259d1ed5bSDimitry Andric else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
81359d1ed5bSDimitry Andric Walker.TraverseDecl(const_cast<CapturedDecl *>(CD));
81459d1ed5bSDimitry Andric assert(Walker.NextCounter > 0 && "no entry counter mapped for decl");
81559d1ed5bSDimitry Andric NumRegionCounters = Walker.NextCounter;
81659d1ed5bSDimitry Andric FunctionHash = Walker.Hash.finalize();
81759d1ed5bSDimitry Andric }
81859d1ed5bSDimitry Andric
skipRegionMappingForDecl(const Decl * D)819e7145dcbSDimitry Andric bool CodeGenPGO::skipRegionMappingForDecl(const Decl *D) {
82051690af2SDimitry Andric if (!D->getBody())
821e7145dcbSDimitry Andric return true;
822e7145dcbSDimitry Andric
823e7145dcbSDimitry Andric // Don't map the functions in system headers.
824e7145dcbSDimitry Andric const auto &SM = CGM.getContext().getSourceManager();
825*b5893f02SDimitry Andric auto Loc = D->getBody()->getBeginLoc();
826e7145dcbSDimitry Andric return SM.isInSystemHeader(Loc);
827e7145dcbSDimitry Andric }
828e7145dcbSDimitry Andric
emitCounterRegionMapping(const Decl * D)829e7145dcbSDimitry Andric void CodeGenPGO::emitCounterRegionMapping(const Decl *D) {
830e7145dcbSDimitry Andric if (skipRegionMappingForDecl(D))
83139d628a0SDimitry Andric return;
83239d628a0SDimitry Andric
83339d628a0SDimitry Andric std::string CoverageMapping;
83439d628a0SDimitry Andric llvm::raw_string_ostream OS(CoverageMapping);
83539d628a0SDimitry Andric CoverageMappingGen MappingGen(*CGM.getCoverageMapping(),
83639d628a0SDimitry Andric CGM.getContext().getSourceManager(),
83739d628a0SDimitry Andric CGM.getLangOpts(), RegionCounterMap.get());
83839d628a0SDimitry Andric MappingGen.emitCounterMapping(D, OS);
83939d628a0SDimitry Andric OS.flush();
84039d628a0SDimitry Andric
84139d628a0SDimitry Andric if (CoverageMapping.empty())
84239d628a0SDimitry Andric return;
84339d628a0SDimitry Andric
84439d628a0SDimitry Andric CGM.getCoverageMapping()->addFunctionMappingRecord(
84539d628a0SDimitry Andric FuncNameVar, FuncName, FunctionHash, CoverageMapping);
84639d628a0SDimitry Andric }
84739d628a0SDimitry Andric
84839d628a0SDimitry Andric void
emitEmptyCounterMapping(const Decl * D,StringRef Name,llvm::GlobalValue::LinkageTypes Linkage)84933956c43SDimitry Andric CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef Name,
85039d628a0SDimitry Andric llvm::GlobalValue::LinkageTypes Linkage) {
851e7145dcbSDimitry Andric if (skipRegionMappingForDecl(D))
85239d628a0SDimitry Andric return;
85339d628a0SDimitry Andric
85439d628a0SDimitry Andric std::string CoverageMapping;
85539d628a0SDimitry Andric llvm::raw_string_ostream OS(CoverageMapping);
85639d628a0SDimitry Andric CoverageMappingGen MappingGen(*CGM.getCoverageMapping(),
85739d628a0SDimitry Andric CGM.getContext().getSourceManager(),
85839d628a0SDimitry Andric CGM.getLangOpts());
85939d628a0SDimitry Andric MappingGen.emitEmptyMapping(D, OS);
86039d628a0SDimitry Andric OS.flush();
86139d628a0SDimitry Andric
86239d628a0SDimitry Andric if (CoverageMapping.empty())
86339d628a0SDimitry Andric return;
86439d628a0SDimitry Andric
86533956c43SDimitry Andric setFuncName(Name, Linkage);
86639d628a0SDimitry Andric CGM.getCoverageMapping()->addFunctionMappingRecord(
867444ed5c5SDimitry Andric FuncNameVar, FuncName, FunctionHash, CoverageMapping, false);
86839d628a0SDimitry Andric }
86939d628a0SDimitry Andric
computeRegionCounts(const Decl * D)87059d1ed5bSDimitry Andric void CodeGenPGO::computeRegionCounts(const Decl *D) {
87159d1ed5bSDimitry Andric StmtCountMap.reset(new llvm::DenseMap<const Stmt *, uint64_t>);
87259d1ed5bSDimitry Andric ComputeRegionCounts Walker(*StmtCountMap, *this);
87359d1ed5bSDimitry Andric if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
87459d1ed5bSDimitry Andric Walker.VisitFunctionDecl(FD);
87559d1ed5bSDimitry Andric else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
87659d1ed5bSDimitry Andric Walker.VisitObjCMethodDecl(MD);
87759d1ed5bSDimitry Andric else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
87859d1ed5bSDimitry Andric Walker.VisitBlockDecl(BD);
87959d1ed5bSDimitry Andric else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
88059d1ed5bSDimitry Andric Walker.VisitCapturedDecl(const_cast<CapturedDecl *>(CD));
88159d1ed5bSDimitry Andric }
88259d1ed5bSDimitry Andric
88359d1ed5bSDimitry Andric void
applyFunctionAttributes(llvm::IndexedInstrProfReader * PGOReader,llvm::Function * Fn)88459d1ed5bSDimitry Andric CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
88559d1ed5bSDimitry Andric llvm::Function *Fn) {
88659d1ed5bSDimitry Andric if (!haveRegionCounts())
88759d1ed5bSDimitry Andric return;
88859d1ed5bSDimitry Andric
8890623d748SDimitry Andric uint64_t FunctionCount = getRegionCount(nullptr);
89097bc6c73SDimitry Andric Fn->setEntryCount(FunctionCount);
89159d1ed5bSDimitry Andric }
89259d1ed5bSDimitry Andric
emitCounterIncrement(CGBuilderTy & Builder,const Stmt * S,llvm::Value * StepV)89320e90f04SDimitry Andric void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S,
89420e90f04SDimitry Andric llvm::Value *StepV) {
895e7145dcbSDimitry Andric if (!CGM.getCodeGenOpts().hasProfileClangInstr() || !RegionCounterMap)
89659d1ed5bSDimitry Andric return;
8970623d748SDimitry Andric if (!Builder.GetInsertBlock())
89839d628a0SDimitry Andric return;
89933956c43SDimitry Andric
90033956c43SDimitry Andric unsigned Counter = (*RegionCounterMap)[S];
90139d628a0SDimitry Andric auto *I8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
90220e90f04SDimitry Andric
90320e90f04SDimitry Andric llvm::Value *Args[] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
90439d628a0SDimitry Andric Builder.getInt64(FunctionHash),
90539d628a0SDimitry Andric Builder.getInt32(NumRegionCounters),
90620e90f04SDimitry Andric Builder.getInt32(Counter), StepV};
90720e90f04SDimitry Andric if (!StepV)
90820e90f04SDimitry Andric Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment),
90920e90f04SDimitry Andric makeArrayRef(Args, 4));
91020e90f04SDimitry Andric else
91120e90f04SDimitry Andric Builder.CreateCall(
91220e90f04SDimitry Andric CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment_step),
91320e90f04SDimitry Andric makeArrayRef(Args));
91459d1ed5bSDimitry Andric }
91559d1ed5bSDimitry Andric
916e7145dcbSDimitry Andric // This method either inserts a call to the profile run-time during
917e7145dcbSDimitry Andric // instrumentation or puts profile data into metadata for PGO use.
valueProfile(CGBuilderTy & Builder,uint32_t ValueKind,llvm::Instruction * ValueSite,llvm::Value * ValuePtr)918e7145dcbSDimitry Andric void CodeGenPGO::valueProfile(CGBuilderTy &Builder, uint32_t ValueKind,
919e7145dcbSDimitry Andric llvm::Instruction *ValueSite, llvm::Value *ValuePtr) {
920e7145dcbSDimitry Andric
921e7145dcbSDimitry Andric if (!EnableValueProfiling)
922e7145dcbSDimitry Andric return;
923e7145dcbSDimitry Andric
924e7145dcbSDimitry Andric if (!ValuePtr || !ValueSite || !Builder.GetInsertBlock())
925e7145dcbSDimitry Andric return;
926e7145dcbSDimitry Andric
927e7145dcbSDimitry Andric if (isa<llvm::Constant>(ValuePtr))
928e7145dcbSDimitry Andric return;
929e7145dcbSDimitry Andric
930e7145dcbSDimitry Andric bool InstrumentValueSites = CGM.getCodeGenOpts().hasProfileClangInstr();
931e7145dcbSDimitry Andric if (InstrumentValueSites && RegionCounterMap) {
932e7145dcbSDimitry Andric auto BuilderInsertPoint = Builder.saveIP();
933e7145dcbSDimitry Andric Builder.SetInsertPoint(ValueSite);
934e7145dcbSDimitry Andric llvm::Value *Args[5] = {
935e7145dcbSDimitry Andric llvm::ConstantExpr::getBitCast(FuncNameVar, Builder.getInt8PtrTy()),
936e7145dcbSDimitry Andric Builder.getInt64(FunctionHash),
937e7145dcbSDimitry Andric Builder.CreatePtrToInt(ValuePtr, Builder.getInt64Ty()),
938e7145dcbSDimitry Andric Builder.getInt32(ValueKind),
939e7145dcbSDimitry Andric Builder.getInt32(NumValueSites[ValueKind]++)
940e7145dcbSDimitry Andric };
941e7145dcbSDimitry Andric Builder.CreateCall(
942e7145dcbSDimitry Andric CGM.getIntrinsic(llvm::Intrinsic::instrprof_value_profile), Args);
943e7145dcbSDimitry Andric Builder.restoreIP(BuilderInsertPoint);
944e7145dcbSDimitry Andric return;
945e7145dcbSDimitry Andric }
946e7145dcbSDimitry Andric
947e7145dcbSDimitry Andric llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
948e7145dcbSDimitry Andric if (PGOReader && haveRegionCounts()) {
949e7145dcbSDimitry Andric // We record the top most called three functions at each call site.
950e7145dcbSDimitry Andric // Profile metadata contains "VP" string identifying this metadata
951e7145dcbSDimitry Andric // as value profiling data, then a uint32_t value for the value profiling
952e7145dcbSDimitry Andric // kind, a uint64_t value for the total number of times the call is
953e7145dcbSDimitry Andric // executed, followed by the function hash and execution count (uint64_t)
954e7145dcbSDimitry Andric // pairs for each function.
955e7145dcbSDimitry Andric if (NumValueSites[ValueKind] >= ProfRecord->getNumValueSites(ValueKind))
956e7145dcbSDimitry Andric return;
957e7145dcbSDimitry Andric
958e7145dcbSDimitry Andric llvm::annotateValueSite(CGM.getModule(), *ValueSite, *ProfRecord,
959e7145dcbSDimitry Andric (llvm::InstrProfValueKind)ValueKind,
960e7145dcbSDimitry Andric NumValueSites[ValueKind]);
961e7145dcbSDimitry Andric
962e7145dcbSDimitry Andric NumValueSites[ValueKind]++;
963e7145dcbSDimitry Andric }
964e7145dcbSDimitry Andric }
965e7145dcbSDimitry Andric
loadRegionCounts(llvm::IndexedInstrProfReader * PGOReader,bool IsInMainFile)96659d1ed5bSDimitry Andric void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
96759d1ed5bSDimitry Andric bool IsInMainFile) {
96859d1ed5bSDimitry Andric CGM.getPGOStats().addVisited(IsInMainFile);
96939d628a0SDimitry Andric RegionCounts.clear();
970e7145dcbSDimitry Andric llvm::Expected<llvm::InstrProfRecord> RecordExpected =
971e7145dcbSDimitry Andric PGOReader->getInstrProfRecord(FuncName, FunctionHash);
972e7145dcbSDimitry Andric if (auto E = RecordExpected.takeError()) {
973e7145dcbSDimitry Andric auto IPE = llvm::InstrProfError::take(std::move(E));
974e7145dcbSDimitry Andric if (IPE == llvm::instrprof_error::unknown_function)
97559d1ed5bSDimitry Andric CGM.getPGOStats().addMissing(IsInMainFile);
976e7145dcbSDimitry Andric else if (IPE == llvm::instrprof_error::hash_mismatch)
97759d1ed5bSDimitry Andric CGM.getPGOStats().addMismatched(IsInMainFile);
978e7145dcbSDimitry Andric else if (IPE == llvm::instrprof_error::malformed)
97939d628a0SDimitry Andric // TODO: Consider a more specific warning for this case.
98039d628a0SDimitry Andric CGM.getPGOStats().addMismatched(IsInMainFile);
981e7145dcbSDimitry Andric return;
98259d1ed5bSDimitry Andric }
983e7145dcbSDimitry Andric ProfRecord =
984e7145dcbSDimitry Andric llvm::make_unique<llvm::InstrProfRecord>(std::move(RecordExpected.get()));
985e7145dcbSDimitry Andric RegionCounts = ProfRecord->Counts;
98659d1ed5bSDimitry Andric }
98759d1ed5bSDimitry Andric
9884ba319b5SDimitry Andric /// Calculate what to divide by to scale weights.
98959d1ed5bSDimitry Andric ///
99059d1ed5bSDimitry Andric /// Given the maximum weight, calculate a divisor that will scale all the
99159d1ed5bSDimitry Andric /// weights to strictly less than UINT32_MAX.
calculateWeightScale(uint64_t MaxWeight)99259d1ed5bSDimitry Andric static uint64_t calculateWeightScale(uint64_t MaxWeight) {
99359d1ed5bSDimitry Andric return MaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1;
99459d1ed5bSDimitry Andric }
99559d1ed5bSDimitry Andric
9964ba319b5SDimitry Andric /// Scale an individual branch weight (and add 1).
99759d1ed5bSDimitry Andric ///
99859d1ed5bSDimitry Andric /// Scale a 64-bit weight down to 32-bits using \c Scale.
99959d1ed5bSDimitry Andric ///
100059d1ed5bSDimitry Andric /// According to Laplace's Rule of Succession, it is better to compute the
100159d1ed5bSDimitry Andric /// weight based on the count plus 1, so universally add 1 to the value.
100259d1ed5bSDimitry Andric ///
100359d1ed5bSDimitry Andric /// \pre \c Scale was calculated by \a calculateWeightScale() with a weight no
100459d1ed5bSDimitry Andric /// greater than \c Weight.
scaleBranchWeight(uint64_t Weight,uint64_t Scale)100559d1ed5bSDimitry Andric static uint32_t scaleBranchWeight(uint64_t Weight, uint64_t Scale) {
100659d1ed5bSDimitry Andric assert(Scale && "scale by 0?");
100759d1ed5bSDimitry Andric uint64_t Scaled = Weight / Scale + 1;
100859d1ed5bSDimitry Andric assert(Scaled <= UINT32_MAX && "overflow 32-bits");
100959d1ed5bSDimitry Andric return Scaled;
101059d1ed5bSDimitry Andric }
101159d1ed5bSDimitry Andric
createProfileWeights(uint64_t TrueCount,uint64_t FalseCount)101233956c43SDimitry Andric llvm::MDNode *CodeGenFunction::createProfileWeights(uint64_t TrueCount,
101359d1ed5bSDimitry Andric uint64_t FalseCount) {
101459d1ed5bSDimitry Andric // Check for empty weights.
101559d1ed5bSDimitry Andric if (!TrueCount && !FalseCount)
101659d1ed5bSDimitry Andric return nullptr;
101759d1ed5bSDimitry Andric
101859d1ed5bSDimitry Andric // Calculate how to scale down to 32-bits.
101959d1ed5bSDimitry Andric uint64_t Scale = calculateWeightScale(std::max(TrueCount, FalseCount));
102059d1ed5bSDimitry Andric
102159d1ed5bSDimitry Andric llvm::MDBuilder MDHelper(CGM.getLLVMContext());
102259d1ed5bSDimitry Andric return MDHelper.createBranchWeights(scaleBranchWeight(TrueCount, Scale),
102359d1ed5bSDimitry Andric scaleBranchWeight(FalseCount, Scale));
102459d1ed5bSDimitry Andric }
102559d1ed5bSDimitry Andric
102633956c43SDimitry Andric llvm::MDNode *
createProfileWeights(ArrayRef<uint64_t> Weights)102733956c43SDimitry Andric CodeGenFunction::createProfileWeights(ArrayRef<uint64_t> Weights) {
102859d1ed5bSDimitry Andric // We need at least two elements to create meaningful weights.
102959d1ed5bSDimitry Andric if (Weights.size() < 2)
103059d1ed5bSDimitry Andric return nullptr;
103159d1ed5bSDimitry Andric
103259d1ed5bSDimitry Andric // Check for empty weights.
103359d1ed5bSDimitry Andric uint64_t MaxWeight = *std::max_element(Weights.begin(), Weights.end());
103459d1ed5bSDimitry Andric if (MaxWeight == 0)
103559d1ed5bSDimitry Andric return nullptr;
103659d1ed5bSDimitry Andric
103759d1ed5bSDimitry Andric // Calculate how to scale down to 32-bits.
103859d1ed5bSDimitry Andric uint64_t Scale = calculateWeightScale(MaxWeight);
103959d1ed5bSDimitry Andric
104059d1ed5bSDimitry Andric SmallVector<uint32_t, 16> ScaledWeights;
104159d1ed5bSDimitry Andric ScaledWeights.reserve(Weights.size());
104259d1ed5bSDimitry Andric for (uint64_t W : Weights)
104359d1ed5bSDimitry Andric ScaledWeights.push_back(scaleBranchWeight(W, Scale));
104459d1ed5bSDimitry Andric
104559d1ed5bSDimitry Andric llvm::MDBuilder MDHelper(CGM.getLLVMContext());
104659d1ed5bSDimitry Andric return MDHelper.createBranchWeights(ScaledWeights);
104759d1ed5bSDimitry Andric }
104859d1ed5bSDimitry Andric
createProfileWeightsForLoop(const Stmt * Cond,uint64_t LoopCount)104933956c43SDimitry Andric llvm::MDNode *CodeGenFunction::createProfileWeightsForLoop(const Stmt *Cond,
105033956c43SDimitry Andric uint64_t LoopCount) {
105133956c43SDimitry Andric if (!PGO.haveRegionCounts())
105259d1ed5bSDimitry Andric return nullptr;
105333956c43SDimitry Andric Optional<uint64_t> CondCount = PGO.getStmtCount(Cond);
105433956c43SDimitry Andric assert(CondCount.hasValue() && "missing expected loop condition count");
105533956c43SDimitry Andric if (*CondCount == 0)
105659d1ed5bSDimitry Andric return nullptr;
105733956c43SDimitry Andric return createProfileWeights(LoopCount,
105833956c43SDimitry Andric std::max(*CondCount, LoopCount) - LoopCount);
105959d1ed5bSDimitry Andric }
1060