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 31*a58f00eaSDimitry Andric extern llvm::cl::opt<bool> SystemHeadersCoverage; 32*a58f00eaSDimitry Andric 330b57cec5SDimitry Andric using namespace clang; 340b57cec5SDimitry Andric using namespace CodeGen; 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric void CodeGenPGO::setFuncName(StringRef Name, 370b57cec5SDimitry Andric llvm::GlobalValue::LinkageTypes Linkage) { 380b57cec5SDimitry Andric llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader(); 390b57cec5SDimitry Andric FuncName = llvm::getPGOFuncName( 400b57cec5SDimitry Andric Name, Linkage, CGM.getCodeGenOpts().MainFileName, 410b57cec5SDimitry Andric PGOReader ? PGOReader->getVersion() : llvm::IndexedInstrProf::Version); 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric // If we're generating a profile, create a variable for the name. 440b57cec5SDimitry Andric if (CGM.getCodeGenOpts().hasProfileClangInstr()) 450b57cec5SDimitry Andric FuncNameVar = llvm::createPGOFuncNameVar(CGM.getModule(), Linkage, FuncName); 460b57cec5SDimitry Andric } 470b57cec5SDimitry Andric 480b57cec5SDimitry Andric void CodeGenPGO::setFuncName(llvm::Function *Fn) { 490b57cec5SDimitry Andric setFuncName(Fn->getName(), Fn->getLinkage()); 500b57cec5SDimitry Andric // Create PGOFuncName meta data. 510b57cec5SDimitry Andric llvm::createPGOFuncNameMetadata(*Fn, FuncName); 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric /// The version of the PGO hash algorithm. 550b57cec5SDimitry Andric enum PGOHashVersion : unsigned { 560b57cec5SDimitry Andric PGO_HASH_V1, 570b57cec5SDimitry Andric PGO_HASH_V2, 585ffd83dbSDimitry Andric PGO_HASH_V3, 590b57cec5SDimitry Andric 600b57cec5SDimitry Andric // Keep this set to the latest hash version. 615ffd83dbSDimitry Andric PGO_HASH_LATEST = PGO_HASH_V3 620b57cec5SDimitry Andric }; 630b57cec5SDimitry Andric 640b57cec5SDimitry Andric namespace { 650b57cec5SDimitry Andric /// Stable hasher for PGO region counters. 660b57cec5SDimitry Andric /// 670b57cec5SDimitry Andric /// PGOHash produces a stable hash of a given function's control flow. 680b57cec5SDimitry Andric /// 690b57cec5SDimitry Andric /// Changing the output of this hash will invalidate all previously generated 700b57cec5SDimitry Andric /// profiles -- i.e., don't do it. 710b57cec5SDimitry Andric /// 720b57cec5SDimitry Andric /// \note When this hash does eventually change (years?), we still need to 730b57cec5SDimitry Andric /// support old hashes. We'll need to pull in the version number from the 740b57cec5SDimitry Andric /// profile data format and use the matching hash function. 750b57cec5SDimitry Andric class PGOHash { 760b57cec5SDimitry Andric uint64_t Working; 770b57cec5SDimitry Andric unsigned Count; 780b57cec5SDimitry Andric PGOHashVersion HashVersion; 790b57cec5SDimitry Andric llvm::MD5 MD5; 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric static const int NumBitsPerType = 6; 820b57cec5SDimitry Andric static const unsigned NumTypesPerWord = sizeof(uint64_t) * 8 / NumBitsPerType; 830b57cec5SDimitry Andric static const unsigned TooBig = 1u << NumBitsPerType; 840b57cec5SDimitry Andric 850b57cec5SDimitry Andric public: 860b57cec5SDimitry Andric /// Hash values for AST nodes. 870b57cec5SDimitry Andric /// 880b57cec5SDimitry Andric /// Distinct values for AST nodes that have region counters attached. 890b57cec5SDimitry Andric /// 900b57cec5SDimitry Andric /// These values must be stable. All new members must be added at the end, 910b57cec5SDimitry Andric /// and no members should be removed. Changing the enumeration value for an 920b57cec5SDimitry Andric /// AST node will affect the hash of every function that contains that node. 930b57cec5SDimitry Andric enum HashType : unsigned char { 940b57cec5SDimitry Andric None = 0, 950b57cec5SDimitry Andric LabelStmt = 1, 960b57cec5SDimitry Andric WhileStmt, 970b57cec5SDimitry Andric DoStmt, 980b57cec5SDimitry Andric ForStmt, 990b57cec5SDimitry Andric CXXForRangeStmt, 1000b57cec5SDimitry Andric ObjCForCollectionStmt, 1010b57cec5SDimitry Andric SwitchStmt, 1020b57cec5SDimitry Andric CaseStmt, 1030b57cec5SDimitry Andric DefaultStmt, 1040b57cec5SDimitry Andric IfStmt, 1050b57cec5SDimitry Andric CXXTryStmt, 1060b57cec5SDimitry Andric CXXCatchStmt, 1070b57cec5SDimitry Andric ConditionalOperator, 1080b57cec5SDimitry Andric BinaryOperatorLAnd, 1090b57cec5SDimitry Andric BinaryOperatorLOr, 1100b57cec5SDimitry Andric BinaryConditionalOperator, 1110b57cec5SDimitry Andric // The preceding values are available with PGO_HASH_V1. 1120b57cec5SDimitry Andric 1130b57cec5SDimitry Andric EndOfScope, 1140b57cec5SDimitry Andric IfThenBranch, 1150b57cec5SDimitry Andric IfElseBranch, 1160b57cec5SDimitry Andric GotoStmt, 1170b57cec5SDimitry Andric IndirectGotoStmt, 1180b57cec5SDimitry Andric BreakStmt, 1190b57cec5SDimitry Andric ContinueStmt, 1200b57cec5SDimitry Andric ReturnStmt, 1210b57cec5SDimitry Andric ThrowExpr, 1220b57cec5SDimitry Andric UnaryOperatorLNot, 1230b57cec5SDimitry Andric BinaryOperatorLT, 1240b57cec5SDimitry Andric BinaryOperatorGT, 1250b57cec5SDimitry Andric BinaryOperatorLE, 1260b57cec5SDimitry Andric BinaryOperatorGE, 1270b57cec5SDimitry Andric BinaryOperatorEQ, 1280b57cec5SDimitry Andric BinaryOperatorNE, 1295ffd83dbSDimitry Andric // The preceding values are available since PGO_HASH_V2. 1300b57cec5SDimitry Andric 1310b57cec5SDimitry Andric // Keep this last. It's for the static assert that follows. 1320b57cec5SDimitry Andric LastHashType 1330b57cec5SDimitry Andric }; 1340b57cec5SDimitry Andric static_assert(LastHashType <= TooBig, "Too many types in HashType"); 1350b57cec5SDimitry Andric 1360b57cec5SDimitry Andric PGOHash(PGOHashVersion HashVersion) 13704eeddc0SDimitry Andric : Working(0), Count(0), HashVersion(HashVersion) {} 1380b57cec5SDimitry Andric void combine(HashType Type); 1390b57cec5SDimitry Andric uint64_t finalize(); 1400b57cec5SDimitry Andric PGOHashVersion getHashVersion() const { return HashVersion; } 1410b57cec5SDimitry Andric }; 1420b57cec5SDimitry Andric const int PGOHash::NumBitsPerType; 1430b57cec5SDimitry Andric const unsigned PGOHash::NumTypesPerWord; 1440b57cec5SDimitry Andric const unsigned PGOHash::TooBig; 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric /// Get the PGO hash version used in the given indexed profile. 1470b57cec5SDimitry Andric static PGOHashVersion getPGOHashVersion(llvm::IndexedInstrProfReader *PGOReader, 1480b57cec5SDimitry Andric CodeGenModule &CGM) { 1490b57cec5SDimitry Andric if (PGOReader->getVersion() <= 4) 1500b57cec5SDimitry Andric return PGO_HASH_V1; 1515ffd83dbSDimitry Andric if (PGOReader->getVersion() <= 5) 1520b57cec5SDimitry Andric return PGO_HASH_V2; 1535ffd83dbSDimitry Andric return PGO_HASH_V3; 1540b57cec5SDimitry Andric } 1550b57cec5SDimitry Andric 1560b57cec5SDimitry Andric /// A RecursiveASTVisitor that fills a map of statements to PGO counters. 1570b57cec5SDimitry Andric struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> { 1580b57cec5SDimitry Andric using Base = RecursiveASTVisitor<MapRegionCounters>; 1590b57cec5SDimitry Andric 1600b57cec5SDimitry Andric /// The next counter value to assign. 1610b57cec5SDimitry Andric unsigned NextCounter; 1620b57cec5SDimitry Andric /// The function hash. 1630b57cec5SDimitry Andric PGOHash Hash; 1640b57cec5SDimitry Andric /// The map of statements to counters. 1650b57cec5SDimitry Andric llvm::DenseMap<const Stmt *, unsigned> &CounterMap; 166cdc20ff6SDimitry Andric /// The next bitmap byte index to assign. 167cdc20ff6SDimitry Andric unsigned NextMCDCBitmapIdx; 168cdc20ff6SDimitry Andric /// The map of statements to MC/DC bitmap coverage objects. 169cdc20ff6SDimitry Andric llvm::DenseMap<const Stmt *, unsigned> &MCDCBitmapMap; 170cdc20ff6SDimitry Andric /// Maximum number of supported MC/DC conditions in a boolean expression. 171cdc20ff6SDimitry Andric unsigned MCDCMaxCond; 172e8d8bef9SDimitry Andric /// The profile version. 173e8d8bef9SDimitry Andric uint64_t ProfileVersion; 174cdc20ff6SDimitry Andric /// Diagnostics Engine used to report warnings. 175cdc20ff6SDimitry Andric DiagnosticsEngine &Diag; 1760b57cec5SDimitry Andric 177e8d8bef9SDimitry Andric MapRegionCounters(PGOHashVersion HashVersion, uint64_t ProfileVersion, 178cdc20ff6SDimitry Andric llvm::DenseMap<const Stmt *, unsigned> &CounterMap, 179cdc20ff6SDimitry Andric llvm::DenseMap<const Stmt *, unsigned> &MCDCBitmapMap, 180cdc20ff6SDimitry Andric unsigned MCDCMaxCond, DiagnosticsEngine &Diag) 181e8d8bef9SDimitry Andric : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap), 182cdc20ff6SDimitry Andric NextMCDCBitmapIdx(0), MCDCBitmapMap(MCDCBitmapMap), 183cdc20ff6SDimitry Andric MCDCMaxCond(MCDCMaxCond), ProfileVersion(ProfileVersion), Diag(Diag) {} 1840b57cec5SDimitry Andric 1850b57cec5SDimitry Andric // Blocks and lambdas are handled as separate functions, so we need not 1860b57cec5SDimitry Andric // traverse them in the parent context. 1870b57cec5SDimitry Andric bool TraverseBlockExpr(BlockExpr *BE) { return true; } 1880b57cec5SDimitry Andric bool TraverseLambdaExpr(LambdaExpr *LE) { 1890b57cec5SDimitry Andric // Traverse the captures, but not the body. 190480093f4SDimitry Andric for (auto C : zip(LE->captures(), LE->capture_inits())) 1910b57cec5SDimitry Andric TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C)); 1920b57cec5SDimitry Andric return true; 1930b57cec5SDimitry Andric } 1940b57cec5SDimitry Andric bool TraverseCapturedStmt(CapturedStmt *CS) { return true; } 1950b57cec5SDimitry Andric 1960b57cec5SDimitry Andric bool VisitDecl(const Decl *D) { 1970b57cec5SDimitry Andric switch (D->getKind()) { 1980b57cec5SDimitry Andric default: 1990b57cec5SDimitry Andric break; 2000b57cec5SDimitry Andric case Decl::Function: 2010b57cec5SDimitry Andric case Decl::CXXMethod: 2020b57cec5SDimitry Andric case Decl::CXXConstructor: 2030b57cec5SDimitry Andric case Decl::CXXDestructor: 2040b57cec5SDimitry Andric case Decl::CXXConversion: 2050b57cec5SDimitry Andric case Decl::ObjCMethod: 2060b57cec5SDimitry Andric case Decl::Block: 2070b57cec5SDimitry Andric case Decl::Captured: 2080b57cec5SDimitry Andric CounterMap[D->getBody()] = NextCounter++; 2090b57cec5SDimitry Andric break; 2100b57cec5SDimitry Andric } 2110b57cec5SDimitry Andric return true; 2120b57cec5SDimitry Andric } 2130b57cec5SDimitry Andric 2140b57cec5SDimitry Andric /// If \p S gets a fresh counter, update the counter mappings. Return the 2150b57cec5SDimitry Andric /// V1 hash of \p S. 2160b57cec5SDimitry Andric PGOHash::HashType updateCounterMappings(Stmt *S) { 2170b57cec5SDimitry Andric auto Type = getHashType(PGO_HASH_V1, S); 2180b57cec5SDimitry Andric if (Type != PGOHash::None) 2190b57cec5SDimitry Andric CounterMap[S] = NextCounter++; 2200b57cec5SDimitry Andric return Type; 2210b57cec5SDimitry Andric } 2220b57cec5SDimitry Andric 223cdc20ff6SDimitry Andric /// The following stacks are used with dataTraverseStmtPre() and 224cdc20ff6SDimitry Andric /// dataTraverseStmtPost() to track the depth of nested logical operators in a 225cdc20ff6SDimitry Andric /// boolean expression in a function. The ultimate purpose is to keep track 226cdc20ff6SDimitry Andric /// of the number of leaf-level conditions in the boolean expression so that a 227cdc20ff6SDimitry Andric /// profile bitmap can be allocated based on that number. 228cdc20ff6SDimitry Andric /// 229cdc20ff6SDimitry Andric /// The stacks are also used to find error cases and notify the user. A 230cdc20ff6SDimitry Andric /// standard logical operator nest for a boolean expression could be in a form 231cdc20ff6SDimitry Andric /// similar to this: "x = a && b && c && (d || f)" 232cdc20ff6SDimitry Andric unsigned NumCond = 0; 233cdc20ff6SDimitry Andric bool SplitNestedLogicalOp = false; 234cdc20ff6SDimitry Andric SmallVector<const Stmt *, 16> NonLogOpStack; 235cdc20ff6SDimitry Andric SmallVector<const BinaryOperator *, 16> LogOpStack; 236cdc20ff6SDimitry Andric 237cdc20ff6SDimitry Andric // Hook: dataTraverseStmtPre() is invoked prior to visiting an AST Stmt node. 238cdc20ff6SDimitry Andric bool dataTraverseStmtPre(Stmt *S) { 239cdc20ff6SDimitry Andric /// If MC/DC is not enabled, MCDCMaxCond will be set to 0. Do nothing. 240cdc20ff6SDimitry Andric if (MCDCMaxCond == 0) 241cdc20ff6SDimitry Andric return true; 242cdc20ff6SDimitry Andric 243cdc20ff6SDimitry Andric /// At the top of the logical operator nest, reset the number of conditions. 244cdc20ff6SDimitry Andric if (LogOpStack.empty()) 245cdc20ff6SDimitry Andric NumCond = 0; 246cdc20ff6SDimitry Andric 247cdc20ff6SDimitry Andric if (const Expr *E = dyn_cast<Expr>(S)) { 248cdc20ff6SDimitry Andric const BinaryOperator *BinOp = dyn_cast<BinaryOperator>(E->IgnoreParens()); 249cdc20ff6SDimitry Andric if (BinOp && BinOp->isLogicalOp()) { 250cdc20ff6SDimitry Andric /// Check for "split-nested" logical operators. This happens when a new 251cdc20ff6SDimitry Andric /// boolean expression logical-op nest is encountered within an existing 252cdc20ff6SDimitry Andric /// boolean expression, separated by a non-logical operator. For 253cdc20ff6SDimitry Andric /// example, in "x = (a && b && c && foo(d && f))", the "d && f" case 254cdc20ff6SDimitry Andric /// starts a new boolean expression that is separated from the other 255cdc20ff6SDimitry Andric /// conditions by the operator foo(). Split-nested cases are not 256cdc20ff6SDimitry Andric /// supported by MC/DC. 257cdc20ff6SDimitry Andric SplitNestedLogicalOp = SplitNestedLogicalOp || !NonLogOpStack.empty(); 258cdc20ff6SDimitry Andric 259cdc20ff6SDimitry Andric LogOpStack.push_back(BinOp); 260cdc20ff6SDimitry Andric return true; 261cdc20ff6SDimitry Andric } 262cdc20ff6SDimitry Andric } 263cdc20ff6SDimitry Andric 264cdc20ff6SDimitry Andric /// Keep track of non-logical operators. These are OK as long as we don't 265cdc20ff6SDimitry Andric /// encounter a new logical operator after seeing one. 266cdc20ff6SDimitry Andric if (!LogOpStack.empty()) 267cdc20ff6SDimitry Andric NonLogOpStack.push_back(S); 268cdc20ff6SDimitry Andric 269cdc20ff6SDimitry Andric return true; 270cdc20ff6SDimitry Andric } 271cdc20ff6SDimitry Andric 272cdc20ff6SDimitry Andric // Hook: dataTraverseStmtPost() is invoked by the AST visitor after visiting 273cdc20ff6SDimitry Andric // an AST Stmt node. MC/DC will use it to to signal when the top of a 274cdc20ff6SDimitry Andric // logical operation (boolean expression) nest is encountered. 275cdc20ff6SDimitry Andric bool dataTraverseStmtPost(Stmt *S) { 276cdc20ff6SDimitry Andric /// If MC/DC is not enabled, MCDCMaxCond will be set to 0. Do nothing. 277cdc20ff6SDimitry Andric if (MCDCMaxCond == 0) 278cdc20ff6SDimitry Andric return true; 279cdc20ff6SDimitry Andric 280cdc20ff6SDimitry Andric if (const Expr *E = dyn_cast<Expr>(S)) { 281cdc20ff6SDimitry Andric const BinaryOperator *BinOp = dyn_cast<BinaryOperator>(E->IgnoreParens()); 282cdc20ff6SDimitry Andric if (BinOp && BinOp->isLogicalOp()) { 283cdc20ff6SDimitry Andric assert(LogOpStack.back() == BinOp); 284cdc20ff6SDimitry Andric LogOpStack.pop_back(); 285cdc20ff6SDimitry Andric 286cdc20ff6SDimitry Andric /// At the top of logical operator nest: 287cdc20ff6SDimitry Andric if (LogOpStack.empty()) { 288cdc20ff6SDimitry Andric /// Was the "split-nested" logical operator case encountered? 289cdc20ff6SDimitry Andric if (SplitNestedLogicalOp) { 290cdc20ff6SDimitry Andric unsigned DiagID = Diag.getCustomDiagID( 291cdc20ff6SDimitry Andric DiagnosticsEngine::Warning, 292cdc20ff6SDimitry Andric "unsupported MC/DC boolean expression; " 293cdc20ff6SDimitry Andric "contains an operation with a nested boolean expression. " 294cdc20ff6SDimitry Andric "Expression will not be covered"); 295cdc20ff6SDimitry Andric Diag.Report(S->getBeginLoc(), DiagID); 296cdc20ff6SDimitry Andric return false; 297cdc20ff6SDimitry Andric } 298cdc20ff6SDimitry Andric 299cdc20ff6SDimitry Andric /// Was the maximum number of conditions encountered? 300cdc20ff6SDimitry Andric if (NumCond > MCDCMaxCond) { 301cdc20ff6SDimitry Andric unsigned DiagID = Diag.getCustomDiagID( 302cdc20ff6SDimitry Andric DiagnosticsEngine::Warning, 303cdc20ff6SDimitry Andric "unsupported MC/DC boolean expression; " 304cdc20ff6SDimitry Andric "number of conditions (%0) exceeds max (%1). " 305cdc20ff6SDimitry Andric "Expression will not be covered"); 306cdc20ff6SDimitry Andric Diag.Report(S->getBeginLoc(), DiagID) << NumCond << MCDCMaxCond; 307cdc20ff6SDimitry Andric return false; 308cdc20ff6SDimitry Andric } 309cdc20ff6SDimitry Andric 310cdc20ff6SDimitry Andric // Otherwise, allocate the number of bytes required for the bitmap 311cdc20ff6SDimitry Andric // based on the number of conditions. Must be at least 1-byte long. 312cdc20ff6SDimitry Andric MCDCBitmapMap[BinOp] = NextMCDCBitmapIdx; 313cdc20ff6SDimitry Andric unsigned SizeInBits = std::max<unsigned>(1L << NumCond, CHAR_BIT); 314cdc20ff6SDimitry Andric NextMCDCBitmapIdx += SizeInBits / CHAR_BIT; 315cdc20ff6SDimitry Andric } 316cdc20ff6SDimitry Andric return true; 317cdc20ff6SDimitry Andric } 318cdc20ff6SDimitry Andric } 319cdc20ff6SDimitry Andric 320cdc20ff6SDimitry Andric if (!LogOpStack.empty()) 321cdc20ff6SDimitry Andric NonLogOpStack.pop_back(); 322cdc20ff6SDimitry Andric 323cdc20ff6SDimitry Andric return true; 324cdc20ff6SDimitry Andric } 325cdc20ff6SDimitry Andric 326e8d8bef9SDimitry Andric /// The RHS of all logical operators gets a fresh counter in order to count 327e8d8bef9SDimitry Andric /// how many times the RHS evaluates to true or false, depending on the 328e8d8bef9SDimitry Andric /// semantics of the operator. This is only valid for ">= v7" of the profile 329cdc20ff6SDimitry Andric /// version so that we facilitate backward compatibility. In addition, in 330cdc20ff6SDimitry Andric /// order to use MC/DC, count the number of total LHS and RHS conditions. 331e8d8bef9SDimitry Andric bool VisitBinaryOperator(BinaryOperator *S) { 332cdc20ff6SDimitry Andric if (S->isLogicalOp()) { 333cdc20ff6SDimitry Andric if (CodeGenFunction::isInstrumentedCondition(S->getLHS())) 334cdc20ff6SDimitry Andric NumCond++; 335cdc20ff6SDimitry Andric 336cdc20ff6SDimitry Andric if (CodeGenFunction::isInstrumentedCondition(S->getRHS())) { 337e8d8bef9SDimitry Andric if (ProfileVersion >= llvm::IndexedInstrProf::Version7) 338e8d8bef9SDimitry Andric CounterMap[S->getRHS()] = NextCounter++; 339cdc20ff6SDimitry Andric 340cdc20ff6SDimitry Andric NumCond++; 341cdc20ff6SDimitry Andric } 342cdc20ff6SDimitry Andric } 343e8d8bef9SDimitry Andric return Base::VisitBinaryOperator(S); 344e8d8bef9SDimitry Andric } 345e8d8bef9SDimitry Andric 3460b57cec5SDimitry Andric /// Include \p S in the function hash. 3470b57cec5SDimitry Andric bool VisitStmt(Stmt *S) { 3480b57cec5SDimitry Andric auto Type = updateCounterMappings(S); 3490b57cec5SDimitry Andric if (Hash.getHashVersion() != PGO_HASH_V1) 3500b57cec5SDimitry Andric Type = getHashType(Hash.getHashVersion(), S); 3510b57cec5SDimitry Andric if (Type != PGOHash::None) 3520b57cec5SDimitry Andric Hash.combine(Type); 3530b57cec5SDimitry Andric return true; 3540b57cec5SDimitry Andric } 3550b57cec5SDimitry Andric 3560b57cec5SDimitry Andric bool TraverseIfStmt(IfStmt *If) { 3570b57cec5SDimitry Andric // If we used the V1 hash, use the default traversal. 3580b57cec5SDimitry Andric if (Hash.getHashVersion() == PGO_HASH_V1) 3590b57cec5SDimitry Andric return Base::TraverseIfStmt(If); 3600b57cec5SDimitry Andric 3610b57cec5SDimitry Andric // Otherwise, keep track of which branch we're in while traversing. 3620b57cec5SDimitry Andric VisitStmt(If); 3630b57cec5SDimitry Andric for (Stmt *CS : If->children()) { 3640b57cec5SDimitry Andric if (!CS) 3650b57cec5SDimitry Andric continue; 3660b57cec5SDimitry Andric if (CS == If->getThen()) 3670b57cec5SDimitry Andric Hash.combine(PGOHash::IfThenBranch); 3680b57cec5SDimitry Andric else if (CS == If->getElse()) 3690b57cec5SDimitry Andric Hash.combine(PGOHash::IfElseBranch); 3700b57cec5SDimitry Andric TraverseStmt(CS); 3710b57cec5SDimitry Andric } 3720b57cec5SDimitry Andric Hash.combine(PGOHash::EndOfScope); 3730b57cec5SDimitry Andric return true; 3740b57cec5SDimitry Andric } 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric // If the statement type \p N is nestable, and its nesting impacts profile 3770b57cec5SDimitry Andric // stability, define a custom traversal which tracks the end of the statement 3780b57cec5SDimitry Andric // in the hash (provided we're not using the V1 hash). 3790b57cec5SDimitry Andric #define DEFINE_NESTABLE_TRAVERSAL(N) \ 3800b57cec5SDimitry Andric bool Traverse##N(N *S) { \ 3810b57cec5SDimitry Andric Base::Traverse##N(S); \ 3820b57cec5SDimitry Andric if (Hash.getHashVersion() != PGO_HASH_V1) \ 3830b57cec5SDimitry Andric Hash.combine(PGOHash::EndOfScope); \ 3840b57cec5SDimitry Andric return true; \ 3850b57cec5SDimitry Andric } 3860b57cec5SDimitry Andric 3870b57cec5SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(WhileStmt) 3880b57cec5SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(DoStmt) 3890b57cec5SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(ForStmt) 3900b57cec5SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(CXXForRangeStmt) 3910b57cec5SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(ObjCForCollectionStmt) 3920b57cec5SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(CXXTryStmt) 3930b57cec5SDimitry Andric DEFINE_NESTABLE_TRAVERSAL(CXXCatchStmt) 3940b57cec5SDimitry Andric 3950b57cec5SDimitry Andric /// Get version \p HashVersion of the PGO hash for \p S. 3960b57cec5SDimitry Andric PGOHash::HashType getHashType(PGOHashVersion HashVersion, const Stmt *S) { 3970b57cec5SDimitry Andric switch (S->getStmtClass()) { 3980b57cec5SDimitry Andric default: 3990b57cec5SDimitry Andric break; 4000b57cec5SDimitry Andric case Stmt::LabelStmtClass: 4010b57cec5SDimitry Andric return PGOHash::LabelStmt; 4020b57cec5SDimitry Andric case Stmt::WhileStmtClass: 4030b57cec5SDimitry Andric return PGOHash::WhileStmt; 4040b57cec5SDimitry Andric case Stmt::DoStmtClass: 4050b57cec5SDimitry Andric return PGOHash::DoStmt; 4060b57cec5SDimitry Andric case Stmt::ForStmtClass: 4070b57cec5SDimitry Andric return PGOHash::ForStmt; 4080b57cec5SDimitry Andric case Stmt::CXXForRangeStmtClass: 4090b57cec5SDimitry Andric return PGOHash::CXXForRangeStmt; 4100b57cec5SDimitry Andric case Stmt::ObjCForCollectionStmtClass: 4110b57cec5SDimitry Andric return PGOHash::ObjCForCollectionStmt; 4120b57cec5SDimitry Andric case Stmt::SwitchStmtClass: 4130b57cec5SDimitry Andric return PGOHash::SwitchStmt; 4140b57cec5SDimitry Andric case Stmt::CaseStmtClass: 4150b57cec5SDimitry Andric return PGOHash::CaseStmt; 4160b57cec5SDimitry Andric case Stmt::DefaultStmtClass: 4170b57cec5SDimitry Andric return PGOHash::DefaultStmt; 4180b57cec5SDimitry Andric case Stmt::IfStmtClass: 4190b57cec5SDimitry Andric return PGOHash::IfStmt; 4200b57cec5SDimitry Andric case Stmt::CXXTryStmtClass: 4210b57cec5SDimitry Andric return PGOHash::CXXTryStmt; 4220b57cec5SDimitry Andric case Stmt::CXXCatchStmtClass: 4230b57cec5SDimitry Andric return PGOHash::CXXCatchStmt; 4240b57cec5SDimitry Andric case Stmt::ConditionalOperatorClass: 4250b57cec5SDimitry Andric return PGOHash::ConditionalOperator; 4260b57cec5SDimitry Andric case Stmt::BinaryConditionalOperatorClass: 4270b57cec5SDimitry Andric return PGOHash::BinaryConditionalOperator; 4280b57cec5SDimitry Andric case Stmt::BinaryOperatorClass: { 4290b57cec5SDimitry Andric const BinaryOperator *BO = cast<BinaryOperator>(S); 4300b57cec5SDimitry Andric if (BO->getOpcode() == BO_LAnd) 4310b57cec5SDimitry Andric return PGOHash::BinaryOperatorLAnd; 4320b57cec5SDimitry Andric if (BO->getOpcode() == BO_LOr) 4330b57cec5SDimitry Andric return PGOHash::BinaryOperatorLOr; 4345ffd83dbSDimitry Andric if (HashVersion >= PGO_HASH_V2) { 4350b57cec5SDimitry Andric switch (BO->getOpcode()) { 4360b57cec5SDimitry Andric default: 4370b57cec5SDimitry Andric break; 4380b57cec5SDimitry Andric case BO_LT: 4390b57cec5SDimitry Andric return PGOHash::BinaryOperatorLT; 4400b57cec5SDimitry Andric case BO_GT: 4410b57cec5SDimitry Andric return PGOHash::BinaryOperatorGT; 4420b57cec5SDimitry Andric case BO_LE: 4430b57cec5SDimitry Andric return PGOHash::BinaryOperatorLE; 4440b57cec5SDimitry Andric case BO_GE: 4450b57cec5SDimitry Andric return PGOHash::BinaryOperatorGE; 4460b57cec5SDimitry Andric case BO_EQ: 4470b57cec5SDimitry Andric return PGOHash::BinaryOperatorEQ; 4480b57cec5SDimitry Andric case BO_NE: 4490b57cec5SDimitry Andric return PGOHash::BinaryOperatorNE; 4500b57cec5SDimitry Andric } 4510b57cec5SDimitry Andric } 4520b57cec5SDimitry Andric break; 4530b57cec5SDimitry Andric } 4540b57cec5SDimitry Andric } 4550b57cec5SDimitry Andric 4565ffd83dbSDimitry Andric if (HashVersion >= PGO_HASH_V2) { 4570b57cec5SDimitry Andric switch (S->getStmtClass()) { 4580b57cec5SDimitry Andric default: 4590b57cec5SDimitry Andric break; 4600b57cec5SDimitry Andric case Stmt::GotoStmtClass: 4610b57cec5SDimitry Andric return PGOHash::GotoStmt; 4620b57cec5SDimitry Andric case Stmt::IndirectGotoStmtClass: 4630b57cec5SDimitry Andric return PGOHash::IndirectGotoStmt; 4640b57cec5SDimitry Andric case Stmt::BreakStmtClass: 4650b57cec5SDimitry Andric return PGOHash::BreakStmt; 4660b57cec5SDimitry Andric case Stmt::ContinueStmtClass: 4670b57cec5SDimitry Andric return PGOHash::ContinueStmt; 4680b57cec5SDimitry Andric case Stmt::ReturnStmtClass: 4690b57cec5SDimitry Andric return PGOHash::ReturnStmt; 4700b57cec5SDimitry Andric case Stmt::CXXThrowExprClass: 4710b57cec5SDimitry Andric return PGOHash::ThrowExpr; 4720b57cec5SDimitry Andric case Stmt::UnaryOperatorClass: { 4730b57cec5SDimitry Andric const UnaryOperator *UO = cast<UnaryOperator>(S); 4740b57cec5SDimitry Andric if (UO->getOpcode() == UO_LNot) 4750b57cec5SDimitry Andric return PGOHash::UnaryOperatorLNot; 4760b57cec5SDimitry Andric break; 4770b57cec5SDimitry Andric } 4780b57cec5SDimitry Andric } 4790b57cec5SDimitry Andric } 4800b57cec5SDimitry Andric 4810b57cec5SDimitry Andric return PGOHash::None; 4820b57cec5SDimitry Andric } 4830b57cec5SDimitry Andric }; 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric /// A StmtVisitor that propagates the raw counts through the AST and 4860b57cec5SDimitry Andric /// records the count at statements where the value may change. 4870b57cec5SDimitry Andric struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> { 4880b57cec5SDimitry Andric /// PGO state. 4890b57cec5SDimitry Andric CodeGenPGO &PGO; 4900b57cec5SDimitry Andric 4910b57cec5SDimitry Andric /// A flag that is set when the current count should be recorded on the 4920b57cec5SDimitry Andric /// next statement, such as at the exit of a loop. 4930b57cec5SDimitry Andric bool RecordNextStmtCount; 4940b57cec5SDimitry Andric 4950b57cec5SDimitry Andric /// The count at the current location in the traversal. 4960b57cec5SDimitry Andric uint64_t CurrentCount; 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric /// The map of statements to count values. 4990b57cec5SDimitry Andric llvm::DenseMap<const Stmt *, uint64_t> &CountMap; 5000b57cec5SDimitry Andric 5010b57cec5SDimitry Andric /// BreakContinueStack - Keep counts of breaks and continues inside loops. 5020b57cec5SDimitry Andric struct BreakContinue { 503c9157d92SDimitry Andric uint64_t BreakCount = 0; 504c9157d92SDimitry Andric uint64_t ContinueCount = 0; 505c9157d92SDimitry Andric BreakContinue() = default; 5060b57cec5SDimitry Andric }; 5070b57cec5SDimitry Andric SmallVector<BreakContinue, 8> BreakContinueStack; 5080b57cec5SDimitry Andric 5090b57cec5SDimitry Andric ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &CountMap, 5100b57cec5SDimitry Andric CodeGenPGO &PGO) 5110b57cec5SDimitry Andric : PGO(PGO), RecordNextStmtCount(false), CountMap(CountMap) {} 5120b57cec5SDimitry Andric 5130b57cec5SDimitry Andric void RecordStmtCount(const Stmt *S) { 5140b57cec5SDimitry Andric if (RecordNextStmtCount) { 5150b57cec5SDimitry Andric CountMap[S] = CurrentCount; 5160b57cec5SDimitry Andric RecordNextStmtCount = false; 5170b57cec5SDimitry Andric } 5180b57cec5SDimitry Andric } 5190b57cec5SDimitry Andric 5200b57cec5SDimitry Andric /// Set and return the current count. 5210b57cec5SDimitry Andric uint64_t setCount(uint64_t Count) { 5220b57cec5SDimitry Andric CurrentCount = Count; 5230b57cec5SDimitry Andric return Count; 5240b57cec5SDimitry Andric } 5250b57cec5SDimitry Andric 5260b57cec5SDimitry Andric void VisitStmt(const Stmt *S) { 5270b57cec5SDimitry Andric RecordStmtCount(S); 5280b57cec5SDimitry Andric for (const Stmt *Child : S->children()) 5290b57cec5SDimitry Andric if (Child) 5300b57cec5SDimitry Andric this->Visit(Child); 5310b57cec5SDimitry Andric } 5320b57cec5SDimitry Andric 5330b57cec5SDimitry Andric void VisitFunctionDecl(const FunctionDecl *D) { 5340b57cec5SDimitry Andric // Counter tracks entry to the function body. 5350b57cec5SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); 5360b57cec5SDimitry Andric CountMap[D->getBody()] = BodyCount; 5370b57cec5SDimitry Andric Visit(D->getBody()); 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric // Skip lambda expressions. We visit these as FunctionDecls when we're 5410b57cec5SDimitry Andric // generating them and aren't interested in the body when generating a 5420b57cec5SDimitry Andric // parent context. 5430b57cec5SDimitry Andric void VisitLambdaExpr(const LambdaExpr *LE) {} 5440b57cec5SDimitry Andric 5450b57cec5SDimitry Andric void VisitCapturedDecl(const CapturedDecl *D) { 5460b57cec5SDimitry Andric // Counter tracks entry to the capture body. 5470b57cec5SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); 5480b57cec5SDimitry Andric CountMap[D->getBody()] = BodyCount; 5490b57cec5SDimitry Andric Visit(D->getBody()); 5500b57cec5SDimitry Andric } 5510b57cec5SDimitry Andric 5520b57cec5SDimitry Andric void VisitObjCMethodDecl(const ObjCMethodDecl *D) { 5530b57cec5SDimitry Andric // Counter tracks entry to the method body. 5540b57cec5SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); 5550b57cec5SDimitry Andric CountMap[D->getBody()] = BodyCount; 5560b57cec5SDimitry Andric Visit(D->getBody()); 5570b57cec5SDimitry Andric } 5580b57cec5SDimitry Andric 5590b57cec5SDimitry Andric void VisitBlockDecl(const BlockDecl *D) { 5600b57cec5SDimitry Andric // Counter tracks entry to the block body. 5610b57cec5SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody())); 5620b57cec5SDimitry Andric CountMap[D->getBody()] = BodyCount; 5630b57cec5SDimitry Andric Visit(D->getBody()); 5640b57cec5SDimitry Andric } 5650b57cec5SDimitry Andric 5660b57cec5SDimitry Andric void VisitReturnStmt(const ReturnStmt *S) { 5670b57cec5SDimitry Andric RecordStmtCount(S); 5680b57cec5SDimitry Andric if (S->getRetValue()) 5690b57cec5SDimitry Andric Visit(S->getRetValue()); 5700b57cec5SDimitry Andric CurrentCount = 0; 5710b57cec5SDimitry Andric RecordNextStmtCount = true; 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric void VisitCXXThrowExpr(const CXXThrowExpr *E) { 5750b57cec5SDimitry Andric RecordStmtCount(E); 5760b57cec5SDimitry Andric if (E->getSubExpr()) 5770b57cec5SDimitry Andric Visit(E->getSubExpr()); 5780b57cec5SDimitry Andric CurrentCount = 0; 5790b57cec5SDimitry Andric RecordNextStmtCount = true; 5800b57cec5SDimitry Andric } 5810b57cec5SDimitry Andric 5820b57cec5SDimitry Andric void VisitGotoStmt(const GotoStmt *S) { 5830b57cec5SDimitry Andric RecordStmtCount(S); 5840b57cec5SDimitry Andric CurrentCount = 0; 5850b57cec5SDimitry Andric RecordNextStmtCount = true; 5860b57cec5SDimitry Andric } 5870b57cec5SDimitry Andric 5880b57cec5SDimitry Andric void VisitLabelStmt(const LabelStmt *S) { 5890b57cec5SDimitry Andric RecordNextStmtCount = false; 5900b57cec5SDimitry Andric // Counter tracks the block following the label. 5910b57cec5SDimitry Andric uint64_t BlockCount = setCount(PGO.getRegionCount(S)); 5920b57cec5SDimitry Andric CountMap[S] = BlockCount; 5930b57cec5SDimitry Andric Visit(S->getSubStmt()); 5940b57cec5SDimitry Andric } 5950b57cec5SDimitry Andric 5960b57cec5SDimitry Andric void VisitBreakStmt(const BreakStmt *S) { 5970b57cec5SDimitry Andric RecordStmtCount(S); 5980b57cec5SDimitry Andric assert(!BreakContinueStack.empty() && "break not in a loop or switch!"); 5990b57cec5SDimitry Andric BreakContinueStack.back().BreakCount += CurrentCount; 6000b57cec5SDimitry Andric CurrentCount = 0; 6010b57cec5SDimitry Andric RecordNextStmtCount = true; 6020b57cec5SDimitry Andric } 6030b57cec5SDimitry Andric 6040b57cec5SDimitry Andric void VisitContinueStmt(const ContinueStmt *S) { 6050b57cec5SDimitry Andric RecordStmtCount(S); 6060b57cec5SDimitry Andric assert(!BreakContinueStack.empty() && "continue stmt not in a loop!"); 6070b57cec5SDimitry Andric BreakContinueStack.back().ContinueCount += CurrentCount; 6080b57cec5SDimitry Andric CurrentCount = 0; 6090b57cec5SDimitry Andric RecordNextStmtCount = true; 6100b57cec5SDimitry Andric } 6110b57cec5SDimitry Andric 6120b57cec5SDimitry Andric void VisitWhileStmt(const WhileStmt *S) { 6130b57cec5SDimitry Andric RecordStmtCount(S); 6140b57cec5SDimitry Andric uint64_t ParentCount = CurrentCount; 6150b57cec5SDimitry Andric 6160b57cec5SDimitry Andric BreakContinueStack.push_back(BreakContinue()); 6170b57cec5SDimitry Andric // Visit the body region first so the break/continue adjustments can be 6180b57cec5SDimitry Andric // included when visiting the condition. 6190b57cec5SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(S)); 6200b57cec5SDimitry Andric CountMap[S->getBody()] = CurrentCount; 6210b57cec5SDimitry Andric Visit(S->getBody()); 6220b57cec5SDimitry Andric uint64_t BackedgeCount = CurrentCount; 6230b57cec5SDimitry Andric 6240b57cec5SDimitry Andric // ...then go back and propagate counts through the condition. The count 6250b57cec5SDimitry Andric // at the start of the condition is the sum of the incoming edges, 6260b57cec5SDimitry Andric // the backedge from the end of the loop body, and the edges from 6270b57cec5SDimitry Andric // continue statements. 6280b57cec5SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val(); 6290b57cec5SDimitry Andric uint64_t CondCount = 6300b57cec5SDimitry Andric setCount(ParentCount + BackedgeCount + BC.ContinueCount); 6310b57cec5SDimitry Andric CountMap[S->getCond()] = CondCount; 6320b57cec5SDimitry Andric Visit(S->getCond()); 6330b57cec5SDimitry Andric setCount(BC.BreakCount + CondCount - BodyCount); 6340b57cec5SDimitry Andric RecordNextStmtCount = true; 6350b57cec5SDimitry Andric } 6360b57cec5SDimitry Andric 6370b57cec5SDimitry Andric void VisitDoStmt(const DoStmt *S) { 6380b57cec5SDimitry Andric RecordStmtCount(S); 6390b57cec5SDimitry Andric uint64_t LoopCount = PGO.getRegionCount(S); 6400b57cec5SDimitry Andric 6410b57cec5SDimitry Andric BreakContinueStack.push_back(BreakContinue()); 6420b57cec5SDimitry Andric // The count doesn't include the fallthrough from the parent scope. Add it. 6430b57cec5SDimitry Andric uint64_t BodyCount = setCount(LoopCount + CurrentCount); 6440b57cec5SDimitry Andric CountMap[S->getBody()] = BodyCount; 6450b57cec5SDimitry Andric Visit(S->getBody()); 6460b57cec5SDimitry Andric uint64_t BackedgeCount = CurrentCount; 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val(); 6490b57cec5SDimitry Andric // The count at the start of the condition is equal to the count at the 6500b57cec5SDimitry Andric // end of the body, plus any continues. 6510b57cec5SDimitry Andric uint64_t CondCount = setCount(BackedgeCount + BC.ContinueCount); 6520b57cec5SDimitry Andric CountMap[S->getCond()] = CondCount; 6530b57cec5SDimitry Andric Visit(S->getCond()); 6540b57cec5SDimitry Andric setCount(BC.BreakCount + CondCount - LoopCount); 6550b57cec5SDimitry Andric RecordNextStmtCount = true; 6560b57cec5SDimitry Andric } 6570b57cec5SDimitry Andric 6580b57cec5SDimitry Andric void VisitForStmt(const ForStmt *S) { 6590b57cec5SDimitry Andric RecordStmtCount(S); 6600b57cec5SDimitry Andric if (S->getInit()) 6610b57cec5SDimitry Andric Visit(S->getInit()); 6620b57cec5SDimitry Andric 6630b57cec5SDimitry Andric uint64_t ParentCount = CurrentCount; 6640b57cec5SDimitry Andric 6650b57cec5SDimitry Andric BreakContinueStack.push_back(BreakContinue()); 6660b57cec5SDimitry Andric // Visit the body region first. (This is basically the same as a while 6670b57cec5SDimitry Andric // loop; see further comments in VisitWhileStmt.) 6680b57cec5SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(S)); 6690b57cec5SDimitry Andric CountMap[S->getBody()] = BodyCount; 6700b57cec5SDimitry Andric Visit(S->getBody()); 6710b57cec5SDimitry Andric uint64_t BackedgeCount = CurrentCount; 6720b57cec5SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val(); 6730b57cec5SDimitry Andric 6740b57cec5SDimitry Andric // The increment is essentially part of the body but it needs to include 6750b57cec5SDimitry Andric // the count for all the continue statements. 6760b57cec5SDimitry Andric if (S->getInc()) { 6770b57cec5SDimitry Andric uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount); 6780b57cec5SDimitry Andric CountMap[S->getInc()] = IncCount; 6790b57cec5SDimitry Andric Visit(S->getInc()); 6800b57cec5SDimitry Andric } 6810b57cec5SDimitry Andric 6820b57cec5SDimitry Andric // ...then go back and propagate counts through the condition. 6830b57cec5SDimitry Andric uint64_t CondCount = 6840b57cec5SDimitry Andric setCount(ParentCount + BackedgeCount + BC.ContinueCount); 6850b57cec5SDimitry Andric if (S->getCond()) { 6860b57cec5SDimitry Andric CountMap[S->getCond()] = CondCount; 6870b57cec5SDimitry Andric Visit(S->getCond()); 6880b57cec5SDimitry Andric } 6890b57cec5SDimitry Andric setCount(BC.BreakCount + CondCount - BodyCount); 6900b57cec5SDimitry Andric RecordNextStmtCount = true; 6910b57cec5SDimitry Andric } 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric void VisitCXXForRangeStmt(const CXXForRangeStmt *S) { 6940b57cec5SDimitry Andric RecordStmtCount(S); 6950b57cec5SDimitry Andric if (S->getInit()) 6960b57cec5SDimitry Andric Visit(S->getInit()); 6970b57cec5SDimitry Andric Visit(S->getLoopVarStmt()); 6980b57cec5SDimitry Andric Visit(S->getRangeStmt()); 6990b57cec5SDimitry Andric Visit(S->getBeginStmt()); 7000b57cec5SDimitry Andric Visit(S->getEndStmt()); 7010b57cec5SDimitry Andric 7020b57cec5SDimitry Andric uint64_t ParentCount = CurrentCount; 7030b57cec5SDimitry Andric BreakContinueStack.push_back(BreakContinue()); 7040b57cec5SDimitry Andric // Visit the body region first. (This is basically the same as a while 7050b57cec5SDimitry Andric // loop; see further comments in VisitWhileStmt.) 7060b57cec5SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(S)); 7070b57cec5SDimitry Andric CountMap[S->getBody()] = BodyCount; 7080b57cec5SDimitry Andric Visit(S->getBody()); 7090b57cec5SDimitry Andric uint64_t BackedgeCount = CurrentCount; 7100b57cec5SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val(); 7110b57cec5SDimitry Andric 7120b57cec5SDimitry Andric // The increment is essentially part of the body but it needs to include 7130b57cec5SDimitry Andric // the count for all the continue statements. 7140b57cec5SDimitry Andric uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount); 7150b57cec5SDimitry Andric CountMap[S->getInc()] = IncCount; 7160b57cec5SDimitry Andric Visit(S->getInc()); 7170b57cec5SDimitry Andric 7180b57cec5SDimitry Andric // ...then go back and propagate counts through the condition. 7190b57cec5SDimitry Andric uint64_t CondCount = 7200b57cec5SDimitry Andric setCount(ParentCount + BackedgeCount + BC.ContinueCount); 7210b57cec5SDimitry Andric CountMap[S->getCond()] = CondCount; 7220b57cec5SDimitry Andric Visit(S->getCond()); 7230b57cec5SDimitry Andric setCount(BC.BreakCount + CondCount - BodyCount); 7240b57cec5SDimitry Andric RecordNextStmtCount = true; 7250b57cec5SDimitry Andric } 7260b57cec5SDimitry Andric 7270b57cec5SDimitry Andric void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) { 7280b57cec5SDimitry Andric RecordStmtCount(S); 7290b57cec5SDimitry Andric Visit(S->getElement()); 7300b57cec5SDimitry Andric uint64_t ParentCount = CurrentCount; 7310b57cec5SDimitry Andric BreakContinueStack.push_back(BreakContinue()); 7320b57cec5SDimitry Andric // Counter tracks the body of the loop. 7330b57cec5SDimitry Andric uint64_t BodyCount = setCount(PGO.getRegionCount(S)); 7340b57cec5SDimitry Andric CountMap[S->getBody()] = BodyCount; 7350b57cec5SDimitry Andric Visit(S->getBody()); 7360b57cec5SDimitry Andric uint64_t BackedgeCount = CurrentCount; 7370b57cec5SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val(); 7380b57cec5SDimitry Andric 7390b57cec5SDimitry Andric setCount(BC.BreakCount + ParentCount + BackedgeCount + BC.ContinueCount - 7400b57cec5SDimitry Andric BodyCount); 7410b57cec5SDimitry Andric RecordNextStmtCount = true; 7420b57cec5SDimitry Andric } 7430b57cec5SDimitry Andric 7440b57cec5SDimitry Andric void VisitSwitchStmt(const SwitchStmt *S) { 7450b57cec5SDimitry Andric RecordStmtCount(S); 7460b57cec5SDimitry Andric if (S->getInit()) 7470b57cec5SDimitry Andric Visit(S->getInit()); 7480b57cec5SDimitry Andric Visit(S->getCond()); 7490b57cec5SDimitry Andric CurrentCount = 0; 7500b57cec5SDimitry Andric BreakContinueStack.push_back(BreakContinue()); 7510b57cec5SDimitry Andric Visit(S->getBody()); 7520b57cec5SDimitry Andric // If the switch is inside a loop, add the continue counts. 7530b57cec5SDimitry Andric BreakContinue BC = BreakContinueStack.pop_back_val(); 7540b57cec5SDimitry Andric if (!BreakContinueStack.empty()) 7550b57cec5SDimitry Andric BreakContinueStack.back().ContinueCount += BC.ContinueCount; 7560b57cec5SDimitry Andric // Counter tracks the exit block of the switch. 7570b57cec5SDimitry Andric setCount(PGO.getRegionCount(S)); 7580b57cec5SDimitry Andric RecordNextStmtCount = true; 7590b57cec5SDimitry Andric } 7600b57cec5SDimitry Andric 7610b57cec5SDimitry Andric void VisitSwitchCase(const SwitchCase *S) { 7620b57cec5SDimitry Andric RecordNextStmtCount = false; 7630b57cec5SDimitry Andric // Counter for this particular case. This counts only jumps from the 7640b57cec5SDimitry Andric // switch header and does not include fallthrough from the case before 7650b57cec5SDimitry Andric // this one. 7660b57cec5SDimitry Andric uint64_t CaseCount = PGO.getRegionCount(S); 7670b57cec5SDimitry Andric setCount(CurrentCount + CaseCount); 7680b57cec5SDimitry Andric // We need the count without fallthrough in the mapping, so it's more useful 7690b57cec5SDimitry Andric // for branch probabilities. 7700b57cec5SDimitry Andric CountMap[S] = CaseCount; 7710b57cec5SDimitry Andric RecordNextStmtCount = true; 7720b57cec5SDimitry Andric Visit(S->getSubStmt()); 7730b57cec5SDimitry Andric } 7740b57cec5SDimitry Andric 7750b57cec5SDimitry Andric void VisitIfStmt(const IfStmt *S) { 7760b57cec5SDimitry Andric RecordStmtCount(S); 777349cc55cSDimitry Andric 778349cc55cSDimitry Andric if (S->isConsteval()) { 779349cc55cSDimitry Andric const Stmt *Stm = S->isNegatedConsteval() ? S->getThen() : S->getElse(); 780349cc55cSDimitry Andric if (Stm) 781349cc55cSDimitry Andric Visit(Stm); 782349cc55cSDimitry Andric return; 783349cc55cSDimitry Andric } 784349cc55cSDimitry Andric 7850b57cec5SDimitry Andric uint64_t ParentCount = CurrentCount; 7860b57cec5SDimitry Andric if (S->getInit()) 7870b57cec5SDimitry Andric Visit(S->getInit()); 7880b57cec5SDimitry Andric Visit(S->getCond()); 7890b57cec5SDimitry Andric 7900b57cec5SDimitry Andric // Counter tracks the "then" part of an if statement. The count for 7910b57cec5SDimitry Andric // the "else" part, if it exists, will be calculated from this counter. 7920b57cec5SDimitry Andric uint64_t ThenCount = setCount(PGO.getRegionCount(S)); 7930b57cec5SDimitry Andric CountMap[S->getThen()] = ThenCount; 7940b57cec5SDimitry Andric Visit(S->getThen()); 7950b57cec5SDimitry Andric uint64_t OutCount = CurrentCount; 7960b57cec5SDimitry Andric 7970b57cec5SDimitry Andric uint64_t ElseCount = ParentCount - ThenCount; 7980b57cec5SDimitry Andric if (S->getElse()) { 7990b57cec5SDimitry Andric setCount(ElseCount); 8000b57cec5SDimitry Andric CountMap[S->getElse()] = ElseCount; 8010b57cec5SDimitry Andric Visit(S->getElse()); 8020b57cec5SDimitry Andric OutCount += CurrentCount; 8030b57cec5SDimitry Andric } else 8040b57cec5SDimitry Andric OutCount += ElseCount; 8050b57cec5SDimitry Andric setCount(OutCount); 8060b57cec5SDimitry Andric RecordNextStmtCount = true; 8070b57cec5SDimitry Andric } 8080b57cec5SDimitry Andric 8090b57cec5SDimitry Andric void VisitCXXTryStmt(const CXXTryStmt *S) { 8100b57cec5SDimitry Andric RecordStmtCount(S); 8110b57cec5SDimitry Andric Visit(S->getTryBlock()); 8120b57cec5SDimitry Andric for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I) 8130b57cec5SDimitry Andric Visit(S->getHandler(I)); 8140b57cec5SDimitry Andric // Counter tracks the continuation block of the try statement. 8150b57cec5SDimitry Andric setCount(PGO.getRegionCount(S)); 8160b57cec5SDimitry Andric RecordNextStmtCount = true; 8170b57cec5SDimitry Andric } 8180b57cec5SDimitry Andric 8190b57cec5SDimitry Andric void VisitCXXCatchStmt(const CXXCatchStmt *S) { 8200b57cec5SDimitry Andric RecordNextStmtCount = false; 8210b57cec5SDimitry Andric // Counter tracks the catch statement's handler block. 8220b57cec5SDimitry Andric uint64_t CatchCount = setCount(PGO.getRegionCount(S)); 8230b57cec5SDimitry Andric CountMap[S] = CatchCount; 8240b57cec5SDimitry Andric Visit(S->getHandlerBlock()); 8250b57cec5SDimitry Andric } 8260b57cec5SDimitry Andric 8270b57cec5SDimitry Andric void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) { 8280b57cec5SDimitry Andric RecordStmtCount(E); 8290b57cec5SDimitry Andric uint64_t ParentCount = CurrentCount; 8300b57cec5SDimitry Andric Visit(E->getCond()); 8310b57cec5SDimitry Andric 8320b57cec5SDimitry Andric // Counter tracks the "true" part of a conditional operator. The 8330b57cec5SDimitry Andric // count in the "false" part will be calculated from this counter. 8340b57cec5SDimitry Andric uint64_t TrueCount = setCount(PGO.getRegionCount(E)); 8350b57cec5SDimitry Andric CountMap[E->getTrueExpr()] = TrueCount; 8360b57cec5SDimitry Andric Visit(E->getTrueExpr()); 8370b57cec5SDimitry Andric uint64_t OutCount = CurrentCount; 8380b57cec5SDimitry Andric 8390b57cec5SDimitry Andric uint64_t FalseCount = setCount(ParentCount - TrueCount); 8400b57cec5SDimitry Andric CountMap[E->getFalseExpr()] = FalseCount; 8410b57cec5SDimitry Andric Visit(E->getFalseExpr()); 8420b57cec5SDimitry Andric OutCount += CurrentCount; 8430b57cec5SDimitry Andric 8440b57cec5SDimitry Andric setCount(OutCount); 8450b57cec5SDimitry Andric RecordNextStmtCount = true; 8460b57cec5SDimitry Andric } 8470b57cec5SDimitry Andric 8480b57cec5SDimitry Andric void VisitBinLAnd(const BinaryOperator *E) { 8490b57cec5SDimitry Andric RecordStmtCount(E); 8500b57cec5SDimitry Andric uint64_t ParentCount = CurrentCount; 8510b57cec5SDimitry Andric Visit(E->getLHS()); 8520b57cec5SDimitry Andric // Counter tracks the right hand side of a logical and operator. 8530b57cec5SDimitry Andric uint64_t RHSCount = setCount(PGO.getRegionCount(E)); 8540b57cec5SDimitry Andric CountMap[E->getRHS()] = RHSCount; 8550b57cec5SDimitry Andric Visit(E->getRHS()); 8560b57cec5SDimitry Andric setCount(ParentCount + RHSCount - CurrentCount); 8570b57cec5SDimitry Andric RecordNextStmtCount = true; 8580b57cec5SDimitry Andric } 8590b57cec5SDimitry Andric 8600b57cec5SDimitry Andric void VisitBinLOr(const BinaryOperator *E) { 8610b57cec5SDimitry Andric RecordStmtCount(E); 8620b57cec5SDimitry Andric uint64_t ParentCount = CurrentCount; 8630b57cec5SDimitry Andric Visit(E->getLHS()); 8640b57cec5SDimitry Andric // Counter tracks the right hand side of a logical or operator. 8650b57cec5SDimitry Andric uint64_t RHSCount = setCount(PGO.getRegionCount(E)); 8660b57cec5SDimitry Andric CountMap[E->getRHS()] = RHSCount; 8670b57cec5SDimitry Andric Visit(E->getRHS()); 8680b57cec5SDimitry Andric setCount(ParentCount + RHSCount - CurrentCount); 8690b57cec5SDimitry Andric RecordNextStmtCount = true; 8700b57cec5SDimitry Andric } 8710b57cec5SDimitry Andric }; 8720b57cec5SDimitry Andric } // end anonymous namespace 8730b57cec5SDimitry Andric 8740b57cec5SDimitry Andric void PGOHash::combine(HashType Type) { 8750b57cec5SDimitry Andric // Check that we never combine 0 and only have six bits. 8760b57cec5SDimitry Andric assert(Type && "Hash is invalid: unexpected type 0"); 8770b57cec5SDimitry Andric assert(unsigned(Type) < TooBig && "Hash is invalid: too many types"); 8780b57cec5SDimitry Andric 8790b57cec5SDimitry Andric // Pass through MD5 if enough work has built up. 8800b57cec5SDimitry Andric if (Count && Count % NumTypesPerWord == 0) { 8810b57cec5SDimitry Andric using namespace llvm::support; 882c9157d92SDimitry Andric uint64_t Swapped = 883c9157d92SDimitry Andric endian::byte_swap<uint64_t, llvm::endianness::little>(Working); 884bdd1243dSDimitry Andric MD5.update(llvm::ArrayRef((uint8_t *)&Swapped, sizeof(Swapped))); 8850b57cec5SDimitry Andric Working = 0; 8860b57cec5SDimitry Andric } 8870b57cec5SDimitry Andric 8880b57cec5SDimitry Andric // Accumulate the current type. 8890b57cec5SDimitry Andric ++Count; 8900b57cec5SDimitry Andric Working = Working << NumBitsPerType | Type; 8910b57cec5SDimitry Andric } 8920b57cec5SDimitry Andric 8930b57cec5SDimitry Andric uint64_t PGOHash::finalize() { 8940b57cec5SDimitry Andric // Use Working as the hash directly if we never used MD5. 8950b57cec5SDimitry Andric if (Count <= NumTypesPerWord) 8960b57cec5SDimitry Andric // No need to byte swap here, since none of the math was endian-dependent. 8970b57cec5SDimitry Andric // This number will be byte-swapped as required on endianness transitions, 8980b57cec5SDimitry Andric // so we will see the same value on the other side. 8990b57cec5SDimitry Andric return Working; 9000b57cec5SDimitry Andric 9010b57cec5SDimitry Andric // Check for remaining work in Working. 9025ffd83dbSDimitry Andric if (Working) { 9035ffd83dbSDimitry Andric // Keep the buggy behavior from v1 and v2 for backward-compatibility. This 9045ffd83dbSDimitry Andric // is buggy because it converts a uint64_t into an array of uint8_t. 9055ffd83dbSDimitry Andric if (HashVersion < PGO_HASH_V3) { 9065ffd83dbSDimitry Andric MD5.update({(uint8_t)Working}); 9075ffd83dbSDimitry Andric } else { 9085ffd83dbSDimitry Andric using namespace llvm::support; 909c9157d92SDimitry Andric uint64_t Swapped = 910c9157d92SDimitry Andric endian::byte_swap<uint64_t, llvm::endianness::little>(Working); 911bdd1243dSDimitry Andric MD5.update(llvm::ArrayRef((uint8_t *)&Swapped, sizeof(Swapped))); 9125ffd83dbSDimitry Andric } 9135ffd83dbSDimitry Andric } 9140b57cec5SDimitry Andric 9150b57cec5SDimitry Andric // Finalize the MD5 and return the hash. 9160b57cec5SDimitry Andric llvm::MD5::MD5Result Result; 9170b57cec5SDimitry Andric MD5.final(Result); 9180b57cec5SDimitry Andric return Result.low(); 9190b57cec5SDimitry Andric } 9200b57cec5SDimitry Andric 9210b57cec5SDimitry Andric void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) { 9220b57cec5SDimitry Andric const Decl *D = GD.getDecl(); 9230b57cec5SDimitry Andric if (!D->hasBody()) 9240b57cec5SDimitry Andric return; 9250b57cec5SDimitry Andric 926e8d8bef9SDimitry Andric // Skip CUDA/HIP kernel launch stub functions. 927e8d8bef9SDimitry Andric if (CGM.getLangOpts().CUDA && !CGM.getLangOpts().CUDAIsDevice && 928e8d8bef9SDimitry Andric D->hasAttr<CUDAGlobalAttr>()) 929e8d8bef9SDimitry Andric return; 930e8d8bef9SDimitry Andric 9310b57cec5SDimitry Andric bool InstrumentRegions = CGM.getCodeGenOpts().hasProfileClangInstr(); 9320b57cec5SDimitry Andric llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader(); 9330b57cec5SDimitry Andric if (!InstrumentRegions && !PGOReader) 9340b57cec5SDimitry Andric return; 9350b57cec5SDimitry Andric if (D->isImplicit()) 9360b57cec5SDimitry Andric return; 9370b57cec5SDimitry Andric // Constructors and destructors may be represented by several functions in IR. 9380b57cec5SDimitry Andric // If so, instrument only base variant, others are implemented by delegation 9390b57cec5SDimitry Andric // to the base one, it would be counted twice otherwise. 9400b57cec5SDimitry Andric if (CGM.getTarget().getCXXABI().hasConstructorVariants()) { 9410b57cec5SDimitry Andric if (const auto *CCD = dyn_cast<CXXConstructorDecl>(D)) 9420b57cec5SDimitry Andric if (GD.getCtorType() != Ctor_Base && 9430b57cec5SDimitry Andric CodeGenFunction::IsConstructorDelegationValid(CCD)) 9440b57cec5SDimitry Andric return; 9450b57cec5SDimitry Andric } 9460b57cec5SDimitry Andric if (isa<CXXDestructorDecl>(D) && GD.getDtorType() != Dtor_Base) 9470b57cec5SDimitry Andric return; 9480b57cec5SDimitry Andric 949fe6060f1SDimitry Andric CGM.ClearUnusedCoverageMapping(D); 950e8d8bef9SDimitry Andric if (Fn->hasFnAttribute(llvm::Attribute::NoProfile)) 951e8d8bef9SDimitry Andric return; 952bdd1243dSDimitry Andric if (Fn->hasFnAttribute(llvm::Attribute::SkipProfile)) 953bdd1243dSDimitry Andric return; 954e8d8bef9SDimitry Andric 9550b57cec5SDimitry Andric setFuncName(Fn); 9560b57cec5SDimitry Andric 9570b57cec5SDimitry Andric mapRegionCounters(D); 9580b57cec5SDimitry Andric if (CGM.getCodeGenOpts().CoverageMapping) 9590b57cec5SDimitry Andric emitCounterRegionMapping(D); 9600b57cec5SDimitry Andric if (PGOReader) { 9610b57cec5SDimitry Andric SourceManager &SM = CGM.getContext().getSourceManager(); 9620b57cec5SDimitry Andric loadRegionCounts(PGOReader, SM.isInMainFile(D->getLocation())); 9630b57cec5SDimitry Andric computeRegionCounts(D); 9640b57cec5SDimitry Andric applyFunctionAttributes(PGOReader, Fn); 9650b57cec5SDimitry Andric } 9660b57cec5SDimitry Andric } 9670b57cec5SDimitry Andric 9680b57cec5SDimitry Andric void CodeGenPGO::mapRegionCounters(const Decl *D) { 9690b57cec5SDimitry Andric // Use the latest hash version when inserting instrumentation, but use the 9700b57cec5SDimitry Andric // version in the indexed profile if we're reading PGO data. 9710b57cec5SDimitry Andric PGOHashVersion HashVersion = PGO_HASH_LATEST; 972e8d8bef9SDimitry Andric uint64_t ProfileVersion = llvm::IndexedInstrProf::Version; 973e8d8bef9SDimitry Andric if (auto *PGOReader = CGM.getPGOReader()) { 9740b57cec5SDimitry Andric HashVersion = getPGOHashVersion(PGOReader, CGM); 975e8d8bef9SDimitry Andric ProfileVersion = PGOReader->getVersion(); 976e8d8bef9SDimitry Andric } 9770b57cec5SDimitry Andric 978cdc20ff6SDimitry Andric // If MC/DC is enabled, set the MaxConditions to a preset value. Otherwise, 979cdc20ff6SDimitry Andric // set it to zero. This value impacts the number of conditions accepted in a 980cdc20ff6SDimitry Andric // given boolean expression, which impacts the size of the bitmap used to 981cdc20ff6SDimitry Andric // track test vector execution for that boolean expression. Because the 982cdc20ff6SDimitry Andric // bitmap scales exponentially (2^n) based on the number of conditions seen, 983cdc20ff6SDimitry Andric // the maximum value is hard-coded at 6 conditions, which is more than enough 984cdc20ff6SDimitry Andric // for most embedded applications. Setting a maximum value prevents the 985cdc20ff6SDimitry Andric // bitmap footprint from growing too large without the user's knowledge. In 986cdc20ff6SDimitry Andric // the future, this value could be adjusted with a command-line option. 987cdc20ff6SDimitry Andric unsigned MCDCMaxConditions = (CGM.getCodeGenOpts().MCDCCoverage) ? 6 : 0; 988cdc20ff6SDimitry Andric 9890b57cec5SDimitry Andric RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>); 990cdc20ff6SDimitry Andric RegionMCDCBitmapMap.reset(new llvm::DenseMap<const Stmt *, unsigned>); 991cdc20ff6SDimitry Andric MapRegionCounters Walker(HashVersion, ProfileVersion, *RegionCounterMap, 992cdc20ff6SDimitry Andric *RegionMCDCBitmapMap, MCDCMaxConditions, 993cdc20ff6SDimitry Andric CGM.getDiags()); 9940b57cec5SDimitry Andric if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) 9950b57cec5SDimitry Andric Walker.TraverseDecl(const_cast<FunctionDecl *>(FD)); 9960b57cec5SDimitry Andric else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D)) 9970b57cec5SDimitry Andric Walker.TraverseDecl(const_cast<ObjCMethodDecl *>(MD)); 9980b57cec5SDimitry Andric else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D)) 9990b57cec5SDimitry Andric Walker.TraverseDecl(const_cast<BlockDecl *>(BD)); 10000b57cec5SDimitry Andric else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D)) 10010b57cec5SDimitry Andric Walker.TraverseDecl(const_cast<CapturedDecl *>(CD)); 10020b57cec5SDimitry Andric assert(Walker.NextCounter > 0 && "no entry counter mapped for decl"); 10030b57cec5SDimitry Andric NumRegionCounters = Walker.NextCounter; 1004cdc20ff6SDimitry Andric MCDCBitmapBytes = Walker.NextMCDCBitmapIdx; 10050b57cec5SDimitry Andric FunctionHash = Walker.Hash.finalize(); 10060b57cec5SDimitry Andric } 10070b57cec5SDimitry Andric 10080b57cec5SDimitry Andric bool CodeGenPGO::skipRegionMappingForDecl(const Decl *D) { 10090b57cec5SDimitry Andric if (!D->getBody()) 10100b57cec5SDimitry Andric return true; 10110b57cec5SDimitry Andric 1012e8d8bef9SDimitry Andric // Skip host-only functions in the CUDA device compilation and device-only 1013e8d8bef9SDimitry Andric // functions in the host compilation. Just roughly filter them out based on 1014e8d8bef9SDimitry Andric // the function attributes. If there are effectively host-only or device-only 1015e8d8bef9SDimitry Andric // ones, their coverage mapping may still be generated. 1016e8d8bef9SDimitry Andric if (CGM.getLangOpts().CUDA && 1017e8d8bef9SDimitry Andric ((CGM.getLangOpts().CUDAIsDevice && !D->hasAttr<CUDADeviceAttr>() && 1018e8d8bef9SDimitry Andric !D->hasAttr<CUDAGlobalAttr>()) || 1019e8d8bef9SDimitry Andric (!CGM.getLangOpts().CUDAIsDevice && 1020e8d8bef9SDimitry Andric (D->hasAttr<CUDAGlobalAttr>() || 1021e8d8bef9SDimitry Andric (!D->hasAttr<CUDAHostAttr>() && D->hasAttr<CUDADeviceAttr>()))))) 1022e8d8bef9SDimitry Andric return true; 1023e8d8bef9SDimitry Andric 10240b57cec5SDimitry Andric // Don't map the functions in system headers. 10250b57cec5SDimitry Andric const auto &SM = CGM.getContext().getSourceManager(); 10260b57cec5SDimitry Andric auto Loc = D->getBody()->getBeginLoc(); 1027*a58f00eaSDimitry Andric return !SystemHeadersCoverage && SM.isInSystemHeader(Loc); 10280b57cec5SDimitry Andric } 10290b57cec5SDimitry Andric 10300b57cec5SDimitry Andric void CodeGenPGO::emitCounterRegionMapping(const Decl *D) { 10310b57cec5SDimitry Andric if (skipRegionMappingForDecl(D)) 10320b57cec5SDimitry Andric return; 10330b57cec5SDimitry Andric 10340b57cec5SDimitry Andric std::string CoverageMapping; 10350b57cec5SDimitry Andric llvm::raw_string_ostream OS(CoverageMapping); 1036cdc20ff6SDimitry Andric RegionCondIDMap.reset(new llvm::DenseMap<const Stmt *, unsigned>); 1037cdc20ff6SDimitry Andric CoverageMappingGen MappingGen( 1038cdc20ff6SDimitry Andric *CGM.getCoverageMapping(), CGM.getContext().getSourceManager(), 1039cdc20ff6SDimitry Andric CGM.getLangOpts(), RegionCounterMap.get(), RegionMCDCBitmapMap.get(), 1040cdc20ff6SDimitry Andric RegionCondIDMap.get()); 10410b57cec5SDimitry Andric MappingGen.emitCounterMapping(D, OS); 10420b57cec5SDimitry Andric OS.flush(); 10430b57cec5SDimitry Andric 10440b57cec5SDimitry Andric if (CoverageMapping.empty()) 10450b57cec5SDimitry Andric return; 10460b57cec5SDimitry Andric 10470b57cec5SDimitry Andric CGM.getCoverageMapping()->addFunctionMappingRecord( 10480b57cec5SDimitry Andric FuncNameVar, FuncName, FunctionHash, CoverageMapping); 10490b57cec5SDimitry Andric } 10500b57cec5SDimitry Andric 10510b57cec5SDimitry Andric void 10520b57cec5SDimitry Andric CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef Name, 10530b57cec5SDimitry Andric llvm::GlobalValue::LinkageTypes Linkage) { 10540b57cec5SDimitry Andric if (skipRegionMappingForDecl(D)) 10550b57cec5SDimitry Andric return; 10560b57cec5SDimitry Andric 10570b57cec5SDimitry Andric std::string CoverageMapping; 10580b57cec5SDimitry Andric llvm::raw_string_ostream OS(CoverageMapping); 10590b57cec5SDimitry Andric CoverageMappingGen MappingGen(*CGM.getCoverageMapping(), 10600b57cec5SDimitry Andric CGM.getContext().getSourceManager(), 10610b57cec5SDimitry Andric CGM.getLangOpts()); 10620b57cec5SDimitry Andric MappingGen.emitEmptyMapping(D, OS); 10630b57cec5SDimitry Andric OS.flush(); 10640b57cec5SDimitry Andric 10650b57cec5SDimitry Andric if (CoverageMapping.empty()) 10660b57cec5SDimitry Andric return; 10670b57cec5SDimitry Andric 10680b57cec5SDimitry Andric setFuncName(Name, Linkage); 10690b57cec5SDimitry Andric CGM.getCoverageMapping()->addFunctionMappingRecord( 10700b57cec5SDimitry Andric FuncNameVar, FuncName, FunctionHash, CoverageMapping, false); 10710b57cec5SDimitry Andric } 10720b57cec5SDimitry Andric 10730b57cec5SDimitry Andric void CodeGenPGO::computeRegionCounts(const Decl *D) { 10740b57cec5SDimitry Andric StmtCountMap.reset(new llvm::DenseMap<const Stmt *, uint64_t>); 10750b57cec5SDimitry Andric ComputeRegionCounts Walker(*StmtCountMap, *this); 10760b57cec5SDimitry Andric if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) 10770b57cec5SDimitry Andric Walker.VisitFunctionDecl(FD); 10780b57cec5SDimitry Andric else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D)) 10790b57cec5SDimitry Andric Walker.VisitObjCMethodDecl(MD); 10800b57cec5SDimitry Andric else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D)) 10810b57cec5SDimitry Andric Walker.VisitBlockDecl(BD); 10820b57cec5SDimitry Andric else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D)) 10830b57cec5SDimitry Andric Walker.VisitCapturedDecl(const_cast<CapturedDecl *>(CD)); 10840b57cec5SDimitry Andric } 10850b57cec5SDimitry Andric 10860b57cec5SDimitry Andric void 10870b57cec5SDimitry Andric CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader, 10880b57cec5SDimitry Andric llvm::Function *Fn) { 10890b57cec5SDimitry Andric if (!haveRegionCounts()) 10900b57cec5SDimitry Andric return; 10910b57cec5SDimitry Andric 10920b57cec5SDimitry Andric uint64_t FunctionCount = getRegionCount(nullptr); 10930b57cec5SDimitry Andric Fn->setEntryCount(FunctionCount); 10940b57cec5SDimitry Andric } 10950b57cec5SDimitry Andric 10960b57cec5SDimitry Andric void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S, 10970b57cec5SDimitry Andric llvm::Value *StepV) { 1098c9157d92SDimitry Andric if (!RegionCounterMap || !Builder.GetInsertBlock()) 10990b57cec5SDimitry Andric return; 11000b57cec5SDimitry Andric 11010b57cec5SDimitry Andric unsigned Counter = (*RegionCounterMap)[S]; 11020b57cec5SDimitry Andric 1103c9157d92SDimitry Andric llvm::Value *Args[] = {FuncNameVar, 11040b57cec5SDimitry Andric Builder.getInt64(FunctionHash), 11050b57cec5SDimitry Andric Builder.getInt32(NumRegionCounters), 11060b57cec5SDimitry Andric Builder.getInt32(Counter), StepV}; 11070b57cec5SDimitry Andric if (!StepV) 11080b57cec5SDimitry Andric Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment), 1109bdd1243dSDimitry Andric ArrayRef(Args, 4)); 11100b57cec5SDimitry Andric else 11110b57cec5SDimitry Andric Builder.CreateCall( 11120b57cec5SDimitry Andric CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment_step), 1113bdd1243dSDimitry Andric ArrayRef(Args)); 11140b57cec5SDimitry Andric } 11150b57cec5SDimitry Andric 1116cdc20ff6SDimitry Andric bool CodeGenPGO::canEmitMCDCCoverage(const CGBuilderTy &Builder) { 1117cdc20ff6SDimitry Andric return (CGM.getCodeGenOpts().hasProfileClangInstr() && 1118cdc20ff6SDimitry Andric CGM.getCodeGenOpts().MCDCCoverage && Builder.GetInsertBlock()); 1119cdc20ff6SDimitry Andric } 1120cdc20ff6SDimitry Andric 1121cdc20ff6SDimitry Andric void CodeGenPGO::emitMCDCParameters(CGBuilderTy &Builder) { 1122cdc20ff6SDimitry Andric if (!canEmitMCDCCoverage(Builder) || !RegionMCDCBitmapMap) 1123cdc20ff6SDimitry Andric return; 1124cdc20ff6SDimitry Andric 1125cdc20ff6SDimitry Andric auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext()); 1126cdc20ff6SDimitry Andric 1127cdc20ff6SDimitry Andric // Emit intrinsic representing MCDC bitmap parameters at function entry. 1128cdc20ff6SDimitry Andric // This is used by the instrumentation pass, but it isn't actually lowered to 1129cdc20ff6SDimitry Andric // anything. 1130cdc20ff6SDimitry Andric llvm::Value *Args[3] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy), 1131cdc20ff6SDimitry Andric Builder.getInt64(FunctionHash), 1132cdc20ff6SDimitry Andric Builder.getInt32(MCDCBitmapBytes)}; 1133cdc20ff6SDimitry Andric Builder.CreateCall( 1134cdc20ff6SDimitry Andric CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_parameters), Args); 1135cdc20ff6SDimitry Andric } 1136cdc20ff6SDimitry Andric 1137cdc20ff6SDimitry Andric void CodeGenPGO::emitMCDCTestVectorBitmapUpdate(CGBuilderTy &Builder, 1138cdc20ff6SDimitry Andric const Expr *S, 1139cdc20ff6SDimitry Andric Address MCDCCondBitmapAddr) { 1140cdc20ff6SDimitry Andric if (!canEmitMCDCCoverage(Builder) || !RegionMCDCBitmapMap) 1141cdc20ff6SDimitry Andric return; 1142cdc20ff6SDimitry Andric 1143cdc20ff6SDimitry Andric S = S->IgnoreParens(); 1144cdc20ff6SDimitry Andric 1145cdc20ff6SDimitry Andric auto ExprMCDCBitmapMapIterator = RegionMCDCBitmapMap->find(S); 1146cdc20ff6SDimitry Andric if (ExprMCDCBitmapMapIterator == RegionMCDCBitmapMap->end()) 1147cdc20ff6SDimitry Andric return; 1148cdc20ff6SDimitry Andric 1149cdc20ff6SDimitry Andric // Extract the ID of the global bitmap associated with this expression. 1150cdc20ff6SDimitry Andric unsigned MCDCTestVectorBitmapID = ExprMCDCBitmapMapIterator->second; 1151cdc20ff6SDimitry Andric auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext()); 1152cdc20ff6SDimitry Andric 1153cdc20ff6SDimitry Andric // Emit intrinsic responsible for updating the global bitmap corresponding to 1154cdc20ff6SDimitry Andric // a boolean expression. The index being set is based on the value loaded 1155cdc20ff6SDimitry Andric // from a pointer to a dedicated temporary value on the stack that is itself 1156cdc20ff6SDimitry Andric // updated via emitMCDCCondBitmapReset() and emitMCDCCondBitmapUpdate(). The 1157cdc20ff6SDimitry Andric // index represents an executed test vector. 1158cdc20ff6SDimitry Andric llvm::Value *Args[5] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy), 1159cdc20ff6SDimitry Andric Builder.getInt64(FunctionHash), 1160cdc20ff6SDimitry Andric Builder.getInt32(MCDCBitmapBytes), 1161cdc20ff6SDimitry Andric Builder.getInt32(MCDCTestVectorBitmapID), 1162cdc20ff6SDimitry Andric MCDCCondBitmapAddr.getPointer()}; 1163cdc20ff6SDimitry Andric Builder.CreateCall( 1164cdc20ff6SDimitry Andric CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_tvbitmap_update), Args); 1165cdc20ff6SDimitry Andric } 1166cdc20ff6SDimitry Andric 1167cdc20ff6SDimitry Andric void CodeGenPGO::emitMCDCCondBitmapReset(CGBuilderTy &Builder, const Expr *S, 1168cdc20ff6SDimitry Andric Address MCDCCondBitmapAddr) { 1169cdc20ff6SDimitry Andric if (!canEmitMCDCCoverage(Builder) || !RegionMCDCBitmapMap) 1170cdc20ff6SDimitry Andric return; 1171cdc20ff6SDimitry Andric 1172cdc20ff6SDimitry Andric S = S->IgnoreParens(); 1173cdc20ff6SDimitry Andric 1174cdc20ff6SDimitry Andric if (RegionMCDCBitmapMap->find(S) == RegionMCDCBitmapMap->end()) 1175cdc20ff6SDimitry Andric return; 1176cdc20ff6SDimitry Andric 1177cdc20ff6SDimitry Andric // Emit intrinsic that resets a dedicated temporary value on the stack to 0. 1178cdc20ff6SDimitry Andric Builder.CreateStore(Builder.getInt32(0), MCDCCondBitmapAddr); 1179cdc20ff6SDimitry Andric } 1180cdc20ff6SDimitry Andric 1181cdc20ff6SDimitry Andric void CodeGenPGO::emitMCDCCondBitmapUpdate(CGBuilderTy &Builder, const Expr *S, 1182cdc20ff6SDimitry Andric Address MCDCCondBitmapAddr, 1183cdc20ff6SDimitry Andric llvm::Value *Val) { 1184cdc20ff6SDimitry Andric if (!canEmitMCDCCoverage(Builder) || !RegionCondIDMap) 1185cdc20ff6SDimitry Andric return; 1186cdc20ff6SDimitry Andric 1187cdc20ff6SDimitry Andric // Even though, for simplicity, parentheses and unary logical-NOT operators 1188cdc20ff6SDimitry Andric // are considered part of their underlying condition for both MC/DC and 1189cdc20ff6SDimitry Andric // branch coverage, the condition IDs themselves are assigned and tracked 1190cdc20ff6SDimitry Andric // using the underlying condition itself. This is done solely for 1191cdc20ff6SDimitry Andric // consistency since parentheses and logical-NOTs are ignored when checking 1192cdc20ff6SDimitry Andric // whether the condition is actually an instrumentable condition. This can 1193cdc20ff6SDimitry Andric // also make debugging a bit easier. 1194cdc20ff6SDimitry Andric S = CodeGenFunction::stripCond(S); 1195cdc20ff6SDimitry Andric 1196cdc20ff6SDimitry Andric auto ExprMCDCConditionIDMapIterator = RegionCondIDMap->find(S); 1197cdc20ff6SDimitry Andric if (ExprMCDCConditionIDMapIterator == RegionCondIDMap->end()) 1198cdc20ff6SDimitry Andric return; 1199cdc20ff6SDimitry Andric 1200cdc20ff6SDimitry Andric // Extract the ID of the condition we are setting in the bitmap. 1201cdc20ff6SDimitry Andric unsigned CondID = ExprMCDCConditionIDMapIterator->second; 1202cdc20ff6SDimitry Andric assert(CondID > 0 && "Condition has no ID!"); 1203cdc20ff6SDimitry Andric 1204cdc20ff6SDimitry Andric auto *I8PtrTy = llvm::PointerType::getUnqual(CGM.getLLVMContext()); 1205cdc20ff6SDimitry Andric 1206cdc20ff6SDimitry Andric // Emit intrinsic that updates a dedicated temporary value on the stack after 1207cdc20ff6SDimitry Andric // a condition is evaluated. After the set of conditions has been updated, 1208cdc20ff6SDimitry Andric // the resulting value is used to update the boolean expression's bitmap. 1209cdc20ff6SDimitry Andric llvm::Value *Args[5] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy), 1210cdc20ff6SDimitry Andric Builder.getInt64(FunctionHash), 1211cdc20ff6SDimitry Andric Builder.getInt32(CondID - 1), 1212cdc20ff6SDimitry Andric MCDCCondBitmapAddr.getPointer(), Val}; 1213cdc20ff6SDimitry Andric Builder.CreateCall( 1214cdc20ff6SDimitry Andric CGM.getIntrinsic(llvm::Intrinsic::instrprof_mcdc_condbitmap_update), 1215cdc20ff6SDimitry Andric Args); 1216cdc20ff6SDimitry Andric } 1217cdc20ff6SDimitry Andric 1218fe6060f1SDimitry Andric void CodeGenPGO::setValueProfilingFlag(llvm::Module &M) { 1219fe6060f1SDimitry Andric if (CGM.getCodeGenOpts().hasProfileClangInstr()) 1220fe6060f1SDimitry Andric M.addModuleFlag(llvm::Module::Warning, "EnableValueProfiling", 1221fe6060f1SDimitry Andric uint32_t(EnableValueProfiling)); 1222fe6060f1SDimitry Andric } 1223fe6060f1SDimitry Andric 12240b57cec5SDimitry Andric // This method either inserts a call to the profile run-time during 12250b57cec5SDimitry Andric // instrumentation or puts profile data into metadata for PGO use. 12260b57cec5SDimitry Andric void CodeGenPGO::valueProfile(CGBuilderTy &Builder, uint32_t ValueKind, 12270b57cec5SDimitry Andric llvm::Instruction *ValueSite, llvm::Value *ValuePtr) { 12280b57cec5SDimitry Andric 12290b57cec5SDimitry Andric if (!EnableValueProfiling) 12300b57cec5SDimitry Andric return; 12310b57cec5SDimitry Andric 12320b57cec5SDimitry Andric if (!ValuePtr || !ValueSite || !Builder.GetInsertBlock()) 12330b57cec5SDimitry Andric return; 12340b57cec5SDimitry Andric 12350b57cec5SDimitry Andric if (isa<llvm::Constant>(ValuePtr)) 12360b57cec5SDimitry Andric return; 12370b57cec5SDimitry Andric 12380b57cec5SDimitry Andric bool InstrumentValueSites = CGM.getCodeGenOpts().hasProfileClangInstr(); 12390b57cec5SDimitry Andric if (InstrumentValueSites && RegionCounterMap) { 12400b57cec5SDimitry Andric auto BuilderInsertPoint = Builder.saveIP(); 12410b57cec5SDimitry Andric Builder.SetInsertPoint(ValueSite); 12420b57cec5SDimitry Andric llvm::Value *Args[5] = { 1243c9157d92SDimitry Andric FuncNameVar, 12440b57cec5SDimitry Andric Builder.getInt64(FunctionHash), 12450b57cec5SDimitry Andric Builder.CreatePtrToInt(ValuePtr, Builder.getInt64Ty()), 12460b57cec5SDimitry Andric Builder.getInt32(ValueKind), 12470b57cec5SDimitry Andric Builder.getInt32(NumValueSites[ValueKind]++) 12480b57cec5SDimitry Andric }; 12490b57cec5SDimitry Andric Builder.CreateCall( 12500b57cec5SDimitry Andric CGM.getIntrinsic(llvm::Intrinsic::instrprof_value_profile), Args); 12510b57cec5SDimitry Andric Builder.restoreIP(BuilderInsertPoint); 12520b57cec5SDimitry Andric return; 12530b57cec5SDimitry Andric } 12540b57cec5SDimitry Andric 12550b57cec5SDimitry Andric llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader(); 12560b57cec5SDimitry Andric if (PGOReader && haveRegionCounts()) { 12570b57cec5SDimitry Andric // We record the top most called three functions at each call site. 12580b57cec5SDimitry Andric // Profile metadata contains "VP" string identifying this metadata 12590b57cec5SDimitry Andric // as value profiling data, then a uint32_t value for the value profiling 12600b57cec5SDimitry Andric // kind, a uint64_t value for the total number of times the call is 12610b57cec5SDimitry Andric // executed, followed by the function hash and execution count (uint64_t) 12620b57cec5SDimitry Andric // pairs for each function. 12630b57cec5SDimitry Andric if (NumValueSites[ValueKind] >= ProfRecord->getNumValueSites(ValueKind)) 12640b57cec5SDimitry Andric return; 12650b57cec5SDimitry Andric 12660b57cec5SDimitry Andric llvm::annotateValueSite(CGM.getModule(), *ValueSite, *ProfRecord, 12670b57cec5SDimitry Andric (llvm::InstrProfValueKind)ValueKind, 12680b57cec5SDimitry Andric NumValueSites[ValueKind]); 12690b57cec5SDimitry Andric 12700b57cec5SDimitry Andric NumValueSites[ValueKind]++; 12710b57cec5SDimitry Andric } 12720b57cec5SDimitry Andric } 12730b57cec5SDimitry Andric 12740b57cec5SDimitry Andric void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader, 12750b57cec5SDimitry Andric bool IsInMainFile) { 12760b57cec5SDimitry Andric CGM.getPGOStats().addVisited(IsInMainFile); 12770b57cec5SDimitry Andric RegionCounts.clear(); 12780b57cec5SDimitry Andric llvm::Expected<llvm::InstrProfRecord> RecordExpected = 12790b57cec5SDimitry Andric PGOReader->getInstrProfRecord(FuncName, FunctionHash); 12800b57cec5SDimitry Andric if (auto E = RecordExpected.takeError()) { 1281fe013be4SDimitry Andric auto IPE = std::get<0>(llvm::InstrProfError::take(std::move(E))); 12820b57cec5SDimitry Andric if (IPE == llvm::instrprof_error::unknown_function) 12830b57cec5SDimitry Andric CGM.getPGOStats().addMissing(IsInMainFile); 12840b57cec5SDimitry Andric else if (IPE == llvm::instrprof_error::hash_mismatch) 12850b57cec5SDimitry Andric CGM.getPGOStats().addMismatched(IsInMainFile); 12860b57cec5SDimitry Andric else if (IPE == llvm::instrprof_error::malformed) 12870b57cec5SDimitry Andric // TODO: Consider a more specific warning for this case. 12880b57cec5SDimitry Andric CGM.getPGOStats().addMismatched(IsInMainFile); 12890b57cec5SDimitry Andric return; 12900b57cec5SDimitry Andric } 12910b57cec5SDimitry Andric ProfRecord = 1292a7dea167SDimitry Andric std::make_unique<llvm::InstrProfRecord>(std::move(RecordExpected.get())); 12930b57cec5SDimitry Andric RegionCounts = ProfRecord->Counts; 12940b57cec5SDimitry Andric } 12950b57cec5SDimitry Andric 12960b57cec5SDimitry Andric /// Calculate what to divide by to scale weights. 12970b57cec5SDimitry Andric /// 12980b57cec5SDimitry Andric /// Given the maximum weight, calculate a divisor that will scale all the 12990b57cec5SDimitry Andric /// weights to strictly less than UINT32_MAX. 13000b57cec5SDimitry Andric static uint64_t calculateWeightScale(uint64_t MaxWeight) { 13010b57cec5SDimitry Andric return MaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1; 13020b57cec5SDimitry Andric } 13030b57cec5SDimitry Andric 13040b57cec5SDimitry Andric /// Scale an individual branch weight (and add 1). 13050b57cec5SDimitry Andric /// 13060b57cec5SDimitry Andric /// Scale a 64-bit weight down to 32-bits using \c Scale. 13070b57cec5SDimitry Andric /// 13080b57cec5SDimitry Andric /// According to Laplace's Rule of Succession, it is better to compute the 13090b57cec5SDimitry Andric /// weight based on the count plus 1, so universally add 1 to the value. 13100b57cec5SDimitry Andric /// 13110b57cec5SDimitry Andric /// \pre \c Scale was calculated by \a calculateWeightScale() with a weight no 13120b57cec5SDimitry Andric /// greater than \c Weight. 13130b57cec5SDimitry Andric static uint32_t scaleBranchWeight(uint64_t Weight, uint64_t Scale) { 13140b57cec5SDimitry Andric assert(Scale && "scale by 0?"); 13150b57cec5SDimitry Andric uint64_t Scaled = Weight / Scale + 1; 13160b57cec5SDimitry Andric assert(Scaled <= UINT32_MAX && "overflow 32-bits"); 13170b57cec5SDimitry Andric return Scaled; 13180b57cec5SDimitry Andric } 13190b57cec5SDimitry Andric 13200b57cec5SDimitry Andric llvm::MDNode *CodeGenFunction::createProfileWeights(uint64_t TrueCount, 1321e8d8bef9SDimitry Andric uint64_t FalseCount) const { 13220b57cec5SDimitry Andric // Check for empty weights. 13230b57cec5SDimitry Andric if (!TrueCount && !FalseCount) 13240b57cec5SDimitry Andric return nullptr; 13250b57cec5SDimitry Andric 13260b57cec5SDimitry Andric // Calculate how to scale down to 32-bits. 13270b57cec5SDimitry Andric uint64_t Scale = calculateWeightScale(std::max(TrueCount, FalseCount)); 13280b57cec5SDimitry Andric 13290b57cec5SDimitry Andric llvm::MDBuilder MDHelper(CGM.getLLVMContext()); 13300b57cec5SDimitry Andric return MDHelper.createBranchWeights(scaleBranchWeight(TrueCount, Scale), 13310b57cec5SDimitry Andric scaleBranchWeight(FalseCount, Scale)); 13320b57cec5SDimitry Andric } 13330b57cec5SDimitry Andric 13340b57cec5SDimitry Andric llvm::MDNode * 1335e8d8bef9SDimitry Andric CodeGenFunction::createProfileWeights(ArrayRef<uint64_t> Weights) const { 13360b57cec5SDimitry Andric // We need at least two elements to create meaningful weights. 13370b57cec5SDimitry Andric if (Weights.size() < 2) 13380b57cec5SDimitry Andric return nullptr; 13390b57cec5SDimitry Andric 13400b57cec5SDimitry Andric // Check for empty weights. 13410b57cec5SDimitry Andric uint64_t MaxWeight = *std::max_element(Weights.begin(), Weights.end()); 13420b57cec5SDimitry Andric if (MaxWeight == 0) 13430b57cec5SDimitry Andric return nullptr; 13440b57cec5SDimitry Andric 13450b57cec5SDimitry Andric // Calculate how to scale down to 32-bits. 13460b57cec5SDimitry Andric uint64_t Scale = calculateWeightScale(MaxWeight); 13470b57cec5SDimitry Andric 13480b57cec5SDimitry Andric SmallVector<uint32_t, 16> ScaledWeights; 13490b57cec5SDimitry Andric ScaledWeights.reserve(Weights.size()); 13500b57cec5SDimitry Andric for (uint64_t W : Weights) 13510b57cec5SDimitry Andric ScaledWeights.push_back(scaleBranchWeight(W, Scale)); 13520b57cec5SDimitry Andric 13530b57cec5SDimitry Andric llvm::MDBuilder MDHelper(CGM.getLLVMContext()); 13540b57cec5SDimitry Andric return MDHelper.createBranchWeights(ScaledWeights); 13550b57cec5SDimitry Andric } 13560b57cec5SDimitry Andric 1357e8d8bef9SDimitry Andric llvm::MDNode * 1358e8d8bef9SDimitry Andric CodeGenFunction::createProfileWeightsForLoop(const Stmt *Cond, 1359e8d8bef9SDimitry Andric uint64_t LoopCount) const { 13600b57cec5SDimitry Andric if (!PGO.haveRegionCounts()) 13610b57cec5SDimitry Andric return nullptr; 1362bdd1243dSDimitry Andric std::optional<uint64_t> CondCount = PGO.getStmtCount(Cond); 13635ffd83dbSDimitry Andric if (!CondCount || *CondCount == 0) 13640b57cec5SDimitry Andric return nullptr; 13650b57cec5SDimitry Andric return createProfileWeights(LoopCount, 13660b57cec5SDimitry Andric std::max(*CondCount, LoopCount) - LoopCount); 13670b57cec5SDimitry Andric } 1368