1ef512b99SJustin Bogner //===--- CodeGenPGO.cpp - PGO Instrumentation for LLVM CodeGen --*- C++ -*-===//
2ef512b99SJustin Bogner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6ef512b99SJustin Bogner //
7ef512b99SJustin Bogner //===----------------------------------------------------------------------===//
8ef512b99SJustin Bogner //
9ef512b99SJustin Bogner // Instrumentation-based profile-guided optimization
10ef512b99SJustin Bogner //
11ef512b99SJustin Bogner //===----------------------------------------------------------------------===//
12ef512b99SJustin Bogner
13ef512b99SJustin Bogner #include "CodeGenPGO.h"
14ef512b99SJustin Bogner #include "CodeGenFunction.h"
15ee02499aSAlex Lorenz #include "CoverageMappingGen.h"
16ef512b99SJustin Bogner #include "clang/AST/RecursiveASTVisitor.h"
17ef512b99SJustin Bogner #include "clang/AST/StmtVisitor.h"
18970ac605SJustin Bogner #include "llvm/IR/Intrinsics.h"
19ef512b99SJustin Bogner #include "llvm/IR/MDBuilder.h"
204c1a1d3cSReid Kleckner #include "llvm/Support/CommandLine.h"
214bc7731aSDuncan P. N. Exon Smith #include "llvm/Support/Endian.h"
22ef512b99SJustin Bogner #include "llvm/Support/FileSystem.h"
234bc7731aSDuncan P. N. Exon Smith #include "llvm/Support/MD5.h"
24ef512b99SJustin Bogner
258065f0b9SZachary Turner static llvm::cl::opt<bool>
26*d86a206fSFangrui Song EnableValueProfiling("enable-value-profiling",
278065f0b9SZachary Turner llvm::cl::desc("Enable value profiling"),
288065f0b9SZachary Turner llvm::cl::Hidden, llvm::cl::init(false));
29518276a5SBetul Buyukkurt
30ef512b99SJustin Bogner using namespace clang;
31ef512b99SJustin Bogner using namespace CodeGen;
32ef512b99SJustin Bogner
setFuncName(StringRef Name,llvm::GlobalValue::LinkageTypes Linkage)33ee02499aSAlex Lorenz void CodeGenPGO::setFuncName(StringRef Name,
34ee02499aSAlex Lorenz llvm::GlobalValue::LinkageTypes Linkage) {
35a569e24aSXinliang David Li llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
36a569e24aSXinliang David Li FuncName = llvm::getPGOFuncName(
37a569e24aSXinliang David Li Name, Linkage, CGM.getCodeGenOpts().MainFileName,
38a569e24aSXinliang David Li PGOReader ? PGOReader->getVersion() : llvm::IndexedInstrProf::Version);
39970ac605SJustin Bogner
40970ac605SJustin Bogner // If we're generating a profile, create a variable for the name.
419837ef56SRong Xu if (CGM.getCodeGenOpts().hasProfileClangInstr())
422d7ec5a9SXinliang David Li FuncNameVar = llvm::createPGOFuncNameVar(CGM.getModule(), Linkage, FuncName);
43da1ebedeSBob Wilson }
44da1ebedeSBob Wilson
setFuncName(llvm::Function * Fn)45ee02499aSAlex Lorenz void CodeGenPGO::setFuncName(llvm::Function *Fn) {
46ee02499aSAlex Lorenz setFuncName(Fn->getName(), Fn->getLinkage());
47f932f542SRong Xu // Create PGOFuncName meta data.
48f932f542SRong Xu llvm::createPGOFuncNameMetadata(*Fn, FuncName);
49ee02499aSAlex Lorenz }
50ee02499aSAlex Lorenz
516186971aSVedant Kumar /// The version of the PGO hash algorithm.
526186971aSVedant Kumar enum PGOHashVersion : unsigned {
536186971aSVedant Kumar PGO_HASH_V1,
546186971aSVedant Kumar PGO_HASH_V2,
55de02a75eSserge-sans-paille PGO_HASH_V3,
566186971aSVedant Kumar
576186971aSVedant Kumar // Keep this set to the latest hash version.
58de02a75eSserge-sans-paille PGO_HASH_LATEST = PGO_HASH_V3
596186971aSVedant Kumar };
606186971aSVedant Kumar
61ef512b99SJustin Bogner namespace {
629fc8faf9SAdrian Prantl /// Stable hasher for PGO region counters.
634bc7731aSDuncan P. N. Exon Smith ///
644bc7731aSDuncan P. N. Exon Smith /// PGOHash produces a stable hash of a given function's control flow.
654bc7731aSDuncan P. N. Exon Smith ///
664bc7731aSDuncan P. N. Exon Smith /// Changing the output of this hash will invalidate all previously generated
674bc7731aSDuncan P. N. Exon Smith /// profiles -- i.e., don't do it.
684bc7731aSDuncan P. N. Exon Smith ///
694bc7731aSDuncan P. N. Exon Smith /// \note When this hash does eventually change (years?), we still need to
704bc7731aSDuncan P. N. Exon Smith /// support old hashes. We'll need to pull in the version number from the
714bc7731aSDuncan P. N. Exon Smith /// profile data format and use the matching hash function.
724bc7731aSDuncan P. N. Exon Smith class PGOHash {
734bc7731aSDuncan P. N. Exon Smith uint64_t Working;
744bc7731aSDuncan P. N. Exon Smith unsigned Count;
756186971aSVedant Kumar PGOHashVersion HashVersion;
764bc7731aSDuncan P. N. Exon Smith llvm::MD5 MD5;
774bc7731aSDuncan P. N. Exon Smith
784bc7731aSDuncan P. N. Exon Smith static const int NumBitsPerType = 6;
794bc7731aSDuncan P. N. Exon Smith static const unsigned NumTypesPerWord = sizeof(uint64_t) * 8 / NumBitsPerType;
804bc7731aSDuncan P. N. Exon Smith static const unsigned TooBig = 1u << NumBitsPerType;
814bc7731aSDuncan P. N. Exon Smith
824bc7731aSDuncan P. N. Exon Smith public:
839fc8faf9SAdrian Prantl /// Hash values for AST nodes.
844bc7731aSDuncan P. N. Exon Smith ///
854bc7731aSDuncan P. N. Exon Smith /// Distinct values for AST nodes that have region counters attached.
864bc7731aSDuncan P. N. Exon Smith ///
874bc7731aSDuncan P. N. Exon Smith /// These values must be stable. All new members must be added at the end,
884bc7731aSDuncan P. N. Exon Smith /// and no members should be removed. Changing the enumeration value for an
894bc7731aSDuncan P. N. Exon Smith /// AST node will affect the hash of every function that contains that node.
904bc7731aSDuncan P. N. Exon Smith enum HashType : unsigned char {
914bc7731aSDuncan P. N. Exon Smith None = 0,
924bc7731aSDuncan P. N. Exon Smith LabelStmt = 1,
934bc7731aSDuncan P. N. Exon Smith WhileStmt,
944bc7731aSDuncan P. N. Exon Smith DoStmt,
954bc7731aSDuncan P. N. Exon Smith ForStmt,
964bc7731aSDuncan P. N. Exon Smith CXXForRangeStmt,
974bc7731aSDuncan P. N. Exon Smith ObjCForCollectionStmt,
984bc7731aSDuncan P. N. Exon Smith SwitchStmt,
994bc7731aSDuncan P. N. Exon Smith CaseStmt,
1004bc7731aSDuncan P. N. Exon Smith DefaultStmt,
1014bc7731aSDuncan P. N. Exon Smith IfStmt,
1024bc7731aSDuncan P. N. Exon Smith CXXTryStmt,
1034bc7731aSDuncan P. N. Exon Smith CXXCatchStmt,
1044bc7731aSDuncan P. N. Exon Smith ConditionalOperator,
1054bc7731aSDuncan P. N. Exon Smith BinaryOperatorLAnd,
1064bc7731aSDuncan P. N. Exon Smith BinaryOperatorLOr,
1074bc7731aSDuncan P. N. Exon Smith BinaryConditionalOperator,
1086186971aSVedant Kumar // The preceding values are available with PGO_HASH_V1.
1096186971aSVedant Kumar
1106186971aSVedant Kumar EndOfScope,
1116186971aSVedant Kumar IfThenBranch,
1126186971aSVedant Kumar IfElseBranch,
1136186971aSVedant Kumar GotoStmt,
1146186971aSVedant Kumar IndirectGotoStmt,
1156186971aSVedant Kumar BreakStmt,
1166186971aSVedant Kumar ContinueStmt,
1176186971aSVedant Kumar ReturnStmt,
1186186971aSVedant Kumar ThrowExpr,
1196186971aSVedant Kumar UnaryOperatorLNot,
1206186971aSVedant Kumar BinaryOperatorLT,
1216186971aSVedant Kumar BinaryOperatorGT,
1226186971aSVedant Kumar BinaryOperatorLE,
1236186971aSVedant Kumar BinaryOperatorGE,
1246186971aSVedant Kumar BinaryOperatorEQ,
1256186971aSVedant Kumar BinaryOperatorNE,
126de02a75eSserge-sans-paille // The preceding values are available since PGO_HASH_V2.
1274bc7731aSDuncan P. N. Exon Smith
1284bc7731aSDuncan P. N. Exon Smith // Keep this last. It's for the static assert that follows.
1294bc7731aSDuncan P. N. Exon Smith LastHashType
1304bc7731aSDuncan P. N. Exon Smith };
1314bc7731aSDuncan P. N. Exon Smith static_assert(LastHashType <= TooBig, "Too many types in HashType");
1324bc7731aSDuncan P. N. Exon Smith
PGOHash(PGOHashVersion HashVersion)1336186971aSVedant Kumar PGOHash(PGOHashVersion HashVersion)
134d677a7cbSKazu Hirata : Working(0), Count(0), HashVersion(HashVersion) {}
1354bc7731aSDuncan P. N. Exon Smith void combine(HashType Type);
1364bc7731aSDuncan P. N. Exon Smith uint64_t finalize();
getHashVersion() const1376186971aSVedant Kumar PGOHashVersion getHashVersion() const { return HashVersion; }
1384bc7731aSDuncan P. N. Exon Smith };
1394bc7731aSDuncan P. N. Exon Smith const int PGOHash::NumBitsPerType;
1404bc7731aSDuncan P. N. Exon Smith const unsigned PGOHash::NumTypesPerWord;
1414bc7731aSDuncan P. N. Exon Smith const unsigned PGOHash::TooBig;
1424bc7731aSDuncan P. N. Exon Smith
1436186971aSVedant Kumar /// Get the PGO hash version used in the given indexed profile.
getPGOHashVersion(llvm::IndexedInstrProfReader * PGOReader,CodeGenModule & CGM)1446186971aSVedant Kumar static PGOHashVersion getPGOHashVersion(llvm::IndexedInstrProfReader *PGOReader,
1456186971aSVedant Kumar CodeGenModule &CGM) {
1466186971aSVedant Kumar if (PGOReader->getVersion() <= 4)
1476186971aSVedant Kumar return PGO_HASH_V1;
148de02a75eSserge-sans-paille if (PGOReader->getVersion() <= 5)
1496186971aSVedant Kumar return PGO_HASH_V2;
150de02a75eSserge-sans-paille return PGO_HASH_V3;
1516186971aSVedant Kumar }
1526186971aSVedant Kumar
153d8931425SBob Wilson /// A RecursiveASTVisitor that fills a map of statements to PGO counters.
154d8931425SBob Wilson struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
1556186971aSVedant Kumar using Base = RecursiveASTVisitor<MapRegionCounters>;
1566186971aSVedant Kumar
157ef512b99SJustin Bogner /// The next counter value to assign.
158ef512b99SJustin Bogner unsigned NextCounter;
1594bc7731aSDuncan P. N. Exon Smith /// The function hash.
1604bc7731aSDuncan P. N. Exon Smith PGOHash Hash;
161ef512b99SJustin Bogner /// The map of statements to counters.
1623586be72SDuncan P. N. Exon Smith llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
1639f2967bcSAlan Phipps /// The profile version.
1649f2967bcSAlan Phipps uint64_t ProfileVersion;
165ef512b99SJustin Bogner
MapRegionCounters__anonc3cc86690111::MapRegionCounters1669f2967bcSAlan Phipps MapRegionCounters(PGOHashVersion HashVersion, uint64_t ProfileVersion,
1676186971aSVedant Kumar llvm::DenseMap<const Stmt *, unsigned> &CounterMap)
1689f2967bcSAlan Phipps : NextCounter(0), Hash(HashVersion), CounterMap(CounterMap),
1699f2967bcSAlan Phipps ProfileVersion(ProfileVersion) {}
170ef512b99SJustin Bogner
171191ec63bSJustin Bogner // Blocks and lambdas are handled as separate functions, so we need not
172191ec63bSJustin Bogner // traverse them in the parent context.
TraverseBlockExpr__anonc3cc86690111::MapRegionCounters173191ec63bSJustin Bogner bool TraverseBlockExpr(BlockExpr *BE) { return true; }
TraverseLambdaExpr__anonc3cc86690111::MapRegionCounters174e60151c9SSam McCall bool TraverseLambdaExpr(LambdaExpr *LE) {
175e60151c9SSam McCall // Traverse the captures, but not the body.
1768dc7b982SMark de Wever for (auto C : zip(LE->captures(), LE->capture_inits()))
177e60151c9SSam McCall TraverseLambdaCapture(LE, &std::get<0>(C), std::get<1>(C));
178e60151c9SSam McCall return true;
179e60151c9SSam McCall }
TraverseCapturedStmt__anonc3cc86690111::MapRegionCounters18081ab90f7SJustin Bogner bool TraverseCapturedStmt(CapturedStmt *CS) { return true; }
181ef512b99SJustin Bogner
VisitDecl__anonc3cc86690111::MapRegionCounters182d8931425SBob Wilson bool VisitDecl(const Decl *D) {
183d8931425SBob Wilson switch (D->getKind()) {
184d8931425SBob Wilson default:
185d8931425SBob Wilson break;
186d8931425SBob Wilson case Decl::Function:
187d8931425SBob Wilson case Decl::CXXMethod:
188d8931425SBob Wilson case Decl::CXXConstructor:
189d8931425SBob Wilson case Decl::CXXDestructor:
190d8931425SBob Wilson case Decl::CXXConversion:
191d8931425SBob Wilson case Decl::ObjCMethod:
192d8931425SBob Wilson case Decl::Block:
19381ab90f7SJustin Bogner case Decl::Captured:
1944a2f5ae8SDuncan P. N. Exon Smith CounterMap[D->getBody()] = NextCounter++;
195d8931425SBob Wilson break;
196ef512b99SJustin Bogner }
197d8931425SBob Wilson return true;
1985ec8fe19SBob Wilson }
199d8931425SBob Wilson
2006186971aSVedant Kumar /// If \p S gets a fresh counter, update the counter mappings. Return the
2016186971aSVedant Kumar /// V1 hash of \p S.
updateCounterMappings__anonc3cc86690111::MapRegionCounters2026186971aSVedant Kumar PGOHash::HashType updateCounterMappings(Stmt *S) {
2036186971aSVedant Kumar auto Type = getHashType(PGO_HASH_V1, S);
2046186971aSVedant Kumar if (Type != PGOHash::None)
2054bc7731aSDuncan P. N. Exon Smith CounterMap[S] = NextCounter++;
2066186971aSVedant Kumar return Type;
2076186971aSVedant Kumar }
2086186971aSVedant Kumar
2099f2967bcSAlan Phipps /// The RHS of all logical operators gets a fresh counter in order to count
2109f2967bcSAlan Phipps /// how many times the RHS evaluates to true or false, depending on the
2119f2967bcSAlan Phipps /// semantics of the operator. This is only valid for ">= v7" of the profile
2129f2967bcSAlan Phipps /// version so that we facilitate backward compatibility.
VisitBinaryOperator__anonc3cc86690111::MapRegionCounters2139f2967bcSAlan Phipps bool VisitBinaryOperator(BinaryOperator *S) {
2149f2967bcSAlan Phipps if (ProfileVersion >= llvm::IndexedInstrProf::Version7)
2159f2967bcSAlan Phipps if (S->isLogicalOp() &&
2169f2967bcSAlan Phipps CodeGenFunction::isInstrumentedCondition(S->getRHS()))
2179f2967bcSAlan Phipps CounterMap[S->getRHS()] = NextCounter++;
2189f2967bcSAlan Phipps return Base::VisitBinaryOperator(S);
2199f2967bcSAlan Phipps }
2209f2967bcSAlan Phipps
2216186971aSVedant Kumar /// Include \p S in the function hash.
VisitStmt__anonc3cc86690111::MapRegionCounters2226186971aSVedant Kumar bool VisitStmt(Stmt *S) {
2236186971aSVedant Kumar auto Type = updateCounterMappings(S);
2246186971aSVedant Kumar if (Hash.getHashVersion() != PGO_HASH_V1)
2256186971aSVedant Kumar Type = getHashType(Hash.getHashVersion(), S);
2266186971aSVedant Kumar if (Type != PGOHash::None)
2274bc7731aSDuncan P. N. Exon Smith Hash.combine(Type);
2284bc7731aSDuncan P. N. Exon Smith return true;
2294bc7731aSDuncan P. N. Exon Smith }
2306186971aSVedant Kumar
TraverseIfStmt__anonc3cc86690111::MapRegionCounters2316186971aSVedant Kumar bool TraverseIfStmt(IfStmt *If) {
2326186971aSVedant Kumar // If we used the V1 hash, use the default traversal.
2336186971aSVedant Kumar if (Hash.getHashVersion() == PGO_HASH_V1)
2346186971aSVedant Kumar return Base::TraverseIfStmt(If);
2356186971aSVedant Kumar
2366186971aSVedant Kumar // Otherwise, keep track of which branch we're in while traversing.
2376186971aSVedant Kumar VisitStmt(If);
2386186971aSVedant Kumar for (Stmt *CS : If->children()) {
2396186971aSVedant Kumar if (!CS)
2406186971aSVedant Kumar continue;
2416186971aSVedant Kumar if (CS == If->getThen())
2426186971aSVedant Kumar Hash.combine(PGOHash::IfThenBranch);
2436186971aSVedant Kumar else if (CS == If->getElse())
2446186971aSVedant Kumar Hash.combine(PGOHash::IfElseBranch);
2456186971aSVedant Kumar TraverseStmt(CS);
2466186971aSVedant Kumar }
2476186971aSVedant Kumar Hash.combine(PGOHash::EndOfScope);
2486186971aSVedant Kumar return true;
2496186971aSVedant Kumar }
2506186971aSVedant Kumar
2516186971aSVedant Kumar // If the statement type \p N is nestable, and its nesting impacts profile
2526186971aSVedant Kumar // stability, define a custom traversal which tracks the end of the statement
2536186971aSVedant Kumar // in the hash (provided we're not using the V1 hash).
2546186971aSVedant Kumar #define DEFINE_NESTABLE_TRAVERSAL(N) \
2556186971aSVedant Kumar bool Traverse##N(N *S) { \
2566186971aSVedant Kumar Base::Traverse##N(S); \
2576186971aSVedant Kumar if (Hash.getHashVersion() != PGO_HASH_V1) \
2586186971aSVedant Kumar Hash.combine(PGOHash::EndOfScope); \
2596186971aSVedant Kumar return true; \
2606186971aSVedant Kumar }
2616186971aSVedant Kumar
2626186971aSVedant Kumar DEFINE_NESTABLE_TRAVERSAL(WhileStmt)
DEFINE_NESTABLE_TRAVERSAL__anonc3cc86690111::MapRegionCounters2636186971aSVedant Kumar DEFINE_NESTABLE_TRAVERSAL(DoStmt)
2646186971aSVedant Kumar DEFINE_NESTABLE_TRAVERSAL(ForStmt)
2656186971aSVedant Kumar DEFINE_NESTABLE_TRAVERSAL(CXXForRangeStmt)
2666186971aSVedant Kumar DEFINE_NESTABLE_TRAVERSAL(ObjCForCollectionStmt)
2676186971aSVedant Kumar DEFINE_NESTABLE_TRAVERSAL(CXXTryStmt)
2686186971aSVedant Kumar DEFINE_NESTABLE_TRAVERSAL(CXXCatchStmt)
2696186971aSVedant Kumar
2706186971aSVedant Kumar /// Get version \p HashVersion of the PGO hash for \p S.
2716186971aSVedant Kumar PGOHash::HashType getHashType(PGOHashVersion HashVersion, const Stmt *S) {
272d8931425SBob Wilson switch (S->getStmtClass()) {
273d8931425SBob Wilson default:
274d8931425SBob Wilson break;
275d8931425SBob Wilson case Stmt::LabelStmtClass:
2764bc7731aSDuncan P. N. Exon Smith return PGOHash::LabelStmt;
277d8931425SBob Wilson case Stmt::WhileStmtClass:
2784bc7731aSDuncan P. N. Exon Smith return PGOHash::WhileStmt;
279d8931425SBob Wilson case Stmt::DoStmtClass:
2804bc7731aSDuncan P. N. Exon Smith return PGOHash::DoStmt;
281d8931425SBob Wilson case Stmt::ForStmtClass:
2824bc7731aSDuncan P. N. Exon Smith return PGOHash::ForStmt;
283d8931425SBob Wilson case Stmt::CXXForRangeStmtClass:
2844bc7731aSDuncan P. N. Exon Smith return PGOHash::CXXForRangeStmt;
285d8931425SBob Wilson case Stmt::ObjCForCollectionStmtClass:
2864bc7731aSDuncan P. N. Exon Smith return PGOHash::ObjCForCollectionStmt;
287d8931425SBob Wilson case Stmt::SwitchStmtClass:
2884bc7731aSDuncan P. N. Exon Smith return PGOHash::SwitchStmt;
289d8931425SBob Wilson case Stmt::CaseStmtClass:
2904bc7731aSDuncan P. N. Exon Smith return PGOHash::CaseStmt;
291d8931425SBob Wilson case Stmt::DefaultStmtClass:
2924bc7731aSDuncan P. N. Exon Smith return PGOHash::DefaultStmt;
293d8931425SBob Wilson case Stmt::IfStmtClass:
2944bc7731aSDuncan P. N. Exon Smith return PGOHash::IfStmt;
295d8931425SBob Wilson case Stmt::CXXTryStmtClass:
2964bc7731aSDuncan P. N. Exon Smith return PGOHash::CXXTryStmt;
297d8931425SBob Wilson case Stmt::CXXCatchStmtClass:
2984bc7731aSDuncan P. N. Exon Smith return PGOHash::CXXCatchStmt;
299d8931425SBob Wilson case Stmt::ConditionalOperatorClass:
3004bc7731aSDuncan P. N. Exon Smith return PGOHash::ConditionalOperator;
301d8931425SBob Wilson case Stmt::BinaryConditionalOperatorClass:
3024bc7731aSDuncan P. N. Exon Smith return PGOHash::BinaryConditionalOperator;
303d8931425SBob Wilson case Stmt::BinaryOperatorClass: {
304d8931425SBob Wilson const BinaryOperator *BO = cast<BinaryOperator>(S);
3054bc7731aSDuncan P. N. Exon Smith if (BO->getOpcode() == BO_LAnd)
3064bc7731aSDuncan P. N. Exon Smith return PGOHash::BinaryOperatorLAnd;
3074bc7731aSDuncan P. N. Exon Smith if (BO->getOpcode() == BO_LOr)
3084bc7731aSDuncan P. N. Exon Smith return PGOHash::BinaryOperatorLOr;
309de02a75eSserge-sans-paille if (HashVersion >= PGO_HASH_V2) {
3106186971aSVedant Kumar switch (BO->getOpcode()) {
3116186971aSVedant Kumar default:
3126186971aSVedant Kumar break;
3136186971aSVedant Kumar case BO_LT:
3146186971aSVedant Kumar return PGOHash::BinaryOperatorLT;
3156186971aSVedant Kumar case BO_GT:
3166186971aSVedant Kumar return PGOHash::BinaryOperatorGT;
3176186971aSVedant Kumar case BO_LE:
3186186971aSVedant Kumar return PGOHash::BinaryOperatorLE;
3196186971aSVedant Kumar case BO_GE:
3206186971aSVedant Kumar return PGOHash::BinaryOperatorGE;
3216186971aSVedant Kumar case BO_EQ:
3226186971aSVedant Kumar return PGOHash::BinaryOperatorEQ;
3236186971aSVedant Kumar case BO_NE:
3246186971aSVedant Kumar return PGOHash::BinaryOperatorNE;
3256186971aSVedant Kumar }
3266186971aSVedant Kumar }
327d8931425SBob Wilson break;
328ef512b99SJustin Bogner }
329ef512b99SJustin Bogner }
3306186971aSVedant Kumar
331de02a75eSserge-sans-paille if (HashVersion >= PGO_HASH_V2) {
3326186971aSVedant Kumar switch (S->getStmtClass()) {
3336186971aSVedant Kumar default:
3346186971aSVedant Kumar break;
3356186971aSVedant Kumar case Stmt::GotoStmtClass:
3366186971aSVedant Kumar return PGOHash::GotoStmt;
3376186971aSVedant Kumar case Stmt::IndirectGotoStmtClass:
3386186971aSVedant Kumar return PGOHash::IndirectGotoStmt;
3396186971aSVedant Kumar case Stmt::BreakStmtClass:
3406186971aSVedant Kumar return PGOHash::BreakStmt;
3416186971aSVedant Kumar case Stmt::ContinueStmtClass:
3426186971aSVedant Kumar return PGOHash::ContinueStmt;
3436186971aSVedant Kumar case Stmt::ReturnStmtClass:
3446186971aSVedant Kumar return PGOHash::ReturnStmt;
3456186971aSVedant Kumar case Stmt::CXXThrowExprClass:
3466186971aSVedant Kumar return PGOHash::ThrowExpr;
3476186971aSVedant Kumar case Stmt::UnaryOperatorClass: {
3486186971aSVedant Kumar const UnaryOperator *UO = cast<UnaryOperator>(S);
3496186971aSVedant Kumar if (UO->getOpcode() == UO_LNot)
3506186971aSVedant Kumar return PGOHash::UnaryOperatorLNot;
3516186971aSVedant Kumar break;
3526186971aSVedant Kumar }
3536186971aSVedant Kumar }
3546186971aSVedant Kumar }
3556186971aSVedant Kumar
3564bc7731aSDuncan P. N. Exon Smith return PGOHash::None;
357ef512b99SJustin Bogner }
358ef512b99SJustin Bogner };
359bf854f0fSBob Wilson
360bf854f0fSBob Wilson /// A StmtVisitor that propagates the raw counts through the AST and
361bf854f0fSBob Wilson /// records the count at statements where the value may change.
362bf854f0fSBob Wilson struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
363bf854f0fSBob Wilson /// PGO state.
364bf854f0fSBob Wilson CodeGenPGO &PGO;
365bf854f0fSBob Wilson
366bf854f0fSBob Wilson /// A flag that is set when the current count should be recorded on the
367bf854f0fSBob Wilson /// next statement, such as at the exit of a loop.
368bf854f0fSBob Wilson bool RecordNextStmtCount;
369bf854f0fSBob Wilson
370a909abfdSJustin Bogner /// The count at the current location in the traversal.
371a909abfdSJustin Bogner uint64_t CurrentCount;
372a909abfdSJustin Bogner
373bf854f0fSBob Wilson /// The map of statements to count values.
3743586be72SDuncan P. N. Exon Smith llvm::DenseMap<const Stmt *, uint64_t> &CountMap;
375bf854f0fSBob Wilson
376bf854f0fSBob Wilson /// BreakContinueStack - Keep counts of breaks and continues inside loops.
377bf854f0fSBob Wilson struct BreakContinue {
378bf854f0fSBob Wilson uint64_t BreakCount;
379bf854f0fSBob Wilson uint64_t ContinueCount;
BreakContinue__anonc3cc86690111::ComputeRegionCounts::BreakContinue380bf854f0fSBob Wilson BreakContinue() : BreakCount(0), ContinueCount(0) {}
381bf854f0fSBob Wilson };
382bf854f0fSBob Wilson SmallVector<BreakContinue, 8> BreakContinueStack;
383bf854f0fSBob Wilson
ComputeRegionCounts__anonc3cc86690111::ComputeRegionCounts3843586be72SDuncan P. N. Exon Smith ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &CountMap,
3853586be72SDuncan P. N. Exon Smith CodeGenPGO &PGO)
3863586be72SDuncan P. N. Exon Smith : PGO(PGO), RecordNextStmtCount(false), CountMap(CountMap) {}
387bf854f0fSBob Wilson
RecordStmtCount__anonc3cc86690111::ComputeRegionCounts388bf854f0fSBob Wilson void RecordStmtCount(const Stmt *S) {
389bf854f0fSBob Wilson if (RecordNextStmtCount) {
390a909abfdSJustin Bogner CountMap[S] = CurrentCount;
391bf854f0fSBob Wilson RecordNextStmtCount = false;
392bf854f0fSBob Wilson }
393bf854f0fSBob Wilson }
394bf854f0fSBob Wilson
39507193cc8SJustin Bogner /// Set and return the current count.
setCount__anonc3cc86690111::ComputeRegionCounts39607193cc8SJustin Bogner uint64_t setCount(uint64_t Count) {
397a909abfdSJustin Bogner CurrentCount = Count;
39807193cc8SJustin Bogner return Count;
39907193cc8SJustin Bogner }
40007193cc8SJustin Bogner
VisitStmt__anonc3cc86690111::ComputeRegionCounts401bf854f0fSBob Wilson void VisitStmt(const Stmt *S) {
402bf854f0fSBob Wilson RecordStmtCount(S);
403642f173aSBenjamin Kramer for (const Stmt *Child : S->children())
404642f173aSBenjamin Kramer if (Child)
405642f173aSBenjamin Kramer this->Visit(Child);
406bf854f0fSBob Wilson }
407bf854f0fSBob Wilson
VisitFunctionDecl__anonc3cc86690111::ComputeRegionCounts4084a2f5ae8SDuncan P. N. Exon Smith void VisitFunctionDecl(const FunctionDecl *D) {
409d8931425SBob Wilson // Counter tracks entry to the function body.
41007193cc8SJustin Bogner uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
41107193cc8SJustin Bogner CountMap[D->getBody()] = BodyCount;
4124a2f5ae8SDuncan P. N. Exon Smith Visit(D->getBody());
413bf854f0fSBob Wilson }
414bf854f0fSBob Wilson
415191ec63bSJustin Bogner // Skip lambda expressions. We visit these as FunctionDecls when we're
416191ec63bSJustin Bogner // generating them and aren't interested in the body when generating a
417191ec63bSJustin Bogner // parent context.
VisitLambdaExpr__anonc3cc86690111::ComputeRegionCounts418191ec63bSJustin Bogner void VisitLambdaExpr(const LambdaExpr *LE) {}
419191ec63bSJustin Bogner
VisitCapturedDecl__anonc3cc86690111::ComputeRegionCounts42081ab90f7SJustin Bogner void VisitCapturedDecl(const CapturedDecl *D) {
42181ab90f7SJustin Bogner // Counter tracks entry to the capture body.
42207193cc8SJustin Bogner uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
42307193cc8SJustin Bogner CountMap[D->getBody()] = BodyCount;
42481ab90f7SJustin Bogner Visit(D->getBody());
42581ab90f7SJustin Bogner }
42681ab90f7SJustin Bogner
VisitObjCMethodDecl__anonc3cc86690111::ComputeRegionCounts4274a2f5ae8SDuncan P. N. Exon Smith void VisitObjCMethodDecl(const ObjCMethodDecl *D) {
428d8931425SBob Wilson // Counter tracks entry to the method body.
42907193cc8SJustin Bogner uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
43007193cc8SJustin Bogner CountMap[D->getBody()] = BodyCount;
4314a2f5ae8SDuncan P. N. Exon Smith Visit(D->getBody());
4325ec8fe19SBob Wilson }
4335ec8fe19SBob Wilson
VisitBlockDecl__anonc3cc86690111::ComputeRegionCounts4344a2f5ae8SDuncan P. N. Exon Smith void VisitBlockDecl(const BlockDecl *D) {
435d8931425SBob Wilson // Counter tracks entry to the block body.
43607193cc8SJustin Bogner uint64_t BodyCount = setCount(PGO.getRegionCount(D->getBody()));
43707193cc8SJustin Bogner CountMap[D->getBody()] = BodyCount;
4384a2f5ae8SDuncan P. N. Exon Smith Visit(D->getBody());
439c845c00aSBob Wilson }
440c845c00aSBob Wilson
VisitReturnStmt__anonc3cc86690111::ComputeRegionCounts441bf854f0fSBob Wilson void VisitReturnStmt(const ReturnStmt *S) {
442bf854f0fSBob Wilson RecordStmtCount(S);
443bf854f0fSBob Wilson if (S->getRetValue())
444bf854f0fSBob Wilson Visit(S->getRetValue());
445a909abfdSJustin Bogner CurrentCount = 0;
446bf854f0fSBob Wilson RecordNextStmtCount = true;
447bf854f0fSBob Wilson }
448bf854f0fSBob Wilson
VisitCXXThrowExpr__anonc3cc86690111::ComputeRegionCounts449f959febfSJustin Bogner void VisitCXXThrowExpr(const CXXThrowExpr *E) {
450f959febfSJustin Bogner RecordStmtCount(E);
451f959febfSJustin Bogner if (E->getSubExpr())
452f959febfSJustin Bogner Visit(E->getSubExpr());
453a909abfdSJustin Bogner CurrentCount = 0;
454f959febfSJustin Bogner RecordNextStmtCount = true;
455f959febfSJustin Bogner }
456f959febfSJustin Bogner
VisitGotoStmt__anonc3cc86690111::ComputeRegionCounts457bf854f0fSBob Wilson void VisitGotoStmt(const GotoStmt *S) {
458bf854f0fSBob Wilson RecordStmtCount(S);
459a909abfdSJustin Bogner CurrentCount = 0;
460bf854f0fSBob Wilson RecordNextStmtCount = true;
461bf854f0fSBob Wilson }
462bf854f0fSBob Wilson
VisitLabelStmt__anonc3cc86690111::ComputeRegionCounts463bf854f0fSBob Wilson void VisitLabelStmt(const LabelStmt *S) {
464bf854f0fSBob Wilson RecordNextStmtCount = false;
465d8931425SBob Wilson // Counter tracks the block following the label.
46607193cc8SJustin Bogner uint64_t BlockCount = setCount(PGO.getRegionCount(S));
46707193cc8SJustin Bogner CountMap[S] = BlockCount;
468bf854f0fSBob Wilson Visit(S->getSubStmt());
469bf854f0fSBob Wilson }
470bf854f0fSBob Wilson
VisitBreakStmt__anonc3cc86690111::ComputeRegionCounts471bf854f0fSBob Wilson void VisitBreakStmt(const BreakStmt *S) {
472bf854f0fSBob Wilson RecordStmtCount(S);
473bf854f0fSBob Wilson assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
474a909abfdSJustin Bogner BreakContinueStack.back().BreakCount += CurrentCount;
475a909abfdSJustin Bogner CurrentCount = 0;
476bf854f0fSBob Wilson RecordNextStmtCount = true;
477bf854f0fSBob Wilson }
478bf854f0fSBob Wilson
VisitContinueStmt__anonc3cc86690111::ComputeRegionCounts479bf854f0fSBob Wilson void VisitContinueStmt(const ContinueStmt *S) {
480bf854f0fSBob Wilson RecordStmtCount(S);
481bf854f0fSBob Wilson assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
482a909abfdSJustin Bogner BreakContinueStack.back().ContinueCount += CurrentCount;
483a909abfdSJustin Bogner CurrentCount = 0;
484bf854f0fSBob Wilson RecordNextStmtCount = true;
485bf854f0fSBob Wilson }
486bf854f0fSBob Wilson
VisitWhileStmt__anonc3cc86690111::ComputeRegionCounts487bf854f0fSBob Wilson void VisitWhileStmt(const WhileStmt *S) {
488bf854f0fSBob Wilson RecordStmtCount(S);
489a909abfdSJustin Bogner uint64_t ParentCount = CurrentCount;
49007193cc8SJustin Bogner
491bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue());
492bf854f0fSBob Wilson // Visit the body region first so the break/continue adjustments can be
493bf854f0fSBob Wilson // included when visiting the condition.
49407193cc8SJustin Bogner uint64_t BodyCount = setCount(PGO.getRegionCount(S));
495a909abfdSJustin Bogner CountMap[S->getBody()] = CurrentCount;
496bf854f0fSBob Wilson Visit(S->getBody());
497a909abfdSJustin Bogner uint64_t BackedgeCount = CurrentCount;
498bf854f0fSBob Wilson
499bf854f0fSBob Wilson // ...then go back and propagate counts through the condition. The count
500bf854f0fSBob Wilson // at the start of the condition is the sum of the incoming edges,
501bf854f0fSBob Wilson // the backedge from the end of the loop body, and the edges from
502bf854f0fSBob Wilson // continue statements.
503bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val();
50407193cc8SJustin Bogner uint64_t CondCount =
50507193cc8SJustin Bogner setCount(ParentCount + BackedgeCount + BC.ContinueCount);
50607193cc8SJustin Bogner CountMap[S->getCond()] = CondCount;
507bf854f0fSBob Wilson Visit(S->getCond());
50807193cc8SJustin Bogner setCount(BC.BreakCount + CondCount - BodyCount);
509bf854f0fSBob Wilson RecordNextStmtCount = true;
510bf854f0fSBob Wilson }
511bf854f0fSBob Wilson
VisitDoStmt__anonc3cc86690111::ComputeRegionCounts512bf854f0fSBob Wilson void VisitDoStmt(const DoStmt *S) {
513bf854f0fSBob Wilson RecordStmtCount(S);
51407193cc8SJustin Bogner uint64_t LoopCount = PGO.getRegionCount(S);
51507193cc8SJustin Bogner
516bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue());
51707193cc8SJustin Bogner // The count doesn't include the fallthrough from the parent scope. Add it.
518a909abfdSJustin Bogner uint64_t BodyCount = setCount(LoopCount + CurrentCount);
51907193cc8SJustin Bogner CountMap[S->getBody()] = BodyCount;
520bf854f0fSBob Wilson Visit(S->getBody());
521a909abfdSJustin Bogner uint64_t BackedgeCount = CurrentCount;
522bf854f0fSBob Wilson
523bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val();
524bf854f0fSBob Wilson // The count at the start of the condition is equal to the count at the
52507193cc8SJustin Bogner // end of the body, plus any continues.
52607193cc8SJustin Bogner uint64_t CondCount = setCount(BackedgeCount + BC.ContinueCount);
52707193cc8SJustin Bogner CountMap[S->getCond()] = CondCount;
528bf854f0fSBob Wilson Visit(S->getCond());
52907193cc8SJustin Bogner setCount(BC.BreakCount + CondCount - LoopCount);
530bf854f0fSBob Wilson RecordNextStmtCount = true;
531bf854f0fSBob Wilson }
532bf854f0fSBob Wilson
VisitForStmt__anonc3cc86690111::ComputeRegionCounts533bf854f0fSBob Wilson void VisitForStmt(const ForStmt *S) {
534bf854f0fSBob Wilson RecordStmtCount(S);
535bf854f0fSBob Wilson if (S->getInit())
536bf854f0fSBob Wilson Visit(S->getInit());
53707193cc8SJustin Bogner
538a909abfdSJustin Bogner uint64_t ParentCount = CurrentCount;
53907193cc8SJustin Bogner
540bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue());
541bf854f0fSBob Wilson // Visit the body region first. (This is basically the same as a while
542bf854f0fSBob Wilson // loop; see further comments in VisitWhileStmt.)
54307193cc8SJustin Bogner uint64_t BodyCount = setCount(PGO.getRegionCount(S));
54407193cc8SJustin Bogner CountMap[S->getBody()] = BodyCount;
545bf854f0fSBob Wilson Visit(S->getBody());
546a909abfdSJustin Bogner uint64_t BackedgeCount = CurrentCount;
54707193cc8SJustin Bogner BreakContinue BC = BreakContinueStack.pop_back_val();
548bf854f0fSBob Wilson
549bf854f0fSBob Wilson // The increment is essentially part of the body but it needs to include
550bf854f0fSBob Wilson // the count for all the continue statements.
551bf854f0fSBob Wilson if (S->getInc()) {
55207193cc8SJustin Bogner uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
55307193cc8SJustin Bogner CountMap[S->getInc()] = IncCount;
554bf854f0fSBob Wilson Visit(S->getInc());
555bf854f0fSBob Wilson }
556bf854f0fSBob Wilson
557bf854f0fSBob Wilson // ...then go back and propagate counts through the condition.
55807193cc8SJustin Bogner uint64_t CondCount =
55907193cc8SJustin Bogner setCount(ParentCount + BackedgeCount + BC.ContinueCount);
560bf854f0fSBob Wilson if (S->getCond()) {
56107193cc8SJustin Bogner CountMap[S->getCond()] = CondCount;
562bf854f0fSBob Wilson Visit(S->getCond());
563bf854f0fSBob Wilson }
56407193cc8SJustin Bogner setCount(BC.BreakCount + CondCount - BodyCount);
565bf854f0fSBob Wilson RecordNextStmtCount = true;
566bf854f0fSBob Wilson }
567bf854f0fSBob Wilson
VisitCXXForRangeStmt__anonc3cc86690111::ComputeRegionCounts568bf854f0fSBob Wilson void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
569bf854f0fSBob Wilson RecordStmtCount(S);
5708baa5001SRichard Smith if (S->getInit())
5718baa5001SRichard Smith Visit(S->getInit());
5722e5d4845SJustin Bogner Visit(S->getLoopVarStmt());
573bf854f0fSBob Wilson Visit(S->getRangeStmt());
57401694c34SRichard Smith Visit(S->getBeginStmt());
57501694c34SRichard Smith Visit(S->getEndStmt());
57607193cc8SJustin Bogner
577a909abfdSJustin Bogner uint64_t ParentCount = CurrentCount;
578bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue());
579bf854f0fSBob Wilson // Visit the body region first. (This is basically the same as a while
580bf854f0fSBob Wilson // loop; see further comments in VisitWhileStmt.)
58107193cc8SJustin Bogner uint64_t BodyCount = setCount(PGO.getRegionCount(S));
58207193cc8SJustin Bogner CountMap[S->getBody()] = BodyCount;
583bf854f0fSBob Wilson Visit(S->getBody());
584a909abfdSJustin Bogner uint64_t BackedgeCount = CurrentCount;
58507193cc8SJustin Bogner BreakContinue BC = BreakContinueStack.pop_back_val();
586bf854f0fSBob Wilson
587bf854f0fSBob Wilson // The increment is essentially part of the body but it needs to include
588bf854f0fSBob Wilson // the count for all the continue statements.
58907193cc8SJustin Bogner uint64_t IncCount = setCount(BackedgeCount + BC.ContinueCount);
59007193cc8SJustin Bogner CountMap[S->getInc()] = IncCount;
591bf854f0fSBob Wilson Visit(S->getInc());
592bf854f0fSBob Wilson
593bf854f0fSBob Wilson // ...then go back and propagate counts through the condition.
59407193cc8SJustin Bogner uint64_t CondCount =
59507193cc8SJustin Bogner setCount(ParentCount + BackedgeCount + BC.ContinueCount);
59607193cc8SJustin Bogner CountMap[S->getCond()] = CondCount;
597bf854f0fSBob Wilson Visit(S->getCond());
59807193cc8SJustin Bogner setCount(BC.BreakCount + CondCount - BodyCount);
599bf854f0fSBob Wilson RecordNextStmtCount = true;
600bf854f0fSBob Wilson }
601bf854f0fSBob Wilson
VisitObjCForCollectionStmt__anonc3cc86690111::ComputeRegionCounts602bf854f0fSBob Wilson void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
603bf854f0fSBob Wilson RecordStmtCount(S);
604bf854f0fSBob Wilson Visit(S->getElement());
605a909abfdSJustin Bogner uint64_t ParentCount = CurrentCount;
606bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue());
60707193cc8SJustin Bogner // Counter tracks the body of the loop.
60807193cc8SJustin Bogner uint64_t BodyCount = setCount(PGO.getRegionCount(S));
60907193cc8SJustin Bogner CountMap[S->getBody()] = BodyCount;
610bf854f0fSBob Wilson Visit(S->getBody());
611a909abfdSJustin Bogner uint64_t BackedgeCount = CurrentCount;
612bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val();
61307193cc8SJustin Bogner
61407193cc8SJustin Bogner setCount(BC.BreakCount + ParentCount + BackedgeCount + BC.ContinueCount -
61507193cc8SJustin Bogner BodyCount);
616bf854f0fSBob Wilson RecordNextStmtCount = true;
617bf854f0fSBob Wilson }
618bf854f0fSBob Wilson
VisitSwitchStmt__anonc3cc86690111::ComputeRegionCounts619bf854f0fSBob Wilson void VisitSwitchStmt(const SwitchStmt *S) {
620bf854f0fSBob Wilson RecordStmtCount(S);
621f2a6ec55SVedant Kumar if (S->getInit())
622f2a6ec55SVedant Kumar Visit(S->getInit());
623bf854f0fSBob Wilson Visit(S->getCond());
624a909abfdSJustin Bogner CurrentCount = 0;
625bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue());
626bf854f0fSBob Wilson Visit(S->getBody());
627bf854f0fSBob Wilson // If the switch is inside a loop, add the continue counts.
628bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val();
629bf854f0fSBob Wilson if (!BreakContinueStack.empty())
630bf854f0fSBob Wilson BreakContinueStack.back().ContinueCount += BC.ContinueCount;
631d8931425SBob Wilson // Counter tracks the exit block of the switch.
63207193cc8SJustin Bogner setCount(PGO.getRegionCount(S));
633bf854f0fSBob Wilson RecordNextStmtCount = true;
634bf854f0fSBob Wilson }
635bf854f0fSBob Wilson
VisitSwitchCase__anonc3cc86690111::ComputeRegionCounts63607193cc8SJustin Bogner void VisitSwitchCase(const SwitchCase *S) {
637bf854f0fSBob Wilson RecordNextStmtCount = false;
638d8931425SBob Wilson // Counter for this particular case. This counts only jumps from the
639d8931425SBob Wilson // switch header and does not include fallthrough from the case before
640d8931425SBob Wilson // this one.
64107193cc8SJustin Bogner uint64_t CaseCount = PGO.getRegionCount(S);
642a909abfdSJustin Bogner setCount(CurrentCount + CaseCount);
64307193cc8SJustin Bogner // We need the count without fallthrough in the mapping, so it's more useful
64407193cc8SJustin Bogner // for branch probabilities.
64507193cc8SJustin Bogner CountMap[S] = CaseCount;
646bf854f0fSBob Wilson RecordNextStmtCount = true;
647bf854f0fSBob Wilson Visit(S->getSubStmt());
648bf854f0fSBob Wilson }
649bf854f0fSBob Wilson
VisitIfStmt__anonc3cc86690111::ComputeRegionCounts650bf854f0fSBob Wilson void VisitIfStmt(const IfStmt *S) {
651bf854f0fSBob Wilson RecordStmtCount(S);
652424733c1SCorentin Jabot
653424733c1SCorentin Jabot if (S->isConsteval()) {
654424733c1SCorentin Jabot const Stmt *Stm = S->isNegatedConsteval() ? S->getThen() : S->getElse();
655424733c1SCorentin Jabot if (Stm)
656424733c1SCorentin Jabot Visit(Stm);
657424733c1SCorentin Jabot return;
658424733c1SCorentin Jabot }
659424733c1SCorentin Jabot
660a909abfdSJustin Bogner uint64_t ParentCount = CurrentCount;
6619d2a16b9SVedant Kumar if (S->getInit())
6629d2a16b9SVedant Kumar Visit(S->getInit());
663bf854f0fSBob Wilson Visit(S->getCond());
664bf854f0fSBob Wilson
66507193cc8SJustin Bogner // Counter tracks the "then" part of an if statement. The count for
66607193cc8SJustin Bogner // the "else" part, if it exists, will be calculated from this counter.
66707193cc8SJustin Bogner uint64_t ThenCount = setCount(PGO.getRegionCount(S));
66807193cc8SJustin Bogner CountMap[S->getThen()] = ThenCount;
669bf854f0fSBob Wilson Visit(S->getThen());
670a909abfdSJustin Bogner uint64_t OutCount = CurrentCount;
671bf854f0fSBob Wilson
67207193cc8SJustin Bogner uint64_t ElseCount = ParentCount - ThenCount;
673bf854f0fSBob Wilson if (S->getElse()) {
67407193cc8SJustin Bogner setCount(ElseCount);
67507193cc8SJustin Bogner CountMap[S->getElse()] = ElseCount;
676bf854f0fSBob Wilson Visit(S->getElse());
677a909abfdSJustin Bogner OutCount += CurrentCount;
67807193cc8SJustin Bogner } else
67907193cc8SJustin Bogner OutCount += ElseCount;
68007193cc8SJustin Bogner setCount(OutCount);
681bf854f0fSBob Wilson RecordNextStmtCount = true;
682bf854f0fSBob Wilson }
683bf854f0fSBob Wilson
VisitCXXTryStmt__anonc3cc86690111::ComputeRegionCounts684bf854f0fSBob Wilson void VisitCXXTryStmt(const CXXTryStmt *S) {
685bf854f0fSBob Wilson RecordStmtCount(S);
686bf854f0fSBob Wilson Visit(S->getTryBlock());
687bf854f0fSBob Wilson for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
688bf854f0fSBob Wilson Visit(S->getHandler(I));
689d8931425SBob Wilson // Counter tracks the continuation block of the try statement.
69007193cc8SJustin Bogner setCount(PGO.getRegionCount(S));
691bf854f0fSBob Wilson RecordNextStmtCount = true;
692bf854f0fSBob Wilson }
693bf854f0fSBob Wilson
VisitCXXCatchStmt__anonc3cc86690111::ComputeRegionCounts694bf854f0fSBob Wilson void VisitCXXCatchStmt(const CXXCatchStmt *S) {
695bf854f0fSBob Wilson RecordNextStmtCount = false;
696d8931425SBob Wilson // Counter tracks the catch statement's handler block.
69707193cc8SJustin Bogner uint64_t CatchCount = setCount(PGO.getRegionCount(S));
69807193cc8SJustin Bogner CountMap[S] = CatchCount;
699bf854f0fSBob Wilson Visit(S->getHandlerBlock());
700bf854f0fSBob Wilson }
701bf854f0fSBob Wilson
VisitAbstractConditionalOperator__anonc3cc86690111::ComputeRegionCounts702e4ca441aSJustin Bogner void VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
703bf854f0fSBob Wilson RecordStmtCount(E);
704a909abfdSJustin Bogner uint64_t ParentCount = CurrentCount;
705bf854f0fSBob Wilson Visit(E->getCond());
706bf854f0fSBob Wilson
70707193cc8SJustin Bogner // Counter tracks the "true" part of a conditional operator. The
70807193cc8SJustin Bogner // count in the "false" part will be calculated from this counter.
70907193cc8SJustin Bogner uint64_t TrueCount = setCount(PGO.getRegionCount(E));
71007193cc8SJustin Bogner CountMap[E->getTrueExpr()] = TrueCount;
711bf854f0fSBob Wilson Visit(E->getTrueExpr());
712a909abfdSJustin Bogner uint64_t OutCount = CurrentCount;
713bf854f0fSBob Wilson
71407193cc8SJustin Bogner uint64_t FalseCount = setCount(ParentCount - TrueCount);
71507193cc8SJustin Bogner CountMap[E->getFalseExpr()] = FalseCount;
716bf854f0fSBob Wilson Visit(E->getFalseExpr());
717a909abfdSJustin Bogner OutCount += CurrentCount;
718bf854f0fSBob Wilson
71907193cc8SJustin Bogner setCount(OutCount);
720bf854f0fSBob Wilson RecordNextStmtCount = true;
721bf854f0fSBob Wilson }
722bf854f0fSBob Wilson
VisitBinLAnd__anonc3cc86690111::ComputeRegionCounts723bf854f0fSBob Wilson void VisitBinLAnd(const BinaryOperator *E) {
724bf854f0fSBob Wilson RecordStmtCount(E);
725a909abfdSJustin Bogner uint64_t ParentCount = CurrentCount;
726bf854f0fSBob Wilson Visit(E->getLHS());
72707193cc8SJustin Bogner // Counter tracks the right hand side of a logical and operator.
72807193cc8SJustin Bogner uint64_t RHSCount = setCount(PGO.getRegionCount(E));
72907193cc8SJustin Bogner CountMap[E->getRHS()] = RHSCount;
730bf854f0fSBob Wilson Visit(E->getRHS());
731a909abfdSJustin Bogner setCount(ParentCount + RHSCount - CurrentCount);
732bf854f0fSBob Wilson RecordNextStmtCount = true;
733bf854f0fSBob Wilson }
734bf854f0fSBob Wilson
VisitBinLOr__anonc3cc86690111::ComputeRegionCounts735bf854f0fSBob Wilson void VisitBinLOr(const BinaryOperator *E) {
736bf854f0fSBob Wilson RecordStmtCount(E);
737a909abfdSJustin Bogner uint64_t ParentCount = CurrentCount;
738bf854f0fSBob Wilson Visit(E->getLHS());
73907193cc8SJustin Bogner // Counter tracks the right hand side of a logical or operator.
74007193cc8SJustin Bogner uint64_t RHSCount = setCount(PGO.getRegionCount(E));
74107193cc8SJustin Bogner CountMap[E->getRHS()] = RHSCount;
742bf854f0fSBob Wilson Visit(E->getRHS());
743a909abfdSJustin Bogner setCount(ParentCount + RHSCount - CurrentCount);
744bf854f0fSBob Wilson RecordNextStmtCount = true;
745bf854f0fSBob Wilson }
746bf854f0fSBob Wilson };
747dcfba334SHans Wennborg } // end anonymous namespace
748ef512b99SJustin Bogner
combine(HashType Type)7494bc7731aSDuncan P. N. Exon Smith void PGOHash::combine(HashType Type) {
7504bc7731aSDuncan P. N. Exon Smith // Check that we never combine 0 and only have six bits.
7514bc7731aSDuncan P. N. Exon Smith assert(Type && "Hash is invalid: unexpected type 0");
7524bc7731aSDuncan P. N. Exon Smith assert(unsigned(Type) < TooBig && "Hash is invalid: too many types");
7534bc7731aSDuncan P. N. Exon Smith
7544bc7731aSDuncan P. N. Exon Smith // Pass through MD5 if enough work has built up.
7554bc7731aSDuncan P. N. Exon Smith if (Count && Count % NumTypesPerWord == 0) {
7564bc7731aSDuncan P. N. Exon Smith using namespace llvm::support;
7574bc7731aSDuncan P. N. Exon Smith uint64_t Swapped = endian::byte_swap<uint64_t, little>(Working);
7584bc7731aSDuncan P. N. Exon Smith MD5.update(llvm::makeArrayRef((uint8_t *)&Swapped, sizeof(Swapped)));
7594bc7731aSDuncan P. N. Exon Smith Working = 0;
7604bc7731aSDuncan P. N. Exon Smith }
7614bc7731aSDuncan P. N. Exon Smith
7624bc7731aSDuncan P. N. Exon Smith // Accumulate the current type.
7634bc7731aSDuncan P. N. Exon Smith ++Count;
7644bc7731aSDuncan P. N. Exon Smith Working = Working << NumBitsPerType | Type;
7654bc7731aSDuncan P. N. Exon Smith }
7664bc7731aSDuncan P. N. Exon Smith
finalize()7674bc7731aSDuncan P. N. Exon Smith uint64_t PGOHash::finalize() {
7684bc7731aSDuncan P. N. Exon Smith // Use Working as the hash directly if we never used MD5.
7694bc7731aSDuncan P. N. Exon Smith if (Count <= NumTypesPerWord)
7704bc7731aSDuncan P. N. Exon Smith // No need to byte swap here, since none of the math was endian-dependent.
7714bc7731aSDuncan P. N. Exon Smith // This number will be byte-swapped as required on endianness transitions,
7724bc7731aSDuncan P. N. Exon Smith // so we will see the same value on the other side.
7734bc7731aSDuncan P. N. Exon Smith return Working;
7744bc7731aSDuncan P. N. Exon Smith
7754bc7731aSDuncan P. N. Exon Smith // Check for remaining work in Working.
776de02a75eSserge-sans-paille if (Working) {
777de02a75eSserge-sans-paille // Keep the buggy behavior from v1 and v2 for backward-compatibility. This
778de02a75eSserge-sans-paille // is buggy because it converts a uint64_t into an array of uint8_t.
779de02a75eSserge-sans-paille if (HashVersion < PGO_HASH_V3) {
780de02a75eSserge-sans-paille MD5.update({(uint8_t)Working});
781de02a75eSserge-sans-paille } else {
782de02a75eSserge-sans-paille using namespace llvm::support;
783de02a75eSserge-sans-paille uint64_t Swapped = endian::byte_swap<uint64_t, little>(Working);
784de02a75eSserge-sans-paille MD5.update(llvm::makeArrayRef((uint8_t *)&Swapped, sizeof(Swapped)));
785de02a75eSserge-sans-paille }
786de02a75eSserge-sans-paille }
7874bc7731aSDuncan P. N. Exon Smith
7884bc7731aSDuncan P. N. Exon Smith // Finalize the MD5 and return the hash.
7894bc7731aSDuncan P. N. Exon Smith llvm::MD5::MD5Result Result;
7904bc7731aSDuncan P. N. Exon Smith MD5.final(Result);
79182a0c97bSZachary Turner return Result.low();
7924bc7731aSDuncan P. N. Exon Smith }
7934bc7731aSDuncan P. N. Exon Smith
assignRegionCounters(GlobalDecl GD,llvm::Function * Fn)7943a561459SSerge Pavlov void CodeGenPGO::assignRegionCounters(GlobalDecl GD, llvm::Function *Fn) {
7953a561459SSerge Pavlov const Decl *D = GD.getDecl();
79633d0a1ccSVedant Kumar if (!D->hasBody())
79733d0a1ccSVedant Kumar return;
79833d0a1ccSVedant Kumar
799c7b683c1SMichael Liao // Skip CUDA/HIP kernel launch stub functions.
800c7b683c1SMichael Liao if (CGM.getLangOpts().CUDA && !CGM.getLangOpts().CUDAIsDevice &&
801c7b683c1SMichael Liao D->hasAttr<CUDAGlobalAttr>())
802c7b683c1SMichael Liao return;
803c7b683c1SMichael Liao
8049837ef56SRong Xu bool InstrumentRegions = CGM.getCodeGenOpts().hasProfileClangInstr();
805837a6f6fSJustin Bogner llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
806837a6f6fSJustin Bogner if (!InstrumentRegions && !PGOReader)
807ef512b99SJustin Bogner return;
8083212b18bSJustin Bogner if (D->isImplicit())
809ef512b99SJustin Bogner return;
8103a561459SSerge Pavlov // Constructors and destructors may be represented by several functions in IR.
8113a561459SSerge Pavlov // If so, instrument only base variant, others are implemented by delegation
8123a561459SSerge Pavlov // to the base one, it would be counted twice otherwise.
8137f809b2fSVedant Kumar if (CGM.getTarget().getCXXABI().hasConstructorVariants()) {
8147f809b2fSVedant Kumar if (const auto *CCD = dyn_cast<CXXConstructorDecl>(D))
8157f809b2fSVedant Kumar if (GD.getCtorType() != Ctor_Base &&
8167f809b2fSVedant Kumar CodeGenFunction::IsConstructorDelegationValid(CCD))
8173a561459SSerge Pavlov return;
8183a561459SSerge Pavlov }
819f9ef9f86SReid Kleckner if (isa<CXXDestructorDecl>(D) && GD.getDtorType() != Dtor_Base)
820f9ef9f86SReid Kleckner return;
821f9ef9f86SReid Kleckner
8229fd9b5a9SPetr Hosek CGM.ClearUnusedCoverageMapping(D);
823bb9eb198SPetr Hosek if (Fn->hasFnAttribute(llvm::Attribute::NoProfile))
824bb9eb198SPetr Hosek return;
825bb9eb198SPetr Hosek
826da1ebedeSBob Wilson setFuncName(Fn);
8277c41451bSDuncan P. N. Exon Smith
828ef512b99SJustin Bogner mapRegionCounters(D);
829ee02499aSAlex Lorenz if (CGM.getCodeGenOpts().CoverageMapping)
830ee02499aSAlex Lorenz emitCounterRegionMapping(D);
831837a6f6fSJustin Bogner if (PGOReader) {
83240b8ba14SJustin Bogner SourceManager &SM = CGM.getContext().getSourceManager();
83340b8ba14SJustin Bogner loadRegionCounts(PGOReader, SM.isInMainFile(D->getLocation()));
834bf854f0fSBob Wilson computeRegionCounts(D);
835837a6f6fSJustin Bogner applyFunctionAttributes(PGOReader, Fn);
836bf854f0fSBob Wilson }
837ef512b99SJustin Bogner }
838ef512b99SJustin Bogner
mapRegionCounters(const Decl * D)839ef512b99SJustin Bogner void CodeGenPGO::mapRegionCounters(const Decl *D) {
8406186971aSVedant Kumar // Use the latest hash version when inserting instrumentation, but use the
8416186971aSVedant Kumar // version in the indexed profile if we're reading PGO data.
8426186971aSVedant Kumar PGOHashVersion HashVersion = PGO_HASH_LATEST;
8439f2967bcSAlan Phipps uint64_t ProfileVersion = llvm::IndexedInstrProf::Version;
8449f2967bcSAlan Phipps if (auto *PGOReader = CGM.getPGOReader()) {
8456186971aSVedant Kumar HashVersion = getPGOHashVersion(PGOReader, CGM);
8469f2967bcSAlan Phipps ProfileVersion = PGOReader->getVersion();
8479f2967bcSAlan Phipps }
8486186971aSVedant Kumar
8491b67cfd4SDuncan P. N. Exon Smith RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>);
8509f2967bcSAlan Phipps MapRegionCounters Walker(HashVersion, ProfileVersion, *RegionCounterMap);
851ef512b99SJustin Bogner if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
852d8931425SBob Wilson Walker.TraverseDecl(const_cast<FunctionDecl *>(FD));
8535ec8fe19SBob Wilson else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
854d8931425SBob Wilson Walker.TraverseDecl(const_cast<ObjCMethodDecl *>(MD));
855c845c00aSBob Wilson else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
856d8931425SBob Wilson Walker.TraverseDecl(const_cast<BlockDecl *>(BD));
85781ab90f7SJustin Bogner else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
85881ab90f7SJustin Bogner Walker.TraverseDecl(const_cast<CapturedDecl *>(CD));
8593212b18bSJustin Bogner assert(Walker.NextCounter > 0 && "no entry counter mapped for decl");
860ef512b99SJustin Bogner NumRegionCounters = Walker.NextCounter;
8614bc7731aSDuncan P. N. Exon Smith FunctionHash = Walker.Hash.finalize();
862ef512b99SJustin Bogner }
863ef512b99SJustin Bogner
skipRegionMappingForDecl(const Decl * D)864c468bb8bSVedant Kumar bool CodeGenPGO::skipRegionMappingForDecl(const Decl *D) {
865bc370f0cSVedant Kumar if (!D->getBody())
866bc370f0cSVedant Kumar return true;
867bc370f0cSVedant Kumar
868c7b683c1SMichael Liao // Skip host-only functions in the CUDA device compilation and device-only
869c7b683c1SMichael Liao // functions in the host compilation. Just roughly filter them out based on
870c7b683c1SMichael Liao // the function attributes. If there are effectively host-only or device-only
871c7b683c1SMichael Liao // ones, their coverage mapping may still be generated.
872c7b683c1SMichael Liao if (CGM.getLangOpts().CUDA &&
873c7b683c1SMichael Liao ((CGM.getLangOpts().CUDAIsDevice && !D->hasAttr<CUDADeviceAttr>() &&
874c7b683c1SMichael Liao !D->hasAttr<CUDAGlobalAttr>()) ||
875c7b683c1SMichael Liao (!CGM.getLangOpts().CUDAIsDevice &&
876c7b683c1SMichael Liao (D->hasAttr<CUDAGlobalAttr>() ||
877c7b683c1SMichael Liao (!D->hasAttr<CUDAHostAttr>() && D->hasAttr<CUDADeviceAttr>())))))
878c7b683c1SMichael Liao return true;
879c7b683c1SMichael Liao
880c468bb8bSVedant Kumar // Don't map the functions in system headers.
881c468bb8bSVedant Kumar const auto &SM = CGM.getContext().getSourceManager();
882f2ceec48SStephen Kelly auto Loc = D->getBody()->getBeginLoc();
883c468bb8bSVedant Kumar return SM.isInSystemHeader(Loc);
884c468bb8bSVedant Kumar }
885c468bb8bSVedant Kumar
emitCounterRegionMapping(const Decl * D)886c468bb8bSVedant Kumar void CodeGenPGO::emitCounterRegionMapping(const Decl *D) {
887c468bb8bSVedant Kumar if (skipRegionMappingForDecl(D))
888ee02499aSAlex Lorenz return;
889ee02499aSAlex Lorenz
890970ac605SJustin Bogner std::string CoverageMapping;
891ee02499aSAlex Lorenz llvm::raw_string_ostream OS(CoverageMapping);
892ee02499aSAlex Lorenz CoverageMappingGen MappingGen(*CGM.getCoverageMapping(),
893ee02499aSAlex Lorenz CGM.getContext().getSourceManager(),
894e5ee6c58SJustin Bogner CGM.getLangOpts(), RegionCounterMap.get());
895ee02499aSAlex Lorenz MappingGen.emitCounterMapping(D, OS);
896ee02499aSAlex Lorenz OS.flush();
897970ac605SJustin Bogner
898970ac605SJustin Bogner if (CoverageMapping.empty())
899970ac605SJustin Bogner return;
900970ac605SJustin Bogner
901970ac605SJustin Bogner CGM.getCoverageMapping()->addFunctionMappingRecord(
902970ac605SJustin Bogner FuncNameVar, FuncName, FunctionHash, CoverageMapping);
903ee02499aSAlex Lorenz }
904ee02499aSAlex Lorenz
905ee02499aSAlex Lorenz void
emitEmptyCounterMapping(const Decl * D,StringRef Name,llvm::GlobalValue::LinkageTypes Linkage)90660d852baSJustin Bogner CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef Name,
907ee02499aSAlex Lorenz llvm::GlobalValue::LinkageTypes Linkage) {
908c468bb8bSVedant Kumar if (skipRegionMappingForDecl(D))
909ee02499aSAlex Lorenz return;
910ee02499aSAlex Lorenz
911970ac605SJustin Bogner std::string CoverageMapping;
912ee02499aSAlex Lorenz llvm::raw_string_ostream OS(CoverageMapping);
913ee02499aSAlex Lorenz CoverageMappingGen MappingGen(*CGM.getCoverageMapping(),
914ee02499aSAlex Lorenz CGM.getContext().getSourceManager(),
915ee02499aSAlex Lorenz CGM.getLangOpts());
916ee02499aSAlex Lorenz MappingGen.emitEmptyMapping(D, OS);
917ee02499aSAlex Lorenz OS.flush();
918970ac605SJustin Bogner
919970ac605SJustin Bogner if (CoverageMapping.empty())
920970ac605SJustin Bogner return;
921970ac605SJustin Bogner
92260d852baSJustin Bogner setFuncName(Name, Linkage);
923970ac605SJustin Bogner CGM.getCoverageMapping()->addFunctionMappingRecord(
9242129ae53SXinliang David Li FuncNameVar, FuncName, FunctionHash, CoverageMapping, false);
925ee02499aSAlex Lorenz }
926ee02499aSAlex Lorenz
computeRegionCounts(const Decl * D)927bf854f0fSBob Wilson void CodeGenPGO::computeRegionCounts(const Decl *D) {
9281b67cfd4SDuncan P. N. Exon Smith StmtCountMap.reset(new llvm::DenseMap<const Stmt *, uint64_t>);
9293586be72SDuncan P. N. Exon Smith ComputeRegionCounts Walker(*StmtCountMap, *this);
930bf854f0fSBob Wilson if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
931bf854f0fSBob Wilson Walker.VisitFunctionDecl(FD);
9325ec8fe19SBob Wilson else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
9335ec8fe19SBob Wilson Walker.VisitObjCMethodDecl(MD);
934c845c00aSBob Wilson else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
935c845c00aSBob Wilson Walker.VisitBlockDecl(BD);
93681ab90f7SJustin Bogner else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
93781ab90f7SJustin Bogner Walker.VisitCapturedDecl(const_cast<CapturedDecl *>(CD));
938bf854f0fSBob Wilson }
939bf854f0fSBob Wilson
940837a6f6fSJustin Bogner void
applyFunctionAttributes(llvm::IndexedInstrProfReader * PGOReader,llvm::Function * Fn)941837a6f6fSJustin Bogner CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
9424c9c45c0SJustin Bogner llvm::Function *Fn) {
9434c9c45c0SJustin Bogner if (!haveRegionCounts())
9444c9c45c0SJustin Bogner return;
9454c9c45c0SJustin Bogner
946dcfba334SHans Wennborg uint64_t FunctionCount = getRegionCount(nullptr);
947aa8b1cb8SDiego Novillo Fn->setEntryCount(FunctionCount);
9484c9c45c0SJustin Bogner }
9494c9c45c0SJustin Bogner
emitCounterIncrement(CGBuilderTy & Builder,const Stmt * S,llvm::Value * StepV)950502bbfafSVedant Kumar void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, const Stmt *S,
951502bbfafSVedant Kumar llvm::Value *StepV) {
9529837ef56SRong Xu if (!CGM.getCodeGenOpts().hasProfileClangInstr() || !RegionCounterMap)
953ef512b99SJustin Bogner return;
9549f5260abSDuncan P. N. Exon Smith if (!Builder.GetInsertBlock())
955203f91e3SJustin Bogner return;
95666242d6cSJustin Bogner
95766242d6cSJustin Bogner unsigned Counter = (*RegionCounterMap)[S];
958970ac605SJustin Bogner auto *I8PtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
959502bbfafSVedant Kumar
960502bbfafSVedant Kumar llvm::Value *Args[] = {llvm::ConstantExpr::getBitCast(FuncNameVar, I8PtrTy),
961a45f315eSVedant Kumar Builder.getInt64(FunctionHash),
962a45f315eSVedant Kumar Builder.getInt32(NumRegionCounters),
963502bbfafSVedant Kumar Builder.getInt32(Counter), StepV};
964502bbfafSVedant Kumar if (!StepV)
965502bbfafSVedant Kumar Builder.CreateCall(CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment),
966502bbfafSVedant Kumar makeArrayRef(Args, 4));
967502bbfafSVedant Kumar else
968502bbfafSVedant Kumar Builder.CreateCall(
969502bbfafSVedant Kumar CGM.getIntrinsic(llvm::Intrinsic::instrprof_increment_step),
970502bbfafSVedant Kumar makeArrayRef(Args));
971ef512b99SJustin Bogner }
972ef512b99SJustin Bogner
setValueProfilingFlag(llvm::Module & M)9738f20ac95SReid Kleckner void CodeGenPGO::setValueProfilingFlag(llvm::Module &M) {
9748f20ac95SReid Kleckner if (CGM.getCodeGenOpts().hasProfileClangInstr())
9758f20ac95SReid Kleckner M.addModuleFlag(llvm::Module::Warning, "EnableValueProfiling",
9768f20ac95SReid Kleckner uint32_t(EnableValueProfiling));
9778f20ac95SReid Kleckner }
9788f20ac95SReid Kleckner
979518276a5SBetul Buyukkurt // This method either inserts a call to the profile run-time during
980518276a5SBetul Buyukkurt // instrumentation or puts profile data into metadata for PGO use.
valueProfile(CGBuilderTy & Builder,uint32_t ValueKind,llvm::Instruction * ValueSite,llvm::Value * ValuePtr)981518276a5SBetul Buyukkurt void CodeGenPGO::valueProfile(CGBuilderTy &Builder, uint32_t ValueKind,
982518276a5SBetul Buyukkurt llvm::Instruction *ValueSite, llvm::Value *ValuePtr) {
983518276a5SBetul Buyukkurt
984518276a5SBetul Buyukkurt if (!EnableValueProfiling)
985518276a5SBetul Buyukkurt return;
986518276a5SBetul Buyukkurt
987518276a5SBetul Buyukkurt if (!ValuePtr || !ValueSite || !Builder.GetInsertBlock())
988518276a5SBetul Buyukkurt return;
989518276a5SBetul Buyukkurt
9903da993c4SBetul Buyukkurt if (isa<llvm::Constant>(ValuePtr))
9913da993c4SBetul Buyukkurt return;
9923da993c4SBetul Buyukkurt
9939837ef56SRong Xu bool InstrumentValueSites = CGM.getCodeGenOpts().hasProfileClangInstr();
994518276a5SBetul Buyukkurt if (InstrumentValueSites && RegionCounterMap) {
995cb6f5f16SBetul Buyukkurt auto BuilderInsertPoint = Builder.saveIP();
996cb6f5f16SBetul Buyukkurt Builder.SetInsertPoint(ValueSite);
997518276a5SBetul Buyukkurt llvm::Value *Args[5] = {
998cb6f5f16SBetul Buyukkurt llvm::ConstantExpr::getBitCast(FuncNameVar, Builder.getInt8PtrTy()),
999518276a5SBetul Buyukkurt Builder.getInt64(FunctionHash),
1000518276a5SBetul Buyukkurt Builder.CreatePtrToInt(ValuePtr, Builder.getInt64Ty()),
1001518276a5SBetul Buyukkurt Builder.getInt32(ValueKind),
1002518276a5SBetul Buyukkurt Builder.getInt32(NumValueSites[ValueKind]++)
1003518276a5SBetul Buyukkurt };
1004518276a5SBetul Buyukkurt Builder.CreateCall(
1005518276a5SBetul Buyukkurt CGM.getIntrinsic(llvm::Intrinsic::instrprof_value_profile), Args);
1006cb6f5f16SBetul Buyukkurt Builder.restoreIP(BuilderInsertPoint);
1007518276a5SBetul Buyukkurt return;
1008518276a5SBetul Buyukkurt }
1009518276a5SBetul Buyukkurt
1010518276a5SBetul Buyukkurt llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
1011518276a5SBetul Buyukkurt if (PGOReader && haveRegionCounts()) {
1012518276a5SBetul Buyukkurt // We record the top most called three functions at each call site.
1013518276a5SBetul Buyukkurt // Profile metadata contains "VP" string identifying this metadata
1014518276a5SBetul Buyukkurt // as value profiling data, then a uint32_t value for the value profiling
1015518276a5SBetul Buyukkurt // kind, a uint64_t value for the total number of times the call is
1016518276a5SBetul Buyukkurt // executed, followed by the function hash and execution count (uint64_t)
1017518276a5SBetul Buyukkurt // pairs for each function.
1018518276a5SBetul Buyukkurt if (NumValueSites[ValueKind] >= ProfRecord->getNumValueSites(ValueKind))
1019518276a5SBetul Buyukkurt return;
10205527a9ddSXinliang David Li
10215527a9ddSXinliang David Li llvm::annotateValueSite(CGM.getModule(), *ValueSite, *ProfRecord,
10225527a9ddSXinliang David Li (llvm::InstrProfValueKind)ValueKind,
1023518276a5SBetul Buyukkurt NumValueSites[ValueKind]);
1024518276a5SBetul Buyukkurt
1025518276a5SBetul Buyukkurt NumValueSites[ValueKind]++;
1026518276a5SBetul Buyukkurt }
1027518276a5SBetul Buyukkurt }
1028518276a5SBetul Buyukkurt
loadRegionCounts(llvm::IndexedInstrProfReader * PGOReader,bool IsInMainFile)102940b8ba14SJustin Bogner void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
103040b8ba14SJustin Bogner bool IsInMainFile) {
103140b8ba14SJustin Bogner CGM.getPGOStats().addVisited(IsInMainFile);
10327f8cf5bfSJustin Bogner RegionCounts.clear();
1033fa2d5955SVedant Kumar llvm::Expected<llvm::InstrProfRecord> RecordExpected =
1034518276a5SBetul Buyukkurt PGOReader->getInstrProfRecord(FuncName, FunctionHash);
1035fa2d5955SVedant Kumar if (auto E = RecordExpected.takeError()) {
1036fa2d5955SVedant Kumar auto IPE = llvm::InstrProfError::take(std::move(E));
1037fa2d5955SVedant Kumar if (IPE == llvm::instrprof_error::unknown_function)
103840b8ba14SJustin Bogner CGM.getPGOStats().addMissing(IsInMainFile);
1039fa2d5955SVedant Kumar else if (IPE == llvm::instrprof_error::hash_mismatch)
10409c6818efSJustin Bogner CGM.getPGOStats().addMismatched(IsInMainFile);
1041fa2d5955SVedant Kumar else if (IPE == llvm::instrprof_error::malformed)
10429c6818efSJustin Bogner // TODO: Consider a more specific warning for this case.
104340b8ba14SJustin Bogner CGM.getPGOStats().addMismatched(IsInMainFile);
1044518276a5SBetul Buyukkurt return;
1045e2ef2a09SJustin Bogner }
1046518276a5SBetul Buyukkurt ProfRecord =
10472b3d49b6SJonas Devlieghere std::make_unique<llvm::InstrProfRecord>(std::move(RecordExpected.get()));
1048518276a5SBetul Buyukkurt RegionCounts = ProfRecord->Counts;
1049ef512b99SJustin Bogner }
1050ef512b99SJustin Bogner
10515c31b8b9SArthur Eubanks /// Calculate what to divide by to scale weights.
10525c31b8b9SArthur Eubanks ///
10535c31b8b9SArthur Eubanks /// Given the maximum weight, calculate a divisor that will scale all the
10545c31b8b9SArthur Eubanks /// weights to strictly less than UINT32_MAX.
calculateWeightScale(uint64_t MaxWeight)10555c31b8b9SArthur Eubanks static uint64_t calculateWeightScale(uint64_t MaxWeight) {
10565c31b8b9SArthur Eubanks return MaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1;
10575c31b8b9SArthur Eubanks }
10585c31b8b9SArthur Eubanks
10595c31b8b9SArthur Eubanks /// Scale an individual branch weight (and add 1).
10605c31b8b9SArthur Eubanks ///
10615c31b8b9SArthur Eubanks /// Scale a 64-bit weight down to 32-bits using \c Scale.
106238402dc9SDuncan P. N. Exon Smith ///
106338402dc9SDuncan P. N. Exon Smith /// According to Laplace's Rule of Succession, it is better to compute the
106438402dc9SDuncan P. N. Exon Smith /// weight based on the count plus 1, so universally add 1 to the value.
10655c31b8b9SArthur Eubanks ///
10665c31b8b9SArthur Eubanks /// \pre \c Scale was calculated by \a calculateWeightScale() with a weight no
10675c31b8b9SArthur Eubanks /// greater than \c Weight.
scaleBranchWeight(uint64_t Weight,uint64_t Scale)10685c31b8b9SArthur Eubanks static uint32_t scaleBranchWeight(uint64_t Weight, uint64_t Scale) {
10695c31b8b9SArthur Eubanks assert(Scale && "scale by 0?");
10705c31b8b9SArthur Eubanks uint64_t Scaled = Weight / Scale + 1;
10715c31b8b9SArthur Eubanks assert(Scaled <= UINT32_MAX && "overflow 32-bits");
10725c31b8b9SArthur Eubanks return Scaled;
10735c31b8b9SArthur Eubanks }
107438402dc9SDuncan P. N. Exon Smith
createProfileWeights(uint64_t TrueCount,uint64_t FalseCount) const107565512647SJustin Bogner llvm::MDNode *CodeGenFunction::createProfileWeights(uint64_t TrueCount,
1076389c8d5bSMark de Wever uint64_t FalseCount) const {
107738402dc9SDuncan P. N. Exon Smith // Check for empty weights.
1078ef512b99SJustin Bogner if (!TrueCount && !FalseCount)
1079a5f804a7SDuncan P. N. Exon Smith return nullptr;
1080ef512b99SJustin Bogner
10815c31b8b9SArthur Eubanks // Calculate how to scale down to 32-bits.
10825c31b8b9SArthur Eubanks uint64_t Scale = calculateWeightScale(std::max(TrueCount, FalseCount));
10835c31b8b9SArthur Eubanks
1084ef512b99SJustin Bogner llvm::MDBuilder MDHelper(CGM.getLLVMContext());
10855c31b8b9SArthur Eubanks return MDHelper.createBranchWeights(scaleBranchWeight(TrueCount, Scale),
10865c31b8b9SArthur Eubanks scaleBranchWeight(FalseCount, Scale));
1087ef512b99SJustin Bogner }
1088ef512b99SJustin Bogner
108965512647SJustin Bogner llvm::MDNode *
createProfileWeights(ArrayRef<uint64_t> Weights) const1090389c8d5bSMark de Wever CodeGenFunction::createProfileWeights(ArrayRef<uint64_t> Weights) const {
109138402dc9SDuncan P. N. Exon Smith // We need at least two elements to create meaningful weights.
109238402dc9SDuncan P. N. Exon Smith if (Weights.size() < 2)
1093a5f804a7SDuncan P. N. Exon Smith return nullptr;
109438402dc9SDuncan P. N. Exon Smith
1095f3aefca7SJustin Bogner // Check for empty weights.
1096f3aefca7SJustin Bogner uint64_t MaxWeight = *std::max_element(Weights.begin(), Weights.end());
1097f3aefca7SJustin Bogner if (MaxWeight == 0)
1098f3aefca7SJustin Bogner return nullptr;
1099f3aefca7SJustin Bogner
11005c31b8b9SArthur Eubanks // Calculate how to scale down to 32-bits.
11015c31b8b9SArthur Eubanks uint64_t Scale = calculateWeightScale(MaxWeight);
11025c31b8b9SArthur Eubanks
11035c31b8b9SArthur Eubanks SmallVector<uint32_t, 16> ScaledWeights;
1104ef512b99SJustin Bogner ScaledWeights.reserve(Weights.size());
110538402dc9SDuncan P. N. Exon Smith for (uint64_t W : Weights)
11065c31b8b9SArthur Eubanks ScaledWeights.push_back(scaleBranchWeight(W, Scale));
110738402dc9SDuncan P. N. Exon Smith
110838402dc9SDuncan P. N. Exon Smith llvm::MDBuilder MDHelper(CGM.getLLVMContext());
1109ef512b99SJustin Bogner return MDHelper.createBranchWeights(ScaledWeights);
1110ef512b99SJustin Bogner }
1111bf854f0fSBob Wilson
1112389c8d5bSMark de Wever llvm::MDNode *
createProfileWeightsForLoop(const Stmt * Cond,uint64_t LoopCount) const1113389c8d5bSMark de Wever CodeGenFunction::createProfileWeightsForLoop(const Stmt *Cond,
1114389c8d5bSMark de Wever uint64_t LoopCount) const {
111565512647SJustin Bogner if (!PGO.haveRegionCounts())
1116a5f804a7SDuncan P. N. Exon Smith return nullptr;
111765512647SJustin Bogner Optional<uint64_t> CondCount = PGO.getStmtCount(Cond);
111855b9b11fSHans Wennborg if (!CondCount || *CondCount == 0)
1119a5f804a7SDuncan P. N. Exon Smith return nullptr;
112065512647SJustin Bogner return createProfileWeights(LoopCount,
11211c21c28bSJustin Bogner std::max(*CondCount, LoopCount) - LoopCount);
1122bf854f0fSBob Wilson }
1123