10b57cec5SDimitry Andric //===--- CodeGenPGO.cpp - PGO Instrumentation for LLVM CodeGen --*- C++ -*-===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric // 90b57cec5SDimitry Andric // Instrumentation-based profile-guided optimization 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #include "CodeGenPGO.h" 140b57cec5SDimitry Andric #include "CodeGenFunction.h" 150b57cec5SDimitry Andric #include "CoverageMappingGen.h" 160b57cec5SDimitry Andric #include "clang/AST/RecursiveASTVisitor.h" 170b57cec5SDimitry Andric #include "clang/AST/StmtVisitor.h" 180b57cec5SDimitry Andric #include "llvm/IR/Intrinsics.h" 190b57cec5SDimitry Andric #include "llvm/IR/MDBuilder.h" 20480093f4SDimitry Andric #include "llvm/Support/CommandLine.h" 210b57cec5SDimitry Andric #include "llvm/Support/Endian.h" 220b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h" 230b57cec5SDimitry Andric #include "llvm/Support/MD5.h" 24bdd1243dSDimitry Andric #include <optional> 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric static llvm::cl::opt<bool> 2781ad6265SDimitry Andric EnableValueProfiling("enable-value-profiling", 280b57cec5SDimitry Andric llvm::cl::desc("Enable value profiling"), 290b57cec5SDimitry Andric llvm::cl::Hidden, llvm::cl::init(false)); 300b57cec5SDimitry Andric 310b57cec5SDimitry Andric using namespace clang; 320b57cec5SDimitry Andric using namespace CodeGen; 330b57cec5SDimitry Andric 340b57cec5SDimitry Andric void CodeGenPGO::setFuncName(StringRef Name, 350b57cec5SDimitry Andric llvm::GlobalValue::LinkageTypes Linkage) { 360b57cec5SDimitry Andric llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader(); 370b57cec5SDimitry Andric FuncName = llvm::getPGOFuncName( 380b57cec5SDimitry Andric Name, Linkage, CGM.getCodeGenOpts().MainFileName, 390b57cec5SDimitry Andric PGOReader ? PGOReader->getVersion() : llvm::IndexedInstrProf::Version); 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric // If we're generating a profile, create a variable for the name. 420b57cec5SDimitry Andric if (CGM.getCodeGenOpts().hasProfileClangInstr()) 430b57cec5SDimitry Andric FuncNameVar = llvm::createPGOFuncNameVar(CGM.getModule(), Linkage, FuncName); 440b57cec5SDimitry Andric } 450b57cec5SDimitry Andric 460b57cec5SDimitry Andric void CodeGenPGO::setFuncName(llvm::Function *Fn) { 470b57cec5SDimitry Andric setFuncName(Fn->getName(), Fn->getLinkage()); 480b57cec5SDimitry Andric // Create PGOFuncName meta data. 490b57cec5SDimitry Andric llvm::createPGOFuncNameMetadata(*Fn, FuncName); 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric /// The version of the PGO hash algorithm. 530b57cec5SDimitry Andric enum PGOHashVersion : unsigned { 540b57cec5SDimitry Andric PGO_HASH_V1, 550b57cec5SDimitry Andric PGO_HASH_V2, 565ffd83dbSDimitry Andric PGO_HASH_V3, 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric // Keep this set to the latest hash version. 595ffd83dbSDimitry Andric PGO_HASH_LATEST = PGO_HASH_V3 600b57cec5SDimitry Andric }; 610b57cec5SDimitry Andric 620b57cec5SDimitry Andric namespace { 630b57cec5SDimitry Andric /// Stable hasher for PGO region counters. 640b57cec5SDimitry Andric /// 650b57cec5SDimitry Andric /// PGOHash produces a stable hash of a given function's control flow. 660b57cec5SDimitry Andric /// 670b57cec5SDimitry Andric /// Changing the output of this hash will invalidate all previously generated 680b57cec5SDimitry Andric /// profiles -- i.e., don't do it. 690b57cec5SDimitry Andric /// 700b57cec5SDimitry Andric /// \note When this hash does eventually change (years?), we still need to 710b57cec5SDimitry Andric /// support old hashes. We'll need to pull in the version number from the 720b57cec5SDimitry Andric /// profile data format and use the matching hash function. 730b57cec5SDimitry Andric class PGOHash { 740b57cec5SDimitry Andric uint64_t Working; 750b57cec5SDimitry Andric unsigned Count; 760b57cec5SDimitry Andric PGOHashVersion HashVersion; 770b57cec5SDimitry Andric llvm::MD5 MD5; 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric static const int NumBitsPerType = 6; 800b57cec5SDimitry Andric static const unsigned NumTypesPerWord = sizeof(uint64_t) * 8 / NumBitsPerType; 810b57cec5SDimitry Andric static const unsigned TooBig = 1u << NumBitsPerType; 820b57cec5SDimitry Andric 830b57cec5SDimitry Andric public: 840b57cec5SDimitry Andric /// Hash values for AST nodes. 850b57cec5SDimitry Andric /// 860b57cec5SDimitry Andric /// Distinct values for AST nodes that have region counters attached. 870b57cec5SDimitry Andric /// 880b57cec5SDimitry Andric /// These values must be stable. All new members must be added at the end, 890b57cec5SDimitry Andric /// and no members should be removed. Changing the enumeration value for an 900b57cec5SDimitry Andric /// AST node will affect the hash of every function that contains that node. 910b57cec5SDimitry Andric enum HashType : unsigned char { 920b57cec5SDimitry Andric None = 0, 930b57cec5SDimitry Andric LabelStmt = 1, 940b57cec5SDimitry Andric WhileStmt, 950b57cec5SDimitry Andric DoStmt, 960b57cec5SDimitry Andric ForStmt, 970b57cec5SDimitry Andric CXXForRangeStmt, 980b57cec5SDimitry Andric ObjCForCollectionStmt, 990b57cec5SDimitry Andric SwitchStmt, 1000b57cec5SDimitry Andric CaseStmt, 1010b57cec5SDimitry Andric DefaultStmt, 1020b57cec5SDimitry Andric IfStmt, 1030b57cec5SDimitry Andric CXXTryStmt, 1040b57cec5SDimitry Andric CXXCatchStmt, 1050b57cec5SDimitry Andric ConditionalOperator, 1060b57cec5SDimitry Andric BinaryOperatorLAnd, 1070b57cec5SDimitry Andric BinaryOperatorLOr, 1080b57cec5SDimitry Andric BinaryConditionalOperator, 1090b57cec5SDimitry Andric // The preceding values are available with PGO_HASH_V1. 1100b57cec5SDimitry Andric 1110b57cec5SDimitry Andric EndOfScope, 1120b57cec5SDimitry Andric IfThenBranch, 1130b57cec5SDimitry Andric IfElseBranch, 1140b57cec5SDimitry Andric GotoStmt, 1150b57cec5SDimitry Andric IndirectGotoStmt, 1160b57cec5SDimitry Andric BreakStmt, 1170b57cec5SDimitry Andric ContinueStmt, 1180b57cec5SDimitry Andric ReturnStmt, 1190b57cec5SDimitry Andric ThrowExpr, 1200b57cec5SDimitry Andric UnaryOperatorLNot, 1210b57cec5SDimitry Andric BinaryOperatorLT, 1220b57cec5SDimitry Andric BinaryOperatorGT, 1230b57cec5SDimitry Andric BinaryOperatorLE, 1240b57cec5SDimitry Andric BinaryOperatorGE, 1250b57cec5SDimitry Andric BinaryOperatorEQ, 1260b57cec5SDimitry Andric BinaryOperatorNE, 1275ffd83dbSDimitry Andric // The preceding values are available since PGO_HASH_V2. 1280b57cec5SDimitry Andric 1290b57cec5SDimitry Andric // Keep this last. It's for the static assert that follows. 1300b57cec5SDimitry Andric LastHashType 1310b57cec5SDimitry Andric }; 1320b57cec5SDimitry Andric static_assert(LastHashType <= TooBig, "Too many types in HashType"); 1330b57cec5SDimitry Andric 1340b57cec5SDimitry Andric PGOHash(PGOHashVersion HashVersion) 13504eeddc0SDimitry Andric : Working(0), Count(0), HashVersion(HashVersion) {} 1360b57cec5SDimitry Andric void combine(HashType Type); 1370b57cec5SDimitry Andric uint64_t finalize(); 1380b57cec5SDimitry Andric PGOHashVersion getHashVersion() const { return HashVersion; } 1390b57cec5SDimitry Andric }; 1400b57cec5SDimitry Andric const int PGOHash::NumBitsPerType; 1410b57cec5SDimitry Andric const unsigned PGOHash::NumTypesPerWord; 1420b57cec5SDimitry Andric const unsigned PGOHash::TooBig; 1430b57cec5SDimitry Andric 1440b57cec5SDimitry Andric /// Get the PGO hash version used in the given indexed profile. 1450b57cec5SDimitry Andric static PGOHashVersion getPGOHashVersion(llvm::IndexedInstrProfReader *PGOReader, 1460b57cec5SDimitry Andric CodeGenModule &CGM) { 1470b57cec5SDimitry Andric if (PGOReader->getVersion() <= 4) 1480b57cec5SDimitry Andric return PGO_HASH_V1; 1495ffd83dbSDimitry Andric if (PGOReader->getVersion() <= 5) 1500b57cec5SDimitry Andric return PGO_HASH_V2; 1515ffd83dbSDimitry Andric return PGO_HASH_V3; 1520b57cec5SDimitry Andric } 1530b57cec5SDimitry Andric 1540b57cec5SDimitry Andric /// A RecursiveASTVisitor that fills a map of statements to PGO counters. 1550b57cec5SDimitry Andric struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> { 1560b57cec5SDimitry Andric using Base = RecursiveASTVisitor<MapRegionCounters>; 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric /// The next counter value to assign. 1590b57cec5SDimitry Andric unsigned NextCounter; 1600b57cec5SDimitry Andric /// The function hash. 1610b57cec5SDimitry Andric PGOHash Hash; 1620b57cec5SDimitry Andric /// The map of statements to counters. 1630b57cec5SDimitry Andric llvm::DenseMap<const Stmt *, unsigned> &CounterMap; 164e8d8bef9SDimitry Andric /// The profile version. 165e8d8bef9SDimitry Andric uint64_t ProfileVersion; 1660b57cec5SDimitry Andric 167e8d8bef9SDimitry Andric MapRegionCounters(PGOHashVersion HashVersion, uint64_t ProfileVersion, 1680b57cec5SDimitry Andric llvm::DenseMap<const Stmt *, unsigned> &CounterMap) 169e8d8bef9SDimitry Andric : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap), 170e8d8bef9SDimitry Andric ProfileVersion(ProfileVersion) {} 1710b57cec5SDimitry Andric 1720b57cec5SDimitry Andric // Blocks and lambdas are handled as separate functions, so we need not 1730b57cec5SDimitry Andric // traverse them in the parent context. 1740b57cec5SDimitry Andric bool TraverseBlockExpr(BlockExpr *BE) { return true; } 1750b57cec5SDimitry Andric bool TraverseLambdaExpr(LambdaExpr *LE) { 1760b57cec5SDimitry Andric // Traverse the captures, but not the body. 177480093f4SDimitry Andric for (auto C : zip(LE->captures(), LE->capture_inits())) 1780b57cec5SDimitry Andric TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C)); 1790b57cec5SDimitry Andric return true; 1800b57cec5SDimitry Andric } 1810b57cec5SDimitry Andric bool TraverseCapturedStmt(CapturedStmt *CS) { return true; } 1820b57cec5SDimitry Andric 1830b57cec5SDimitry Andric bool VisitDecl(const Decl *D) { 1840b57cec5SDimitry Andric switch (D->getKind()) { 1850b57cec5SDimitry Andric default: 1860b57cec5SDimitry Andric break; 1870b57cec5SDimitry Andric case Decl::Function: 1880b57cec5SDimitry Andric case Decl::CXXMethod: 1890b57cec5SDimitry Andric case Decl::CXXConstructor: 1900b57cec5SDimitry Andric case Decl::CXXDestructor: 1910b57cec5SDimitry Andric case Decl::CXXConversion: 1920b57cec5SDimitry Andric case Decl::ObjCMethod: 1930b57cec5SDimitry Andric case Decl::Block: 1940b57cec5SDimitry Andric case Decl::Captured: 1950b57cec5SDimitry Andric CounterMap[D->getBody()] = NextCounter++; 1960b57cec5SDimitry Andric break; 1970b57cec5SDimitry Andric } 1980b57cec5SDimitry Andric return true; 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric /// If \p S gets a fresh counter, update the counter mappings. Return the 2020b57cec5SDimitry Andric /// V1 hash of \p S. 2030b57cec5SDimitry Andric PGOHash::HashType updateCounterMappings(Stmt *S) { 2040b57cec5SDimitry Andric auto Type = getHashType(PGO_HASH_V1, S); 2050b57cec5SDimitry Andric if (Type != PGOHash::None) 2060b57cec5SDimitry Andric CounterMap[S] = NextCounter++; 2070b57cec5SDimitry Andric return Type; 2080b57cec5SDimitry Andric } 2090b57cec5SDimitry Andric 210e8d8bef9SDimitry Andric /// The RHS of all logical operators gets a fresh counter in order to count 211e8d8bef9SDimitry Andric /// how many times the RHS evaluates to true or false, depending on the 212e8d8bef9SDimitry Andric /// semantics of the operator. This is only valid for ">= v7" of the profile 213e8d8bef9SDimitry Andric /// version so that we facilitate backward compatibility. 214e8d8bef9SDimitry Andric bool VisitBinaryOperator(BinaryOperator *S) { 215e8d8bef9SDimitry Andric if (ProfileVersion >= llvm::IndexedInstrProf::Version7) 216e8d8bef9SDimitry Andric if (S->isLogicalOp() && 217e8d8bef9SDimitry Andric CodeGenFunction::isInstrumentedCondition(S->getRHS())) 218e8d8bef9SDimitry Andric CounterMap[S->getRHS()] = NextCounter++; 219e8d8bef9SDimitry Andric return Base::VisitBinaryOperator(S); 220e8d8bef9SDimitry Andric } 221e8d8bef9SDimitry Andric 2220b57cec5SDimitry Andric /// Include \p S in the function hash. 2230b57cec5SDimitry Andric bool VisitStmt(Stmt *S) { 2240b57cec5SDimitry Andric auto Type = updateCounterMappings(S); 2250b57cec5SDimitry Andric if (Hash.getHashVersion() != PGO_HASH_V1) 2260b57cec5SDimitry Andric Type = getHashType(Hash.getHashVersion(), S); 2270b57cec5SDimitry Andric if (Type != PGOHash::None) 2280b57cec5SDimitry Andric Hash.combine(Type); 2290b57cec5SDimitry Andric return true; 2300b57cec5SDimitry Andric } 2310b57cec5SDimitry Andric 2320b57cec5SDimitry Andric bool TraverseIfStmt(IfStmt *If) { 2330b57cec5SDimitry Andric // If we used the V1 hash, use the default traversal. 2340b57cec5SDimitry Andric if (Hash.getHashVersion() == PGO_HASH_V1) 2350b57cec5SDimitry Andric return Base::TraverseIfStmt(If); 2360b57cec5SDimitry Andric 2370b57cec5SDimitry Andric // Otherwise, keep track of which branch we're in while traversing. 2380b57cec5SDimitry Andric VisitStmt(If); 2390b57cec5SDimitry Andric for (Stmt *CS : If->children()) { 2400b57cec5SDimitry Andric if (!CS) 2410b57cec5SDimitry Andric continue; 2420b57cec5SDimitry Andric if (CS == If->getThen()) 2430b57cec5SDimitry Andric Hash.combine(PGOHash::IfThenBranch); 2440b57cec5SDimitry Andric else if (CS == If->getElse()) 2450b57cec5SDimitry Andric Hash.combine(PGOHash::IfElseBranch); 2460b57cec5SDimitry Andric TraverseStmt(CS); 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric Hash.combine(PGOHash::EndOfScope); 2490b57cec5SDimitry Andric return true; 2500b57cec5SDimitry Andric } 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric // If the statement type \p N is nestable, and its nesting impacts profile 2530b57cec5SDimitry Andric // stability, define a custom traversal which tracks the end of the statement 2540b57cec5SDimitry Andric // in the hash (provided we're not using the V1 hash). 2550b57cec5SDimitry Andric #define DEFINE_NESTABLE_TRAVERSAL(N) \ 2560b57cec5SDimitry Andric bool Traverse##N(N *S) { \ 2570b57cec5SDimitry Andric Base::Traverse##N(S); \ 2580b57cec5SDimitry Andric if (Hash.getHashVersion() != PGO_HASH_V1) \ 2590b57cec5SDimitry Andric Hash.combine(PGOHash::EndOfScope); \ 2600b57cec5SDimitry Andric return true; \ 2610b57cec5SDimitry Andric } 2620b57cec5SDimitry Andric 2630b57cec5SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(WhileStmt) 2640b57cec5SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(DoStmt) 2650b57cec5SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(ForStmt) 2660b57cec5SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(CXXForRangeStmt) 2670b57cec5SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(ObjCForCollectionStmt) 2680b57cec5SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(CXXTryStmt) 2690b57cec5SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(CXXCatchStmt) 2700b57cec5SDimitry Andric 2710b57cec5SDimitry Andric /// Get version \p HashVersion of the PGO hash for \p S. 2720b57cec5SDimitry Andric PGOHash::HashType getHashType(PGOHashVersion HashVersion, const Stmt *S) { 2730b57cec5SDimitry Andric switch (S->getStmtClass()) { 2740b57cec5SDimitry Andric default: 2750b57cec5SDimitry Andric break; 2760b57cec5SDimitry Andric case Stmt::LabelStmtClass: 2770b57cec5SDimitry Andric return PGOHash::LabelStmt; 2780b57cec5SDimitry Andric case Stmt::WhileStmtClass: 2790b57cec5SDimitry Andric return PGOHash::WhileStmt; 2800b57cec5SDimitry Andric case Stmt::DoStmtClass: 2810b57cec5SDimitry Andric return PGOHash::DoStmt; 2820b57cec5SDimitry Andric case Stmt::ForStmtClass: 2830b57cec5SDimitry Andric return PGOHash::ForStmt; 2840b57cec5SDimitry Andric case Stmt::CXXForRangeStmtClass: 2850b57cec5SDimitry Andric return PGOHash::CXXForRangeStmt; 2860b57cec5SDimitry Andric case Stmt::ObjCForCollectionStmtClass: 2870b57cec5SDimitry Andric return PGOHash::ObjCForCollectionStmt; 2880b57cec5SDimitry Andric case Stmt::SwitchStmtClass: 2890b57cec5SDimitry Andric return PGOHash::SwitchStmt; 2900b57cec5SDimitry Andric case Stmt::CaseStmtClass: 2910b57cec5SDimitry Andric return PGOHash::CaseStmt; 2920b57cec5SDimitry Andric case Stmt::DefaultStmtClass: 2930b57cec5SDimitry Andric return PGOHash::DefaultStmt; 2940b57cec5SDimitry Andric case Stmt::IfStmtClass: 2950b57cec5SDimitry Andric return PGOHash::IfStmt; 2960b57cec5SDimitry Andric case Stmt::CXXTryStmtClass: 2970b57cec5SDimitry Andric return PGOHash::CXXTryStmt; 2980b57cec5SDimitry Andric case Stmt::CXXCatchStmtClass: 2990b57cec5SDimitry Andric return PGOHash::CXXCatchStmt; 3000b57cec5SDimitry Andric case Stmt::ConditionalOperatorClass: 3010b57cec5SDimitry Andric return PGOHash::ConditionalOperator; 3020b57cec5SDimitry Andric case Stmt::BinaryConditionalOperatorClass: 3030b57cec5SDimitry Andric return PGOHash::BinaryConditionalOperator; 3040b57cec5SDimitry Andric case Stmt::BinaryOperatorClass: { 3050b57cec5SDimitry Andric const BinaryOperator *BO = cast<BinaryOperator>(S); 3060b57cec5SDimitry Andric if (BO->getOpcode() == BO_LAnd) 3070b57cec5SDimitry Andric return PGOHash::BinaryOperatorLAnd; 3080b57cec5SDimitry Andric if (BO->getOpcode() == BO_LOr) 3090b57cec5SDimitry Andric return PGOHash::BinaryOperatorLOr; 3105ffd83dbSDimitry Andric if (HashVersion >= PGO_HASH_V2) { 3110b57cec5SDimitry Andric switch (BO->getOpcode()) { 3120b57cec5SDimitry Andric default: 3130b57cec5SDimitry Andric break; 3140b57cec5SDimitry Andric case BO_LT: 3150b57cec5SDimitry Andric return PGOHash::BinaryOperatorLT; 3160b57cec5SDimitry Andric case BO_GT: 3170b57cec5SDimitry Andric return PGOHash::BinaryOperatorGT; 3180b57cec5SDimitry Andric case BO_LE: 3190b57cec5SDimitry Andric return PGOHash::BinaryOperatorLE; 3200b57cec5SDimitry Andric case BO_GE: 3210b57cec5SDimitry Andric return PGOHash::BinaryOperatorGE; 3220b57cec5SDimitry Andric case BO_EQ: 3230b57cec5SDimitry Andric return PGOHash::BinaryOperatorEQ; 3240b57cec5SDimitry Andric case BO_NE: 3250b57cec5SDimitry Andric return PGOHash::BinaryOperatorNE; 3260b57cec5SDimitry Andric } 3270b57cec5SDimitry Andric } 3280b57cec5SDimitry Andric break; 3290b57cec5SDimitry Andric } 3300b57cec5SDimitry Andric } 3310b57cec5SDimitry Andric 3325ffd83dbSDimitry Andric if (HashVersion >= PGO_HASH_V2) { 3330b57cec5SDimitry Andric switch (S->getStmtClass()) { 3340b57cec5SDimitry Andric default: 3350b57cec5SDimitry Andric break; 3360b57cec5SDimitry Andric case Stmt::GotoStmtClass: 3370b57cec5SDimitry Andric return PGOHash::GotoStmt; 3380b57cec5SDimitry Andric case Stmt::IndirectGotoStmtClass: 3390b57cec5SDimitry Andric return PGOHash::IndirectGotoStmt; 3400b57cec5SDimitry Andric case Stmt::BreakStmtClass: 3410b57cec5SDimitry Andric return PGOHash::BreakStmt; 3420b57cec5SDimitry Andric case Stmt::ContinueStmtClass: 3430b57cec5SDimitry Andric return PGOHash::ContinueStmt; 3440b57cec5SDimitry Andric case Stmt::ReturnStmtClass: 3450b57cec5SDimitry Andric return PGOHash::ReturnStmt; 3460b57cec5SDimitry Andric case Stmt::CXXThrowExprClass: 3470b57cec5SDimitry Andric return PGOHash::ThrowExpr; 3480b57cec5SDimitry Andric case Stmt::UnaryOperatorClass: { 3490b57cec5SDimitry Andric const UnaryOperator *UO = cast<UnaryOperator>(S); 3500b57cec5SDimitry Andric if (UO->getOpcode() == UO_LNot) 3510b57cec5SDimitry Andric return PGOHash::UnaryOperatorLNot; 3520b57cec5SDimitry Andric break; 3530b57cec5SDimitry Andric } 3540b57cec5SDimitry Andric } 3550b57cec5SDimitry Andric } 3560b57cec5SDimitry Andric 3570b57cec5SDimitry Andric return PGOHash::None; 3580b57cec5SDimitry Andric } 3590b57cec5SDimitry Andric }; 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric /// A StmtVisitor that propagates the raw counts through the AST and 3620b57cec5SDimitry Andric /// records the count at statements where the value may change. 3630b57cec5SDimitry Andric struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> { 3640b57cec5SDimitry Andric /// PGO state. 3650b57cec5SDimitry Andric CodeGenPGO &PGO; 3660b57cec5SDimitry Andric 3670b57cec5SDimitry Andric /// A flag that is set when the current count should be recorded on the 3680b57cec5SDimitry Andric /// next statement, such as at the exit of a loop. 3690b57cec5SDimitry Andric bool RecordNextStmtCount; 3700b57cec5SDimitry Andric 3710b57cec5SDimitry Andric /// The count at the current location in the traversal. 3720b57cec5SDimitry Andric uint64_t CurrentCount; 3730b57cec5SDimitry Andric 3740b57cec5SDimitry Andric /// The map of statements to count values. 3750b57cec5SDimitry Andric llvm::DenseMap<const Stmt *, uint64_t> &CountMap; 3760b57cec5SDimitry Andric 3770b57cec5SDimitry Andric /// BreakContinueStack - Keep counts of breaks and continues inside loops. 3780b57cec5SDimitry Andric struct BreakContinue { 3790b57cec5SDimitry Andric uint64_t BreakCount; 3800b57cec5SDimitry Andric uint64_t ContinueCount; 3810b57cec5SDimitry Andric BreakContinue() : BreakCount(0), ContinueCount(0) {} 3820b57cec5SDimitry Andric }; 3830b57cec5SDimitry Andric SmallVector<BreakContinue, 8> BreakContinueStack; 3840b57cec5SDimitry Andric 3850b57cec5SDimitry Andric ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &CountMap, 3860b57cec5SDimitry Andric CodeGenPGO &PGO) 3870b57cec5SDimitry Andric : PGO(PGO), RecordNextStmtCount(false), CountMap(CountMap) {} 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric void RecordStmtCount(const Stmt *S) { 3900b57cec5SDimitry Andric if (RecordNextStmtCount) { 3910b57cec5SDimitry Andric CountMap[S] = CurrentCount; 3920b57cec5SDimitry Andric RecordNextStmtCount = false; 3930b57cec5SDimitry Andric } 3940b57cec5SDimitry Andric } 3950b57cec5SDimitry Andric 3960b57cec5SDimitry Andric /// Set and return the current count. 3970b57cec5SDimitry Andric uint64_t setCount(uint64_t Count) { 3980b57cec5SDimitry Andric CurrentCount = Count; 3990b57cec5SDimitry Andric return Count; 4000b57cec5SDimitry Andric } 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric void VisitStmt(const Stmt *S) { 4030b57cec5SDimitry Andric RecordStmtCount(S); 4040b57cec5SDimitry Andric for (const Stmt *Child : S->children()) 4050b57cec5SDimitry Andric if (Child) 4060b57cec5SDimitry Andric this->Visit(Child); 4070b57cec5SDimitry Andric } 4080b57cec5SDimitry Andric 4090b57cec5SDimitry Andric void VisitFunctionDecl(const FunctionDecl *D) { 4100b57cec5SDimitry Andric // Counter tracks entry to the function body. 4110b57cec5SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); 4120b57cec5SDimitry Andric CountMap[D->getBody()] = BodyCount; 4130b57cec5SDimitry Andric Visit(D->getBody()); 4140b57cec5SDimitry Andric } 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric // Skip lambda expressions. We visit these as FunctionDecls when we're 4170b57cec5SDimitry Andric // generating them and aren't interested in the body when generating a 4180b57cec5SDimitry Andric // parent context. 4190b57cec5SDimitry Andric void VisitLambdaExpr(const LambdaExpr *LE) {} 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric void VisitCapturedDecl(const CapturedDecl *D) { 4220b57cec5SDimitry Andric // Counter tracks entry to the capture body. 4230b57cec5SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); 4240b57cec5SDimitry Andric CountMap[D->getBody()] = BodyCount; 4250b57cec5SDimitry Andric Visit(D->getBody()); 4260b57cec5SDimitry Andric } 4270b57cec5SDimitry Andric 4280b57cec5SDimitry Andric void VisitObjCMethodDecl(const ObjCMethodDecl *D) { 4290b57cec5SDimitry Andric // Counter tracks entry to the method body. 4300b57cec5SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); 4310b57cec5SDimitry Andric CountMap[D->getBody()] = BodyCount; 4320b57cec5SDimitry Andric Visit(D->getBody()); 4330b57cec5SDimitry Andric } 4340b57cec5SDimitry Andric 4350b57cec5SDimitry Andric void VisitBlockDecl(const BlockDecl *D) { 4360b57cec5SDimitry Andric // Counter tracks entry to the block body. 4370b57cec5SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); 4380b57cec5SDimitry Andric CountMap[D->getBody()] = BodyCount; 4390b57cec5SDimitry Andric Visit(D->getBody()); 4400b57cec5SDimitry Andric } 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric void VisitReturnStmt(const ReturnStmt *S) { 4430b57cec5SDimitry Andric RecordStmtCount(S); 4440b57cec5SDimitry Andric if (S->getRetValue()) 4450b57cec5SDimitry Andric Visit(S->getRetValue()); 4460b57cec5SDimitry Andric CurrentCount = 0; 4470b57cec5SDimitry Andric RecordNextStmtCount = true; 4480b57cec5SDimitry Andric } 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric void VisitCXXThrowExpr(const CXXThrowExpr *E) { 4510b57cec5SDimitry Andric RecordStmtCount(E); 4520b57cec5SDimitry Andric if (E->getSubExpr()) 4530b57cec5SDimitry Andric Visit(E->getSubExpr()); 4540b57cec5SDimitry Andric CurrentCount = 0; 4550b57cec5SDimitry Andric RecordNextStmtCount = true; 4560b57cec5SDimitry Andric } 4570b57cec5SDimitry Andric 4580b57cec5SDimitry Andric void VisitGotoStmt(const GotoStmt *S) { 4590b57cec5SDimitry Andric RecordStmtCount(S); 4600b57cec5SDimitry Andric CurrentCount = 0; 4610b57cec5SDimitry Andric RecordNextStmtCount = true; 4620b57cec5SDimitry Andric } 4630b57cec5SDimitry Andric 4640b57cec5SDimitry Andric void VisitLabelStmt(const LabelStmt *S) { 4650b57cec5SDimitry Andric RecordNextStmtCount = false; 4660b57cec5SDimitry Andric // Counter tracks the block following the label. 4670b57cec5SDimitry Andric uint64_t BlockCount = setCount(PGO.getRegionCount(S)); 4680b57cec5SDimitry Andric CountMap[S] = BlockCount; 4690b57cec5SDimitry Andric Visit(S->getSubStmt()); 4700b57cec5SDimitry Andric } 4710b57cec5SDimitry Andric 4720b57cec5SDimitry Andric void VisitBreakStmt(const BreakStmt *S) { 4730b57cec5SDimitry Andric RecordStmtCount(S); 4740b57cec5SDimitry Andric assert(!BreakContinueStack.empty() && "break not in a loop or switch!"); 4750b57cec5SDimitry Andric BreakContinueStack.back().BreakCount += CurrentCount; 4760b57cec5SDimitry Andric CurrentCount = 0; 4770b57cec5SDimitry Andric RecordNextStmtCount = true; 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric 4800b57cec5SDimitry Andric void VisitContinueStmt(const ContinueStmt *S) { 4810b57cec5SDimitry Andric RecordStmtCount(S); 4820b57cec5SDimitry Andric assert(!BreakContinueStack.empty() && "continue stmt not in a loop!"); 4830b57cec5SDimitry Andric BreakContinueStack.back().ContinueCount += CurrentCount; 4840b57cec5SDimitry Andric CurrentCount = 0; 4850b57cec5SDimitry Andric RecordNextStmtCount = true; 4860b57cec5SDimitry Andric } 4870b57cec5SDimitry Andric 4880b57cec5SDimitry Andric void VisitWhileStmt(const WhileStmt *S) { 4890b57cec5SDimitry Andric RecordStmtCount(S); 4900b57cec5SDimitry Andric uint64_t ParentCount = CurrentCount; 4910b57cec5SDimitry Andric 4920b57cec5SDimitry Andric BreakContinueStack.push_back(BreakContinue()); 4930b57cec5SDimitry Andric // Visit the body region first so the break/continue adjustments can be 4940b57cec5SDimitry Andric // included when visiting the condition. 4950b57cec5SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(S)); 4960b57cec5SDimitry Andric CountMap[S->getBody()] = CurrentCount; 4970b57cec5SDimitry Andric Visit(S->getBody()); 4980b57cec5SDimitry Andric uint64_t BackedgeCount = CurrentCount; 4990b57cec5SDimitry Andric 5000b57cec5SDimitry Andric // ...then go back and propagate counts through the condition. The count 5010b57cec5SDimitry Andric // at the start of the condition is the sum of the incoming edges, 5020b57cec5SDimitry Andric // the backedge from the end of the loop body, and the edges from 5030b57cec5SDimitry Andric // continue statements. 5040b57cec5SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val(); 5050b57cec5SDimitry Andric uint64_t CondCount = 5060b57cec5SDimitry Andric setCount(ParentCount + BackedgeCount + BC.ContinueCount); 5070b57cec5SDimitry Andric CountMap[S->getCond()] = CondCount; 5080b57cec5SDimitry Andric Visit(S->getCond()); 5090b57cec5SDimitry Andric setCount(BC.BreakCount + CondCount - BodyCount); 5100b57cec5SDimitry Andric RecordNextStmtCount = true; 5110b57cec5SDimitry Andric } 5120b57cec5SDimitry Andric 5130b57cec5SDimitry Andric void VisitDoStmt(const DoStmt *S) { 5140b57cec5SDimitry Andric RecordStmtCount(S); 5150b57cec5SDimitry Andric uint64_t LoopCount = PGO.getRegionCount(S); 5160b57cec5SDimitry Andric 5170b57cec5SDimitry Andric BreakContinueStack.push_back(BreakContinue()); 5180b57cec5SDimitry Andric // The count doesn't include the fallthrough from the parent scope. Add it. 5190b57cec5SDimitry Andric uint64_t BodyCount = setCount(LoopCount + CurrentCount); 5200b57cec5SDimitry Andric CountMap[S->getBody()] = BodyCount; 5210b57cec5SDimitry Andric Visit(S->getBody()); 5220b57cec5SDimitry Andric uint64_t BackedgeCount = CurrentCount; 5230b57cec5SDimitry Andric 5240b57cec5SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val(); 5250b57cec5SDimitry Andric // The count at the start of the condition is equal to the count at the 5260b57cec5SDimitry Andric // end of the body, plus any continues. 5270b57cec5SDimitry Andric uint64_t CondCount = setCount(BackedgeCount + BC.ContinueCount); 5280b57cec5SDimitry Andric CountMap[S->getCond()] = CondCount; 5290b57cec5SDimitry Andric Visit(S->getCond()); 5300b57cec5SDimitry Andric setCount(BC.BreakCount + CondCount - LoopCount); 5310b57cec5SDimitry Andric RecordNextStmtCount = true; 5320b57cec5SDimitry Andric } 5330b57cec5SDimitry Andric 5340b57cec5SDimitry Andric void VisitForStmt(const ForStmt *S) { 5350b57cec5SDimitry Andric RecordStmtCount(S); 5360b57cec5SDimitry Andric if (S->getInit()) 5370b57cec5SDimitry Andric Visit(S->getInit()); 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric uint64_t ParentCount = CurrentCount; 5400b57cec5SDimitry Andric 5410b57cec5SDimitry Andric BreakContinueStack.push_back(BreakContinue()); 5420b57cec5SDimitry Andric // Visit the body region first. (This is basically the same as a while 5430b57cec5SDimitry Andric // loop; see further comments in VisitWhileStmt.) 5440b57cec5SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(S)); 5450b57cec5SDimitry Andric CountMap[S->getBody()] = BodyCount; 5460b57cec5SDimitry Andric Visit(S->getBody()); 5470b57cec5SDimitry Andric uint64_t BackedgeCount = CurrentCount; 5480b57cec5SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val(); 5490b57cec5SDimitry Andric 5500b57cec5SDimitry Andric // The increment is essentially part of the body but it needs to include 5510b57cec5SDimitry Andric // the count for all the continue statements. 5520b57cec5SDimitry Andric if (S->getInc()) { 5530b57cec5SDimitry Andric uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount); 5540b57cec5SDimitry Andric CountMap[S->getInc()] = IncCount; 5550b57cec5SDimitry Andric Visit(S->getInc()); 5560b57cec5SDimitry Andric } 5570b57cec5SDimitry Andric 5580b57cec5SDimitry Andric // ...then go back and propagate counts through the condition. 5590b57cec5SDimitry Andric uint64_t CondCount = 5600b57cec5SDimitry Andric setCount(ParentCount + BackedgeCount + BC.ContinueCount); 5610b57cec5SDimitry Andric if (S->getCond()) { 5620b57cec5SDimitry Andric CountMap[S->getCond()] = CondCount; 5630b57cec5SDimitry Andric Visit(S->getCond()); 5640b57cec5SDimitry Andric } 5650b57cec5SDimitry Andric setCount(BC.BreakCount + CondCount - BodyCount); 5660b57cec5SDimitry Andric RecordNextStmtCount = true; 5670b57cec5SDimitry Andric } 5680b57cec5SDimitry Andric 5690b57cec5SDimitry Andric void VisitCXXForRangeStmt(const CXXForRangeStmt *S) { 5700b57cec5SDimitry Andric RecordStmtCount(S); 5710b57cec5SDimitry Andric if (S->getInit()) 5720b57cec5SDimitry Andric Visit(S->getInit()); 5730b57cec5SDimitry Andric Visit(S->getLoopVarStmt()); 5740b57cec5SDimitry Andric Visit(S->getRangeStmt()); 5750b57cec5SDimitry Andric Visit(S->getBeginStmt()); 5760b57cec5SDimitry Andric Visit(S->getEndStmt()); 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andric uint64_t ParentCount = CurrentCount; 5790b57cec5SDimitry Andric BreakContinueStack.push_back(BreakContinue()); 5800b57cec5SDimitry Andric // Visit the body region first. (This is basically the same as a while 5810b57cec5SDimitry Andric // loop; see further comments in VisitWhileStmt.) 5820b57cec5SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(S)); 5830b57cec5SDimitry Andric CountMap[S->getBody()] = BodyCount; 5840b57cec5SDimitry Andric Visit(S->getBody()); 5850b57cec5SDimitry Andric uint64_t BackedgeCount = CurrentCount; 5860b57cec5SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val(); 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric // The increment is essentially part of the body but it needs to include 5890b57cec5SDimitry Andric // the count for all the continue statements. 5900b57cec5SDimitry Andric uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount); 5910b57cec5SDimitry Andric CountMap[S->getInc()] = IncCount; 5920b57cec5SDimitry Andric Visit(S->getInc()); 5930b57cec5SDimitry Andric 5940b57cec5SDimitry Andric // ...then go back and propagate counts through the condition. 5950b57cec5SDimitry Andric uint64_t CondCount = 5960b57cec5SDimitry Andric setCount(ParentCount + BackedgeCount + BC.ContinueCount); 5970b57cec5SDimitry Andric CountMap[S->getCond()] = CondCount; 5980b57cec5SDimitry Andric Visit(S->getCond()); 5990b57cec5SDimitry Andric setCount(BC.BreakCount + CondCount - BodyCount); 6000b57cec5SDimitry Andric RecordNextStmtCount = true; 6010b57cec5SDimitry Andric } 6020b57cec5SDimitry Andric 6030b57cec5SDimitry Andric void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) { 6040b57cec5SDimitry Andric RecordStmtCount(S); 6050b57cec5SDimitry Andric Visit(S->getElement()); 6060b57cec5SDimitry Andric uint64_t ParentCount = CurrentCount; 6070b57cec5SDimitry Andric BreakContinueStack.push_back(BreakContinue()); 6080b57cec5SDimitry Andric // Counter tracks the body of the loop. 6090b57cec5SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(S)); 6100b57cec5SDimitry Andric CountMap[S->getBody()] = BodyCount; 6110b57cec5SDimitry Andric Visit(S->getBody()); 6120b57cec5SDimitry Andric uint64_t BackedgeCount = CurrentCount; 6130b57cec5SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val(); 6140b57cec5SDimitry Andric 6150b57cec5SDimitry Andric setCount(BC.BreakCount + ParentCount + BackedgeCount + BC.ContinueCount - 6160b57cec5SDimitry Andric BodyCount); 6170b57cec5SDimitry Andric RecordNextStmtCount = true; 6180b57cec5SDimitry Andric } 6190b57cec5SDimitry Andric 6200b57cec5SDimitry Andric void VisitSwitchStmt(const SwitchStmt *S) { 6210b57cec5SDimitry Andric RecordStmtCount(S); 6220b57cec5SDimitry Andric if (S->getInit()) 6230b57cec5SDimitry Andric Visit(S->getInit()); 6240b57cec5SDimitry Andric Visit(S->getCond()); 6250b57cec5SDimitry Andric CurrentCount = 0; 6260b57cec5SDimitry Andric BreakContinueStack.push_back(BreakContinue()); 6270b57cec5SDimitry Andric Visit(S->getBody()); 6280b57cec5SDimitry Andric // If the switch is inside a loop, add the continue counts. 6290b57cec5SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val(); 6300b57cec5SDimitry Andric if (!BreakContinueStack.empty()) 6310b57cec5SDimitry Andric BreakContinueStack.back().ContinueCount += BC.ContinueCount; 6320b57cec5SDimitry Andric // Counter tracks the exit block of the switch. 6330b57cec5SDimitry Andric setCount(PGO.getRegionCount(S)); 6340b57cec5SDimitry Andric RecordNextStmtCount = true; 6350b57cec5SDimitry Andric } 6360b57cec5SDimitry Andric 6370b57cec5SDimitry Andric void VisitSwitchCase(const SwitchCase *S) { 6380b57cec5SDimitry Andric RecordNextStmtCount = false; 6390b57cec5SDimitry Andric // Counter for this particular case. This counts only jumps from the 6400b57cec5SDimitry Andric // switch header and does not include fallthrough from the case before 6410b57cec5SDimitry Andric // this one. 6420b57cec5SDimitry Andric uint64_t CaseCount = PGO.getRegionCount(S); 6430b57cec5SDimitry Andric setCount(CurrentCount + CaseCount); 6440b57cec5SDimitry Andric // We need the count without fallthrough in the mapping, so it's more useful 6450b57cec5SDimitry Andric // for branch probabilities. 6460b57cec5SDimitry Andric CountMap[S] = CaseCount; 6470b57cec5SDimitry Andric RecordNextStmtCount = true; 6480b57cec5SDimitry Andric Visit(S->getSubStmt()); 6490b57cec5SDimitry Andric } 6500b57cec5SDimitry Andric 6510b57cec5SDimitry Andric void VisitIfStmt(const IfStmt *S) { 6520b57cec5SDimitry Andric RecordStmtCount(S); 653349cc55cSDimitry Andric 654349cc55cSDimitry Andric if (S->isConsteval()) { 655349cc55cSDimitry Andric const Stmt *Stm = S->isNegatedConsteval() ? S->getThen() : S->getElse(); 656349cc55cSDimitry Andric if (Stm) 657349cc55cSDimitry Andric Visit(Stm); 658349cc55cSDimitry Andric return; 659349cc55cSDimitry Andric } 660349cc55cSDimitry Andric 6610b57cec5SDimitry Andric uint64_t ParentCount = CurrentCount; 6620b57cec5SDimitry Andric if (S->getInit()) 6630b57cec5SDimitry Andric Visit(S->getInit()); 6640b57cec5SDimitry Andric Visit(S->getCond()); 6650b57cec5SDimitry Andric 6660b57cec5SDimitry Andric // Counter tracks the "then" part of an if statement. The count for 6670b57cec5SDimitry Andric // the "else" part, if it exists, will be calculated from this counter. 6680b57cec5SDimitry Andric uint64_t ThenCount = setCount(PGO.getRegionCount(S)); 6690b57cec5SDimitry Andric CountMap[S->getThen()] = ThenCount; 6700b57cec5SDimitry Andric Visit(S->getThen()); 6710b57cec5SDimitry Andric uint64_t OutCount = CurrentCount; 6720b57cec5SDimitry Andric 6730b57cec5SDimitry Andric uint64_t ElseCount = ParentCount - ThenCount; 6740b57cec5SDimitry Andric if (S->getElse()) { 6750b57cec5SDimitry Andric setCount(ElseCount); 6760b57cec5SDimitry Andric CountMap[S->getElse()] = ElseCount; 6770b57cec5SDimitry Andric Visit(S->getElse()); 6780b57cec5SDimitry Andric OutCount += CurrentCount; 6790b57cec5SDimitry Andric } else 6800b57cec5SDimitry Andric OutCount += ElseCount; 6810b57cec5SDimitry Andric setCount(OutCount); 6820b57cec5SDimitry Andric RecordNextStmtCount = true; 6830b57cec5SDimitry Andric } 6840b57cec5SDimitry Andric 6850b57cec5SDimitry Andric void VisitCXXTryStmt(const CXXTryStmt *S) { 6860b57cec5SDimitry Andric RecordStmtCount(S); 6870b57cec5SDimitry Andric Visit(S->getTryBlock()); 6880b57cec5SDimitry Andric for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I) 6890b57cec5SDimitry Andric Visit(S->getHandler(I)); 6900b57cec5SDimitry Andric // Counter tracks the continuation block of the try statement. 6910b57cec5SDimitry Andric setCount(PGO.getRegionCount(S)); 6920b57cec5SDimitry Andric RecordNextStmtCount = true; 6930b57cec5SDimitry Andric } 6940b57cec5SDimitry Andric 6950b57cec5SDimitry Andric void VisitCXXCatchStmt(const CXXCatchStmt *S) { 6960b57cec5SDimitry Andric RecordNextStmtCount = false; 6970b57cec5SDimitry Andric // Counter tracks the catch statement's handler block. 6980b57cec5SDimitry Andric uint64_t CatchCount = setCount(PGO.getRegionCount(S)); 6990b57cec5SDimitry Andric CountMap[S] = CatchCount; 7000b57cec5SDimitry Andric Visit(S->getHandlerBlock()); 7010b57cec5SDimitry Andric } 7020b57cec5SDimitry Andric 7030b57cec5SDimitry Andric void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { 7040b57cec5SDimitry Andric RecordStmtCount(E); 7050b57cec5SDimitry Andric uint64_t ParentCount = CurrentCount; 7060b57cec5SDimitry Andric Visit(E->getCond()); 7070b57cec5SDimitry Andric 7080b57cec5SDimitry Andric // Counter tracks the "true" part of a conditional operator. The 7090b57cec5SDimitry Andric // count in the "false" part will be calculated from this counter. 7100b57cec5SDimitry Andric uint64_t TrueCount = setCount(PGO.getRegionCount(E)); 7110b57cec5SDimitry Andric CountMap[E->getTrueExpr()] = TrueCount; 7120b57cec5SDimitry Andric Visit(E->getTrueExpr()); 7130b57cec5SDimitry Andric uint64_t OutCount = CurrentCount; 7140b57cec5SDimitry Andric 7150b57cec5SDimitry Andric uint64_t FalseCount = setCount(ParentCount - TrueCount); 7160b57cec5SDimitry Andric CountMap[E->getFalseExpr()] = FalseCount; 7170b57cec5SDimitry Andric Visit(E->getFalseExpr()); 7180b57cec5SDimitry Andric OutCount += CurrentCount; 7190b57cec5SDimitry Andric 7200b57cec5SDimitry Andric setCount(OutCount); 7210b57cec5SDimitry Andric RecordNextStmtCount = true; 7220b57cec5SDimitry Andric } 7230b57cec5SDimitry Andric 7240b57cec5SDimitry Andric void VisitBinLAnd(const BinaryOperator *E) { 7250b57cec5SDimitry Andric RecordStmtCount(E); 7260b57cec5SDimitry Andric uint64_t ParentCount = CurrentCount; 7270b57cec5SDimitry Andric Visit(E->getLHS()); 7280b57cec5SDimitry Andric // Counter tracks the right hand side of a logical and operator. 7290b57cec5SDimitry Andric uint64_t RHSCount = setCount(PGO.getRegionCount(E)); 7300b57cec5SDimitry Andric CountMap[E->getRHS()] = RHSCount; 7310b57cec5SDimitry Andric Visit(E->getRHS()); 7320b57cec5SDimitry Andric setCount(ParentCount + RHSCount - CurrentCount); 7330b57cec5SDimitry Andric RecordNextStmtCount = true; 7340b57cec5SDimitry Andric } 7350b57cec5SDimitry Andric 7360b57cec5SDimitry Andric void VisitBinLOr(const BinaryOperator *E) { 7370b57cec5SDimitry Andric RecordStmtCount(E); 7380b57cec5SDimitry Andric uint64_t ParentCount = CurrentCount; 7390b57cec5SDimitry Andric Visit(E->getLHS()); 7400b57cec5SDimitry Andric // Counter tracks the right hand side of a logical or operator. 7410b57cec5SDimitry Andric uint64_t RHSCount = setCount(PGO.getRegionCount(E)); 7420b57cec5SDimitry Andric CountMap[E->getRHS()] = RHSCount; 7430b57cec5SDimitry Andric Visit(E->getRHS()); 7440b57cec5SDimitry Andric setCount(ParentCount + RHSCount - CurrentCount); 7450b57cec5SDimitry Andric RecordNextStmtCount = true; 7460b57cec5SDimitry Andric } 7470b57cec5SDimitry Andric }; 7480b57cec5SDimitry Andric } // end anonymous namespace 7490b57cec5SDimitry Andric 7500b57cec5SDimitry Andric void PGOHash::combine(HashType Type) { 7510b57cec5SDimitry Andric // Check that we never combine 0 and only have six bits. 7520b57cec5SDimitry Andric assert(Type && "Hash is invalid: unexpected type 0"); 7530b57cec5SDimitry Andric assert(unsigned(Type) < TooBig && "Hash is invalid: too many types"); 7540b57cec5SDimitry Andric 7550b57cec5SDimitry Andric // Pass through MD5 if enough work has built up. 7560b57cec5SDimitry Andric if (Count && Count % NumTypesPerWord == 0) { 7570b57cec5SDimitry Andric using namespace llvm::support; 7580b57cec5SDimitry Andric uint64_t Swapped = endian::byte_swap<uint64_t, little>(Working); 759bdd1243dSDimitry Andric MD5.update(llvm::ArrayRef((uint8_t *)&Swapped, sizeof(Swapped))); 7600b57cec5SDimitry Andric Working = 0; 7610b57cec5SDimitry Andric } 7620b57cec5SDimitry Andric 7630b57cec5SDimitry Andric // Accumulate the current type. 7640b57cec5SDimitry Andric ++Count; 7650b57cec5SDimitry Andric Working = Working << NumBitsPerType | Type; 7660b57cec5SDimitry Andric } 7670b57cec5SDimitry Andric 7680b57cec5SDimitry Andric uint64_t PGOHash::finalize() { 7690b57cec5SDimitry Andric // Use Working as the hash directly if we never used MD5. 7700b57cec5SDimitry Andric if (Count <= NumTypesPerWord) 7710b57cec5SDimitry Andric // No need to byte swap here, since none of the math was endian-dependent. 7720b57cec5SDimitry Andric // This number will be byte-swapped as required on endianness transitions, 7730b57cec5SDimitry Andric // so we will see the same value on the other side. 7740b57cec5SDimitry Andric return Working; 7750b57cec5SDimitry Andric 7760b57cec5SDimitry Andric // Check for remaining work in Working. 7775ffd83dbSDimitry Andric if (Working) { 7785ffd83dbSDimitry Andric // Keep the buggy behavior from v1 and v2 for backward-compatibility. This 7795ffd83dbSDimitry Andric // is buggy because it converts a uint64_t into an array of uint8_t. 7805ffd83dbSDimitry Andric if (HashVersion < PGO_HASH_V3) { 7815ffd83dbSDimitry Andric MD5.update({(uint8_t)Working}); 7825ffd83dbSDimitry Andric } else { 7835ffd83dbSDimitry Andric using namespace llvm::support; 7845ffd83dbSDimitry Andric uint64_t Swapped = endian::byte_swap<uint64_t, little>(Working); 785bdd1243dSDimitry Andric MD5.update(llvm::ArrayRef((uint8_t *)&Swapped, sizeof(Swapped))); 7865ffd83dbSDimitry Andric } 7875ffd83dbSDimitry Andric } 7880b57cec5SDimitry Andric 7890b57cec5SDimitry Andric // Finalize the MD5 and return the hash. 7900b57cec5SDimitry Andric llvm::MD5::MD5Result Result; 7910b57cec5SDimitry Andric MD5.final(Result); 7920b57cec5SDimitry Andric return Result.low(); 7930b57cec5SDimitry Andric } 7940b57cec5SDimitry Andric 7950b57cec5SDimitry Andric void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) { 7960b57cec5SDimitry Andric const Decl *D = GD.getDecl(); 7970b57cec5SDimitry Andric if (!D->hasBody()) 7980b57cec5SDimitry Andric return; 7990b57cec5SDimitry Andric 800e8d8bef9SDimitry Andric // Skip CUDA/HIP kernel launch stub functions. 801e8d8bef9SDimitry Andric if (CGM.getLangOpts().CUDA && !CGM.getLangOpts().CUDAIsDevice && 802e8d8bef9SDimitry Andric D->hasAttr<CUDAGlobalAttr>()) 803e8d8bef9SDimitry Andric return; 804e8d8bef9SDimitry Andric 8050b57cec5SDimitry Andric bool InstrumentRegions = CGM.getCodeGenOpts().hasProfileClangInstr(); 8060b57cec5SDimitry Andric llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader(); 8070b57cec5SDimitry Andric if (!InstrumentRegions && !PGOReader) 8080b57cec5SDimitry Andric return; 8090b57cec5SDimitry Andric if (D->isImplicit()) 8100b57cec5SDimitry Andric return; 8110b57cec5SDimitry Andric // Constructors and destructors may be represented by several functions in IR. 8120b57cec5SDimitry Andric // If so, instrument only base variant, others are implemented by delegation 8130b57cec5SDimitry Andric // to the base one, it would be counted twice otherwise. 8140b57cec5SDimitry Andric if (CGM.getTarget().getCXXABI().hasConstructorVariants()) { 8150b57cec5SDimitry Andric if (const auto *CCD = dyn_cast<CXXConstructorDecl>(D)) 8160b57cec5SDimitry Andric if (GD.getCtorType() != Ctor_Base && 8170b57cec5SDimitry Andric CodeGenFunction::IsConstructorDelegationValid(CCD)) 8180b57cec5SDimitry Andric return; 8190b57cec5SDimitry Andric } 8200b57cec5SDimitry Andric if (isa<CXXDestructorDecl>(D) && GD.getDtorType() != Dtor_Base) 8210b57cec5SDimitry Andric return; 8220b57cec5SDimitry Andric 823fe6060f1SDimitry Andric CGM.ClearUnusedCoverageMapping(D); 824e8d8bef9SDimitry Andric if (Fn->hasFnAttribute(llvm::Attribute::NoProfile)) 825e8d8bef9SDimitry Andric return; 826bdd1243dSDimitry Andric if (Fn->hasFnAttribute(llvm::Attribute::SkipProfile)) 827bdd1243dSDimitry Andric return; 828e8d8bef9SDimitry Andric 8290b57cec5SDimitry Andric setFuncName(Fn); 8300b57cec5SDimitry Andric 8310b57cec5SDimitry Andric mapRegionCounters(D); 8320b57cec5SDimitry Andric if (CGM.getCodeGenOpts().CoverageMapping) 8330b57cec5SDimitry Andric emitCounterRegionMapping(D); 8340b57cec5SDimitry Andric if (PGOReader) { 8350b57cec5SDimitry Andric SourceManager &SM = CGM.getContext().getSourceManager(); 8360b57cec5SDimitry Andric loadRegionCounts(PGOReader, SM.isInMainFile(D->getLocation())); 8370b57cec5SDimitry Andric computeRegionCounts(D); 8380b57cec5SDimitry Andric applyFunctionAttributes(PGOReader, Fn); 8390b57cec5SDimitry Andric } 8400b57cec5SDimitry Andric } 8410b57cec5SDimitry Andric 8420b57cec5SDimitry Andric void CodeGenPGO::mapRegionCounters(const Decl *D) { 8430b57cec5SDimitry Andric // Use the latest hash version when inserting instrumentation, but use the 8440b57cec5SDimitry Andric // version in the indexed profile if we're reading PGO data. 8450b57cec5SDimitry Andric PGOHashVersion HashVersion = PGO_HASH_LATEST; 846e8d8bef9SDimitry Andric uint64_t ProfileVersion = llvm::IndexedInstrProf::Version; 847e8d8bef9SDimitry Andric if (auto *PGOReader = CGM.getPGOReader()) { 8480b57cec5SDimitry Andric HashVersion = getPGOHashVersion(PGOReader, CGM); 849e8d8bef9SDimitry Andric ProfileVersion = PGOReader->getVersion(); 850e8d8bef9SDimitry Andric } 8510b57cec5SDimitry Andric 8520b57cec5SDimitry Andric RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>); 853e8d8bef9SDimitry Andric MapRegionCounters Walker(HashVersion, ProfileVersion, *RegionCounterMap); 8540b57cec5SDimitry Andric if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) 8550b57cec5SDimitry Andric Walker.TraverseDecl(const_cast<FunctionDecl *>(FD)); 8560b57cec5SDimitry Andric else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D)) 8570b57cec5SDimitry Andric Walker.TraverseDecl(const_cast<ObjCMethodDecl *>(MD)); 8580b57cec5SDimitry Andric else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D)) 8590b57cec5SDimitry Andric Walker.TraverseDecl(const_cast<BlockDecl *>(BD)); 8600b57cec5SDimitry Andric else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D)) 8610b57cec5SDimitry Andric Walker.TraverseDecl(const_cast<CapturedDecl *>(CD)); 8620b57cec5SDimitry Andric assert(Walker.NextCounter > 0 && "no entry counter mapped for decl"); 8630b57cec5SDimitry Andric NumRegionCounters = Walker.NextCounter; 8640b57cec5SDimitry Andric FunctionHash = Walker.Hash.finalize(); 8650b57cec5SDimitry Andric } 8660b57cec5SDimitry Andric 8670b57cec5SDimitry Andric bool CodeGenPGO::skipRegionMappingForDecl(const Decl *D) { 8680b57cec5SDimitry Andric if (!D->getBody()) 8690b57cec5SDimitry Andric return true; 8700b57cec5SDimitry Andric 871e8d8bef9SDimitry Andric // Skip host-only functions in the CUDA device compilation and device-only 872e8d8bef9SDimitry Andric // functions in the host compilation. Just roughly filter them out based on 873e8d8bef9SDimitry Andric // the function attributes. If there are effectively host-only or device-only 874e8d8bef9SDimitry Andric // ones, their coverage mapping may still be generated. 875e8d8bef9SDimitry Andric if (CGM.getLangOpts().CUDA && 876e8d8bef9SDimitry Andric ((CGM.getLangOpts().CUDAIsDevice && !D->hasAttr<CUDADeviceAttr>() && 877e8d8bef9SDimitry Andric !D->hasAttr<CUDAGlobalAttr>()) || 878e8d8bef9SDimitry Andric (!CGM.getLangOpts().CUDAIsDevice && 879e8d8bef9SDimitry Andric (D->hasAttr<CUDAGlobalAttr>() || 880e8d8bef9SDimitry Andric (!D->hasAttr<CUDAHostAttr>() && D->hasAttr<CUDADeviceAttr>()))))) 881e8d8bef9SDimitry Andric return true; 882e8d8bef9SDimitry Andric 8830b57cec5SDimitry Andric // Don't map the functions in system headers. 8840b57cec5SDimitry Andric const auto &SM = CGM.getContext().getSourceManager(); 8850b57cec5SDimitry Andric auto Loc = D->getBody()->getBeginLoc(); 8860b57cec5SDimitry Andric return SM.isInSystemHeader(Loc); 8870b57cec5SDimitry Andric } 8880b57cec5SDimitry Andric 8890b57cec5SDimitry Andric void CodeGenPGO::emitCounterRegionMapping(const Decl *D) { 8900b57cec5SDimitry Andric if (skipRegionMappingForDecl(D)) 8910b57cec5SDimitry Andric return; 8920b57cec5SDimitry Andric 8930b57cec5SDimitry Andric std::string CoverageMapping; 8940b57cec5SDimitry Andric llvm::raw_string_ostream OS(CoverageMapping); 8950b57cec5SDimitry Andric CoverageMappingGen MappingGen(*CGM.getCoverageMapping(), 8960b57cec5SDimitry Andric CGM.getContext().getSourceManager(), 8970b57cec5SDimitry Andric CGM.getLangOpts(), RegionCounterMap.get()); 8980b57cec5SDimitry Andric MappingGen.emitCounterMapping(D, OS); 8990b57cec5SDimitry Andric OS.flush(); 9000b57cec5SDimitry Andric 9010b57cec5SDimitry Andric if (CoverageMapping.empty()) 9020b57cec5SDimitry Andric return; 9030b57cec5SDimitry Andric 9040b57cec5SDimitry Andric CGM.getCoverageMapping()->addFunctionMappingRecord( 9050b57cec5SDimitry Andric FuncNameVar, FuncName, FunctionHash, CoverageMapping); 9060b57cec5SDimitry Andric } 9070b57cec5SDimitry Andric 9080b57cec5SDimitry Andric void 9090b57cec5SDimitry Andric CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef Name, 9100b57cec5SDimitry Andric llvm::GlobalValue::LinkageTypes Linkage) { 9110b57cec5SDimitry Andric if (skipRegionMappingForDecl(D)) 9120b57cec5SDimitry Andric return; 9130b57cec5SDimitry Andric 9140b57cec5SDimitry Andric std::string CoverageMapping; 9150b57cec5SDimitry Andric llvm::raw_string_ostream OS(CoverageMapping); 9160b57cec5SDimitry Andric CoverageMappingGen MappingGen(*CGM.getCoverageMapping(), 9170b57cec5SDimitry Andric CGM.getContext().getSourceManager(), 9180b57cec5SDimitry Andric CGM.getLangOpts()); 9190b57cec5SDimitry Andric MappingGen.emitEmptyMapping(D, OS); 9200b57cec5SDimitry Andric OS.flush(); 9210b57cec5SDimitry Andric 9220b57cec5SDimitry Andric if (CoverageMapping.empty()) 9230b57cec5SDimitry Andric return; 9240b57cec5SDimitry Andric 9250b57cec5SDimitry Andric setFuncName(Name, Linkage); 9260b57cec5SDimitry Andric CGM.getCoverageMapping()->addFunctionMappingRecord( 9270b57cec5SDimitry Andric FuncNameVar, FuncName, FunctionHash, CoverageMapping, false); 9280b57cec5SDimitry Andric } 9290b57cec5SDimitry Andric 9300b57cec5SDimitry Andric void CodeGenPGO::computeRegionCounts(const Decl *D) { 9310b57cec5SDimitry Andric StmtCountMap.reset(new llvm::DenseMap<const Stmt *, uint64_t>); 9320b57cec5SDimitry Andric ComputeRegionCounts Walker(*StmtCountMap, *this); 9330b57cec5SDimitry Andric if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) 9340b57cec5SDimitry Andric Walker.VisitFunctionDecl(FD); 9350b57cec5SDimitry Andric else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D)) 9360b57cec5SDimitry Andric Walker.VisitObjCMethodDecl(MD); 9370b57cec5SDimitry Andric else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D)) 9380b57cec5SDimitry Andric Walker.VisitBlockDecl(BD); 9390b57cec5SDimitry Andric else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D)) 9400b57cec5SDimitry Andric Walker.VisitCapturedDecl(const_cast<CapturedDecl *>(CD)); 9410b57cec5SDimitry Andric } 9420b57cec5SDimitry Andric 9430b57cec5SDimitry Andric void 9440b57cec5SDimitry Andric CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader, 9450b57cec5SDimitry Andric llvm::Function *Fn) { 9460b57cec5SDimitry Andric if (!haveRegionCounts()) 9470b57cec5SDimitry Andric return; 9480b57cec5SDimitry Andric 9490b57cec5SDimitry Andric uint64_t FunctionCount = getRegionCount(nullptr); 9500b57cec5SDimitry Andric Fn->setEntryCount(FunctionCount); 9510b57cec5SDimitry Andric } 9520b57cec5SDimitry Andric 9530b57cec5SDimitry Andric void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S, 9540b57cec5SDimitry Andric llvm::Value *StepV) { 9550b57cec5SDimitry Andric if (!CGM.getCodeGenOpts().hasProfileClangInstr() || !RegionCounterMap) 9560b57cec5SDimitry Andric return; 9570b57cec5SDimitry Andric if (!Builder.GetInsertBlock()) 9580b57cec5SDimitry Andric return; 9590b57cec5SDimitry Andric 9600b57cec5SDimitry Andric unsigned Counter = (*RegionCounterMap)[S]; 9610b57cec5SDimitry Andric auto *I8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); 9620b57cec5SDimitry Andric 9630b57cec5SDimitry Andric llvm::Value *Args[] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy), 9640b57cec5SDimitry Andric Builder.getInt64(FunctionHash), 9650b57cec5SDimitry Andric Builder.getInt32(NumRegionCounters), 9660b57cec5SDimitry Andric Builder.getInt32(Counter), StepV}; 9670b57cec5SDimitry Andric if (!StepV) 9680b57cec5SDimitry Andric Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment), 969bdd1243dSDimitry Andric ArrayRef(Args, 4)); 9700b57cec5SDimitry Andric else 9710b57cec5SDimitry Andric Builder.CreateCall( 9720b57cec5SDimitry Andric CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment_step), 973bdd1243dSDimitry Andric ArrayRef(Args)); 9740b57cec5SDimitry Andric } 9750b57cec5SDimitry Andric 976fe6060f1SDimitry Andric void CodeGenPGO::setValueProfilingFlag(llvm::Module &M) { 977fe6060f1SDimitry Andric if (CGM.getCodeGenOpts().hasProfileClangInstr()) 978fe6060f1SDimitry Andric M.addModuleFlag(llvm::Module::Warning, "EnableValueProfiling", 979fe6060f1SDimitry Andric uint32_t(EnableValueProfiling)); 980fe6060f1SDimitry Andric } 981fe6060f1SDimitry Andric 9820b57cec5SDimitry Andric // This method either inserts a call to the profile run-time during 9830b57cec5SDimitry Andric // instrumentation or puts profile data into metadata for PGO use. 9840b57cec5SDimitry Andric void CodeGenPGO::valueProfile(CGBuilderTy &Builder, uint32_t ValueKind, 9850b57cec5SDimitry Andric llvm::Instruction *ValueSite, llvm::Value *ValuePtr) { 9860b57cec5SDimitry Andric 9870b57cec5SDimitry Andric if (!EnableValueProfiling) 9880b57cec5SDimitry Andric return; 9890b57cec5SDimitry Andric 9900b57cec5SDimitry Andric if (!ValuePtr || !ValueSite || !Builder.GetInsertBlock()) 9910b57cec5SDimitry Andric return; 9920b57cec5SDimitry Andric 9930b57cec5SDimitry Andric if (isa<llvm::Constant>(ValuePtr)) 9940b57cec5SDimitry Andric return; 9950b57cec5SDimitry Andric 9960b57cec5SDimitry Andric bool InstrumentValueSites = CGM.getCodeGenOpts().hasProfileClangInstr(); 9970b57cec5SDimitry Andric if (InstrumentValueSites && RegionCounterMap) { 9980b57cec5SDimitry Andric auto BuilderInsertPoint = Builder.saveIP(); 9990b57cec5SDimitry Andric Builder.SetInsertPoint(ValueSite); 10000b57cec5SDimitry Andric llvm::Value *Args[5] = { 10010b57cec5SDimitry Andric llvm::ConstantExpr::getBitCast(FuncNameVar, Builder.getInt8PtrTy()), 10020b57cec5SDimitry Andric Builder.getInt64(FunctionHash), 10030b57cec5SDimitry Andric Builder.CreatePtrToInt(ValuePtr, Builder.getInt64Ty()), 10040b57cec5SDimitry Andric Builder.getInt32(ValueKind), 10050b57cec5SDimitry Andric Builder.getInt32(NumValueSites[ValueKind]++) 10060b57cec5SDimitry Andric }; 10070b57cec5SDimitry Andric Builder.CreateCall( 10080b57cec5SDimitry Andric CGM.getIntrinsic(llvm::Intrinsic::instrprof_value_profile), Args); 10090b57cec5SDimitry Andric Builder.restoreIP(BuilderInsertPoint); 10100b57cec5SDimitry Andric return; 10110b57cec5SDimitry Andric } 10120b57cec5SDimitry Andric 10130b57cec5SDimitry Andric llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader(); 10140b57cec5SDimitry Andric if (PGOReader && haveRegionCounts()) { 10150b57cec5SDimitry Andric // We record the top most called three functions at each call site. 10160b57cec5SDimitry Andric // Profile metadata contains "VP" string identifying this metadata 10170b57cec5SDimitry Andric // as value profiling data, then a uint32_t value for the value profiling 10180b57cec5SDimitry Andric // kind, a uint64_t value for the total number of times the call is 10190b57cec5SDimitry Andric // executed, followed by the function hash and execution count (uint64_t) 10200b57cec5SDimitry Andric // pairs for each function. 10210b57cec5SDimitry Andric if (NumValueSites[ValueKind] >= ProfRecord->getNumValueSites(ValueKind)) 10220b57cec5SDimitry Andric return; 10230b57cec5SDimitry Andric 10240b57cec5SDimitry Andric llvm::annotateValueSite(CGM.getModule(), *ValueSite, *ProfRecord, 10250b57cec5SDimitry Andric (llvm::InstrProfValueKind)ValueKind, 10260b57cec5SDimitry Andric NumValueSites[ValueKind]); 10270b57cec5SDimitry Andric 10280b57cec5SDimitry Andric NumValueSites[ValueKind]++; 10290b57cec5SDimitry Andric } 10300b57cec5SDimitry Andric } 10310b57cec5SDimitry Andric 10320b57cec5SDimitry Andric void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader, 10330b57cec5SDimitry Andric bool IsInMainFile) { 10340b57cec5SDimitry Andric CGM.getPGOStats().addVisited(IsInMainFile); 10350b57cec5SDimitry Andric RegionCounts.clear(); 10360b57cec5SDimitry Andric llvm::Expected<llvm::InstrProfRecord> RecordExpected = 10370b57cec5SDimitry Andric PGOReader->getInstrProfRecord(FuncName, FunctionHash); 10380b57cec5SDimitry Andric if (auto E = RecordExpected.takeError()) { 1039*fe013be4SDimitry Andric auto IPE = std::get<0>(llvm::InstrProfError::take(std::move(E))); 10400b57cec5SDimitry Andric if (IPE == llvm::instrprof_error::unknown_function) 10410b57cec5SDimitry Andric CGM.getPGOStats().addMissing(IsInMainFile); 10420b57cec5SDimitry Andric else if (IPE == llvm::instrprof_error::hash_mismatch) 10430b57cec5SDimitry Andric CGM.getPGOStats().addMismatched(IsInMainFile); 10440b57cec5SDimitry Andric else if (IPE == llvm::instrprof_error::malformed) 10450b57cec5SDimitry Andric // TODO: Consider a more specific warning for this case. 10460b57cec5SDimitry Andric CGM.getPGOStats().addMismatched(IsInMainFile); 10470b57cec5SDimitry Andric return; 10480b57cec5SDimitry Andric } 10490b57cec5SDimitry Andric ProfRecord = 1050a7dea167SDimitry Andric std::make_unique<llvm::InstrProfRecord>(std::move(RecordExpected.get())); 10510b57cec5SDimitry Andric RegionCounts = ProfRecord->Counts; 10520b57cec5SDimitry Andric } 10530b57cec5SDimitry Andric 10540b57cec5SDimitry Andric /// Calculate what to divide by to scale weights. 10550b57cec5SDimitry Andric /// 10560b57cec5SDimitry Andric /// Given the maximum weight, calculate a divisor that will scale all the 10570b57cec5SDimitry Andric /// weights to strictly less than UINT32_MAX. 10580b57cec5SDimitry Andric static uint64_t calculateWeightScale(uint64_t MaxWeight) { 10590b57cec5SDimitry Andric return MaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1; 10600b57cec5SDimitry Andric } 10610b57cec5SDimitry Andric 10620b57cec5SDimitry Andric /// Scale an individual branch weight (and add 1). 10630b57cec5SDimitry Andric /// 10640b57cec5SDimitry Andric /// Scale a 64-bit weight down to 32-bits using \c Scale. 10650b57cec5SDimitry Andric /// 10660b57cec5SDimitry Andric /// According to Laplace's Rule of Succession, it is better to compute the 10670b57cec5SDimitry Andric /// weight based on the count plus 1, so universally add 1 to the value. 10680b57cec5SDimitry Andric /// 10690b57cec5SDimitry Andric /// \pre \c Scale was calculated by \a calculateWeightScale() with a weight no 10700b57cec5SDimitry Andric /// greater than \c Weight. 10710b57cec5SDimitry Andric static uint32_t scaleBranchWeight(uint64_t Weight, uint64_t Scale) { 10720b57cec5SDimitry Andric assert(Scale && "scale by 0?"); 10730b57cec5SDimitry Andric uint64_t Scaled = Weight / Scale + 1; 10740b57cec5SDimitry Andric assert(Scaled <= UINT32_MAX && "overflow 32-bits"); 10750b57cec5SDimitry Andric return Scaled; 10760b57cec5SDimitry Andric } 10770b57cec5SDimitry Andric 10780b57cec5SDimitry Andric llvm::MDNode *CodeGenFunction::createProfileWeights(uint64_t TrueCount, 1079e8d8bef9SDimitry Andric uint64_t FalseCount) const { 10800b57cec5SDimitry Andric // Check for empty weights. 10810b57cec5SDimitry Andric if (!TrueCount && !FalseCount) 10820b57cec5SDimitry Andric return nullptr; 10830b57cec5SDimitry Andric 10840b57cec5SDimitry Andric // Calculate how to scale down to 32-bits. 10850b57cec5SDimitry Andric uint64_t Scale = calculateWeightScale(std::max(TrueCount, FalseCount)); 10860b57cec5SDimitry Andric 10870b57cec5SDimitry Andric llvm::MDBuilder MDHelper(CGM.getLLVMContext()); 10880b57cec5SDimitry Andric return MDHelper.createBranchWeights(scaleBranchWeight(TrueCount, Scale), 10890b57cec5SDimitry Andric scaleBranchWeight(FalseCount, Scale)); 10900b57cec5SDimitry Andric } 10910b57cec5SDimitry Andric 10920b57cec5SDimitry Andric llvm::MDNode * 1093e8d8bef9SDimitry Andric CodeGenFunction::createProfileWeights(ArrayRef<uint64_t> Weights) const { 10940b57cec5SDimitry Andric // We need at least two elements to create meaningful weights. 10950b57cec5SDimitry Andric if (Weights.size() < 2) 10960b57cec5SDimitry Andric return nullptr; 10970b57cec5SDimitry Andric 10980b57cec5SDimitry Andric // Check for empty weights. 10990b57cec5SDimitry Andric uint64_t MaxWeight = *std::max_element(Weights.begin(), Weights.end()); 11000b57cec5SDimitry Andric if (MaxWeight == 0) 11010b57cec5SDimitry Andric return nullptr; 11020b57cec5SDimitry Andric 11030b57cec5SDimitry Andric // Calculate how to scale down to 32-bits. 11040b57cec5SDimitry Andric uint64_t Scale = calculateWeightScale(MaxWeight); 11050b57cec5SDimitry Andric 11060b57cec5SDimitry Andric SmallVector<uint32_t, 16> ScaledWeights; 11070b57cec5SDimitry Andric ScaledWeights.reserve(Weights.size()); 11080b57cec5SDimitry Andric for (uint64_t W : Weights) 11090b57cec5SDimitry Andric ScaledWeights.push_back(scaleBranchWeight(W, Scale)); 11100b57cec5SDimitry Andric 11110b57cec5SDimitry Andric llvm::MDBuilder MDHelper(CGM.getLLVMContext()); 11120b57cec5SDimitry Andric return MDHelper.createBranchWeights(ScaledWeights); 11130b57cec5SDimitry Andric } 11140b57cec5SDimitry Andric 1115e8d8bef9SDimitry Andric llvm::MDNode * 1116e8d8bef9SDimitry Andric CodeGenFunction::createProfileWeightsForLoop(const Stmt *Cond, 1117e8d8bef9SDimitry Andric uint64_t LoopCount) const { 11180b57cec5SDimitry Andric if (!PGO.haveRegionCounts()) 11190b57cec5SDimitry Andric return nullptr; 1120bdd1243dSDimitry Andric std::optional<uint64_t> CondCount = PGO.getStmtCount(Cond); 11215ffd83dbSDimitry Andric if (!CondCount || *CondCount == 0) 11220b57cec5SDimitry Andric return nullptr; 11230b57cec5SDimitry Andric return createProfileWeights(LoopCount, 11240b57cec5SDimitry Andric std::max(*CondCount, LoopCount) - LoopCount); 11250b57cec5SDimitry Andric } 1126