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 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 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 { 6159d1ed5bSDimitry Andric /// \brief 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: 8259d1ed5bSDimitry Andric /// \brief 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 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(); 1369a199699SDimitry 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. 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 1619a199699SDimitry 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. 16759d1ed5bSDimitry Andric bool TraverseBlockExpr(BlockExpr *BE) { return true; } 16859d1ed5bSDimitry Andric bool TraverseLambdaBody(LambdaExpr *LE) { return true; } 16959d1ed5bSDimitry Andric bool TraverseCapturedStmt(CapturedStmt *CS) { return true; } 17059d1ed5bSDimitry Andric 17159d1ed5bSDimitry Andric bool VisitDecl(const Decl *D) { 17259d1ed5bSDimitry Andric switch (D->getKind()) { 17359d1ed5bSDimitry Andric default: 17459d1ed5bSDimitry Andric break; 17559d1ed5bSDimitry Andric case Decl::Function: 17659d1ed5bSDimitry Andric case Decl::CXXMethod: 17759d1ed5bSDimitry Andric case Decl::CXXConstructor: 17859d1ed5bSDimitry Andric case Decl::CXXDestructor: 17959d1ed5bSDimitry Andric case Decl::CXXConversion: 18059d1ed5bSDimitry Andric case Decl::ObjCMethod: 18159d1ed5bSDimitry Andric case Decl::Block: 18259d1ed5bSDimitry Andric case Decl::Captured: 18359d1ed5bSDimitry Andric CounterMap[D->getBody()] = NextCounter++; 18459d1ed5bSDimitry Andric break; 18559d1ed5bSDimitry Andric } 18659d1ed5bSDimitry Andric return true; 18759d1ed5bSDimitry Andric } 18859d1ed5bSDimitry Andric 1899a199699SDimitry Andric /// If \p S gets a fresh counter, update the counter mappings. Return the 1909a199699SDimitry Andric /// V1 hash of \p S. 1919a199699SDimitry Andric PGOHash::HashType updateCounterMappings(Stmt *S) { 1929a199699SDimitry Andric auto Type = getHashType(PGO_HASH_V1, S); 1939a199699SDimitry Andric if (Type != PGOHash::None) 19459d1ed5bSDimitry Andric CounterMap[S] = NextCounter++; 1959a199699SDimitry Andric return Type; 1969a199699SDimitry Andric } 1979a199699SDimitry Andric 1989a199699SDimitry Andric /// Include \p S in the function hash. 1999a199699SDimitry Andric bool VisitStmt(Stmt *S) { 2009a199699SDimitry Andric auto Type = updateCounterMappings(S); 2019a199699SDimitry Andric if (Hash.getHashVersion() != PGO_HASH_V1) 2029a199699SDimitry Andric Type = getHashType(Hash.getHashVersion(), S); 2039a199699SDimitry Andric if (Type != PGOHash::None) 20459d1ed5bSDimitry Andric Hash.combine(Type); 20559d1ed5bSDimitry Andric return true; 20659d1ed5bSDimitry Andric } 2079a199699SDimitry Andric 2089a199699SDimitry Andric bool TraverseIfStmt(IfStmt *If) { 2099a199699SDimitry Andric // If we used the V1 hash, use the default traversal. 2109a199699SDimitry Andric if (Hash.getHashVersion() == PGO_HASH_V1) 2119a199699SDimitry Andric return Base::TraverseIfStmt(If); 2129a199699SDimitry Andric 2139a199699SDimitry Andric // Otherwise, keep track of which branch we're in while traversing. 2149a199699SDimitry Andric VisitStmt(If); 2159a199699SDimitry Andric for (Stmt *CS : If->children()) { 2169a199699SDimitry Andric if (!CS) 2179a199699SDimitry Andric continue; 2189a199699SDimitry Andric if (CS == If->getThen()) 2199a199699SDimitry Andric Hash.combine(PGOHash::IfThenBranch); 2209a199699SDimitry Andric else if (CS == If->getElse()) 2219a199699SDimitry Andric Hash.combine(PGOHash::IfElseBranch); 2229a199699SDimitry Andric TraverseStmt(CS); 2239a199699SDimitry Andric } 2249a199699SDimitry Andric Hash.combine(PGOHash::EndOfScope); 2259a199699SDimitry Andric return true; 2269a199699SDimitry Andric } 2279a199699SDimitry Andric 2289a199699SDimitry Andric // If the statement type \p N is nestable, and its nesting impacts profile 2299a199699SDimitry Andric // stability, define a custom traversal which tracks the end of the statement 2309a199699SDimitry Andric // in the hash (provided we're not using the V1 hash). 2319a199699SDimitry Andric #define DEFINE_NESTABLE_TRAVERSAL(N) \ 2329a199699SDimitry Andric bool Traverse##N(N *S) { \ 2339a199699SDimitry Andric Base::Traverse##N(S); \ 2349a199699SDimitry Andric if (Hash.getHashVersion() != PGO_HASH_V1) \ 2359a199699SDimitry Andric Hash.combine(PGOHash::EndOfScope); \ 2369a199699SDimitry Andric return true; \ 2379a199699SDimitry Andric } 2389a199699SDimitry Andric 2399a199699SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(WhileStmt) 2409a199699SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(DoStmt) 2419a199699SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(ForStmt) 2429a199699SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(CXXForRangeStmt) 2439a199699SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(ObjCForCollectionStmt) 2449a199699SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(CXXTryStmt) 2459a199699SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(CXXCatchStmt) 2469a199699SDimitry Andric 2479a199699SDimitry Andric /// Get version \p HashVersion of the PGO hash for \p S. 2489a199699SDimitry Andric PGOHash::HashType getHashType(PGOHashVersion HashVersion, const Stmt *S) { 24959d1ed5bSDimitry Andric switch (S->getStmtClass()) { 25059d1ed5bSDimitry Andric default: 25159d1ed5bSDimitry Andric break; 25259d1ed5bSDimitry Andric case Stmt::LabelStmtClass: 25359d1ed5bSDimitry Andric return PGOHash::LabelStmt; 25459d1ed5bSDimitry Andric case Stmt::WhileStmtClass: 25559d1ed5bSDimitry Andric return PGOHash::WhileStmt; 25659d1ed5bSDimitry Andric case Stmt::DoStmtClass: 25759d1ed5bSDimitry Andric return PGOHash::DoStmt; 25859d1ed5bSDimitry Andric case Stmt::ForStmtClass: 25959d1ed5bSDimitry Andric return PGOHash::ForStmt; 26059d1ed5bSDimitry Andric case Stmt::CXXForRangeStmtClass: 26159d1ed5bSDimitry Andric return PGOHash::CXXForRangeStmt; 26259d1ed5bSDimitry Andric case Stmt::ObjCForCollectionStmtClass: 26359d1ed5bSDimitry Andric return PGOHash::ObjCForCollectionStmt; 26459d1ed5bSDimitry Andric case Stmt::SwitchStmtClass: 26559d1ed5bSDimitry Andric return PGOHash::SwitchStmt; 26659d1ed5bSDimitry Andric case Stmt::CaseStmtClass: 26759d1ed5bSDimitry Andric return PGOHash::CaseStmt; 26859d1ed5bSDimitry Andric case Stmt::DefaultStmtClass: 26959d1ed5bSDimitry Andric return PGOHash::DefaultStmt; 27059d1ed5bSDimitry Andric case Stmt::IfStmtClass: 27159d1ed5bSDimitry Andric return PGOHash::IfStmt; 27259d1ed5bSDimitry Andric case Stmt::CXXTryStmtClass: 27359d1ed5bSDimitry Andric return PGOHash::CXXTryStmt; 27459d1ed5bSDimitry Andric case Stmt::CXXCatchStmtClass: 27559d1ed5bSDimitry Andric return PGOHash::CXXCatchStmt; 27659d1ed5bSDimitry Andric case Stmt::ConditionalOperatorClass: 27759d1ed5bSDimitry Andric return PGOHash::ConditionalOperator; 27859d1ed5bSDimitry Andric case Stmt::BinaryConditionalOperatorClass: 27959d1ed5bSDimitry Andric return PGOHash::BinaryConditionalOperator; 28059d1ed5bSDimitry Andric case Stmt::BinaryOperatorClass: { 28159d1ed5bSDimitry Andric const BinaryOperator *BO = cast<BinaryOperator>(S); 28259d1ed5bSDimitry Andric if (BO->getOpcode() == BO_LAnd) 28359d1ed5bSDimitry Andric return PGOHash::BinaryOperatorLAnd; 28459d1ed5bSDimitry Andric if (BO->getOpcode() == BO_LOr) 28559d1ed5bSDimitry Andric return PGOHash::BinaryOperatorLOr; 2869a199699SDimitry Andric if (HashVersion == PGO_HASH_V2) { 2879a199699SDimitry Andric switch (BO->getOpcode()) { 2889a199699SDimitry Andric default: 2899a199699SDimitry Andric break; 2909a199699SDimitry Andric case BO_LT: 2919a199699SDimitry Andric return PGOHash::BinaryOperatorLT; 2929a199699SDimitry Andric case BO_GT: 2939a199699SDimitry Andric return PGOHash::BinaryOperatorGT; 2949a199699SDimitry Andric case BO_LE: 2959a199699SDimitry Andric return PGOHash::BinaryOperatorLE; 2969a199699SDimitry Andric case BO_GE: 2979a199699SDimitry Andric return PGOHash::BinaryOperatorGE; 2989a199699SDimitry Andric case BO_EQ: 2999a199699SDimitry Andric return PGOHash::BinaryOperatorEQ; 3009a199699SDimitry Andric case BO_NE: 3019a199699SDimitry Andric return PGOHash::BinaryOperatorNE; 3029a199699SDimitry Andric } 3039a199699SDimitry Andric } 30459d1ed5bSDimitry Andric break; 30559d1ed5bSDimitry Andric } 30659d1ed5bSDimitry Andric } 3079a199699SDimitry Andric 3089a199699SDimitry Andric if (HashVersion == PGO_HASH_V2) { 3099a199699SDimitry Andric switch (S->getStmtClass()) { 3109a199699SDimitry Andric default: 3119a199699SDimitry Andric break; 3129a199699SDimitry Andric case Stmt::GotoStmtClass: 3139a199699SDimitry Andric return PGOHash::GotoStmt; 3149a199699SDimitry Andric case Stmt::IndirectGotoStmtClass: 3159a199699SDimitry Andric return PGOHash::IndirectGotoStmt; 3169a199699SDimitry Andric case Stmt::BreakStmtClass: 3179a199699SDimitry Andric return PGOHash::BreakStmt; 3189a199699SDimitry Andric case Stmt::ContinueStmtClass: 3199a199699SDimitry Andric return PGOHash::ContinueStmt; 3209a199699SDimitry Andric case Stmt::ReturnStmtClass: 3219a199699SDimitry Andric return PGOHash::ReturnStmt; 3229a199699SDimitry Andric case Stmt::CXXThrowExprClass: 3239a199699SDimitry Andric return PGOHash::ThrowExpr; 3249a199699SDimitry Andric case Stmt::UnaryOperatorClass: { 3259a199699SDimitry Andric const UnaryOperator *UO = cast<UnaryOperator>(S); 3269a199699SDimitry Andric if (UO->getOpcode() == UO_LNot) 3279a199699SDimitry Andric return PGOHash::UnaryOperatorLNot; 3289a199699SDimitry Andric break; 3299a199699SDimitry Andric } 3309a199699SDimitry Andric } 3319a199699SDimitry Andric } 3329a199699SDimitry Andric 33359d1ed5bSDimitry Andric return PGOHash::None; 33459d1ed5bSDimitry Andric } 33559d1ed5bSDimitry Andric }; 33659d1ed5bSDimitry Andric 33759d1ed5bSDimitry Andric /// A StmtVisitor that propagates the raw counts through the AST and 33859d1ed5bSDimitry Andric /// records the count at statements where the value may change. 33959d1ed5bSDimitry Andric struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> { 34059d1ed5bSDimitry Andric /// PGO state. 34159d1ed5bSDimitry Andric CodeGenPGO &PGO; 34259d1ed5bSDimitry Andric 34359d1ed5bSDimitry Andric /// A flag that is set when the current count should be recorded on the 34459d1ed5bSDimitry Andric /// next statement, such as at the exit of a loop. 34559d1ed5bSDimitry Andric bool RecordNextStmtCount; 34659d1ed5bSDimitry Andric 34733956c43SDimitry Andric /// The count at the current location in the traversal. 34833956c43SDimitry Andric uint64_t CurrentCount; 34933956c43SDimitry Andric 35059d1ed5bSDimitry Andric /// The map of statements to count values. 35159d1ed5bSDimitry Andric llvm::DenseMap<const Stmt *, uint64_t> &CountMap; 35259d1ed5bSDimitry Andric 35359d1ed5bSDimitry Andric /// BreakContinueStack - Keep counts of breaks and continues inside loops. 35459d1ed5bSDimitry Andric struct BreakContinue { 35559d1ed5bSDimitry Andric uint64_t BreakCount; 35659d1ed5bSDimitry Andric uint64_t ContinueCount; 35759d1ed5bSDimitry Andric BreakContinue() : BreakCount(0), ContinueCount(0) {} 35859d1ed5bSDimitry Andric }; 35959d1ed5bSDimitry Andric SmallVector<BreakContinue, 8> BreakContinueStack; 36059d1ed5bSDimitry Andric 36159d1ed5bSDimitry Andric ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &CountMap, 36259d1ed5bSDimitry Andric CodeGenPGO &PGO) 36359d1ed5bSDimitry Andric : PGO(PGO), RecordNextStmtCount(false), CountMap(CountMap) {} 36459d1ed5bSDimitry Andric 36559d1ed5bSDimitry Andric void RecordStmtCount(const Stmt *S) { 36659d1ed5bSDimitry Andric if (RecordNextStmtCount) { 36733956c43SDimitry Andric CountMap[S] = CurrentCount; 36859d1ed5bSDimitry Andric RecordNextStmtCount = false; 36959d1ed5bSDimitry Andric } 37059d1ed5bSDimitry Andric } 37159d1ed5bSDimitry Andric 37233956c43SDimitry Andric /// Set and return the current count. 37333956c43SDimitry Andric uint64_t setCount(uint64_t Count) { 37433956c43SDimitry Andric CurrentCount = Count; 37533956c43SDimitry Andric return Count; 37633956c43SDimitry Andric } 37733956c43SDimitry Andric 37859d1ed5bSDimitry Andric void VisitStmt(const Stmt *S) { 37959d1ed5bSDimitry Andric RecordStmtCount(S); 3803dac3a9bSDimitry Andric for (const Stmt *Child : S->children()) 3813dac3a9bSDimitry Andric if (Child) 3823dac3a9bSDimitry Andric this->Visit(Child); 38359d1ed5bSDimitry Andric } 38459d1ed5bSDimitry Andric 38559d1ed5bSDimitry Andric void VisitFunctionDecl(const FunctionDecl *D) { 38659d1ed5bSDimitry Andric // Counter tracks entry to the function body. 38733956c43SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); 38833956c43SDimitry Andric CountMap[D->getBody()] = BodyCount; 38959d1ed5bSDimitry Andric Visit(D->getBody()); 39059d1ed5bSDimitry Andric } 39159d1ed5bSDimitry Andric 39259d1ed5bSDimitry Andric // Skip lambda expressions. We visit these as FunctionDecls when we're 39359d1ed5bSDimitry Andric // generating them and aren't interested in the body when generating a 39459d1ed5bSDimitry Andric // parent context. 39559d1ed5bSDimitry Andric void VisitLambdaExpr(const LambdaExpr *LE) {} 39659d1ed5bSDimitry Andric 39759d1ed5bSDimitry Andric void VisitCapturedDecl(const CapturedDecl *D) { 39859d1ed5bSDimitry Andric // Counter tracks entry to the capture body. 39933956c43SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); 40033956c43SDimitry Andric CountMap[D->getBody()] = BodyCount; 40159d1ed5bSDimitry Andric Visit(D->getBody()); 40259d1ed5bSDimitry Andric } 40359d1ed5bSDimitry Andric 40459d1ed5bSDimitry Andric void VisitObjCMethodDecl(const ObjCMethodDecl *D) { 40559d1ed5bSDimitry Andric // Counter tracks entry to the method body. 40633956c43SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); 40733956c43SDimitry Andric CountMap[D->getBody()] = BodyCount; 40859d1ed5bSDimitry Andric Visit(D->getBody()); 40959d1ed5bSDimitry Andric } 41059d1ed5bSDimitry Andric 41159d1ed5bSDimitry Andric void VisitBlockDecl(const BlockDecl *D) { 41259d1ed5bSDimitry Andric // Counter tracks entry to the block body. 41333956c43SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); 41433956c43SDimitry Andric CountMap[D->getBody()] = BodyCount; 41559d1ed5bSDimitry Andric Visit(D->getBody()); 41659d1ed5bSDimitry Andric } 41759d1ed5bSDimitry Andric 41859d1ed5bSDimitry Andric void VisitReturnStmt(const ReturnStmt *S) { 41959d1ed5bSDimitry Andric RecordStmtCount(S); 42059d1ed5bSDimitry Andric if (S->getRetValue()) 42159d1ed5bSDimitry Andric Visit(S->getRetValue()); 42233956c43SDimitry Andric CurrentCount = 0; 42333956c43SDimitry Andric RecordNextStmtCount = true; 42433956c43SDimitry Andric } 42533956c43SDimitry Andric 42633956c43SDimitry Andric void VisitCXXThrowExpr(const CXXThrowExpr *E) { 42733956c43SDimitry Andric RecordStmtCount(E); 42833956c43SDimitry Andric if (E->getSubExpr()) 42933956c43SDimitry Andric Visit(E->getSubExpr()); 43033956c43SDimitry Andric CurrentCount = 0; 43159d1ed5bSDimitry Andric RecordNextStmtCount = true; 43259d1ed5bSDimitry Andric } 43359d1ed5bSDimitry Andric 43459d1ed5bSDimitry Andric void VisitGotoStmt(const GotoStmt *S) { 43559d1ed5bSDimitry Andric RecordStmtCount(S); 43633956c43SDimitry Andric CurrentCount = 0; 43759d1ed5bSDimitry Andric RecordNextStmtCount = true; 43859d1ed5bSDimitry Andric } 43959d1ed5bSDimitry Andric 44059d1ed5bSDimitry Andric void VisitLabelStmt(const LabelStmt *S) { 44159d1ed5bSDimitry Andric RecordNextStmtCount = false; 44259d1ed5bSDimitry Andric // Counter tracks the block following the label. 44333956c43SDimitry Andric uint64_t BlockCount = setCount(PGO.getRegionCount(S)); 44433956c43SDimitry Andric CountMap[S] = BlockCount; 44559d1ed5bSDimitry Andric Visit(S->getSubStmt()); 44659d1ed5bSDimitry Andric } 44759d1ed5bSDimitry Andric 44859d1ed5bSDimitry Andric void VisitBreakStmt(const BreakStmt *S) { 44959d1ed5bSDimitry Andric RecordStmtCount(S); 45059d1ed5bSDimitry Andric assert(!BreakContinueStack.empty() && "break not in a loop or switch!"); 45133956c43SDimitry Andric BreakContinueStack.back().BreakCount += CurrentCount; 45233956c43SDimitry Andric CurrentCount = 0; 45359d1ed5bSDimitry Andric RecordNextStmtCount = true; 45459d1ed5bSDimitry Andric } 45559d1ed5bSDimitry Andric 45659d1ed5bSDimitry Andric void VisitContinueStmt(const ContinueStmt *S) { 45759d1ed5bSDimitry Andric RecordStmtCount(S); 45859d1ed5bSDimitry Andric assert(!BreakContinueStack.empty() && "continue stmt not in a loop!"); 45933956c43SDimitry Andric BreakContinueStack.back().ContinueCount += CurrentCount; 46033956c43SDimitry Andric CurrentCount = 0; 46159d1ed5bSDimitry Andric RecordNextStmtCount = true; 46259d1ed5bSDimitry Andric } 46359d1ed5bSDimitry Andric 46459d1ed5bSDimitry Andric void VisitWhileStmt(const WhileStmt *S) { 46559d1ed5bSDimitry Andric RecordStmtCount(S); 46633956c43SDimitry Andric uint64_t ParentCount = CurrentCount; 46733956c43SDimitry Andric 46859d1ed5bSDimitry Andric BreakContinueStack.push_back(BreakContinue()); 46959d1ed5bSDimitry Andric // Visit the body region first so the break/continue adjustments can be 47059d1ed5bSDimitry Andric // included when visiting the condition. 47133956c43SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(S)); 47233956c43SDimitry Andric CountMap[S->getBody()] = CurrentCount; 47359d1ed5bSDimitry Andric Visit(S->getBody()); 47433956c43SDimitry Andric uint64_t BackedgeCount = CurrentCount; 47559d1ed5bSDimitry Andric 47659d1ed5bSDimitry Andric // ...then go back and propagate counts through the condition. The count 47759d1ed5bSDimitry Andric // at the start of the condition is the sum of the incoming edges, 47859d1ed5bSDimitry Andric // the backedge from the end of the loop body, and the edges from 47959d1ed5bSDimitry Andric // continue statements. 48059d1ed5bSDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val(); 48133956c43SDimitry Andric uint64_t CondCount = 48233956c43SDimitry Andric setCount(ParentCount + BackedgeCount + BC.ContinueCount); 48333956c43SDimitry Andric CountMap[S->getCond()] = CondCount; 48459d1ed5bSDimitry Andric Visit(S->getCond()); 48533956c43SDimitry Andric setCount(BC.BreakCount + CondCount - BodyCount); 48659d1ed5bSDimitry Andric RecordNextStmtCount = true; 48759d1ed5bSDimitry Andric } 48859d1ed5bSDimitry Andric 48959d1ed5bSDimitry Andric void VisitDoStmt(const DoStmt *S) { 49059d1ed5bSDimitry Andric RecordStmtCount(S); 49133956c43SDimitry Andric uint64_t LoopCount = PGO.getRegionCount(S); 49233956c43SDimitry Andric 49359d1ed5bSDimitry Andric BreakContinueStack.push_back(BreakContinue()); 49433956c43SDimitry Andric // The count doesn't include the fallthrough from the parent scope. Add it. 49533956c43SDimitry Andric uint64_t BodyCount = setCount(LoopCount + CurrentCount); 49633956c43SDimitry Andric CountMap[S->getBody()] = BodyCount; 49759d1ed5bSDimitry Andric Visit(S->getBody()); 49833956c43SDimitry Andric uint64_t BackedgeCount = CurrentCount; 49959d1ed5bSDimitry Andric 50059d1ed5bSDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val(); 50159d1ed5bSDimitry Andric // The count at the start of the condition is equal to the count at the 50233956c43SDimitry Andric // end of the body, plus any continues. 50333956c43SDimitry Andric uint64_t CondCount = setCount(BackedgeCount + BC.ContinueCount); 50433956c43SDimitry Andric CountMap[S->getCond()] = CondCount; 50559d1ed5bSDimitry Andric Visit(S->getCond()); 50633956c43SDimitry Andric setCount(BC.BreakCount + CondCount - LoopCount); 50759d1ed5bSDimitry Andric RecordNextStmtCount = true; 50859d1ed5bSDimitry Andric } 50959d1ed5bSDimitry Andric 51059d1ed5bSDimitry Andric void VisitForStmt(const ForStmt *S) { 51159d1ed5bSDimitry Andric RecordStmtCount(S); 51259d1ed5bSDimitry Andric if (S->getInit()) 51359d1ed5bSDimitry Andric Visit(S->getInit()); 51433956c43SDimitry Andric 51533956c43SDimitry Andric uint64_t ParentCount = CurrentCount; 51633956c43SDimitry Andric 51759d1ed5bSDimitry Andric BreakContinueStack.push_back(BreakContinue()); 51859d1ed5bSDimitry Andric // Visit the body region first. (This is basically the same as a while 51959d1ed5bSDimitry Andric // loop; see further comments in VisitWhileStmt.) 52033956c43SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(S)); 52133956c43SDimitry Andric CountMap[S->getBody()] = BodyCount; 52259d1ed5bSDimitry Andric Visit(S->getBody()); 52333956c43SDimitry Andric uint64_t BackedgeCount = CurrentCount; 52433956c43SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val(); 52559d1ed5bSDimitry Andric 52659d1ed5bSDimitry Andric // The increment is essentially part of the body but it needs to include 52759d1ed5bSDimitry Andric // the count for all the continue statements. 52859d1ed5bSDimitry Andric if (S->getInc()) { 52933956c43SDimitry Andric uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount); 53033956c43SDimitry Andric CountMap[S->getInc()] = IncCount; 53159d1ed5bSDimitry Andric Visit(S->getInc()); 53259d1ed5bSDimitry Andric } 53359d1ed5bSDimitry Andric 53459d1ed5bSDimitry Andric // ...then go back and propagate counts through the condition. 53533956c43SDimitry Andric uint64_t CondCount = 53633956c43SDimitry Andric setCount(ParentCount + BackedgeCount + BC.ContinueCount); 53759d1ed5bSDimitry Andric if (S->getCond()) { 53833956c43SDimitry Andric CountMap[S->getCond()] = CondCount; 53959d1ed5bSDimitry Andric Visit(S->getCond()); 54059d1ed5bSDimitry Andric } 54133956c43SDimitry Andric setCount(BC.BreakCount + CondCount - BodyCount); 54259d1ed5bSDimitry Andric RecordNextStmtCount = true; 54359d1ed5bSDimitry Andric } 54459d1ed5bSDimitry Andric 54559d1ed5bSDimitry Andric void VisitCXXForRangeStmt(const CXXForRangeStmt *S) { 54659d1ed5bSDimitry Andric RecordStmtCount(S); 54733956c43SDimitry Andric Visit(S->getLoopVarStmt()); 54859d1ed5bSDimitry Andric Visit(S->getRangeStmt()); 549e7145dcbSDimitry Andric Visit(S->getBeginStmt()); 550e7145dcbSDimitry Andric Visit(S->getEndStmt()); 55133956c43SDimitry Andric 55233956c43SDimitry Andric uint64_t ParentCount = CurrentCount; 55359d1ed5bSDimitry Andric BreakContinueStack.push_back(BreakContinue()); 55459d1ed5bSDimitry Andric // Visit the body region first. (This is basically the same as a while 55559d1ed5bSDimitry Andric // loop; see further comments in VisitWhileStmt.) 55633956c43SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(S)); 55733956c43SDimitry Andric CountMap[S->getBody()] = BodyCount; 55859d1ed5bSDimitry Andric Visit(S->getBody()); 55933956c43SDimitry Andric uint64_t BackedgeCount = CurrentCount; 56033956c43SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val(); 56159d1ed5bSDimitry Andric 56259d1ed5bSDimitry Andric // The increment is essentially part of the body but it needs to include 56359d1ed5bSDimitry Andric // the count for all the continue statements. 56433956c43SDimitry Andric uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount); 56533956c43SDimitry Andric CountMap[S->getInc()] = IncCount; 56659d1ed5bSDimitry Andric Visit(S->getInc()); 56759d1ed5bSDimitry Andric 56859d1ed5bSDimitry Andric // ...then go back and propagate counts through the condition. 56933956c43SDimitry Andric uint64_t CondCount = 57033956c43SDimitry Andric setCount(ParentCount + BackedgeCount + BC.ContinueCount); 57133956c43SDimitry Andric CountMap[S->getCond()] = CondCount; 57259d1ed5bSDimitry Andric Visit(S->getCond()); 57333956c43SDimitry Andric setCount(BC.BreakCount + CondCount - BodyCount); 57459d1ed5bSDimitry Andric RecordNextStmtCount = true; 57559d1ed5bSDimitry Andric } 57659d1ed5bSDimitry Andric 57759d1ed5bSDimitry Andric void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) { 57859d1ed5bSDimitry Andric RecordStmtCount(S); 57959d1ed5bSDimitry Andric Visit(S->getElement()); 58033956c43SDimitry Andric uint64_t ParentCount = CurrentCount; 58159d1ed5bSDimitry Andric BreakContinueStack.push_back(BreakContinue()); 58233956c43SDimitry Andric // Counter tracks the body of the loop. 58333956c43SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(S)); 58433956c43SDimitry Andric CountMap[S->getBody()] = BodyCount; 58559d1ed5bSDimitry Andric Visit(S->getBody()); 58633956c43SDimitry Andric uint64_t BackedgeCount = CurrentCount; 58759d1ed5bSDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val(); 58833956c43SDimitry Andric 58933956c43SDimitry Andric setCount(BC.BreakCount + ParentCount + BackedgeCount + BC.ContinueCount - 59033956c43SDimitry Andric BodyCount); 59159d1ed5bSDimitry Andric RecordNextStmtCount = true; 59259d1ed5bSDimitry Andric } 59359d1ed5bSDimitry Andric 59459d1ed5bSDimitry Andric void VisitSwitchStmt(const SwitchStmt *S) { 59559d1ed5bSDimitry Andric RecordStmtCount(S); 59644290647SDimitry Andric if (S->getInit()) 59744290647SDimitry Andric Visit(S->getInit()); 59859d1ed5bSDimitry Andric Visit(S->getCond()); 59933956c43SDimitry Andric CurrentCount = 0; 60059d1ed5bSDimitry Andric BreakContinueStack.push_back(BreakContinue()); 60159d1ed5bSDimitry Andric Visit(S->getBody()); 60259d1ed5bSDimitry Andric // If the switch is inside a loop, add the continue counts. 60359d1ed5bSDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val(); 60459d1ed5bSDimitry Andric if (!BreakContinueStack.empty()) 60559d1ed5bSDimitry Andric BreakContinueStack.back().ContinueCount += BC.ContinueCount; 60659d1ed5bSDimitry Andric // Counter tracks the exit block of the switch. 60733956c43SDimitry Andric setCount(PGO.getRegionCount(S)); 60859d1ed5bSDimitry Andric RecordNextStmtCount = true; 60959d1ed5bSDimitry Andric } 61059d1ed5bSDimitry Andric 61133956c43SDimitry Andric void VisitSwitchCase(const SwitchCase *S) { 61259d1ed5bSDimitry Andric RecordNextStmtCount = false; 61359d1ed5bSDimitry Andric // Counter for this particular case. This counts only jumps from the 61459d1ed5bSDimitry Andric // switch header and does not include fallthrough from the case before 61559d1ed5bSDimitry Andric // this one. 61633956c43SDimitry Andric uint64_t CaseCount = PGO.getRegionCount(S); 61733956c43SDimitry Andric setCount(CurrentCount + CaseCount); 61833956c43SDimitry Andric // We need the count without fallthrough in the mapping, so it's more useful 61933956c43SDimitry Andric // for branch probabilities. 62033956c43SDimitry Andric CountMap[S] = CaseCount; 62159d1ed5bSDimitry Andric RecordNextStmtCount = true; 62259d1ed5bSDimitry Andric Visit(S->getSubStmt()); 62359d1ed5bSDimitry Andric } 62459d1ed5bSDimitry Andric 62559d1ed5bSDimitry Andric void VisitIfStmt(const IfStmt *S) { 62659d1ed5bSDimitry Andric RecordStmtCount(S); 62733956c43SDimitry Andric uint64_t ParentCount = CurrentCount; 62844290647SDimitry Andric if (S->getInit()) 62944290647SDimitry Andric Visit(S->getInit()); 63059d1ed5bSDimitry Andric Visit(S->getCond()); 63159d1ed5bSDimitry Andric 63233956c43SDimitry Andric // Counter tracks the "then" part of an if statement. The count for 63333956c43SDimitry Andric // the "else" part, if it exists, will be calculated from this counter. 63433956c43SDimitry Andric uint64_t ThenCount = setCount(PGO.getRegionCount(S)); 63533956c43SDimitry Andric CountMap[S->getThen()] = ThenCount; 63659d1ed5bSDimitry Andric Visit(S->getThen()); 63733956c43SDimitry Andric uint64_t OutCount = CurrentCount; 63859d1ed5bSDimitry Andric 63933956c43SDimitry Andric uint64_t ElseCount = ParentCount - ThenCount; 64059d1ed5bSDimitry Andric if (S->getElse()) { 64133956c43SDimitry Andric setCount(ElseCount); 64233956c43SDimitry Andric CountMap[S->getElse()] = ElseCount; 64359d1ed5bSDimitry Andric Visit(S->getElse()); 64433956c43SDimitry Andric OutCount += CurrentCount; 64533956c43SDimitry Andric } else 64633956c43SDimitry Andric OutCount += ElseCount; 64733956c43SDimitry Andric setCount(OutCount); 64859d1ed5bSDimitry Andric RecordNextStmtCount = true; 64959d1ed5bSDimitry Andric } 65059d1ed5bSDimitry Andric 65159d1ed5bSDimitry Andric void VisitCXXTryStmt(const CXXTryStmt *S) { 65259d1ed5bSDimitry Andric RecordStmtCount(S); 65359d1ed5bSDimitry Andric Visit(S->getTryBlock()); 65459d1ed5bSDimitry Andric for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I) 65559d1ed5bSDimitry Andric Visit(S->getHandler(I)); 65659d1ed5bSDimitry Andric // Counter tracks the continuation block of the try statement. 65733956c43SDimitry Andric setCount(PGO.getRegionCount(S)); 65859d1ed5bSDimitry Andric RecordNextStmtCount = true; 65959d1ed5bSDimitry Andric } 66059d1ed5bSDimitry Andric 66159d1ed5bSDimitry Andric void VisitCXXCatchStmt(const CXXCatchStmt *S) { 66259d1ed5bSDimitry Andric RecordNextStmtCount = false; 66359d1ed5bSDimitry Andric // Counter tracks the catch statement's handler block. 66433956c43SDimitry Andric uint64_t CatchCount = setCount(PGO.getRegionCount(S)); 66533956c43SDimitry Andric CountMap[S] = CatchCount; 66659d1ed5bSDimitry Andric Visit(S->getHandlerBlock()); 66759d1ed5bSDimitry Andric } 66859d1ed5bSDimitry Andric 66933956c43SDimitry Andric void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { 67059d1ed5bSDimitry Andric RecordStmtCount(E); 67133956c43SDimitry Andric uint64_t ParentCount = CurrentCount; 67259d1ed5bSDimitry Andric Visit(E->getCond()); 67359d1ed5bSDimitry Andric 67433956c43SDimitry Andric // Counter tracks the "true" part of a conditional operator. The 67533956c43SDimitry Andric // count in the "false" part will be calculated from this counter. 67633956c43SDimitry Andric uint64_t TrueCount = setCount(PGO.getRegionCount(E)); 67733956c43SDimitry Andric CountMap[E->getTrueExpr()] = TrueCount; 67859d1ed5bSDimitry Andric Visit(E->getTrueExpr()); 67933956c43SDimitry Andric uint64_t OutCount = CurrentCount; 68059d1ed5bSDimitry Andric 68133956c43SDimitry Andric uint64_t FalseCount = setCount(ParentCount - TrueCount); 68233956c43SDimitry Andric CountMap[E->getFalseExpr()] = FalseCount; 68359d1ed5bSDimitry Andric Visit(E->getFalseExpr()); 68433956c43SDimitry Andric OutCount += CurrentCount; 68559d1ed5bSDimitry Andric 68633956c43SDimitry Andric setCount(OutCount); 68759d1ed5bSDimitry Andric RecordNextStmtCount = true; 68859d1ed5bSDimitry Andric } 68959d1ed5bSDimitry Andric 69059d1ed5bSDimitry Andric void VisitBinLAnd(const BinaryOperator *E) { 69159d1ed5bSDimitry Andric RecordStmtCount(E); 69233956c43SDimitry Andric uint64_t ParentCount = CurrentCount; 69359d1ed5bSDimitry Andric Visit(E->getLHS()); 69433956c43SDimitry Andric // Counter tracks the right hand side of a logical and operator. 69533956c43SDimitry Andric uint64_t RHSCount = setCount(PGO.getRegionCount(E)); 69633956c43SDimitry Andric CountMap[E->getRHS()] = RHSCount; 69759d1ed5bSDimitry Andric Visit(E->getRHS()); 69833956c43SDimitry Andric setCount(ParentCount + RHSCount - CurrentCount); 69959d1ed5bSDimitry Andric RecordNextStmtCount = true; 70059d1ed5bSDimitry Andric } 70159d1ed5bSDimitry Andric 70259d1ed5bSDimitry Andric void VisitBinLOr(const BinaryOperator *E) { 70359d1ed5bSDimitry Andric RecordStmtCount(E); 70433956c43SDimitry Andric uint64_t ParentCount = CurrentCount; 70559d1ed5bSDimitry Andric Visit(E->getLHS()); 70633956c43SDimitry Andric // Counter tracks the right hand side of a logical or operator. 70733956c43SDimitry Andric uint64_t RHSCount = setCount(PGO.getRegionCount(E)); 70833956c43SDimitry Andric CountMap[E->getRHS()] = RHSCount; 70959d1ed5bSDimitry Andric Visit(E->getRHS()); 71033956c43SDimitry Andric setCount(ParentCount + RHSCount - CurrentCount); 71159d1ed5bSDimitry Andric RecordNextStmtCount = true; 71259d1ed5bSDimitry Andric } 71359d1ed5bSDimitry Andric }; 7140623d748SDimitry Andric } // end anonymous namespace 71559d1ed5bSDimitry Andric 71659d1ed5bSDimitry Andric void PGOHash::combine(HashType Type) { 71759d1ed5bSDimitry Andric // Check that we never combine 0 and only have six bits. 71859d1ed5bSDimitry Andric assert(Type && "Hash is invalid: unexpected type 0"); 71959d1ed5bSDimitry Andric assert(unsigned(Type) < TooBig && "Hash is invalid: too many types"); 72059d1ed5bSDimitry Andric 72159d1ed5bSDimitry Andric // Pass through MD5 if enough work has built up. 72259d1ed5bSDimitry Andric if (Count && Count % NumTypesPerWord == 0) { 72359d1ed5bSDimitry Andric using namespace llvm::support; 72459d1ed5bSDimitry Andric uint64_t Swapped = endian::byte_swap<uint64_t, little>(Working); 72559d1ed5bSDimitry Andric MD5.update(llvm::makeArrayRef((uint8_t *)&Swapped, sizeof(Swapped))); 72659d1ed5bSDimitry Andric Working = 0; 72759d1ed5bSDimitry Andric } 72859d1ed5bSDimitry Andric 72959d1ed5bSDimitry Andric // Accumulate the current type. 73059d1ed5bSDimitry Andric ++Count; 73159d1ed5bSDimitry Andric Working = Working << NumBitsPerType | Type; 73259d1ed5bSDimitry Andric } 73359d1ed5bSDimitry Andric 73459d1ed5bSDimitry Andric uint64_t PGOHash::finalize() { 73559d1ed5bSDimitry Andric // Use Working as the hash directly if we never used MD5. 73659d1ed5bSDimitry Andric if (Count <= NumTypesPerWord) 73759d1ed5bSDimitry Andric // No need to byte swap here, since none of the math was endian-dependent. 73859d1ed5bSDimitry Andric // This number will be byte-swapped as required on endianness transitions, 73959d1ed5bSDimitry Andric // so we will see the same value on the other side. 74059d1ed5bSDimitry Andric return Working; 74159d1ed5bSDimitry Andric 74259d1ed5bSDimitry Andric // Check for remaining work in Working. 74359d1ed5bSDimitry Andric if (Working) 74459d1ed5bSDimitry Andric MD5.update(Working); 74559d1ed5bSDimitry Andric 74659d1ed5bSDimitry Andric // Finalize the MD5 and return the hash. 74759d1ed5bSDimitry Andric llvm::MD5::MD5Result Result; 74859d1ed5bSDimitry Andric MD5.final(Result); 74959d1ed5bSDimitry Andric using namespace llvm::support; 75020e90f04SDimitry Andric return Result.low(); 75159d1ed5bSDimitry Andric } 75259d1ed5bSDimitry Andric 7530623d748SDimitry Andric void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) { 7540623d748SDimitry Andric const Decl *D = GD.getDecl(); 755a580b014SDimitry Andric if (!D->hasBody()) 756a580b014SDimitry Andric return; 757a580b014SDimitry Andric 758e7145dcbSDimitry Andric bool InstrumentRegions = CGM.getCodeGenOpts().hasProfileClangInstr(); 75959d1ed5bSDimitry Andric llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader(); 76059d1ed5bSDimitry Andric if (!InstrumentRegions && !PGOReader) 76159d1ed5bSDimitry Andric return; 76259d1ed5bSDimitry Andric if (D->isImplicit()) 76359d1ed5bSDimitry Andric return; 7640623d748SDimitry Andric // Constructors and destructors may be represented by several functions in IR. 7650623d748SDimitry Andric // If so, instrument only base variant, others are implemented by delegation 7660623d748SDimitry Andric // to the base one, it would be counted twice otherwise. 76720e90f04SDimitry Andric if (CGM.getTarget().getCXXABI().hasConstructorVariants()) { 76820e90f04SDimitry Andric if (isa<CXXDestructorDecl>(D) && GD.getDtorType() != Dtor_Base) 76920e90f04SDimitry Andric return; 77020e90f04SDimitry Andric 77120e90f04SDimitry Andric if (const auto *CCD = dyn_cast<CXXConstructorDecl>(D)) 77220e90f04SDimitry Andric if (GD.getCtorType() != Ctor_Base && 77320e90f04SDimitry Andric CodeGenFunction::IsConstructorDelegationValid(CCD)) 7740623d748SDimitry Andric return; 7750623d748SDimitry Andric } 77639d628a0SDimitry Andric CGM.ClearUnusedCoverageMapping(D); 77759d1ed5bSDimitry Andric setFuncName(Fn); 77859d1ed5bSDimitry Andric 77959d1ed5bSDimitry Andric mapRegionCounters(D); 78039d628a0SDimitry Andric if (CGM.getCodeGenOpts().CoverageMapping) 78139d628a0SDimitry Andric emitCounterRegionMapping(D); 78259d1ed5bSDimitry Andric if (PGOReader) { 78359d1ed5bSDimitry Andric SourceManager &SM = CGM.getContext().getSourceManager(); 78459d1ed5bSDimitry Andric loadRegionCounts(PGOReader, SM.isInMainFile(D->getLocation())); 78559d1ed5bSDimitry Andric computeRegionCounts(D); 78659d1ed5bSDimitry Andric applyFunctionAttributes(PGOReader, Fn); 78759d1ed5bSDimitry Andric } 78859d1ed5bSDimitry Andric } 78959d1ed5bSDimitry Andric 79059d1ed5bSDimitry Andric void CodeGenPGO::mapRegionCounters(const Decl *D) { 7919a199699SDimitry Andric // Use the latest hash version when inserting instrumentation, but use the 7929a199699SDimitry Andric // version in the indexed profile if we're reading PGO data. 7939a199699SDimitry Andric PGOHashVersion HashVersion = PGO_HASH_LATEST; 7949a199699SDimitry Andric if (auto *PGOReader = CGM.getPGOReader()) 7959a199699SDimitry Andric HashVersion = getPGOHashVersion(PGOReader, CGM); 7969a199699SDimitry Andric 79759d1ed5bSDimitry Andric RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>); 7989a199699SDimitry Andric MapRegionCounters Walker(HashVersion, *RegionCounterMap); 79959d1ed5bSDimitry Andric if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) 80059d1ed5bSDimitry Andric Walker.TraverseDecl(const_cast<FunctionDecl *>(FD)); 80159d1ed5bSDimitry Andric else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D)) 80259d1ed5bSDimitry Andric Walker.TraverseDecl(const_cast<ObjCMethodDecl *>(MD)); 80359d1ed5bSDimitry Andric else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D)) 80459d1ed5bSDimitry Andric Walker.TraverseDecl(const_cast<BlockDecl *>(BD)); 80559d1ed5bSDimitry Andric else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D)) 80659d1ed5bSDimitry Andric Walker.TraverseDecl(const_cast<CapturedDecl *>(CD)); 80759d1ed5bSDimitry Andric assert(Walker.NextCounter > 0 && "no entry counter mapped for decl"); 80859d1ed5bSDimitry Andric NumRegionCounters = Walker.NextCounter; 80959d1ed5bSDimitry Andric FunctionHash = Walker.Hash.finalize(); 81059d1ed5bSDimitry Andric } 81159d1ed5bSDimitry Andric 812e7145dcbSDimitry Andric bool CodeGenPGO::skipRegionMappingForDecl(const Decl *D) { 81351690af2SDimitry Andric if (!D->getBody()) 814e7145dcbSDimitry Andric return true; 815e7145dcbSDimitry Andric 816e7145dcbSDimitry Andric // Don't map the functions in system headers. 817e7145dcbSDimitry Andric const auto &SM = CGM.getContext().getSourceManager(); 81839d628a0SDimitry Andric auto Loc = D->getBody()->getLocStart(); 819e7145dcbSDimitry Andric return SM.isInSystemHeader(Loc); 820e7145dcbSDimitry Andric } 821e7145dcbSDimitry Andric 822e7145dcbSDimitry Andric void CodeGenPGO::emitCounterRegionMapping(const Decl *D) { 823e7145dcbSDimitry Andric if (skipRegionMappingForDecl(D)) 82439d628a0SDimitry Andric return; 82539d628a0SDimitry Andric 82639d628a0SDimitry Andric std::string CoverageMapping; 82739d628a0SDimitry Andric llvm::raw_string_ostream OS(CoverageMapping); 82839d628a0SDimitry Andric CoverageMappingGen MappingGen(*CGM.getCoverageMapping(), 82939d628a0SDimitry Andric CGM.getContext().getSourceManager(), 83039d628a0SDimitry Andric CGM.getLangOpts(), RegionCounterMap.get()); 83139d628a0SDimitry Andric MappingGen.emitCounterMapping(D, OS); 83239d628a0SDimitry Andric OS.flush(); 83339d628a0SDimitry Andric 83439d628a0SDimitry Andric if (CoverageMapping.empty()) 83539d628a0SDimitry Andric return; 83639d628a0SDimitry Andric 83739d628a0SDimitry Andric CGM.getCoverageMapping()->addFunctionMappingRecord( 83839d628a0SDimitry Andric FuncNameVar, FuncName, FunctionHash, CoverageMapping); 83939d628a0SDimitry Andric } 84039d628a0SDimitry Andric 84139d628a0SDimitry Andric void 84233956c43SDimitry Andric CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef Name, 84339d628a0SDimitry Andric llvm::GlobalValue::LinkageTypes Linkage) { 844e7145dcbSDimitry Andric if (skipRegionMappingForDecl(D)) 84539d628a0SDimitry Andric return; 84639d628a0SDimitry Andric 84739d628a0SDimitry Andric std::string CoverageMapping; 84839d628a0SDimitry Andric llvm::raw_string_ostream OS(CoverageMapping); 84939d628a0SDimitry Andric CoverageMappingGen MappingGen(*CGM.getCoverageMapping(), 85039d628a0SDimitry Andric CGM.getContext().getSourceManager(), 85139d628a0SDimitry Andric CGM.getLangOpts()); 85239d628a0SDimitry Andric MappingGen.emitEmptyMapping(D, OS); 85339d628a0SDimitry Andric OS.flush(); 85439d628a0SDimitry Andric 85539d628a0SDimitry Andric if (CoverageMapping.empty()) 85639d628a0SDimitry Andric return; 85739d628a0SDimitry Andric 85833956c43SDimitry Andric setFuncName(Name, Linkage); 85939d628a0SDimitry Andric CGM.getCoverageMapping()->addFunctionMappingRecord( 860444ed5c5SDimitry Andric FuncNameVar, FuncName, FunctionHash, CoverageMapping, false); 86139d628a0SDimitry Andric } 86239d628a0SDimitry Andric 86359d1ed5bSDimitry Andric void CodeGenPGO::computeRegionCounts(const Decl *D) { 86459d1ed5bSDimitry Andric StmtCountMap.reset(new llvm::DenseMap<const Stmt *, uint64_t>); 86559d1ed5bSDimitry Andric ComputeRegionCounts Walker(*StmtCountMap, *this); 86659d1ed5bSDimitry Andric if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) 86759d1ed5bSDimitry Andric Walker.VisitFunctionDecl(FD); 86859d1ed5bSDimitry Andric else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D)) 86959d1ed5bSDimitry Andric Walker.VisitObjCMethodDecl(MD); 87059d1ed5bSDimitry Andric else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D)) 87159d1ed5bSDimitry Andric Walker.VisitBlockDecl(BD); 87259d1ed5bSDimitry Andric else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D)) 87359d1ed5bSDimitry Andric Walker.VisitCapturedDecl(const_cast<CapturedDecl *>(CD)); 87459d1ed5bSDimitry Andric } 87559d1ed5bSDimitry Andric 87659d1ed5bSDimitry Andric void 87759d1ed5bSDimitry Andric CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader, 87859d1ed5bSDimitry Andric llvm::Function *Fn) { 87959d1ed5bSDimitry Andric if (!haveRegionCounts()) 88059d1ed5bSDimitry Andric return; 88159d1ed5bSDimitry Andric 8820623d748SDimitry Andric uint64_t FunctionCount = getRegionCount(nullptr); 88397bc6c73SDimitry Andric Fn->setEntryCount(FunctionCount); 88459d1ed5bSDimitry Andric } 88559d1ed5bSDimitry Andric 88620e90f04SDimitry Andric void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S, 88720e90f04SDimitry Andric llvm::Value *StepV) { 888e7145dcbSDimitry Andric if (!CGM.getCodeGenOpts().hasProfileClangInstr() || !RegionCounterMap) 88959d1ed5bSDimitry Andric return; 8900623d748SDimitry Andric if (!Builder.GetInsertBlock()) 89139d628a0SDimitry Andric return; 89233956c43SDimitry Andric 89333956c43SDimitry Andric unsigned Counter = (*RegionCounterMap)[S]; 89439d628a0SDimitry Andric auto *I8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); 89520e90f04SDimitry Andric 89620e90f04SDimitry Andric llvm::Value *Args[] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy), 89739d628a0SDimitry Andric Builder.getInt64(FunctionHash), 89839d628a0SDimitry Andric Builder.getInt32(NumRegionCounters), 89920e90f04SDimitry Andric Builder.getInt32(Counter), StepV}; 90020e90f04SDimitry Andric if (!StepV) 90120e90f04SDimitry Andric Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment), 90220e90f04SDimitry Andric makeArrayRef(Args, 4)); 90320e90f04SDimitry Andric else 90420e90f04SDimitry Andric Builder.CreateCall( 90520e90f04SDimitry Andric CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment_step), 90620e90f04SDimitry Andric makeArrayRef(Args)); 90759d1ed5bSDimitry Andric } 90859d1ed5bSDimitry Andric 909e7145dcbSDimitry Andric // This method either inserts a call to the profile run-time during 910e7145dcbSDimitry Andric // instrumentation or puts profile data into metadata for PGO use. 911e7145dcbSDimitry Andric void CodeGenPGO::valueProfile(CGBuilderTy &Builder, uint32_t ValueKind, 912e7145dcbSDimitry Andric llvm::Instruction *ValueSite, llvm::Value *ValuePtr) { 913e7145dcbSDimitry Andric 914e7145dcbSDimitry Andric if (!EnableValueProfiling) 915e7145dcbSDimitry Andric return; 916e7145dcbSDimitry Andric 917e7145dcbSDimitry Andric if (!ValuePtr || !ValueSite || !Builder.GetInsertBlock()) 918e7145dcbSDimitry Andric return; 919e7145dcbSDimitry Andric 920e7145dcbSDimitry Andric if (isa<llvm::Constant>(ValuePtr)) 921e7145dcbSDimitry Andric return; 922e7145dcbSDimitry Andric 923e7145dcbSDimitry Andric bool InstrumentValueSites = CGM.getCodeGenOpts().hasProfileClangInstr(); 924e7145dcbSDimitry Andric if (InstrumentValueSites && RegionCounterMap) { 925e7145dcbSDimitry Andric auto BuilderInsertPoint = Builder.saveIP(); 926e7145dcbSDimitry Andric Builder.SetInsertPoint(ValueSite); 927e7145dcbSDimitry Andric llvm::Value *Args[5] = { 928e7145dcbSDimitry Andric llvm::ConstantExpr::getBitCast(FuncNameVar, Builder.getInt8PtrTy()), 929e7145dcbSDimitry Andric Builder.getInt64(FunctionHash), 930e7145dcbSDimitry Andric Builder.CreatePtrToInt(ValuePtr, Builder.getInt64Ty()), 931e7145dcbSDimitry Andric Builder.getInt32(ValueKind), 932e7145dcbSDimitry Andric Builder.getInt32(NumValueSites[ValueKind]++) 933e7145dcbSDimitry Andric }; 934e7145dcbSDimitry Andric Builder.CreateCall( 935e7145dcbSDimitry Andric CGM.getIntrinsic(llvm::Intrinsic::instrprof_value_profile), Args); 936e7145dcbSDimitry Andric Builder.restoreIP(BuilderInsertPoint); 937e7145dcbSDimitry Andric return; 938e7145dcbSDimitry Andric } 939e7145dcbSDimitry Andric 940e7145dcbSDimitry Andric llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader(); 941e7145dcbSDimitry Andric if (PGOReader && haveRegionCounts()) { 942e7145dcbSDimitry Andric // We record the top most called three functions at each call site. 943e7145dcbSDimitry Andric // Profile metadata contains "VP" string identifying this metadata 944e7145dcbSDimitry Andric // as value profiling data, then a uint32_t value for the value profiling 945e7145dcbSDimitry Andric // kind, a uint64_t value for the total number of times the call is 946e7145dcbSDimitry Andric // executed, followed by the function hash and execution count (uint64_t) 947e7145dcbSDimitry Andric // pairs for each function. 948e7145dcbSDimitry Andric if (NumValueSites[ValueKind] >= ProfRecord->getNumValueSites(ValueKind)) 949e7145dcbSDimitry Andric return; 950e7145dcbSDimitry Andric 951e7145dcbSDimitry Andric llvm::annotateValueSite(CGM.getModule(), *ValueSite, *ProfRecord, 952e7145dcbSDimitry Andric (llvm::InstrProfValueKind)ValueKind, 953e7145dcbSDimitry Andric NumValueSites[ValueKind]); 954e7145dcbSDimitry Andric 955e7145dcbSDimitry Andric NumValueSites[ValueKind]++; 956e7145dcbSDimitry Andric } 957e7145dcbSDimitry Andric } 958e7145dcbSDimitry Andric 95959d1ed5bSDimitry Andric void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader, 96059d1ed5bSDimitry Andric bool IsInMainFile) { 96159d1ed5bSDimitry Andric CGM.getPGOStats().addVisited(IsInMainFile); 96239d628a0SDimitry Andric RegionCounts.clear(); 963e7145dcbSDimitry Andric llvm::Expected<llvm::InstrProfRecord> RecordExpected = 964e7145dcbSDimitry Andric PGOReader->getInstrProfRecord(FuncName, FunctionHash); 965e7145dcbSDimitry Andric if (auto E = RecordExpected.takeError()) { 966e7145dcbSDimitry Andric auto IPE = llvm::InstrProfError::take(std::move(E)); 967e7145dcbSDimitry Andric if (IPE == llvm::instrprof_error::unknown_function) 96859d1ed5bSDimitry Andric CGM.getPGOStats().addMissing(IsInMainFile); 969e7145dcbSDimitry Andric else if (IPE == llvm::instrprof_error::hash_mismatch) 97059d1ed5bSDimitry Andric CGM.getPGOStats().addMismatched(IsInMainFile); 971e7145dcbSDimitry Andric else if (IPE == llvm::instrprof_error::malformed) 97239d628a0SDimitry Andric // TODO: Consider a more specific warning for this case. 97339d628a0SDimitry Andric CGM.getPGOStats().addMismatched(IsInMainFile); 974e7145dcbSDimitry Andric return; 97559d1ed5bSDimitry Andric } 976e7145dcbSDimitry Andric ProfRecord = 977e7145dcbSDimitry Andric llvm::make_unique<llvm::InstrProfRecord>(std::move(RecordExpected.get())); 978e7145dcbSDimitry Andric RegionCounts = ProfRecord->Counts; 97959d1ed5bSDimitry Andric } 98059d1ed5bSDimitry Andric 98159d1ed5bSDimitry Andric /// \brief Calculate what to divide by to scale weights. 98259d1ed5bSDimitry Andric /// 98359d1ed5bSDimitry Andric /// Given the maximum weight, calculate a divisor that will scale all the 98459d1ed5bSDimitry Andric /// weights to strictly less than UINT32_MAX. 98559d1ed5bSDimitry Andric static uint64_t calculateWeightScale(uint64_t MaxWeight) { 98659d1ed5bSDimitry Andric return MaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1; 98759d1ed5bSDimitry Andric } 98859d1ed5bSDimitry Andric 98959d1ed5bSDimitry Andric /// \brief Scale an individual branch weight (and add 1). 99059d1ed5bSDimitry Andric /// 99159d1ed5bSDimitry Andric /// Scale a 64-bit weight down to 32-bits using \c Scale. 99259d1ed5bSDimitry Andric /// 99359d1ed5bSDimitry Andric /// According to Laplace's Rule of Succession, it is better to compute the 99459d1ed5bSDimitry Andric /// weight based on the count plus 1, so universally add 1 to the value. 99559d1ed5bSDimitry Andric /// 99659d1ed5bSDimitry Andric /// \pre \c Scale was calculated by \a calculateWeightScale() with a weight no 99759d1ed5bSDimitry Andric /// greater than \c Weight. 99859d1ed5bSDimitry Andric static uint32_t scaleBranchWeight(uint64_t Weight, uint64_t Scale) { 99959d1ed5bSDimitry Andric assert(Scale && "scale by 0?"); 100059d1ed5bSDimitry Andric uint64_t Scaled = Weight / Scale + 1; 100159d1ed5bSDimitry Andric assert(Scaled <= UINT32_MAX && "overflow 32-bits"); 100259d1ed5bSDimitry Andric return Scaled; 100359d1ed5bSDimitry Andric } 100459d1ed5bSDimitry Andric 100533956c43SDimitry Andric llvm::MDNode *CodeGenFunction::createProfileWeights(uint64_t TrueCount, 100659d1ed5bSDimitry Andric uint64_t FalseCount) { 100759d1ed5bSDimitry Andric // Check for empty weights. 100859d1ed5bSDimitry Andric if (!TrueCount && !FalseCount) 100959d1ed5bSDimitry Andric return nullptr; 101059d1ed5bSDimitry Andric 101159d1ed5bSDimitry Andric // Calculate how to scale down to 32-bits. 101259d1ed5bSDimitry Andric uint64_t Scale = calculateWeightScale(std::max(TrueCount, FalseCount)); 101359d1ed5bSDimitry Andric 101459d1ed5bSDimitry Andric llvm::MDBuilder MDHelper(CGM.getLLVMContext()); 101559d1ed5bSDimitry Andric return MDHelper.createBranchWeights(scaleBranchWeight(TrueCount, Scale), 101659d1ed5bSDimitry Andric scaleBranchWeight(FalseCount, Scale)); 101759d1ed5bSDimitry Andric } 101859d1ed5bSDimitry Andric 101933956c43SDimitry Andric llvm::MDNode * 102033956c43SDimitry Andric CodeGenFunction::createProfileWeights(ArrayRef<uint64_t> Weights) { 102159d1ed5bSDimitry Andric // We need at least two elements to create meaningful weights. 102259d1ed5bSDimitry Andric if (Weights.size() < 2) 102359d1ed5bSDimitry Andric return nullptr; 102459d1ed5bSDimitry Andric 102559d1ed5bSDimitry Andric // Check for empty weights. 102659d1ed5bSDimitry Andric uint64_t MaxWeight = *std::max_element(Weights.begin(), Weights.end()); 102759d1ed5bSDimitry Andric if (MaxWeight == 0) 102859d1ed5bSDimitry Andric return nullptr; 102959d1ed5bSDimitry Andric 103059d1ed5bSDimitry Andric // Calculate how to scale down to 32-bits. 103159d1ed5bSDimitry Andric uint64_t Scale = calculateWeightScale(MaxWeight); 103259d1ed5bSDimitry Andric 103359d1ed5bSDimitry Andric SmallVector<uint32_t, 16> ScaledWeights; 103459d1ed5bSDimitry Andric ScaledWeights.reserve(Weights.size()); 103559d1ed5bSDimitry Andric for (uint64_t W : Weights) 103659d1ed5bSDimitry Andric ScaledWeights.push_back(scaleBranchWeight(W, Scale)); 103759d1ed5bSDimitry Andric 103859d1ed5bSDimitry Andric llvm::MDBuilder MDHelper(CGM.getLLVMContext()); 103959d1ed5bSDimitry Andric return MDHelper.createBranchWeights(ScaledWeights); 104059d1ed5bSDimitry Andric } 104159d1ed5bSDimitry Andric 104233956c43SDimitry Andric llvm::MDNode *CodeGenFunction::createProfileWeightsForLoop(const Stmt *Cond, 104333956c43SDimitry Andric uint64_t LoopCount) { 104433956c43SDimitry Andric if (!PGO.haveRegionCounts()) 104559d1ed5bSDimitry Andric return nullptr; 104633956c43SDimitry Andric Optional<uint64_t> CondCount = PGO.getStmtCount(Cond); 104733956c43SDimitry Andric assert(CondCount.hasValue() && "missing expected loop condition count"); 104833956c43SDimitry Andric if (*CondCount == 0) 104959d1ed5bSDimitry Andric return nullptr; 105033956c43SDimitry Andric return createProfileWeights(LoopCount, 105133956c43SDimitry Andric std::max(*CondCount, LoopCount) - LoopCount); 105259d1ed5bSDimitry Andric } 1053