1ef512b99SJustin Bogner //===--- CodeGenPGO.cpp - PGO Instrumentation for LLVM CodeGen --*- C++ -*-===// 2ef512b99SJustin Bogner // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6ef512b99SJustin Bogner // 7ef512b99SJustin Bogner //===----------------------------------------------------------------------===// 8ef512b99SJustin Bogner // 9ef512b99SJustin Bogner // Instrumentation-based profile-guided optimization 10ef512b99SJustin Bogner // 11ef512b99SJustin Bogner //===----------------------------------------------------------------------===// 12ef512b99SJustin Bogner 13ef512b99SJustin Bogner #include "CodeGenPGO.h" 14ef512b99SJustin Bogner #include "CodeGenFunction.h" 15ee02499aSAlex Lorenz #include "CoverageMappingGen.h" 16ef512b99SJustin Bogner #include "clang/AST/RecursiveASTVisitor.h" 17ef512b99SJustin Bogner #include "clang/AST/StmtVisitor.h" 18970ac605SJustin Bogner #include "llvm/IR/Intrinsics.h" 19ef512b99SJustin Bogner #include "llvm/IR/MDBuilder.h" 204c1a1d3cSReid Kleckner #include "llvm/Support/CommandLine.h" 214bc7731aSDuncan P. N. Exon Smith #include "llvm/Support/Endian.h" 22ef512b99SJustin Bogner #include "llvm/Support/FileSystem.h" 234bc7731aSDuncan P. N. Exon Smith #include "llvm/Support/MD5.h" 24ef512b99SJustin Bogner 258065f0b9SZachary Turner static llvm::cl::opt<bool> 268065f0b9SZachary Turner EnableValueProfiling("enable-value-profiling", llvm::cl::ZeroOrMore, 278065f0b9SZachary Turner llvm::cl::desc("Enable value profiling"), 288065f0b9SZachary Turner llvm::cl::Hidden, llvm::cl::init(false)); 29518276a5SBetul Buyukkurt 30ef512b99SJustin Bogner using namespace clang; 31ef512b99SJustin Bogner using namespace CodeGen; 32ef512b99SJustin Bogner 33ee02499aSAlex Lorenz void CodeGenPGO::setFuncName(StringRef Name, 34ee02499aSAlex Lorenz llvm::GlobalValue::LinkageTypes Linkage) { 35a569e24aSXinliang David Li llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader(); 36a569e24aSXinliang David Li FuncName = llvm::getPGOFuncName( 37a569e24aSXinliang David Li Name, Linkage, CGM.getCodeGenOpts().MainFileName, 38a569e24aSXinliang David Li PGOReader ? PGOReader->getVersion() : llvm::IndexedInstrProf::Version); 39970ac605SJustin Bogner 40970ac605SJustin Bogner // If we're generating a profile, create a variable for the name. 419837ef56SRong Xu if (CGM.getCodeGenOpts().hasProfileClangInstr()) 422d7ec5a9SXinliang David Li FuncNameVar = llvm::createPGOFuncNameVar(CGM.getModule(), Linkage, FuncName); 43da1ebedeSBob Wilson } 44da1ebedeSBob Wilson 45ee02499aSAlex Lorenz void CodeGenPGO::setFuncName(llvm::Function *Fn) { 46ee02499aSAlex Lorenz setFuncName(Fn->getName(), Fn->getLinkage()); 47f932f542SRong Xu // Create PGOFuncName meta data. 48f932f542SRong Xu llvm::createPGOFuncNameMetadata(*Fn, FuncName); 49ee02499aSAlex Lorenz } 50ee02499aSAlex Lorenz 516186971aSVedant Kumar /// The version of the PGO hash algorithm. 526186971aSVedant Kumar enum PGOHashVersion : unsigned { 536186971aSVedant Kumar PGO_HASH_V1, 546186971aSVedant Kumar PGO_HASH_V2, 55de02a75eSserge-sans-paille PGO_HASH_V3, 566186971aSVedant Kumar 576186971aSVedant Kumar // Keep this set to the latest hash version. 58de02a75eSserge-sans-paille PGO_HASH_LATEST = PGO_HASH_V3 596186971aSVedant Kumar }; 606186971aSVedant Kumar 61ef512b99SJustin Bogner namespace { 629fc8faf9SAdrian Prantl /// Stable hasher for PGO region counters. 634bc7731aSDuncan P. N. Exon Smith /// 644bc7731aSDuncan P. N. Exon Smith /// PGOHash produces a stable hash of a given function's control flow. 654bc7731aSDuncan P. N. Exon Smith /// 664bc7731aSDuncan P. N. Exon Smith /// Changing the output of this hash will invalidate all previously generated 674bc7731aSDuncan P. N. Exon Smith /// profiles -- i.e., don't do it. 684bc7731aSDuncan P. N. Exon Smith /// 694bc7731aSDuncan P. N. Exon Smith /// \note When this hash does eventually change (years?), we still need to 704bc7731aSDuncan P. N. Exon Smith /// support old hashes. We'll need to pull in the version number from the 714bc7731aSDuncan P. N. Exon Smith /// profile data format and use the matching hash function. 724bc7731aSDuncan P. N. Exon Smith class PGOHash { 734bc7731aSDuncan P. N. Exon Smith uint64_t Working; 744bc7731aSDuncan P. N. Exon Smith unsigned Count; 756186971aSVedant Kumar PGOHashVersion HashVersion; 764bc7731aSDuncan P. N. Exon Smith llvm::MD5 MD5; 774bc7731aSDuncan P. N. Exon Smith 784bc7731aSDuncan P. N. Exon Smith static const int NumBitsPerType = 6; 794bc7731aSDuncan P. N. Exon Smith static const unsigned NumTypesPerWord = sizeof(uint64_t) * 8 / NumBitsPerType; 804bc7731aSDuncan P. N. Exon Smith static const unsigned TooBig = 1u << NumBitsPerType; 814bc7731aSDuncan P. N. Exon Smith 824bc7731aSDuncan P. N. Exon Smith public: 839fc8faf9SAdrian Prantl /// Hash values for AST nodes. 844bc7731aSDuncan P. N. Exon Smith /// 854bc7731aSDuncan P. N. Exon Smith /// Distinct values for AST nodes that have region counters attached. 864bc7731aSDuncan P. N. Exon Smith /// 874bc7731aSDuncan P. N. Exon Smith /// These values must be stable. All new members must be added at the end, 884bc7731aSDuncan P. N. Exon Smith /// and no members should be removed. Changing the enumeration value for an 894bc7731aSDuncan P. N. Exon Smith /// AST node will affect the hash of every function that contains that node. 904bc7731aSDuncan P. N. Exon Smith enum HashType : unsigned char { 914bc7731aSDuncan P. N. Exon Smith None = 0, 924bc7731aSDuncan P. N. Exon Smith LabelStmt = 1, 934bc7731aSDuncan P. N. Exon Smith WhileStmt, 944bc7731aSDuncan P. N. Exon Smith DoStmt, 954bc7731aSDuncan P. N. Exon Smith ForStmt, 964bc7731aSDuncan P. N. Exon Smith CXXForRangeStmt, 974bc7731aSDuncan P. N. Exon Smith ObjCForCollectionStmt, 984bc7731aSDuncan P. N. Exon Smith SwitchStmt, 994bc7731aSDuncan P. N. Exon Smith CaseStmt, 1004bc7731aSDuncan P. N. Exon Smith DefaultStmt, 1014bc7731aSDuncan P. N. Exon Smith IfStmt, 1024bc7731aSDuncan P. N. Exon Smith CXXTryStmt, 1034bc7731aSDuncan P. N. Exon Smith CXXCatchStmt, 1044bc7731aSDuncan P. N. Exon Smith ConditionalOperator, 1054bc7731aSDuncan P. N. Exon Smith BinaryOperatorLAnd, 1064bc7731aSDuncan P. N. Exon Smith BinaryOperatorLOr, 1074bc7731aSDuncan P. N. Exon Smith BinaryConditionalOperator, 1086186971aSVedant Kumar // The preceding values are available with PGO_HASH_V1. 1096186971aSVedant Kumar 1106186971aSVedant Kumar EndOfScope, 1116186971aSVedant Kumar IfThenBranch, 1126186971aSVedant Kumar IfElseBranch, 1136186971aSVedant Kumar GotoStmt, 1146186971aSVedant Kumar IndirectGotoStmt, 1156186971aSVedant Kumar BreakStmt, 1166186971aSVedant Kumar ContinueStmt, 1176186971aSVedant Kumar ReturnStmt, 1186186971aSVedant Kumar ThrowExpr, 1196186971aSVedant Kumar UnaryOperatorLNot, 1206186971aSVedant Kumar BinaryOperatorLT, 1216186971aSVedant Kumar BinaryOperatorGT, 1226186971aSVedant Kumar BinaryOperatorLE, 1236186971aSVedant Kumar BinaryOperatorGE, 1246186971aSVedant Kumar BinaryOperatorEQ, 1256186971aSVedant Kumar BinaryOperatorNE, 126de02a75eSserge-sans-paille // The preceding values are available since PGO_HASH_V2. 1274bc7731aSDuncan P. N. Exon Smith 1284bc7731aSDuncan P. N. Exon Smith // Keep this last. It's for the static assert that follows. 1294bc7731aSDuncan P. N. Exon Smith LastHashType 1304bc7731aSDuncan P. N. Exon Smith }; 1314bc7731aSDuncan P. N. Exon Smith static_assert(LastHashType <= TooBig, "Too many types in HashType"); 1324bc7731aSDuncan P. N. Exon Smith 1336186971aSVedant Kumar PGOHash(PGOHashVersion HashVersion) 1346186971aSVedant Kumar : Working(0), Count(0), HashVersion(HashVersion), MD5() {} 1354bc7731aSDuncan P. N. Exon Smith void combine(HashType Type); 1364bc7731aSDuncan P. N. Exon Smith uint64_t finalize(); 1376186971aSVedant Kumar PGOHashVersion getHashVersion() const { return HashVersion; } 1384bc7731aSDuncan P. N. Exon Smith }; 1394bc7731aSDuncan P. N. Exon Smith const int PGOHash::NumBitsPerType; 1404bc7731aSDuncan P. N. Exon Smith const unsigned PGOHash::NumTypesPerWord; 1414bc7731aSDuncan P. N. Exon Smith const unsigned PGOHash::TooBig; 1424bc7731aSDuncan P. N. Exon Smith 1436186971aSVedant Kumar /// Get the PGO hash version used in the given indexed profile. 1446186971aSVedant Kumar static PGOHashVersion getPGOHashVersion(llvm::IndexedInstrProfReader *PGOReader, 1456186971aSVedant Kumar CodeGenModule &CGM) { 1466186971aSVedant Kumar if (PGOReader->getVersion() <= 4) 1476186971aSVedant Kumar return PGO_HASH_V1; 148de02a75eSserge-sans-paille if (PGOReader->getVersion() <= 5) 1496186971aSVedant Kumar return PGO_HASH_V2; 150de02a75eSserge-sans-paille return PGO_HASH_V3; 1516186971aSVedant Kumar } 1526186971aSVedant Kumar 153d8931425SBob Wilson /// A RecursiveASTVisitor that fills a map of statements to PGO counters. 154d8931425SBob Wilson struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> { 1556186971aSVedant Kumar using Base = RecursiveASTVisitor<MapRegionCounters>; 1566186971aSVedant Kumar 157ef512b99SJustin Bogner /// The next counter value to assign. 158ef512b99SJustin Bogner unsigned NextCounter; 1594bc7731aSDuncan P. N. Exon Smith /// The function hash. 1604bc7731aSDuncan P. N. Exon Smith PGOHash Hash; 161ef512b99SJustin Bogner /// The map of statements to counters. 1623586be72SDuncan P. N. Exon Smith llvm::DenseMap<const Stmt *, unsigned> &CounterMap; 1639f2967bcSAlan Phipps /// The profile version. 1649f2967bcSAlan Phipps uint64_t ProfileVersion; 165ef512b99SJustin Bogner 1669f2967bcSAlan Phipps MapRegionCounters(PGOHashVersion HashVersion, uint64_t ProfileVersion, 1676186971aSVedant Kumar llvm::DenseMap<const Stmt *, unsigned> &CounterMap) 1689f2967bcSAlan Phipps : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap), 1699f2967bcSAlan Phipps ProfileVersion(ProfileVersion) {} 170ef512b99SJustin Bogner 171191ec63bSJustin Bogner // Blocks and lambdas are handled as separate functions, so we need not 172191ec63bSJustin Bogner // traverse them in the parent context. 173191ec63bSJustin Bogner bool TraverseBlockExpr(BlockExpr *BE) { return true; } 174e60151c9SSam McCall bool TraverseLambdaExpr(LambdaExpr *LE) { 175e60151c9SSam McCall // Traverse the captures, but not the body. 1768dc7b982SMark de Wever for (auto C : zip(LE->captures(), LE->capture_inits())) 177e60151c9SSam McCall TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C)); 178e60151c9SSam McCall return true; 179e60151c9SSam McCall } 18081ab90f7SJustin Bogner bool TraverseCapturedStmt(CapturedStmt *CS) { return true; } 181ef512b99SJustin Bogner 182d8931425SBob Wilson bool VisitDecl(const Decl *D) { 183d8931425SBob Wilson switch (D->getKind()) { 184d8931425SBob Wilson default: 185d8931425SBob Wilson break; 186d8931425SBob Wilson case Decl::Function: 187d8931425SBob Wilson case Decl::CXXMethod: 188d8931425SBob Wilson case Decl::CXXConstructor: 189d8931425SBob Wilson case Decl::CXXDestructor: 190d8931425SBob Wilson case Decl::CXXConversion: 191d8931425SBob Wilson case Decl::ObjCMethod: 192d8931425SBob Wilson case Decl::Block: 19381ab90f7SJustin Bogner case Decl::Captured: 1944a2f5ae8SDuncan P. N. Exon Smith CounterMap[D->getBody()] = NextCounter++; 195d8931425SBob Wilson break; 196ef512b99SJustin Bogner } 197d8931425SBob Wilson return true; 1985ec8fe19SBob Wilson } 199d8931425SBob Wilson 2006186971aSVedant Kumar /// If \p S gets a fresh counter, update the counter mappings. Return the 2016186971aSVedant Kumar /// V1 hash of \p S. 2026186971aSVedant Kumar PGOHash::HashType updateCounterMappings(Stmt *S) { 2036186971aSVedant Kumar auto Type = getHashType(PGO_HASH_V1, S); 2046186971aSVedant Kumar if (Type != PGOHash::None) 2054bc7731aSDuncan P. N. Exon Smith CounterMap[S] = NextCounter++; 2066186971aSVedant Kumar return Type; 2076186971aSVedant Kumar } 2086186971aSVedant Kumar 2099f2967bcSAlan Phipps /// The RHS of all logical operators gets a fresh counter in order to count 2109f2967bcSAlan Phipps /// how many times the RHS evaluates to true or false, depending on the 2119f2967bcSAlan Phipps /// semantics of the operator. This is only valid for ">= v7" of the profile 2129f2967bcSAlan Phipps /// version so that we facilitate backward compatibility. 2139f2967bcSAlan Phipps bool VisitBinaryOperator(BinaryOperator *S) { 2149f2967bcSAlan Phipps if (ProfileVersion >= llvm::IndexedInstrProf::Version7) 2159f2967bcSAlan Phipps if (S->isLogicalOp() && 2169f2967bcSAlan Phipps CodeGenFunction::isInstrumentedCondition(S->getRHS())) 2179f2967bcSAlan Phipps CounterMap[S->getRHS()] = NextCounter++; 2189f2967bcSAlan Phipps return Base::VisitBinaryOperator(S); 2199f2967bcSAlan Phipps } 2209f2967bcSAlan Phipps 2216186971aSVedant Kumar /// Include \p S in the function hash. 2226186971aSVedant Kumar bool VisitStmt(Stmt *S) { 2236186971aSVedant Kumar auto Type = updateCounterMappings(S); 2246186971aSVedant Kumar if (Hash.getHashVersion() != PGO_HASH_V1) 2256186971aSVedant Kumar Type = getHashType(Hash.getHashVersion(), S); 2266186971aSVedant Kumar if (Type != PGOHash::None) 2274bc7731aSDuncan P. N. Exon Smith Hash.combine(Type); 2284bc7731aSDuncan P. N. Exon Smith return true; 2294bc7731aSDuncan P. N. Exon Smith } 2306186971aSVedant Kumar 2316186971aSVedant Kumar bool TraverseIfStmt(IfStmt *If) { 2326186971aSVedant Kumar // If we used the V1 hash, use the default traversal. 2336186971aSVedant Kumar if (Hash.getHashVersion() == PGO_HASH_V1) 2346186971aSVedant Kumar return Base::TraverseIfStmt(If); 2356186971aSVedant Kumar 2366186971aSVedant Kumar // Otherwise, keep track of which branch we're in while traversing. 2376186971aSVedant Kumar VisitStmt(If); 2386186971aSVedant Kumar for (Stmt *CS : If->children()) { 2396186971aSVedant Kumar if (!CS) 2406186971aSVedant Kumar continue; 2416186971aSVedant Kumar if (CS == If->getThen()) 2426186971aSVedant Kumar Hash.combine(PGOHash::IfThenBranch); 2436186971aSVedant Kumar else if (CS == If->getElse()) 2446186971aSVedant Kumar Hash.combine(PGOHash::IfElseBranch); 2456186971aSVedant Kumar TraverseStmt(CS); 2466186971aSVedant Kumar } 2476186971aSVedant Kumar Hash.combine(PGOHash::EndOfScope); 2486186971aSVedant Kumar return true; 2496186971aSVedant Kumar } 2506186971aSVedant Kumar 2516186971aSVedant Kumar // If the statement type \p N is nestable, and its nesting impacts profile 2526186971aSVedant Kumar // stability, define a custom traversal which tracks the end of the statement 2536186971aSVedant Kumar // in the hash (provided we're not using the V1 hash). 2546186971aSVedant Kumar #define DEFINE_NESTABLE_TRAVERSAL(N) \ 2556186971aSVedant Kumar bool Traverse##N(N *S) { \ 2566186971aSVedant Kumar Base::Traverse##N(S); \ 2576186971aSVedant Kumar if (Hash.getHashVersion() != PGO_HASH_V1) \ 2586186971aSVedant Kumar Hash.combine(PGOHash::EndOfScope); \ 2596186971aSVedant Kumar return true; \ 2606186971aSVedant Kumar } 2616186971aSVedant Kumar 2626186971aSVedant Kumar DEFINE_NESTABLE_TRAVERSAL(WhileStmt) 2636186971aSVedant Kumar DEFINE_NESTABLE_TRAVERSAL(DoStmt) 2646186971aSVedant Kumar DEFINE_NESTABLE_TRAVERSAL(ForStmt) 2656186971aSVedant Kumar DEFINE_NESTABLE_TRAVERSAL(CXXForRangeStmt) 2666186971aSVedant Kumar DEFINE_NESTABLE_TRAVERSAL(ObjCForCollectionStmt) 2676186971aSVedant Kumar DEFINE_NESTABLE_TRAVERSAL(CXXTryStmt) 2686186971aSVedant Kumar DEFINE_NESTABLE_TRAVERSAL(CXXCatchStmt) 2696186971aSVedant Kumar 2706186971aSVedant Kumar /// Get version \p HashVersion of the PGO hash for \p S. 2716186971aSVedant Kumar PGOHash::HashType getHashType(PGOHashVersion HashVersion, const Stmt *S) { 272d8931425SBob Wilson switch (S->getStmtClass()) { 273d8931425SBob Wilson default: 274d8931425SBob Wilson break; 275d8931425SBob Wilson case Stmt::LabelStmtClass: 2764bc7731aSDuncan P. N. Exon Smith return PGOHash::LabelStmt; 277d8931425SBob Wilson case Stmt::WhileStmtClass: 2784bc7731aSDuncan P. N. Exon Smith return PGOHash::WhileStmt; 279d8931425SBob Wilson case Stmt::DoStmtClass: 2804bc7731aSDuncan P. N. Exon Smith return PGOHash::DoStmt; 281d8931425SBob Wilson case Stmt::ForStmtClass: 2824bc7731aSDuncan P. N. Exon Smith return PGOHash::ForStmt; 283d8931425SBob Wilson case Stmt::CXXForRangeStmtClass: 2844bc7731aSDuncan P. N. Exon Smith return PGOHash::CXXForRangeStmt; 285d8931425SBob Wilson case Stmt::ObjCForCollectionStmtClass: 2864bc7731aSDuncan P. N. Exon Smith return PGOHash::ObjCForCollectionStmt; 287d8931425SBob Wilson case Stmt::SwitchStmtClass: 2884bc7731aSDuncan P. N. Exon Smith return PGOHash::SwitchStmt; 289d8931425SBob Wilson case Stmt::CaseStmtClass: 2904bc7731aSDuncan P. N. Exon Smith return PGOHash::CaseStmt; 291d8931425SBob Wilson case Stmt::DefaultStmtClass: 2924bc7731aSDuncan P. N. Exon Smith return PGOHash::DefaultStmt; 293d8931425SBob Wilson case Stmt::IfStmtClass: 2944bc7731aSDuncan P. N. Exon Smith return PGOHash::IfStmt; 295d8931425SBob Wilson case Stmt::CXXTryStmtClass: 2964bc7731aSDuncan P. N. Exon Smith return PGOHash::CXXTryStmt; 297d8931425SBob Wilson case Stmt::CXXCatchStmtClass: 2984bc7731aSDuncan P. N. Exon Smith return PGOHash::CXXCatchStmt; 299d8931425SBob Wilson case Stmt::ConditionalOperatorClass: 3004bc7731aSDuncan P. N. Exon Smith return PGOHash::ConditionalOperator; 301d8931425SBob Wilson case Stmt::BinaryConditionalOperatorClass: 3024bc7731aSDuncan P. N. Exon Smith return PGOHash::BinaryConditionalOperator; 303d8931425SBob Wilson case Stmt::BinaryOperatorClass: { 304d8931425SBob Wilson const BinaryOperator *BO = cast<BinaryOperator>(S); 3054bc7731aSDuncan P. N. Exon Smith if (BO->getOpcode() == BO_LAnd) 3064bc7731aSDuncan P. N. Exon Smith return PGOHash::BinaryOperatorLAnd; 3074bc7731aSDuncan P. N. Exon Smith if (BO->getOpcode() == BO_LOr) 3084bc7731aSDuncan P. N. Exon Smith return PGOHash::BinaryOperatorLOr; 309de02a75eSserge-sans-paille if (HashVersion >= PGO_HASH_V2) { 3106186971aSVedant Kumar switch (BO->getOpcode()) { 3116186971aSVedant Kumar default: 3126186971aSVedant Kumar break; 3136186971aSVedant Kumar case BO_LT: 3146186971aSVedant Kumar return PGOHash::BinaryOperatorLT; 3156186971aSVedant Kumar case BO_GT: 3166186971aSVedant Kumar return PGOHash::BinaryOperatorGT; 3176186971aSVedant Kumar case BO_LE: 3186186971aSVedant Kumar return PGOHash::BinaryOperatorLE; 3196186971aSVedant Kumar case BO_GE: 3206186971aSVedant Kumar return PGOHash::BinaryOperatorGE; 3216186971aSVedant Kumar case BO_EQ: 3226186971aSVedant Kumar return PGOHash::BinaryOperatorEQ; 3236186971aSVedant Kumar case BO_NE: 3246186971aSVedant Kumar return PGOHash::BinaryOperatorNE; 3256186971aSVedant Kumar } 3266186971aSVedant Kumar } 327d8931425SBob Wilson break; 328ef512b99SJustin Bogner } 329ef512b99SJustin Bogner } 3306186971aSVedant Kumar 331de02a75eSserge-sans-paille if (HashVersion >= PGO_HASH_V2) { 3326186971aSVedant Kumar switch (S->getStmtClass()) { 3336186971aSVedant Kumar default: 3346186971aSVedant Kumar break; 3356186971aSVedant Kumar case Stmt::GotoStmtClass: 3366186971aSVedant Kumar return PGOHash::GotoStmt; 3376186971aSVedant Kumar case Stmt::IndirectGotoStmtClass: 3386186971aSVedant Kumar return PGOHash::IndirectGotoStmt; 3396186971aSVedant Kumar case Stmt::BreakStmtClass: 3406186971aSVedant Kumar return PGOHash::BreakStmt; 3416186971aSVedant Kumar case Stmt::ContinueStmtClass: 3426186971aSVedant Kumar return PGOHash::ContinueStmt; 3436186971aSVedant Kumar case Stmt::ReturnStmtClass: 3446186971aSVedant Kumar return PGOHash::ReturnStmt; 3456186971aSVedant Kumar case Stmt::CXXThrowExprClass: 3466186971aSVedant Kumar return PGOHash::ThrowExpr; 3476186971aSVedant Kumar case Stmt::UnaryOperatorClass: { 3486186971aSVedant Kumar const UnaryOperator *UO = cast<UnaryOperator>(S); 3496186971aSVedant Kumar if (UO->getOpcode() == UO_LNot) 3506186971aSVedant Kumar return PGOHash::UnaryOperatorLNot; 3516186971aSVedant Kumar break; 3526186971aSVedant Kumar } 3536186971aSVedant Kumar } 3546186971aSVedant Kumar } 3556186971aSVedant Kumar 3564bc7731aSDuncan P. N. Exon Smith return PGOHash::None; 357ef512b99SJustin Bogner } 358ef512b99SJustin Bogner }; 359bf854f0fSBob Wilson 360bf854f0fSBob Wilson /// A StmtVisitor that propagates the raw counts through the AST and 361bf854f0fSBob Wilson /// records the count at statements where the value may change. 362bf854f0fSBob Wilson struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> { 363bf854f0fSBob Wilson /// PGO state. 364bf854f0fSBob Wilson CodeGenPGO &PGO; 365bf854f0fSBob Wilson 366bf854f0fSBob Wilson /// A flag that is set when the current count should be recorded on the 367bf854f0fSBob Wilson /// next statement, such as at the exit of a loop. 368bf854f0fSBob Wilson bool RecordNextStmtCount; 369bf854f0fSBob Wilson 370a909abfdSJustin Bogner /// The count at the current location in the traversal. 371a909abfdSJustin Bogner uint64_t CurrentCount; 372a909abfdSJustin Bogner 373bf854f0fSBob Wilson /// The map of statements to count values. 3743586be72SDuncan P. N. Exon Smith llvm::DenseMap<const Stmt *, uint64_t> &CountMap; 375bf854f0fSBob Wilson 376bf854f0fSBob Wilson /// BreakContinueStack - Keep counts of breaks and continues inside loops. 377bf854f0fSBob Wilson struct BreakContinue { 378bf854f0fSBob Wilson uint64_t BreakCount; 379bf854f0fSBob Wilson uint64_t ContinueCount; 380bf854f0fSBob Wilson BreakContinue() : BreakCount(0), ContinueCount(0) {} 381bf854f0fSBob Wilson }; 382bf854f0fSBob Wilson SmallVector<BreakContinue, 8> BreakContinueStack; 383bf854f0fSBob Wilson 3843586be72SDuncan P. N. Exon Smith ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &CountMap, 3853586be72SDuncan P. N. Exon Smith CodeGenPGO &PGO) 3863586be72SDuncan P. N. Exon Smith : PGO(PGO), RecordNextStmtCount(false), CountMap(CountMap) {} 387bf854f0fSBob Wilson 388bf854f0fSBob Wilson void RecordStmtCount(const Stmt *S) { 389bf854f0fSBob Wilson if (RecordNextStmtCount) { 390a909abfdSJustin Bogner CountMap[S] = CurrentCount; 391bf854f0fSBob Wilson RecordNextStmtCount = false; 392bf854f0fSBob Wilson } 393bf854f0fSBob Wilson } 394bf854f0fSBob Wilson 39507193cc8SJustin Bogner /// Set and return the current count. 39607193cc8SJustin Bogner uint64_t setCount(uint64_t Count) { 397a909abfdSJustin Bogner CurrentCount = Count; 39807193cc8SJustin Bogner return Count; 39907193cc8SJustin Bogner } 40007193cc8SJustin Bogner 401bf854f0fSBob Wilson void VisitStmt(const Stmt *S) { 402bf854f0fSBob Wilson RecordStmtCount(S); 403642f173aSBenjamin Kramer for (const Stmt *Child : S->children()) 404642f173aSBenjamin Kramer if (Child) 405642f173aSBenjamin Kramer this->Visit(Child); 406bf854f0fSBob Wilson } 407bf854f0fSBob Wilson 4084a2f5ae8SDuncan P. N. Exon Smith void VisitFunctionDecl(const FunctionDecl *D) { 409d8931425SBob Wilson // Counter tracks entry to the function body. 41007193cc8SJustin Bogner uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); 41107193cc8SJustin Bogner CountMap[D->getBody()] = BodyCount; 4124a2f5ae8SDuncan P. N. Exon Smith Visit(D->getBody()); 413bf854f0fSBob Wilson } 414bf854f0fSBob Wilson 415191ec63bSJustin Bogner // Skip lambda expressions. We visit these as FunctionDecls when we're 416191ec63bSJustin Bogner // generating them and aren't interested in the body when generating a 417191ec63bSJustin Bogner // parent context. 418191ec63bSJustin Bogner void VisitLambdaExpr(const LambdaExpr *LE) {} 419191ec63bSJustin Bogner 42081ab90f7SJustin Bogner void VisitCapturedDecl(const CapturedDecl *D) { 42181ab90f7SJustin Bogner // Counter tracks entry to the capture body. 42207193cc8SJustin Bogner uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); 42307193cc8SJustin Bogner CountMap[D->getBody()] = BodyCount; 42481ab90f7SJustin Bogner Visit(D->getBody()); 42581ab90f7SJustin Bogner } 42681ab90f7SJustin Bogner 4274a2f5ae8SDuncan P. N. Exon Smith void VisitObjCMethodDecl(const ObjCMethodDecl *D) { 428d8931425SBob Wilson // Counter tracks entry to the method body. 42907193cc8SJustin Bogner uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); 43007193cc8SJustin Bogner CountMap[D->getBody()] = BodyCount; 4314a2f5ae8SDuncan P. N. Exon Smith Visit(D->getBody()); 4325ec8fe19SBob Wilson } 4335ec8fe19SBob Wilson 4344a2f5ae8SDuncan P. N. Exon Smith void VisitBlockDecl(const BlockDecl *D) { 435d8931425SBob Wilson // Counter tracks entry to the block body. 43607193cc8SJustin Bogner uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); 43707193cc8SJustin Bogner CountMap[D->getBody()] = BodyCount; 4384a2f5ae8SDuncan P. N. Exon Smith Visit(D->getBody()); 439c845c00aSBob Wilson } 440c845c00aSBob Wilson 441bf854f0fSBob Wilson void VisitReturnStmt(const ReturnStmt *S) { 442bf854f0fSBob Wilson RecordStmtCount(S); 443bf854f0fSBob Wilson if (S->getRetValue()) 444bf854f0fSBob Wilson Visit(S->getRetValue()); 445a909abfdSJustin Bogner CurrentCount = 0; 446bf854f0fSBob Wilson RecordNextStmtCount = true; 447bf854f0fSBob Wilson } 448bf854f0fSBob Wilson 449f959febfSJustin Bogner void VisitCXXThrowExpr(const CXXThrowExpr *E) { 450f959febfSJustin Bogner RecordStmtCount(E); 451f959febfSJustin Bogner if (E->getSubExpr()) 452f959febfSJustin Bogner Visit(E->getSubExpr()); 453a909abfdSJustin Bogner CurrentCount = 0; 454f959febfSJustin Bogner RecordNextStmtCount = true; 455f959febfSJustin Bogner } 456f959febfSJustin Bogner 457bf854f0fSBob Wilson void VisitGotoStmt(const GotoStmt *S) { 458bf854f0fSBob Wilson RecordStmtCount(S); 459a909abfdSJustin Bogner CurrentCount = 0; 460bf854f0fSBob Wilson RecordNextStmtCount = true; 461bf854f0fSBob Wilson } 462bf854f0fSBob Wilson 463bf854f0fSBob Wilson void VisitLabelStmt(const LabelStmt *S) { 464bf854f0fSBob Wilson RecordNextStmtCount = false; 465d8931425SBob Wilson // Counter tracks the block following the label. 46607193cc8SJustin Bogner uint64_t BlockCount = setCount(PGO.getRegionCount(S)); 46707193cc8SJustin Bogner CountMap[S] = BlockCount; 468bf854f0fSBob Wilson Visit(S->getSubStmt()); 469bf854f0fSBob Wilson } 470bf854f0fSBob Wilson 471bf854f0fSBob Wilson void VisitBreakStmt(const BreakStmt *S) { 472bf854f0fSBob Wilson RecordStmtCount(S); 473bf854f0fSBob Wilson assert(!BreakContinueStack.empty() && "break not in a loop or switch!"); 474a909abfdSJustin Bogner BreakContinueStack.back().BreakCount += CurrentCount; 475a909abfdSJustin Bogner CurrentCount = 0; 476bf854f0fSBob Wilson RecordNextStmtCount = true; 477bf854f0fSBob Wilson } 478bf854f0fSBob Wilson 479bf854f0fSBob Wilson void VisitContinueStmt(const ContinueStmt *S) { 480bf854f0fSBob Wilson RecordStmtCount(S); 481bf854f0fSBob Wilson assert(!BreakContinueStack.empty() && "continue stmt not in a loop!"); 482a909abfdSJustin Bogner BreakContinueStack.back().ContinueCount += CurrentCount; 483a909abfdSJustin Bogner CurrentCount = 0; 484bf854f0fSBob Wilson RecordNextStmtCount = true; 485bf854f0fSBob Wilson } 486bf854f0fSBob Wilson 487bf854f0fSBob Wilson void VisitWhileStmt(const WhileStmt *S) { 488bf854f0fSBob Wilson RecordStmtCount(S); 489a909abfdSJustin Bogner uint64_t ParentCount = CurrentCount; 49007193cc8SJustin Bogner 491bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue()); 492bf854f0fSBob Wilson // Visit the body region first so the break/continue adjustments can be 493bf854f0fSBob Wilson // included when visiting the condition. 49407193cc8SJustin Bogner uint64_t BodyCount = setCount(PGO.getRegionCount(S)); 495a909abfdSJustin Bogner CountMap[S->getBody()] = CurrentCount; 496bf854f0fSBob Wilson Visit(S->getBody()); 497a909abfdSJustin Bogner uint64_t BackedgeCount = CurrentCount; 498bf854f0fSBob Wilson 499bf854f0fSBob Wilson // ...then go back and propagate counts through the condition. The count 500bf854f0fSBob Wilson // at the start of the condition is the sum of the incoming edges, 501bf854f0fSBob Wilson // the backedge from the end of the loop body, and the edges from 502bf854f0fSBob Wilson // continue statements. 503bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val(); 50407193cc8SJustin Bogner uint64_t CondCount = 50507193cc8SJustin Bogner setCount(ParentCount + BackedgeCount + BC.ContinueCount); 50607193cc8SJustin Bogner CountMap[S->getCond()] = CondCount; 507bf854f0fSBob Wilson Visit(S->getCond()); 50807193cc8SJustin Bogner setCount(BC.BreakCount + CondCount - BodyCount); 509bf854f0fSBob Wilson RecordNextStmtCount = true; 510bf854f0fSBob Wilson } 511bf854f0fSBob Wilson 512bf854f0fSBob Wilson void VisitDoStmt(const DoStmt *S) { 513bf854f0fSBob Wilson RecordStmtCount(S); 51407193cc8SJustin Bogner uint64_t LoopCount = PGO.getRegionCount(S); 51507193cc8SJustin Bogner 516bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue()); 51707193cc8SJustin Bogner // The count doesn't include the fallthrough from the parent scope. Add it. 518a909abfdSJustin Bogner uint64_t BodyCount = setCount(LoopCount + CurrentCount); 51907193cc8SJustin Bogner CountMap[S->getBody()] = BodyCount; 520bf854f0fSBob Wilson Visit(S->getBody()); 521a909abfdSJustin Bogner uint64_t BackedgeCount = CurrentCount; 522bf854f0fSBob Wilson 523bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val(); 524bf854f0fSBob Wilson // The count at the start of the condition is equal to the count at the 52507193cc8SJustin Bogner // end of the body, plus any continues. 52607193cc8SJustin Bogner uint64_t CondCount = setCount(BackedgeCount + BC.ContinueCount); 52707193cc8SJustin Bogner CountMap[S->getCond()] = CondCount; 528bf854f0fSBob Wilson Visit(S->getCond()); 52907193cc8SJustin Bogner setCount(BC.BreakCount + CondCount - LoopCount); 530bf854f0fSBob Wilson RecordNextStmtCount = true; 531bf854f0fSBob Wilson } 532bf854f0fSBob Wilson 533bf854f0fSBob Wilson void VisitForStmt(const ForStmt *S) { 534bf854f0fSBob Wilson RecordStmtCount(S); 535bf854f0fSBob Wilson if (S->getInit()) 536bf854f0fSBob Wilson Visit(S->getInit()); 53707193cc8SJustin Bogner 538a909abfdSJustin Bogner uint64_t ParentCount = CurrentCount; 53907193cc8SJustin Bogner 540bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue()); 541bf854f0fSBob Wilson // Visit the body region first. (This is basically the same as a while 542bf854f0fSBob Wilson // loop; see further comments in VisitWhileStmt.) 54307193cc8SJustin Bogner uint64_t BodyCount = setCount(PGO.getRegionCount(S)); 54407193cc8SJustin Bogner CountMap[S->getBody()] = BodyCount; 545bf854f0fSBob Wilson Visit(S->getBody()); 546a909abfdSJustin Bogner uint64_t BackedgeCount = CurrentCount; 54707193cc8SJustin Bogner BreakContinue BC = BreakContinueStack.pop_back_val(); 548bf854f0fSBob Wilson 549bf854f0fSBob Wilson // The increment is essentially part of the body but it needs to include 550bf854f0fSBob Wilson // the count for all the continue statements. 551bf854f0fSBob Wilson if (S->getInc()) { 55207193cc8SJustin Bogner uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount); 55307193cc8SJustin Bogner CountMap[S->getInc()] = IncCount; 554bf854f0fSBob Wilson Visit(S->getInc()); 555bf854f0fSBob Wilson } 556bf854f0fSBob Wilson 557bf854f0fSBob Wilson // ...then go back and propagate counts through the condition. 55807193cc8SJustin Bogner uint64_t CondCount = 55907193cc8SJustin Bogner setCount(ParentCount + BackedgeCount + BC.ContinueCount); 560bf854f0fSBob Wilson if (S->getCond()) { 56107193cc8SJustin Bogner CountMap[S->getCond()] = CondCount; 562bf854f0fSBob Wilson Visit(S->getCond()); 563bf854f0fSBob Wilson } 56407193cc8SJustin Bogner setCount(BC.BreakCount + CondCount - BodyCount); 565bf854f0fSBob Wilson RecordNextStmtCount = true; 566bf854f0fSBob Wilson } 567bf854f0fSBob Wilson 568bf854f0fSBob Wilson void VisitCXXForRangeStmt(const CXXForRangeStmt *S) { 569bf854f0fSBob Wilson RecordStmtCount(S); 5708baa5001SRichard Smith if (S->getInit()) 5718baa5001SRichard Smith Visit(S->getInit()); 5722e5d4845SJustin Bogner Visit(S->getLoopVarStmt()); 573bf854f0fSBob Wilson Visit(S->getRangeStmt()); 57401694c34SRichard Smith Visit(S->getBeginStmt()); 57501694c34SRichard Smith Visit(S->getEndStmt()); 57607193cc8SJustin Bogner 577a909abfdSJustin Bogner uint64_t ParentCount = CurrentCount; 578bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue()); 579bf854f0fSBob Wilson // Visit the body region first. (This is basically the same as a while 580bf854f0fSBob Wilson // loop; see further comments in VisitWhileStmt.) 58107193cc8SJustin Bogner uint64_t BodyCount = setCount(PGO.getRegionCount(S)); 58207193cc8SJustin Bogner CountMap[S->getBody()] = BodyCount; 583bf854f0fSBob Wilson Visit(S->getBody()); 584a909abfdSJustin Bogner uint64_t BackedgeCount = CurrentCount; 58507193cc8SJustin Bogner BreakContinue BC = BreakContinueStack.pop_back_val(); 586bf854f0fSBob Wilson 587bf854f0fSBob Wilson // The increment is essentially part of the body but it needs to include 588bf854f0fSBob Wilson // the count for all the continue statements. 58907193cc8SJustin Bogner uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount); 59007193cc8SJustin Bogner CountMap[S->getInc()] = IncCount; 591bf854f0fSBob Wilson Visit(S->getInc()); 592bf854f0fSBob Wilson 593bf854f0fSBob Wilson // ...then go back and propagate counts through the condition. 59407193cc8SJustin Bogner uint64_t CondCount = 59507193cc8SJustin Bogner setCount(ParentCount + BackedgeCount + BC.ContinueCount); 59607193cc8SJustin Bogner CountMap[S->getCond()] = CondCount; 597bf854f0fSBob Wilson Visit(S->getCond()); 59807193cc8SJustin Bogner setCount(BC.BreakCount + CondCount - BodyCount); 599bf854f0fSBob Wilson RecordNextStmtCount = true; 600bf854f0fSBob Wilson } 601bf854f0fSBob Wilson 602bf854f0fSBob Wilson void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) { 603bf854f0fSBob Wilson RecordStmtCount(S); 604bf854f0fSBob Wilson Visit(S->getElement()); 605a909abfdSJustin Bogner uint64_t ParentCount = CurrentCount; 606bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue()); 60707193cc8SJustin Bogner // Counter tracks the body of the loop. 60807193cc8SJustin Bogner uint64_t BodyCount = setCount(PGO.getRegionCount(S)); 60907193cc8SJustin Bogner CountMap[S->getBody()] = BodyCount; 610bf854f0fSBob Wilson Visit(S->getBody()); 611a909abfdSJustin Bogner uint64_t BackedgeCount = CurrentCount; 612bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val(); 61307193cc8SJustin Bogner 61407193cc8SJustin Bogner setCount(BC.BreakCount + ParentCount + BackedgeCount + BC.ContinueCount - 61507193cc8SJustin Bogner BodyCount); 616bf854f0fSBob Wilson RecordNextStmtCount = true; 617bf854f0fSBob Wilson } 618bf854f0fSBob Wilson 619bf854f0fSBob Wilson void VisitSwitchStmt(const SwitchStmt *S) { 620bf854f0fSBob Wilson RecordStmtCount(S); 621f2a6ec55SVedant Kumar if (S->getInit()) 622f2a6ec55SVedant Kumar Visit(S->getInit()); 623bf854f0fSBob Wilson Visit(S->getCond()); 624a909abfdSJustin Bogner CurrentCount = 0; 625bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue()); 626bf854f0fSBob Wilson Visit(S->getBody()); 627bf854f0fSBob Wilson // If the switch is inside a loop, add the continue counts. 628bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val(); 629bf854f0fSBob Wilson if (!BreakContinueStack.empty()) 630bf854f0fSBob Wilson BreakContinueStack.back().ContinueCount += BC.ContinueCount; 631d8931425SBob Wilson // Counter tracks the exit block of the switch. 63207193cc8SJustin Bogner setCount(PGO.getRegionCount(S)); 633bf854f0fSBob Wilson RecordNextStmtCount = true; 634bf854f0fSBob Wilson } 635bf854f0fSBob Wilson 63607193cc8SJustin Bogner void VisitSwitchCase(const SwitchCase *S) { 637bf854f0fSBob Wilson RecordNextStmtCount = false; 638d8931425SBob Wilson // Counter for this particular case. This counts only jumps from the 639d8931425SBob Wilson // switch header and does not include fallthrough from the case before 640d8931425SBob Wilson // this one. 64107193cc8SJustin Bogner uint64_t CaseCount = PGO.getRegionCount(S); 642a909abfdSJustin Bogner setCount(CurrentCount + CaseCount); 64307193cc8SJustin Bogner // We need the count without fallthrough in the mapping, so it's more useful 64407193cc8SJustin Bogner // for branch probabilities. 64507193cc8SJustin Bogner CountMap[S] = CaseCount; 646bf854f0fSBob Wilson RecordNextStmtCount = true; 647bf854f0fSBob Wilson Visit(S->getSubStmt()); 648bf854f0fSBob Wilson } 649bf854f0fSBob Wilson 650bf854f0fSBob Wilson void VisitIfStmt(const IfStmt *S) { 651bf854f0fSBob Wilson RecordStmtCount(S); 652a909abfdSJustin Bogner uint64_t ParentCount = CurrentCount; 6539d2a16b9SVedant Kumar if (S->getInit()) 6549d2a16b9SVedant Kumar Visit(S->getInit()); 655bf854f0fSBob Wilson Visit(S->getCond()); 656bf854f0fSBob Wilson 65707193cc8SJustin Bogner // Counter tracks the "then" part of an if statement. The count for 65807193cc8SJustin Bogner // the "else" part, if it exists, will be calculated from this counter. 65907193cc8SJustin Bogner uint64_t ThenCount = setCount(PGO.getRegionCount(S)); 66007193cc8SJustin Bogner CountMap[S->getThen()] = ThenCount; 661bf854f0fSBob Wilson Visit(S->getThen()); 662a909abfdSJustin Bogner uint64_t OutCount = CurrentCount; 663bf854f0fSBob Wilson 66407193cc8SJustin Bogner uint64_t ElseCount = ParentCount - ThenCount; 665bf854f0fSBob Wilson if (S->getElse()) { 66607193cc8SJustin Bogner setCount(ElseCount); 66707193cc8SJustin Bogner CountMap[S->getElse()] = ElseCount; 668bf854f0fSBob Wilson Visit(S->getElse()); 669a909abfdSJustin Bogner OutCount += CurrentCount; 67007193cc8SJustin Bogner } else 67107193cc8SJustin Bogner OutCount += ElseCount; 67207193cc8SJustin Bogner setCount(OutCount); 673bf854f0fSBob Wilson RecordNextStmtCount = true; 674bf854f0fSBob Wilson } 675bf854f0fSBob Wilson 676bf854f0fSBob Wilson void VisitCXXTryStmt(const CXXTryStmt *S) { 677bf854f0fSBob Wilson RecordStmtCount(S); 678bf854f0fSBob Wilson Visit(S->getTryBlock()); 679bf854f0fSBob Wilson for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I) 680bf854f0fSBob Wilson Visit(S->getHandler(I)); 681d8931425SBob Wilson // Counter tracks the continuation block of the try statement. 68207193cc8SJustin Bogner setCount(PGO.getRegionCount(S)); 683bf854f0fSBob Wilson RecordNextStmtCount = true; 684bf854f0fSBob Wilson } 685bf854f0fSBob Wilson 686bf854f0fSBob Wilson void VisitCXXCatchStmt(const CXXCatchStmt *S) { 687bf854f0fSBob Wilson RecordNextStmtCount = false; 688d8931425SBob Wilson // Counter tracks the catch statement's handler block. 68907193cc8SJustin Bogner uint64_t CatchCount = setCount(PGO.getRegionCount(S)); 69007193cc8SJustin Bogner CountMap[S] = CatchCount; 691bf854f0fSBob Wilson Visit(S->getHandlerBlock()); 692bf854f0fSBob Wilson } 693bf854f0fSBob Wilson 694e4ca441aSJustin Bogner void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { 695bf854f0fSBob Wilson RecordStmtCount(E); 696a909abfdSJustin Bogner uint64_t ParentCount = CurrentCount; 697bf854f0fSBob Wilson Visit(E->getCond()); 698bf854f0fSBob Wilson 69907193cc8SJustin Bogner // Counter tracks the "true" part of a conditional operator. The 70007193cc8SJustin Bogner // count in the "false" part will be calculated from this counter. 70107193cc8SJustin Bogner uint64_t TrueCount = setCount(PGO.getRegionCount(E)); 70207193cc8SJustin Bogner CountMap[E->getTrueExpr()] = TrueCount; 703bf854f0fSBob Wilson Visit(E->getTrueExpr()); 704a909abfdSJustin Bogner uint64_t OutCount = CurrentCount; 705bf854f0fSBob Wilson 70607193cc8SJustin Bogner uint64_t FalseCount = setCount(ParentCount - TrueCount); 70707193cc8SJustin Bogner CountMap[E->getFalseExpr()] = FalseCount; 708bf854f0fSBob Wilson Visit(E->getFalseExpr()); 709a909abfdSJustin Bogner OutCount += CurrentCount; 710bf854f0fSBob Wilson 71107193cc8SJustin Bogner setCount(OutCount); 712bf854f0fSBob Wilson RecordNextStmtCount = true; 713bf854f0fSBob Wilson } 714bf854f0fSBob Wilson 715bf854f0fSBob Wilson void VisitBinLAnd(const BinaryOperator *E) { 716bf854f0fSBob Wilson RecordStmtCount(E); 717a909abfdSJustin Bogner uint64_t ParentCount = CurrentCount; 718bf854f0fSBob Wilson Visit(E->getLHS()); 71907193cc8SJustin Bogner // Counter tracks the right hand side of a logical and operator. 72007193cc8SJustin Bogner uint64_t RHSCount = setCount(PGO.getRegionCount(E)); 72107193cc8SJustin Bogner CountMap[E->getRHS()] = RHSCount; 722bf854f0fSBob Wilson Visit(E->getRHS()); 723a909abfdSJustin Bogner setCount(ParentCount + RHSCount - CurrentCount); 724bf854f0fSBob Wilson RecordNextStmtCount = true; 725bf854f0fSBob Wilson } 726bf854f0fSBob Wilson 727bf854f0fSBob Wilson void VisitBinLOr(const BinaryOperator *E) { 728bf854f0fSBob Wilson RecordStmtCount(E); 729a909abfdSJustin Bogner uint64_t ParentCount = CurrentCount; 730bf854f0fSBob Wilson Visit(E->getLHS()); 73107193cc8SJustin Bogner // Counter tracks the right hand side of a logical or operator. 73207193cc8SJustin Bogner uint64_t RHSCount = setCount(PGO.getRegionCount(E)); 73307193cc8SJustin Bogner CountMap[E->getRHS()] = RHSCount; 734bf854f0fSBob Wilson Visit(E->getRHS()); 735a909abfdSJustin Bogner setCount(ParentCount + RHSCount - CurrentCount); 736bf854f0fSBob Wilson RecordNextStmtCount = true; 737bf854f0fSBob Wilson } 738bf854f0fSBob Wilson }; 739dcfba334SHans Wennborg } // end anonymous namespace 740ef512b99SJustin Bogner 7414bc7731aSDuncan P. N. Exon Smith void PGOHash::combine(HashType Type) { 7424bc7731aSDuncan P. N. Exon Smith // Check that we never combine 0 and only have six bits. 7434bc7731aSDuncan P. N. Exon Smith assert(Type && "Hash is invalid: unexpected type 0"); 7444bc7731aSDuncan P. N. Exon Smith assert(unsigned(Type) < TooBig && "Hash is invalid: too many types"); 7454bc7731aSDuncan P. N. Exon Smith 7464bc7731aSDuncan P. N. Exon Smith // Pass through MD5 if enough work has built up. 7474bc7731aSDuncan P. N. Exon Smith if (Count && Count % NumTypesPerWord == 0) { 7484bc7731aSDuncan P. N. Exon Smith using namespace llvm::support; 7494bc7731aSDuncan P. N. Exon Smith uint64_t Swapped = endian::byte_swap<uint64_t, little>(Working); 7504bc7731aSDuncan P. N. Exon Smith MD5.update(llvm::makeArrayRef((uint8_t *)&Swapped, sizeof(Swapped))); 7514bc7731aSDuncan P. N. Exon Smith Working = 0; 7524bc7731aSDuncan P. N. Exon Smith } 7534bc7731aSDuncan P. N. Exon Smith 7544bc7731aSDuncan P. N. Exon Smith // Accumulate the current type. 7554bc7731aSDuncan P. N. Exon Smith ++Count; 7564bc7731aSDuncan P. N. Exon Smith Working = Working << NumBitsPerType | Type; 7574bc7731aSDuncan P. N. Exon Smith } 7584bc7731aSDuncan P. N. Exon Smith 7594bc7731aSDuncan P. N. Exon Smith uint64_t PGOHash::finalize() { 7604bc7731aSDuncan P. N. Exon Smith // Use Working as the hash directly if we never used MD5. 7614bc7731aSDuncan P. N. Exon Smith if (Count <= NumTypesPerWord) 7624bc7731aSDuncan P. N. Exon Smith // No need to byte swap here, since none of the math was endian-dependent. 7634bc7731aSDuncan P. N. Exon Smith // This number will be byte-swapped as required on endianness transitions, 7644bc7731aSDuncan P. N. Exon Smith // so we will see the same value on the other side. 7654bc7731aSDuncan P. N. Exon Smith return Working; 7664bc7731aSDuncan P. N. Exon Smith 7674bc7731aSDuncan P. N. Exon Smith // Check for remaining work in Working. 768de02a75eSserge-sans-paille if (Working) { 769de02a75eSserge-sans-paille // Keep the buggy behavior from v1 and v2 for backward-compatibility. This 770de02a75eSserge-sans-paille // is buggy because it converts a uint64_t into an array of uint8_t. 771de02a75eSserge-sans-paille if (HashVersion < PGO_HASH_V3) { 772de02a75eSserge-sans-paille MD5.update({(uint8_t)Working}); 773de02a75eSserge-sans-paille } else { 774de02a75eSserge-sans-paille using namespace llvm::support; 775de02a75eSserge-sans-paille uint64_t Swapped = endian::byte_swap<uint64_t, little>(Working); 776de02a75eSserge-sans-paille MD5.update(llvm::makeArrayRef((uint8_t *)&Swapped, sizeof(Swapped))); 777de02a75eSserge-sans-paille } 778de02a75eSserge-sans-paille } 7794bc7731aSDuncan P. N. Exon Smith 7804bc7731aSDuncan P. N. Exon Smith // Finalize the MD5 and return the hash. 7814bc7731aSDuncan P. N. Exon Smith llvm::MD5::MD5Result Result; 7824bc7731aSDuncan P. N. Exon Smith MD5.final(Result); 78382a0c97bSZachary Turner return Result.low(); 7844bc7731aSDuncan P. N. Exon Smith } 7854bc7731aSDuncan P. N. Exon Smith 7863a561459SSerge Pavlov void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) { 7873a561459SSerge Pavlov const Decl *D = GD.getDecl(); 78833d0a1ccSVedant Kumar if (!D->hasBody()) 78933d0a1ccSVedant Kumar return; 79033d0a1ccSVedant Kumar 791c7b683c1SMichael Liao // Skip CUDA/HIP kernel launch stub functions. 792c7b683c1SMichael Liao if (CGM.getLangOpts().CUDA && !CGM.getLangOpts().CUDAIsDevice && 793c7b683c1SMichael Liao D->hasAttr<CUDAGlobalAttr>()) 794c7b683c1SMichael Liao return; 795c7b683c1SMichael Liao 7969837ef56SRong Xu bool InstrumentRegions = CGM.getCodeGenOpts().hasProfileClangInstr(); 797837a6f6fSJustin Bogner llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader(); 798837a6f6fSJustin Bogner if (!InstrumentRegions && !PGOReader) 799ef512b99SJustin Bogner return; 8003212b18bSJustin Bogner if (D->isImplicit()) 801ef512b99SJustin Bogner return; 8023a561459SSerge Pavlov // Constructors and destructors may be represented by several functions in IR. 8033a561459SSerge Pavlov // If so, instrument only base variant, others are implemented by delegation 8043a561459SSerge Pavlov // to the base one, it would be counted twice otherwise. 8057f809b2fSVedant Kumar if (CGM.getTarget().getCXXABI().hasConstructorVariants()) { 8067f809b2fSVedant Kumar if (const auto *CCD = dyn_cast<CXXConstructorDecl>(D)) 8077f809b2fSVedant Kumar if (GD.getCtorType() != Ctor_Base && 8087f809b2fSVedant Kumar CodeGenFunction::IsConstructorDelegationValid(CCD)) 8093a561459SSerge Pavlov return; 8103a561459SSerge Pavlov } 811f9ef9f86SReid Kleckner if (isa<CXXDestructorDecl>(D) && GD.getDtorType() != Dtor_Base) 812f9ef9f86SReid Kleckner return; 813f9ef9f86SReid Kleckner 814*bb9eb198SPetr Hosek if (Fn->hasFnAttribute(llvm::Attribute::NoProfile)) 815*bb9eb198SPetr Hosek return; 816*bb9eb198SPetr Hosek 817ee02499aSAlex Lorenz CGM.ClearUnusedCoverageMapping(D); 818da1ebedeSBob Wilson setFuncName(Fn); 8197c41451bSDuncan P. N. Exon Smith 820ef512b99SJustin Bogner mapRegionCounters(D); 821ee02499aSAlex Lorenz if (CGM.getCodeGenOpts().CoverageMapping) 822ee02499aSAlex Lorenz emitCounterRegionMapping(D); 823837a6f6fSJustin Bogner if (PGOReader) { 82440b8ba14SJustin Bogner SourceManager &SM = CGM.getContext().getSourceManager(); 82540b8ba14SJustin Bogner loadRegionCounts(PGOReader, SM.isInMainFile(D->getLocation())); 826bf854f0fSBob Wilson computeRegionCounts(D); 827837a6f6fSJustin Bogner applyFunctionAttributes(PGOReader, Fn); 828bf854f0fSBob Wilson } 829ef512b99SJustin Bogner } 830ef512b99SJustin Bogner 831ef512b99SJustin Bogner void CodeGenPGO::mapRegionCounters(const Decl *D) { 8326186971aSVedant Kumar // Use the latest hash version when inserting instrumentation, but use the 8336186971aSVedant Kumar // version in the indexed profile if we're reading PGO data. 8346186971aSVedant Kumar PGOHashVersion HashVersion = PGO_HASH_LATEST; 8359f2967bcSAlan Phipps uint64_t ProfileVersion = llvm::IndexedInstrProf::Version; 8369f2967bcSAlan Phipps if (auto *PGOReader = CGM.getPGOReader()) { 8376186971aSVedant Kumar HashVersion = getPGOHashVersion(PGOReader, CGM); 8389f2967bcSAlan Phipps ProfileVersion = PGOReader->getVersion(); 8399f2967bcSAlan Phipps } 8406186971aSVedant Kumar 8411b67cfd4SDuncan P. N. Exon Smith RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>); 8429f2967bcSAlan Phipps MapRegionCounters Walker(HashVersion, ProfileVersion, *RegionCounterMap); 843ef512b99SJustin Bogner if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) 844d8931425SBob Wilson Walker.TraverseDecl(const_cast<FunctionDecl *>(FD)); 8455ec8fe19SBob Wilson else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D)) 846d8931425SBob Wilson Walker.TraverseDecl(const_cast<ObjCMethodDecl *>(MD)); 847c845c00aSBob Wilson else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D)) 848d8931425SBob Wilson Walker.TraverseDecl(const_cast<BlockDecl *>(BD)); 84981ab90f7SJustin Bogner else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D)) 85081ab90f7SJustin Bogner Walker.TraverseDecl(const_cast<CapturedDecl *>(CD)); 8513212b18bSJustin Bogner assert(Walker.NextCounter > 0 && "no entry counter mapped for decl"); 852ef512b99SJustin Bogner NumRegionCounters = Walker.NextCounter; 8534bc7731aSDuncan P. N. Exon Smith FunctionHash = Walker.Hash.finalize(); 854ef512b99SJustin Bogner } 855ef512b99SJustin Bogner 856c468bb8bSVedant Kumar bool CodeGenPGO::skipRegionMappingForDecl(const Decl *D) { 857bc370f0cSVedant Kumar if (!D->getBody()) 858bc370f0cSVedant Kumar return true; 859bc370f0cSVedant Kumar 860c7b683c1SMichael Liao // Skip host-only functions in the CUDA device compilation and device-only 861c7b683c1SMichael Liao // functions in the host compilation. Just roughly filter them out based on 862c7b683c1SMichael Liao // the function attributes. If there are effectively host-only or device-only 863c7b683c1SMichael Liao // ones, their coverage mapping may still be generated. 864c7b683c1SMichael Liao if (CGM.getLangOpts().CUDA && 865c7b683c1SMichael Liao ((CGM.getLangOpts().CUDAIsDevice && !D->hasAttr<CUDADeviceAttr>() && 866c7b683c1SMichael Liao !D->hasAttr<CUDAGlobalAttr>()) || 867c7b683c1SMichael Liao (!CGM.getLangOpts().CUDAIsDevice && 868c7b683c1SMichael Liao (D->hasAttr<CUDAGlobalAttr>() || 869c7b683c1SMichael Liao (!D->hasAttr<CUDAHostAttr>() && D->hasAttr<CUDADeviceAttr>()))))) 870c7b683c1SMichael Liao return true; 871c7b683c1SMichael Liao 872c468bb8bSVedant Kumar // Don't map the functions in system headers. 873c468bb8bSVedant Kumar const auto &SM = CGM.getContext().getSourceManager(); 874f2ceec48SStephen Kelly auto Loc = D->getBody()->getBeginLoc(); 875c468bb8bSVedant Kumar return SM.isInSystemHeader(Loc); 876c468bb8bSVedant Kumar } 877c468bb8bSVedant Kumar 878c468bb8bSVedant Kumar void CodeGenPGO::emitCounterRegionMapping(const Decl *D) { 879c468bb8bSVedant Kumar if (skipRegionMappingForDecl(D)) 880ee02499aSAlex Lorenz return; 881ee02499aSAlex Lorenz 882970ac605SJustin Bogner std::string CoverageMapping; 883ee02499aSAlex Lorenz llvm::raw_string_ostream OS(CoverageMapping); 884ee02499aSAlex Lorenz CoverageMappingGen MappingGen(*CGM.getCoverageMapping(), 885ee02499aSAlex Lorenz CGM.getContext().getSourceManager(), 886e5ee6c58SJustin Bogner CGM.getLangOpts(), RegionCounterMap.get()); 887ee02499aSAlex Lorenz MappingGen.emitCounterMapping(D, OS); 888ee02499aSAlex Lorenz OS.flush(); 889970ac605SJustin Bogner 890970ac605SJustin Bogner if (CoverageMapping.empty()) 891970ac605SJustin Bogner return; 892970ac605SJustin Bogner 893970ac605SJustin Bogner CGM.getCoverageMapping()->addFunctionMappingRecord( 894970ac605SJustin Bogner FuncNameVar, FuncName, FunctionHash, CoverageMapping); 895ee02499aSAlex Lorenz } 896ee02499aSAlex Lorenz 897ee02499aSAlex Lorenz void 89860d852baSJustin Bogner CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef Name, 899ee02499aSAlex Lorenz llvm::GlobalValue::LinkageTypes Linkage) { 900c468bb8bSVedant Kumar if (skipRegionMappingForDecl(D)) 901ee02499aSAlex Lorenz return; 902ee02499aSAlex Lorenz 903970ac605SJustin Bogner std::string CoverageMapping; 904ee02499aSAlex Lorenz llvm::raw_string_ostream OS(CoverageMapping); 905ee02499aSAlex Lorenz CoverageMappingGen MappingGen(*CGM.getCoverageMapping(), 906ee02499aSAlex Lorenz CGM.getContext().getSourceManager(), 907ee02499aSAlex Lorenz CGM.getLangOpts()); 908ee02499aSAlex Lorenz MappingGen.emitEmptyMapping(D, OS); 909ee02499aSAlex Lorenz OS.flush(); 910970ac605SJustin Bogner 911970ac605SJustin Bogner if (CoverageMapping.empty()) 912970ac605SJustin Bogner return; 913970ac605SJustin Bogner 91460d852baSJustin Bogner setFuncName(Name, Linkage); 915970ac605SJustin Bogner CGM.getCoverageMapping()->addFunctionMappingRecord( 9162129ae53SXinliang David Li FuncNameVar, FuncName, FunctionHash, CoverageMapping, false); 917ee02499aSAlex Lorenz } 918ee02499aSAlex Lorenz 919bf854f0fSBob Wilson void CodeGenPGO::computeRegionCounts(const Decl *D) { 9201b67cfd4SDuncan P. N. Exon Smith StmtCountMap.reset(new llvm::DenseMap<const Stmt *, uint64_t>); 9213586be72SDuncan P. N. Exon Smith ComputeRegionCounts Walker(*StmtCountMap, *this); 922bf854f0fSBob Wilson if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) 923bf854f0fSBob Wilson Walker.VisitFunctionDecl(FD); 9245ec8fe19SBob Wilson else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D)) 9255ec8fe19SBob Wilson Walker.VisitObjCMethodDecl(MD); 926c845c00aSBob Wilson else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D)) 927c845c00aSBob Wilson Walker.VisitBlockDecl(BD); 92881ab90f7SJustin Bogner else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D)) 92981ab90f7SJustin Bogner Walker.VisitCapturedDecl(const_cast<CapturedDecl *>(CD)); 930bf854f0fSBob Wilson } 931bf854f0fSBob Wilson 932837a6f6fSJustin Bogner void 933837a6f6fSJustin Bogner CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader, 9344c9c45c0SJustin Bogner llvm::Function *Fn) { 9354c9c45c0SJustin Bogner if (!haveRegionCounts()) 9364c9c45c0SJustin Bogner return; 9374c9c45c0SJustin Bogner 938dcfba334SHans Wennborg uint64_t FunctionCount = getRegionCount(nullptr); 939aa8b1cb8SDiego Novillo Fn->setEntryCount(FunctionCount); 9404c9c45c0SJustin Bogner } 9414c9c45c0SJustin Bogner 942502bbfafSVedant Kumar void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S, 943502bbfafSVedant Kumar llvm::Value *StepV) { 9449837ef56SRong Xu if (!CGM.getCodeGenOpts().hasProfileClangInstr() || !RegionCounterMap) 945ef512b99SJustin Bogner return; 9469f5260abSDuncan P. N. Exon Smith if (!Builder.GetInsertBlock()) 947203f91e3SJustin Bogner return; 94866242d6cSJustin Bogner 94966242d6cSJustin Bogner unsigned Counter = (*RegionCounterMap)[S]; 950970ac605SJustin Bogner auto *I8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); 951502bbfafSVedant Kumar 952502bbfafSVedant Kumar llvm::Value *Args[] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy), 953a45f315eSVedant Kumar Builder.getInt64(FunctionHash), 954a45f315eSVedant Kumar Builder.getInt32(NumRegionCounters), 955502bbfafSVedant Kumar Builder.getInt32(Counter), StepV}; 956502bbfafSVedant Kumar if (!StepV) 957502bbfafSVedant Kumar Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment), 958502bbfafSVedant Kumar makeArrayRef(Args, 4)); 959502bbfafSVedant Kumar else 960502bbfafSVedant Kumar Builder.CreateCall( 961502bbfafSVedant Kumar CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment_step), 962502bbfafSVedant Kumar makeArrayRef(Args)); 963ef512b99SJustin Bogner } 964ef512b99SJustin Bogner 965518276a5SBetul Buyukkurt // This method either inserts a call to the profile run-time during 966518276a5SBetul Buyukkurt // instrumentation or puts profile data into metadata for PGO use. 967518276a5SBetul Buyukkurt void CodeGenPGO::valueProfile(CGBuilderTy &Builder, uint32_t ValueKind, 968518276a5SBetul Buyukkurt llvm::Instruction *ValueSite, llvm::Value *ValuePtr) { 969518276a5SBetul Buyukkurt 970518276a5SBetul Buyukkurt if (!EnableValueProfiling) 971518276a5SBetul Buyukkurt return; 972518276a5SBetul Buyukkurt 973518276a5SBetul Buyukkurt if (!ValuePtr || !ValueSite || !Builder.GetInsertBlock()) 974518276a5SBetul Buyukkurt return; 975518276a5SBetul Buyukkurt 9763da993c4SBetul Buyukkurt if (isa<llvm::Constant>(ValuePtr)) 9773da993c4SBetul Buyukkurt return; 9783da993c4SBetul Buyukkurt 9799837ef56SRong Xu bool InstrumentValueSites = CGM.getCodeGenOpts().hasProfileClangInstr(); 980518276a5SBetul Buyukkurt if (InstrumentValueSites && RegionCounterMap) { 981cb6f5f16SBetul Buyukkurt auto BuilderInsertPoint = Builder.saveIP(); 982cb6f5f16SBetul Buyukkurt Builder.SetInsertPoint(ValueSite); 983518276a5SBetul Buyukkurt llvm::Value *Args[5] = { 984cb6f5f16SBetul Buyukkurt llvm::ConstantExpr::getBitCast(FuncNameVar, Builder.getInt8PtrTy()), 985518276a5SBetul Buyukkurt Builder.getInt64(FunctionHash), 986518276a5SBetul Buyukkurt Builder.CreatePtrToInt(ValuePtr, Builder.getInt64Ty()), 987518276a5SBetul Buyukkurt Builder.getInt32(ValueKind), 988518276a5SBetul Buyukkurt Builder.getInt32(NumValueSites[ValueKind]++) 989518276a5SBetul Buyukkurt }; 990518276a5SBetul Buyukkurt Builder.CreateCall( 991518276a5SBetul Buyukkurt CGM.getIntrinsic(llvm::Intrinsic::instrprof_value_profile), Args); 992cb6f5f16SBetul Buyukkurt Builder.restoreIP(BuilderInsertPoint); 993518276a5SBetul Buyukkurt return; 994518276a5SBetul Buyukkurt } 995518276a5SBetul Buyukkurt 996518276a5SBetul Buyukkurt llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader(); 997518276a5SBetul Buyukkurt if (PGOReader && haveRegionCounts()) { 998518276a5SBetul Buyukkurt // We record the top most called three functions at each call site. 999518276a5SBetul Buyukkurt // Profile metadata contains "VP" string identifying this metadata 1000518276a5SBetul Buyukkurt // as value profiling data, then a uint32_t value for the value profiling 1001518276a5SBetul Buyukkurt // kind, a uint64_t value for the total number of times the call is 1002518276a5SBetul Buyukkurt // executed, followed by the function hash and execution count (uint64_t) 1003518276a5SBetul Buyukkurt // pairs for each function. 1004518276a5SBetul Buyukkurt if (NumValueSites[ValueKind] >= ProfRecord->getNumValueSites(ValueKind)) 1005518276a5SBetul Buyukkurt return; 10065527a9ddSXinliang David Li 10075527a9ddSXinliang David Li llvm::annotateValueSite(CGM.getModule(), *ValueSite, *ProfRecord, 10085527a9ddSXinliang David Li (llvm::InstrProfValueKind)ValueKind, 1009518276a5SBetul Buyukkurt NumValueSites[ValueKind]); 1010518276a5SBetul Buyukkurt 1011518276a5SBetul Buyukkurt NumValueSites[ValueKind]++; 1012518276a5SBetul Buyukkurt } 1013518276a5SBetul Buyukkurt } 1014518276a5SBetul Buyukkurt 101540b8ba14SJustin Bogner void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader, 101640b8ba14SJustin Bogner bool IsInMainFile) { 101740b8ba14SJustin Bogner CGM.getPGOStats().addVisited(IsInMainFile); 10187f8cf5bfSJustin Bogner RegionCounts.clear(); 1019fa2d5955SVedant Kumar llvm::Expected<llvm::InstrProfRecord> RecordExpected = 1020518276a5SBetul Buyukkurt PGOReader->getInstrProfRecord(FuncName, FunctionHash); 1021fa2d5955SVedant Kumar if (auto E = RecordExpected.takeError()) { 1022fa2d5955SVedant Kumar auto IPE = llvm::InstrProfError::take(std::move(E)); 1023fa2d5955SVedant Kumar if (IPE == llvm::instrprof_error::unknown_function) 102440b8ba14SJustin Bogner CGM.getPGOStats().addMissing(IsInMainFile); 1025fa2d5955SVedant Kumar else if (IPE == llvm::instrprof_error::hash_mismatch) 10269c6818efSJustin Bogner CGM.getPGOStats().addMismatched(IsInMainFile); 1027fa2d5955SVedant Kumar else if (IPE == llvm::instrprof_error::malformed) 10289c6818efSJustin Bogner // TODO: Consider a more specific warning for this case. 102940b8ba14SJustin Bogner CGM.getPGOStats().addMismatched(IsInMainFile); 1030518276a5SBetul Buyukkurt return; 1031e2ef2a09SJustin Bogner } 1032518276a5SBetul Buyukkurt ProfRecord = 10332b3d49b6SJonas Devlieghere std::make_unique<llvm::InstrProfRecord>(std::move(RecordExpected.get())); 1034518276a5SBetul Buyukkurt RegionCounts = ProfRecord->Counts; 1035ef512b99SJustin Bogner } 1036ef512b99SJustin Bogner 10375c31b8b9SArthur Eubanks /// Calculate what to divide by to scale weights. 10385c31b8b9SArthur Eubanks /// 10395c31b8b9SArthur Eubanks /// Given the maximum weight, calculate a divisor that will scale all the 10405c31b8b9SArthur Eubanks /// weights to strictly less than UINT32_MAX. 10415c31b8b9SArthur Eubanks static uint64_t calculateWeightScale(uint64_t MaxWeight) { 10425c31b8b9SArthur Eubanks return MaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1; 10435c31b8b9SArthur Eubanks } 10445c31b8b9SArthur Eubanks 10455c31b8b9SArthur Eubanks /// Scale an individual branch weight (and add 1). 10465c31b8b9SArthur Eubanks /// 10475c31b8b9SArthur Eubanks /// Scale a 64-bit weight down to 32-bits using \c Scale. 104838402dc9SDuncan P. N. Exon Smith /// 104938402dc9SDuncan P. N. Exon Smith /// According to Laplace's Rule of Succession, it is better to compute the 105038402dc9SDuncan P. N. Exon Smith /// weight based on the count plus 1, so universally add 1 to the value. 10515c31b8b9SArthur Eubanks /// 10525c31b8b9SArthur Eubanks /// \pre \c Scale was calculated by \a calculateWeightScale() with a weight no 10535c31b8b9SArthur Eubanks /// greater than \c Weight. 10545c31b8b9SArthur Eubanks static uint32_t scaleBranchWeight(uint64_t Weight, uint64_t Scale) { 10555c31b8b9SArthur Eubanks assert(Scale && "scale by 0?"); 10565c31b8b9SArthur Eubanks uint64_t Scaled = Weight / Scale + 1; 10575c31b8b9SArthur Eubanks assert(Scaled <= UINT32_MAX && "overflow 32-bits"); 10585c31b8b9SArthur Eubanks return Scaled; 10595c31b8b9SArthur Eubanks } 106038402dc9SDuncan P. N. Exon Smith 106165512647SJustin Bogner llvm::MDNode *CodeGenFunction::createProfileWeights(uint64_t TrueCount, 1062389c8d5bSMark de Wever uint64_t FalseCount) const { 106338402dc9SDuncan P. N. Exon Smith // Check for empty weights. 1064ef512b99SJustin Bogner if (!TrueCount && !FalseCount) 1065a5f804a7SDuncan P. N. Exon Smith return nullptr; 1066ef512b99SJustin Bogner 10675c31b8b9SArthur Eubanks // Calculate how to scale down to 32-bits. 10685c31b8b9SArthur Eubanks uint64_t Scale = calculateWeightScale(std::max(TrueCount, FalseCount)); 10695c31b8b9SArthur Eubanks 1070ef512b99SJustin Bogner llvm::MDBuilder MDHelper(CGM.getLLVMContext()); 10715c31b8b9SArthur Eubanks return MDHelper.createBranchWeights(scaleBranchWeight(TrueCount, Scale), 10725c31b8b9SArthur Eubanks scaleBranchWeight(FalseCount, Scale)); 1073ef512b99SJustin Bogner } 1074ef512b99SJustin Bogner 107565512647SJustin Bogner llvm::MDNode * 1076389c8d5bSMark de Wever CodeGenFunction::createProfileWeights(ArrayRef<uint64_t> Weights) const { 107738402dc9SDuncan P. N. Exon Smith // We need at least two elements to create meaningful weights. 107838402dc9SDuncan P. N. Exon Smith if (Weights.size() < 2) 1079a5f804a7SDuncan P. N. Exon Smith return nullptr; 108038402dc9SDuncan P. N. Exon Smith 1081f3aefca7SJustin Bogner // Check for empty weights. 1082f3aefca7SJustin Bogner uint64_t MaxWeight = *std::max_element(Weights.begin(), Weights.end()); 1083f3aefca7SJustin Bogner if (MaxWeight == 0) 1084f3aefca7SJustin Bogner return nullptr; 1085f3aefca7SJustin Bogner 10865c31b8b9SArthur Eubanks // Calculate how to scale down to 32-bits. 10875c31b8b9SArthur Eubanks uint64_t Scale = calculateWeightScale(MaxWeight); 10885c31b8b9SArthur Eubanks 10895c31b8b9SArthur Eubanks SmallVector<uint32_t, 16> ScaledWeights; 1090ef512b99SJustin Bogner ScaledWeights.reserve(Weights.size()); 109138402dc9SDuncan P. N. Exon Smith for (uint64_t W : Weights) 10925c31b8b9SArthur Eubanks ScaledWeights.push_back(scaleBranchWeight(W, Scale)); 109338402dc9SDuncan P. N. Exon Smith 109438402dc9SDuncan P. N. Exon Smith llvm::MDBuilder MDHelper(CGM.getLLVMContext()); 1095ef512b99SJustin Bogner return MDHelper.createBranchWeights(ScaledWeights); 1096ef512b99SJustin Bogner } 1097bf854f0fSBob Wilson 1098389c8d5bSMark de Wever llvm::MDNode * 1099389c8d5bSMark de Wever CodeGenFunction::createProfileWeightsForLoop(const Stmt *Cond, 1100389c8d5bSMark de Wever uint64_t LoopCount) const { 110165512647SJustin Bogner if (!PGO.haveRegionCounts()) 1102a5f804a7SDuncan P. N. Exon Smith return nullptr; 110365512647SJustin Bogner Optional<uint64_t> CondCount = PGO.getStmtCount(Cond); 110455b9b11fSHans Wennborg if (!CondCount || *CondCount == 0) 1105a5f804a7SDuncan P. N. Exon Smith return nullptr; 110665512647SJustin Bogner return createProfileWeights(LoopCount, 11071c21c28bSJustin Bogner std::max(*CondCount, LoopCount) - LoopCount); 1108bf854f0fSBob Wilson } 1109