159d1ed5bSDimitry Andric //===--- CodeGenPGO.cpp - PGO Instrumentation for LLVM CodeGen --*- C++ -*-===//
259d1ed5bSDimitry Andric //
359d1ed5bSDimitry Andric //                     The LLVM Compiler Infrastructure
459d1ed5bSDimitry Andric //
559d1ed5bSDimitry Andric // This file is distributed under the University of Illinois Open Source
659d1ed5bSDimitry Andric // License. See LICENSE.TXT for details.
759d1ed5bSDimitry Andric //
859d1ed5bSDimitry Andric //===----------------------------------------------------------------------===//
959d1ed5bSDimitry Andric //
1059d1ed5bSDimitry Andric // Instrumentation-based profile-guided optimization
1159d1ed5bSDimitry Andric //
1259d1ed5bSDimitry Andric //===----------------------------------------------------------------------===//
1359d1ed5bSDimitry Andric 
1459d1ed5bSDimitry Andric #include "CodeGenPGO.h"
1559d1ed5bSDimitry Andric #include "CodeGenFunction.h"
1659d1ed5bSDimitry Andric #include "clang/AST/RecursiveASTVisitor.h"
1759d1ed5bSDimitry Andric #include "clang/AST/StmtVisitor.h"
1859d1ed5bSDimitry Andric #include "llvm/IR/MDBuilder.h"
1959d1ed5bSDimitry Andric #include "llvm/ProfileData/InstrProfReader.h"
2059d1ed5bSDimitry Andric #include "llvm/Support/Endian.h"
2159d1ed5bSDimitry Andric #include "llvm/Support/FileSystem.h"
2259d1ed5bSDimitry Andric #include "llvm/Support/MD5.h"
2359d1ed5bSDimitry Andric 
2459d1ed5bSDimitry Andric using namespace clang;
2559d1ed5bSDimitry Andric using namespace CodeGen;
2659d1ed5bSDimitry Andric 
2759d1ed5bSDimitry Andric void CodeGenPGO::setFuncName(llvm::Function *Fn) {
2859d1ed5bSDimitry Andric   RawFuncName = Fn->getName();
2959d1ed5bSDimitry Andric 
3059d1ed5bSDimitry Andric   // Function names may be prefixed with a binary '1' to indicate
3159d1ed5bSDimitry Andric   // that the backend should not modify the symbols due to any platform
3259d1ed5bSDimitry Andric   // naming convention. Do not include that '1' in the PGO profile name.
3359d1ed5bSDimitry Andric   if (RawFuncName[0] == '\1')
3459d1ed5bSDimitry Andric     RawFuncName = RawFuncName.substr(1);
3559d1ed5bSDimitry Andric 
3659d1ed5bSDimitry Andric   if (!Fn->hasLocalLinkage()) {
3759d1ed5bSDimitry Andric     PrefixedFuncName.reset(new std::string(RawFuncName));
3859d1ed5bSDimitry Andric     return;
3959d1ed5bSDimitry Andric   }
4059d1ed5bSDimitry Andric 
4159d1ed5bSDimitry Andric   // For local symbols, prepend the main file name to distinguish them.
4259d1ed5bSDimitry Andric   // Do not include the full path in the file name since there's no guarantee
4359d1ed5bSDimitry Andric   // that it will stay the same, e.g., if the files are checked out from
4459d1ed5bSDimitry Andric   // version control in different locations.
4559d1ed5bSDimitry Andric   PrefixedFuncName.reset(new std::string(CGM.getCodeGenOpts().MainFileName));
4659d1ed5bSDimitry Andric   if (PrefixedFuncName->empty())
4759d1ed5bSDimitry Andric     PrefixedFuncName->assign("<unknown>");
4859d1ed5bSDimitry Andric   PrefixedFuncName->append(":");
4959d1ed5bSDimitry Andric   PrefixedFuncName->append(RawFuncName);
5059d1ed5bSDimitry Andric }
5159d1ed5bSDimitry Andric 
5259d1ed5bSDimitry Andric static llvm::Function *getRegisterFunc(CodeGenModule &CGM) {
5359d1ed5bSDimitry Andric   return CGM.getModule().getFunction("__llvm_profile_register_functions");
5459d1ed5bSDimitry Andric }
5559d1ed5bSDimitry Andric 
5659d1ed5bSDimitry Andric static llvm::BasicBlock *getOrInsertRegisterBB(CodeGenModule &CGM) {
5759d1ed5bSDimitry Andric   // Don't do this for Darwin.  compiler-rt uses linker magic.
5859d1ed5bSDimitry Andric   if (CGM.getTarget().getTriple().isOSDarwin())
5959d1ed5bSDimitry Andric     return nullptr;
6059d1ed5bSDimitry Andric 
6159d1ed5bSDimitry Andric   // Only need to insert this once per module.
6259d1ed5bSDimitry Andric   if (llvm::Function *RegisterF = getRegisterFunc(CGM))
6359d1ed5bSDimitry Andric     return &RegisterF->getEntryBlock();
6459d1ed5bSDimitry Andric 
6559d1ed5bSDimitry Andric   // Construct the function.
6659d1ed5bSDimitry Andric   auto *VoidTy = llvm::Type::getVoidTy(CGM.getLLVMContext());
6759d1ed5bSDimitry Andric   auto *RegisterFTy = llvm::FunctionType::get(VoidTy, false);
6859d1ed5bSDimitry Andric   auto *RegisterF = llvm::Function::Create(RegisterFTy,
6959d1ed5bSDimitry Andric                                            llvm::GlobalValue::InternalLinkage,
7059d1ed5bSDimitry Andric                                            "__llvm_profile_register_functions",
7159d1ed5bSDimitry Andric                                            &CGM.getModule());
7259d1ed5bSDimitry Andric   RegisterF->setUnnamedAddr(true);
7359d1ed5bSDimitry Andric   if (CGM.getCodeGenOpts().DisableRedZone)
7459d1ed5bSDimitry Andric     RegisterF->addFnAttr(llvm::Attribute::NoRedZone);
7559d1ed5bSDimitry Andric 
7659d1ed5bSDimitry Andric   // Construct and return the entry block.
7759d1ed5bSDimitry Andric   auto *BB = llvm::BasicBlock::Create(CGM.getLLVMContext(), "", RegisterF);
7859d1ed5bSDimitry Andric   CGBuilderTy Builder(BB);
7959d1ed5bSDimitry Andric   Builder.CreateRetVoid();
8059d1ed5bSDimitry Andric   return BB;
8159d1ed5bSDimitry Andric }
8259d1ed5bSDimitry Andric 
8359d1ed5bSDimitry Andric static llvm::Constant *getOrInsertRuntimeRegister(CodeGenModule &CGM) {
8459d1ed5bSDimitry Andric   auto *VoidTy = llvm::Type::getVoidTy(CGM.getLLVMContext());
8559d1ed5bSDimitry Andric   auto *VoidPtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
8659d1ed5bSDimitry Andric   auto *RuntimeRegisterTy = llvm::FunctionType::get(VoidTy, VoidPtrTy, false);
8759d1ed5bSDimitry Andric   return CGM.getModule().getOrInsertFunction("__llvm_profile_register_function",
8859d1ed5bSDimitry Andric                                              RuntimeRegisterTy);
8959d1ed5bSDimitry Andric }
9059d1ed5bSDimitry Andric 
9159d1ed5bSDimitry Andric static bool isMachO(const CodeGenModule &CGM) {
9259d1ed5bSDimitry Andric   return CGM.getTarget().getTriple().isOSBinFormatMachO();
9359d1ed5bSDimitry Andric }
9459d1ed5bSDimitry Andric 
9559d1ed5bSDimitry Andric static StringRef getCountersSection(const CodeGenModule &CGM) {
9659d1ed5bSDimitry Andric   return isMachO(CGM) ? "__DATA,__llvm_prf_cnts" : "__llvm_prf_cnts";
9759d1ed5bSDimitry Andric }
9859d1ed5bSDimitry Andric 
9959d1ed5bSDimitry Andric static StringRef getNameSection(const CodeGenModule &CGM) {
10059d1ed5bSDimitry Andric   return isMachO(CGM) ? "__DATA,__llvm_prf_names" : "__llvm_prf_names";
10159d1ed5bSDimitry Andric }
10259d1ed5bSDimitry Andric 
10359d1ed5bSDimitry Andric static StringRef getDataSection(const CodeGenModule &CGM) {
10459d1ed5bSDimitry Andric   return isMachO(CGM) ? "__DATA,__llvm_prf_data" : "__llvm_prf_data";
10559d1ed5bSDimitry Andric }
10659d1ed5bSDimitry Andric 
10759d1ed5bSDimitry Andric llvm::GlobalVariable *CodeGenPGO::buildDataVar() {
10859d1ed5bSDimitry Andric   // Create name variable.
10959d1ed5bSDimitry Andric   llvm::LLVMContext &Ctx = CGM.getLLVMContext();
11059d1ed5bSDimitry Andric   auto *VarName = llvm::ConstantDataArray::getString(Ctx, getFuncName(),
11159d1ed5bSDimitry Andric                                                      false);
11259d1ed5bSDimitry Andric   auto *Name = new llvm::GlobalVariable(CGM.getModule(), VarName->getType(),
11359d1ed5bSDimitry Andric                                         true, VarLinkage, VarName,
11459d1ed5bSDimitry Andric                                         getFuncVarName("name"));
11559d1ed5bSDimitry Andric   Name->setSection(getNameSection(CGM));
11659d1ed5bSDimitry Andric   Name->setAlignment(1);
11759d1ed5bSDimitry Andric 
11859d1ed5bSDimitry Andric   // Create data variable.
11959d1ed5bSDimitry Andric   auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
12059d1ed5bSDimitry Andric   auto *Int64Ty = llvm::Type::getInt64Ty(Ctx);
12159d1ed5bSDimitry Andric   auto *Int8PtrTy = llvm::Type::getInt8PtrTy(Ctx);
12259d1ed5bSDimitry Andric   auto *Int64PtrTy = llvm::Type::getInt64PtrTy(Ctx);
12359d1ed5bSDimitry Andric   llvm::Type *DataTypes[] = {
12459d1ed5bSDimitry Andric     Int32Ty, Int32Ty, Int64Ty, Int8PtrTy, Int64PtrTy
12559d1ed5bSDimitry Andric   };
12659d1ed5bSDimitry Andric   auto *DataTy = llvm::StructType::get(Ctx, makeArrayRef(DataTypes));
12759d1ed5bSDimitry Andric   llvm::Constant *DataVals[] = {
12859d1ed5bSDimitry Andric     llvm::ConstantInt::get(Int32Ty, getFuncName().size()),
12959d1ed5bSDimitry Andric     llvm::ConstantInt::get(Int32Ty, NumRegionCounters),
13059d1ed5bSDimitry Andric     llvm::ConstantInt::get(Int64Ty, FunctionHash),
13159d1ed5bSDimitry Andric     llvm::ConstantExpr::getBitCast(Name, Int8PtrTy),
13259d1ed5bSDimitry Andric     llvm::ConstantExpr::getBitCast(RegionCounters, Int64PtrTy)
13359d1ed5bSDimitry Andric   };
13459d1ed5bSDimitry Andric   auto *Data =
13559d1ed5bSDimitry Andric     new llvm::GlobalVariable(CGM.getModule(), DataTy, true, VarLinkage,
13659d1ed5bSDimitry Andric                              llvm::ConstantStruct::get(DataTy, DataVals),
13759d1ed5bSDimitry Andric                              getFuncVarName("data"));
13859d1ed5bSDimitry Andric 
13959d1ed5bSDimitry Andric   // All the data should be packed into an array in its own section.
14059d1ed5bSDimitry Andric   Data->setSection(getDataSection(CGM));
14159d1ed5bSDimitry Andric   Data->setAlignment(8);
14259d1ed5bSDimitry Andric 
14359d1ed5bSDimitry Andric   // Hide all these symbols so that we correctly get a copy for each
14459d1ed5bSDimitry Andric   // executable.  The profile format expects names and counters to be
14559d1ed5bSDimitry Andric   // contiguous, so references into shared objects would be invalid.
14659d1ed5bSDimitry Andric   if (!llvm::GlobalValue::isLocalLinkage(VarLinkage)) {
14759d1ed5bSDimitry Andric     Name->setVisibility(llvm::GlobalValue::HiddenVisibility);
14859d1ed5bSDimitry Andric     Data->setVisibility(llvm::GlobalValue::HiddenVisibility);
14959d1ed5bSDimitry Andric     RegionCounters->setVisibility(llvm::GlobalValue::HiddenVisibility);
15059d1ed5bSDimitry Andric   }
15159d1ed5bSDimitry Andric 
15259d1ed5bSDimitry Andric   // Make sure the data doesn't get deleted.
15359d1ed5bSDimitry Andric   CGM.addUsedGlobal(Data);
15459d1ed5bSDimitry Andric   return Data;
15559d1ed5bSDimitry Andric }
15659d1ed5bSDimitry Andric 
15759d1ed5bSDimitry Andric void CodeGenPGO::emitInstrumentationData() {
15859d1ed5bSDimitry Andric   if (!RegionCounters)
15959d1ed5bSDimitry Andric     return;
16059d1ed5bSDimitry Andric 
16159d1ed5bSDimitry Andric   // Build the data.
16259d1ed5bSDimitry Andric   auto *Data = buildDataVar();
16359d1ed5bSDimitry Andric 
16459d1ed5bSDimitry Andric   // Register the data.
16559d1ed5bSDimitry Andric   auto *RegisterBB = getOrInsertRegisterBB(CGM);
16659d1ed5bSDimitry Andric   if (!RegisterBB)
16759d1ed5bSDimitry Andric     return;
16859d1ed5bSDimitry Andric   CGBuilderTy Builder(RegisterBB->getTerminator());
16959d1ed5bSDimitry Andric   auto *VoidPtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext());
17059d1ed5bSDimitry Andric   Builder.CreateCall(getOrInsertRuntimeRegister(CGM),
17159d1ed5bSDimitry Andric                      Builder.CreateBitCast(Data, VoidPtrTy));
17259d1ed5bSDimitry Andric }
17359d1ed5bSDimitry Andric 
17459d1ed5bSDimitry Andric llvm::Function *CodeGenPGO::emitInitialization(CodeGenModule &CGM) {
17559d1ed5bSDimitry Andric   if (!CGM.getCodeGenOpts().ProfileInstrGenerate)
17659d1ed5bSDimitry Andric     return nullptr;
17759d1ed5bSDimitry Andric 
17859d1ed5bSDimitry Andric   assert(CGM.getModule().getFunction("__llvm_profile_init") == nullptr &&
17959d1ed5bSDimitry Andric          "profile initialization already emitted");
18059d1ed5bSDimitry Andric 
18159d1ed5bSDimitry Andric   // Get the function to call at initialization.
18259d1ed5bSDimitry Andric   llvm::Constant *RegisterF = getRegisterFunc(CGM);
18359d1ed5bSDimitry Andric   if (!RegisterF)
18459d1ed5bSDimitry Andric     return nullptr;
18559d1ed5bSDimitry Andric 
18659d1ed5bSDimitry Andric   // Create the initialization function.
18759d1ed5bSDimitry Andric   auto *VoidTy = llvm::Type::getVoidTy(CGM.getLLVMContext());
18859d1ed5bSDimitry Andric   auto *F = llvm::Function::Create(llvm::FunctionType::get(VoidTy, false),
18959d1ed5bSDimitry Andric                                    llvm::GlobalValue::InternalLinkage,
19059d1ed5bSDimitry Andric                                    "__llvm_profile_init", &CGM.getModule());
19159d1ed5bSDimitry Andric   F->setUnnamedAddr(true);
19259d1ed5bSDimitry Andric   F->addFnAttr(llvm::Attribute::NoInline);
19359d1ed5bSDimitry Andric   if (CGM.getCodeGenOpts().DisableRedZone)
19459d1ed5bSDimitry Andric     F->addFnAttr(llvm::Attribute::NoRedZone);
19559d1ed5bSDimitry Andric 
19659d1ed5bSDimitry Andric   // Add the basic block and the necessary calls.
19759d1ed5bSDimitry Andric   CGBuilderTy Builder(llvm::BasicBlock::Create(CGM.getLLVMContext(), "", F));
19859d1ed5bSDimitry Andric   Builder.CreateCall(RegisterF);
19959d1ed5bSDimitry Andric   Builder.CreateRetVoid();
20059d1ed5bSDimitry Andric 
20159d1ed5bSDimitry Andric   return F;
20259d1ed5bSDimitry Andric }
20359d1ed5bSDimitry Andric 
20459d1ed5bSDimitry Andric namespace {
20559d1ed5bSDimitry Andric /// \brief Stable hasher for PGO region counters.
20659d1ed5bSDimitry Andric ///
20759d1ed5bSDimitry Andric /// PGOHash produces a stable hash of a given function's control flow.
20859d1ed5bSDimitry Andric ///
20959d1ed5bSDimitry Andric /// Changing the output of this hash will invalidate all previously generated
21059d1ed5bSDimitry Andric /// profiles -- i.e., don't do it.
21159d1ed5bSDimitry Andric ///
21259d1ed5bSDimitry Andric /// \note  When this hash does eventually change (years?), we still need to
21359d1ed5bSDimitry Andric /// support old hashes.  We'll need to pull in the version number from the
21459d1ed5bSDimitry Andric /// profile data format and use the matching hash function.
21559d1ed5bSDimitry Andric class PGOHash {
21659d1ed5bSDimitry Andric   uint64_t Working;
21759d1ed5bSDimitry Andric   unsigned Count;
21859d1ed5bSDimitry Andric   llvm::MD5 MD5;
21959d1ed5bSDimitry Andric 
22059d1ed5bSDimitry Andric   static const int NumBitsPerType = 6;
22159d1ed5bSDimitry Andric   static const unsigned NumTypesPerWord = sizeof(uint64_t) * 8 / NumBitsPerType;
22259d1ed5bSDimitry Andric   static const unsigned TooBig = 1u << NumBitsPerType;
22359d1ed5bSDimitry Andric 
22459d1ed5bSDimitry Andric public:
22559d1ed5bSDimitry Andric   /// \brief Hash values for AST nodes.
22659d1ed5bSDimitry Andric   ///
22759d1ed5bSDimitry Andric   /// Distinct values for AST nodes that have region counters attached.
22859d1ed5bSDimitry Andric   ///
22959d1ed5bSDimitry Andric   /// These values must be stable.  All new members must be added at the end,
23059d1ed5bSDimitry Andric   /// and no members should be removed.  Changing the enumeration value for an
23159d1ed5bSDimitry Andric   /// AST node will affect the hash of every function that contains that node.
23259d1ed5bSDimitry Andric   enum HashType : unsigned char {
23359d1ed5bSDimitry Andric     None = 0,
23459d1ed5bSDimitry Andric     LabelStmt = 1,
23559d1ed5bSDimitry Andric     WhileStmt,
23659d1ed5bSDimitry Andric     DoStmt,
23759d1ed5bSDimitry Andric     ForStmt,
23859d1ed5bSDimitry Andric     CXXForRangeStmt,
23959d1ed5bSDimitry Andric     ObjCForCollectionStmt,
24059d1ed5bSDimitry Andric     SwitchStmt,
24159d1ed5bSDimitry Andric     CaseStmt,
24259d1ed5bSDimitry Andric     DefaultStmt,
24359d1ed5bSDimitry Andric     IfStmt,
24459d1ed5bSDimitry Andric     CXXTryStmt,
24559d1ed5bSDimitry Andric     CXXCatchStmt,
24659d1ed5bSDimitry Andric     ConditionalOperator,
24759d1ed5bSDimitry Andric     BinaryOperatorLAnd,
24859d1ed5bSDimitry Andric     BinaryOperatorLOr,
24959d1ed5bSDimitry Andric     BinaryConditionalOperator,
25059d1ed5bSDimitry Andric 
25159d1ed5bSDimitry Andric     // Keep this last.  It's for the static assert that follows.
25259d1ed5bSDimitry Andric     LastHashType
25359d1ed5bSDimitry Andric   };
25459d1ed5bSDimitry Andric   static_assert(LastHashType <= TooBig, "Too many types in HashType");
25559d1ed5bSDimitry Andric 
25659d1ed5bSDimitry Andric   // TODO: When this format changes, take in a version number here, and use the
25759d1ed5bSDimitry Andric   // old hash calculation for file formats that used the old hash.
25859d1ed5bSDimitry Andric   PGOHash() : Working(0), Count(0) {}
25959d1ed5bSDimitry Andric   void combine(HashType Type);
26059d1ed5bSDimitry Andric   uint64_t finalize();
26159d1ed5bSDimitry Andric };
26259d1ed5bSDimitry Andric const int PGOHash::NumBitsPerType;
26359d1ed5bSDimitry Andric const unsigned PGOHash::NumTypesPerWord;
26459d1ed5bSDimitry Andric const unsigned PGOHash::TooBig;
26559d1ed5bSDimitry Andric 
26659d1ed5bSDimitry Andric   /// A RecursiveASTVisitor that fills a map of statements to PGO counters.
26759d1ed5bSDimitry Andric   struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> {
26859d1ed5bSDimitry Andric     /// The next counter value to assign.
26959d1ed5bSDimitry Andric     unsigned NextCounter;
27059d1ed5bSDimitry Andric     /// The function hash.
27159d1ed5bSDimitry Andric     PGOHash Hash;
27259d1ed5bSDimitry Andric     /// The map of statements to counters.
27359d1ed5bSDimitry Andric     llvm::DenseMap<const Stmt *, unsigned> &CounterMap;
27459d1ed5bSDimitry Andric 
27559d1ed5bSDimitry Andric     MapRegionCounters(llvm::DenseMap<const Stmt *, unsigned> &CounterMap)
27659d1ed5bSDimitry Andric         : NextCounter(0), CounterMap(CounterMap) {}
27759d1ed5bSDimitry Andric 
27859d1ed5bSDimitry Andric     // Blocks and lambdas are handled as separate functions, so we need not
27959d1ed5bSDimitry Andric     // traverse them in the parent context.
28059d1ed5bSDimitry Andric     bool TraverseBlockExpr(BlockExpr *BE) { return true; }
28159d1ed5bSDimitry Andric     bool TraverseLambdaBody(LambdaExpr *LE) { return true; }
28259d1ed5bSDimitry Andric     bool TraverseCapturedStmt(CapturedStmt *CS) { return true; }
28359d1ed5bSDimitry Andric 
28459d1ed5bSDimitry Andric     bool VisitDecl(const Decl *D) {
28559d1ed5bSDimitry Andric       switch (D->getKind()) {
28659d1ed5bSDimitry Andric       default:
28759d1ed5bSDimitry Andric         break;
28859d1ed5bSDimitry Andric       case Decl::Function:
28959d1ed5bSDimitry Andric       case Decl::CXXMethod:
29059d1ed5bSDimitry Andric       case Decl::CXXConstructor:
29159d1ed5bSDimitry Andric       case Decl::CXXDestructor:
29259d1ed5bSDimitry Andric       case Decl::CXXConversion:
29359d1ed5bSDimitry Andric       case Decl::ObjCMethod:
29459d1ed5bSDimitry Andric       case Decl::Block:
29559d1ed5bSDimitry Andric       case Decl::Captured:
29659d1ed5bSDimitry Andric         CounterMap[D->getBody()] = NextCounter++;
29759d1ed5bSDimitry Andric         break;
29859d1ed5bSDimitry Andric       }
29959d1ed5bSDimitry Andric       return true;
30059d1ed5bSDimitry Andric     }
30159d1ed5bSDimitry Andric 
30259d1ed5bSDimitry Andric     bool VisitStmt(const Stmt *S) {
30359d1ed5bSDimitry Andric       auto Type = getHashType(S);
30459d1ed5bSDimitry Andric       if (Type == PGOHash::None)
30559d1ed5bSDimitry Andric         return true;
30659d1ed5bSDimitry Andric 
30759d1ed5bSDimitry Andric       CounterMap[S] = NextCounter++;
30859d1ed5bSDimitry Andric       Hash.combine(Type);
30959d1ed5bSDimitry Andric       return true;
31059d1ed5bSDimitry Andric     }
31159d1ed5bSDimitry Andric     PGOHash::HashType getHashType(const Stmt *S) {
31259d1ed5bSDimitry Andric       switch (S->getStmtClass()) {
31359d1ed5bSDimitry Andric       default:
31459d1ed5bSDimitry Andric         break;
31559d1ed5bSDimitry Andric       case Stmt::LabelStmtClass:
31659d1ed5bSDimitry Andric         return PGOHash::LabelStmt;
31759d1ed5bSDimitry Andric       case Stmt::WhileStmtClass:
31859d1ed5bSDimitry Andric         return PGOHash::WhileStmt;
31959d1ed5bSDimitry Andric       case Stmt::DoStmtClass:
32059d1ed5bSDimitry Andric         return PGOHash::DoStmt;
32159d1ed5bSDimitry Andric       case Stmt::ForStmtClass:
32259d1ed5bSDimitry Andric         return PGOHash::ForStmt;
32359d1ed5bSDimitry Andric       case Stmt::CXXForRangeStmtClass:
32459d1ed5bSDimitry Andric         return PGOHash::CXXForRangeStmt;
32559d1ed5bSDimitry Andric       case Stmt::ObjCForCollectionStmtClass:
32659d1ed5bSDimitry Andric         return PGOHash::ObjCForCollectionStmt;
32759d1ed5bSDimitry Andric       case Stmt::SwitchStmtClass:
32859d1ed5bSDimitry Andric         return PGOHash::SwitchStmt;
32959d1ed5bSDimitry Andric       case Stmt::CaseStmtClass:
33059d1ed5bSDimitry Andric         return PGOHash::CaseStmt;
33159d1ed5bSDimitry Andric       case Stmt::DefaultStmtClass:
33259d1ed5bSDimitry Andric         return PGOHash::DefaultStmt;
33359d1ed5bSDimitry Andric       case Stmt::IfStmtClass:
33459d1ed5bSDimitry Andric         return PGOHash::IfStmt;
33559d1ed5bSDimitry Andric       case Stmt::CXXTryStmtClass:
33659d1ed5bSDimitry Andric         return PGOHash::CXXTryStmt;
33759d1ed5bSDimitry Andric       case Stmt::CXXCatchStmtClass:
33859d1ed5bSDimitry Andric         return PGOHash::CXXCatchStmt;
33959d1ed5bSDimitry Andric       case Stmt::ConditionalOperatorClass:
34059d1ed5bSDimitry Andric         return PGOHash::ConditionalOperator;
34159d1ed5bSDimitry Andric       case Stmt::BinaryConditionalOperatorClass:
34259d1ed5bSDimitry Andric         return PGOHash::BinaryConditionalOperator;
34359d1ed5bSDimitry Andric       case Stmt::BinaryOperatorClass: {
34459d1ed5bSDimitry Andric         const BinaryOperator *BO = cast<BinaryOperator>(S);
34559d1ed5bSDimitry Andric         if (BO->getOpcode() == BO_LAnd)
34659d1ed5bSDimitry Andric           return PGOHash::BinaryOperatorLAnd;
34759d1ed5bSDimitry Andric         if (BO->getOpcode() == BO_LOr)
34859d1ed5bSDimitry Andric           return PGOHash::BinaryOperatorLOr;
34959d1ed5bSDimitry Andric         break;
35059d1ed5bSDimitry Andric       }
35159d1ed5bSDimitry Andric       }
35259d1ed5bSDimitry Andric       return PGOHash::None;
35359d1ed5bSDimitry Andric     }
35459d1ed5bSDimitry Andric   };
35559d1ed5bSDimitry Andric 
35659d1ed5bSDimitry Andric   /// A StmtVisitor that propagates the raw counts through the AST and
35759d1ed5bSDimitry Andric   /// records the count at statements where the value may change.
35859d1ed5bSDimitry Andric   struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> {
35959d1ed5bSDimitry Andric     /// PGO state.
36059d1ed5bSDimitry Andric     CodeGenPGO &PGO;
36159d1ed5bSDimitry Andric 
36259d1ed5bSDimitry Andric     /// A flag that is set when the current count should be recorded on the
36359d1ed5bSDimitry Andric     /// next statement, such as at the exit of a loop.
36459d1ed5bSDimitry Andric     bool RecordNextStmtCount;
36559d1ed5bSDimitry Andric 
36659d1ed5bSDimitry Andric     /// The map of statements to count values.
36759d1ed5bSDimitry Andric     llvm::DenseMap<const Stmt *, uint64_t> &CountMap;
36859d1ed5bSDimitry Andric 
36959d1ed5bSDimitry Andric     /// BreakContinueStack - Keep counts of breaks and continues inside loops.
37059d1ed5bSDimitry Andric     struct BreakContinue {
37159d1ed5bSDimitry Andric       uint64_t BreakCount;
37259d1ed5bSDimitry Andric       uint64_t ContinueCount;
37359d1ed5bSDimitry Andric       BreakContinue() : BreakCount(0), ContinueCount(0) {}
37459d1ed5bSDimitry Andric     };
37559d1ed5bSDimitry Andric     SmallVector<BreakContinue, 8> BreakContinueStack;
37659d1ed5bSDimitry Andric 
37759d1ed5bSDimitry Andric     ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &CountMap,
37859d1ed5bSDimitry Andric                         CodeGenPGO &PGO)
37959d1ed5bSDimitry Andric         : PGO(PGO), RecordNextStmtCount(false), CountMap(CountMap) {}
38059d1ed5bSDimitry Andric 
38159d1ed5bSDimitry Andric     void RecordStmtCount(const Stmt *S) {
38259d1ed5bSDimitry Andric       if (RecordNextStmtCount) {
38359d1ed5bSDimitry Andric         CountMap[S] = PGO.getCurrentRegionCount();
38459d1ed5bSDimitry Andric         RecordNextStmtCount = false;
38559d1ed5bSDimitry Andric       }
38659d1ed5bSDimitry Andric     }
38759d1ed5bSDimitry Andric 
38859d1ed5bSDimitry Andric     void VisitStmt(const Stmt *S) {
38959d1ed5bSDimitry Andric       RecordStmtCount(S);
39059d1ed5bSDimitry Andric       for (Stmt::const_child_range I = S->children(); I; ++I) {
39159d1ed5bSDimitry Andric         if (*I)
39259d1ed5bSDimitry Andric          this->Visit(*I);
39359d1ed5bSDimitry Andric       }
39459d1ed5bSDimitry Andric     }
39559d1ed5bSDimitry Andric 
39659d1ed5bSDimitry Andric     void VisitFunctionDecl(const FunctionDecl *D) {
39759d1ed5bSDimitry Andric       // Counter tracks entry to the function body.
39859d1ed5bSDimitry Andric       RegionCounter Cnt(PGO, D->getBody());
39959d1ed5bSDimitry Andric       Cnt.beginRegion();
40059d1ed5bSDimitry Andric       CountMap[D->getBody()] = PGO.getCurrentRegionCount();
40159d1ed5bSDimitry Andric       Visit(D->getBody());
40259d1ed5bSDimitry Andric     }
40359d1ed5bSDimitry Andric 
40459d1ed5bSDimitry Andric     // Skip lambda expressions. We visit these as FunctionDecls when we're
40559d1ed5bSDimitry Andric     // generating them and aren't interested in the body when generating a
40659d1ed5bSDimitry Andric     // parent context.
40759d1ed5bSDimitry Andric     void VisitLambdaExpr(const LambdaExpr *LE) {}
40859d1ed5bSDimitry Andric 
40959d1ed5bSDimitry Andric     void VisitCapturedDecl(const CapturedDecl *D) {
41059d1ed5bSDimitry Andric       // Counter tracks entry to the capture body.
41159d1ed5bSDimitry Andric       RegionCounter Cnt(PGO, D->getBody());
41259d1ed5bSDimitry Andric       Cnt.beginRegion();
41359d1ed5bSDimitry Andric       CountMap[D->getBody()] = PGO.getCurrentRegionCount();
41459d1ed5bSDimitry Andric       Visit(D->getBody());
41559d1ed5bSDimitry Andric     }
41659d1ed5bSDimitry Andric 
41759d1ed5bSDimitry Andric     void VisitObjCMethodDecl(const ObjCMethodDecl *D) {
41859d1ed5bSDimitry Andric       // Counter tracks entry to the method body.
41959d1ed5bSDimitry Andric       RegionCounter Cnt(PGO, D->getBody());
42059d1ed5bSDimitry Andric       Cnt.beginRegion();
42159d1ed5bSDimitry Andric       CountMap[D->getBody()] = PGO.getCurrentRegionCount();
42259d1ed5bSDimitry Andric       Visit(D->getBody());
42359d1ed5bSDimitry Andric     }
42459d1ed5bSDimitry Andric 
42559d1ed5bSDimitry Andric     void VisitBlockDecl(const BlockDecl *D) {
42659d1ed5bSDimitry Andric       // Counter tracks entry to the block body.
42759d1ed5bSDimitry Andric       RegionCounter Cnt(PGO, D->getBody());
42859d1ed5bSDimitry Andric       Cnt.beginRegion();
42959d1ed5bSDimitry Andric       CountMap[D->getBody()] = PGO.getCurrentRegionCount();
43059d1ed5bSDimitry Andric       Visit(D->getBody());
43159d1ed5bSDimitry Andric     }
43259d1ed5bSDimitry Andric 
43359d1ed5bSDimitry Andric     void VisitReturnStmt(const ReturnStmt *S) {
43459d1ed5bSDimitry Andric       RecordStmtCount(S);
43559d1ed5bSDimitry Andric       if (S->getRetValue())
43659d1ed5bSDimitry Andric         Visit(S->getRetValue());
43759d1ed5bSDimitry Andric       PGO.setCurrentRegionUnreachable();
43859d1ed5bSDimitry Andric       RecordNextStmtCount = true;
43959d1ed5bSDimitry Andric     }
44059d1ed5bSDimitry Andric 
44159d1ed5bSDimitry Andric     void VisitGotoStmt(const GotoStmt *S) {
44259d1ed5bSDimitry Andric       RecordStmtCount(S);
44359d1ed5bSDimitry Andric       PGO.setCurrentRegionUnreachable();
44459d1ed5bSDimitry Andric       RecordNextStmtCount = true;
44559d1ed5bSDimitry Andric     }
44659d1ed5bSDimitry Andric 
44759d1ed5bSDimitry Andric     void VisitLabelStmt(const LabelStmt *S) {
44859d1ed5bSDimitry Andric       RecordNextStmtCount = false;
44959d1ed5bSDimitry Andric       // Counter tracks the block following the label.
45059d1ed5bSDimitry Andric       RegionCounter Cnt(PGO, S);
45159d1ed5bSDimitry Andric       Cnt.beginRegion();
45259d1ed5bSDimitry Andric       CountMap[S] = PGO.getCurrentRegionCount();
45359d1ed5bSDimitry Andric       Visit(S->getSubStmt());
45459d1ed5bSDimitry Andric     }
45559d1ed5bSDimitry Andric 
45659d1ed5bSDimitry Andric     void VisitBreakStmt(const BreakStmt *S) {
45759d1ed5bSDimitry Andric       RecordStmtCount(S);
45859d1ed5bSDimitry Andric       assert(!BreakContinueStack.empty() && "break not in a loop or switch!");
45959d1ed5bSDimitry Andric       BreakContinueStack.back().BreakCount += PGO.getCurrentRegionCount();
46059d1ed5bSDimitry Andric       PGO.setCurrentRegionUnreachable();
46159d1ed5bSDimitry Andric       RecordNextStmtCount = true;
46259d1ed5bSDimitry Andric     }
46359d1ed5bSDimitry Andric 
46459d1ed5bSDimitry Andric     void VisitContinueStmt(const ContinueStmt *S) {
46559d1ed5bSDimitry Andric       RecordStmtCount(S);
46659d1ed5bSDimitry Andric       assert(!BreakContinueStack.empty() && "continue stmt not in a loop!");
46759d1ed5bSDimitry Andric       BreakContinueStack.back().ContinueCount += PGO.getCurrentRegionCount();
46859d1ed5bSDimitry Andric       PGO.setCurrentRegionUnreachable();
46959d1ed5bSDimitry Andric       RecordNextStmtCount = true;
47059d1ed5bSDimitry Andric     }
47159d1ed5bSDimitry Andric 
47259d1ed5bSDimitry Andric     void VisitWhileStmt(const WhileStmt *S) {
47359d1ed5bSDimitry Andric       RecordStmtCount(S);
47459d1ed5bSDimitry Andric       // Counter tracks the body of the loop.
47559d1ed5bSDimitry Andric       RegionCounter Cnt(PGO, S);
47659d1ed5bSDimitry Andric       BreakContinueStack.push_back(BreakContinue());
47759d1ed5bSDimitry Andric       // Visit the body region first so the break/continue adjustments can be
47859d1ed5bSDimitry Andric       // included when visiting the condition.
47959d1ed5bSDimitry Andric       Cnt.beginRegion();
48059d1ed5bSDimitry Andric       CountMap[S->getBody()] = PGO.getCurrentRegionCount();
48159d1ed5bSDimitry Andric       Visit(S->getBody());
48259d1ed5bSDimitry Andric       Cnt.adjustForControlFlow();
48359d1ed5bSDimitry Andric 
48459d1ed5bSDimitry Andric       // ...then go back and propagate counts through the condition. The count
48559d1ed5bSDimitry Andric       // at the start of the condition is the sum of the incoming edges,
48659d1ed5bSDimitry Andric       // the backedge from the end of the loop body, and the edges from
48759d1ed5bSDimitry Andric       // continue statements.
48859d1ed5bSDimitry Andric       BreakContinue BC = BreakContinueStack.pop_back_val();
48959d1ed5bSDimitry Andric       Cnt.setCurrentRegionCount(Cnt.getParentCount() +
49059d1ed5bSDimitry Andric                                 Cnt.getAdjustedCount() + BC.ContinueCount);
49159d1ed5bSDimitry Andric       CountMap[S->getCond()] = PGO.getCurrentRegionCount();
49259d1ed5bSDimitry Andric       Visit(S->getCond());
49359d1ed5bSDimitry Andric       Cnt.adjustForControlFlow();
49459d1ed5bSDimitry Andric       Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
49559d1ed5bSDimitry Andric       RecordNextStmtCount = true;
49659d1ed5bSDimitry Andric     }
49759d1ed5bSDimitry Andric 
49859d1ed5bSDimitry Andric     void VisitDoStmt(const DoStmt *S) {
49959d1ed5bSDimitry Andric       RecordStmtCount(S);
50059d1ed5bSDimitry Andric       // Counter tracks the body of the loop.
50159d1ed5bSDimitry Andric       RegionCounter Cnt(PGO, S);
50259d1ed5bSDimitry Andric       BreakContinueStack.push_back(BreakContinue());
50359d1ed5bSDimitry Andric       Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
50459d1ed5bSDimitry Andric       CountMap[S->getBody()] = PGO.getCurrentRegionCount();
50559d1ed5bSDimitry Andric       Visit(S->getBody());
50659d1ed5bSDimitry Andric       Cnt.adjustForControlFlow();
50759d1ed5bSDimitry Andric 
50859d1ed5bSDimitry Andric       BreakContinue BC = BreakContinueStack.pop_back_val();
50959d1ed5bSDimitry Andric       // The count at the start of the condition is equal to the count at the
51059d1ed5bSDimitry Andric       // end of the body. The adjusted count does not include either the
51159d1ed5bSDimitry Andric       // fall-through count coming into the loop or the continue count, so add
51259d1ed5bSDimitry Andric       // both of those separately. This is coincidentally the same equation as
51359d1ed5bSDimitry Andric       // with while loops but for different reasons.
51459d1ed5bSDimitry Andric       Cnt.setCurrentRegionCount(Cnt.getParentCount() +
51559d1ed5bSDimitry Andric                                 Cnt.getAdjustedCount() + BC.ContinueCount);
51659d1ed5bSDimitry Andric       CountMap[S->getCond()] = PGO.getCurrentRegionCount();
51759d1ed5bSDimitry Andric       Visit(S->getCond());
51859d1ed5bSDimitry Andric       Cnt.adjustForControlFlow();
51959d1ed5bSDimitry Andric       Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
52059d1ed5bSDimitry Andric       RecordNextStmtCount = true;
52159d1ed5bSDimitry Andric     }
52259d1ed5bSDimitry Andric 
52359d1ed5bSDimitry Andric     void VisitForStmt(const ForStmt *S) {
52459d1ed5bSDimitry Andric       RecordStmtCount(S);
52559d1ed5bSDimitry Andric       if (S->getInit())
52659d1ed5bSDimitry Andric         Visit(S->getInit());
52759d1ed5bSDimitry Andric       // Counter tracks the body of the loop.
52859d1ed5bSDimitry Andric       RegionCounter Cnt(PGO, S);
52959d1ed5bSDimitry Andric       BreakContinueStack.push_back(BreakContinue());
53059d1ed5bSDimitry Andric       // Visit the body region first. (This is basically the same as a while
53159d1ed5bSDimitry Andric       // loop; see further comments in VisitWhileStmt.)
53259d1ed5bSDimitry Andric       Cnt.beginRegion();
53359d1ed5bSDimitry Andric       CountMap[S->getBody()] = PGO.getCurrentRegionCount();
53459d1ed5bSDimitry Andric       Visit(S->getBody());
53559d1ed5bSDimitry Andric       Cnt.adjustForControlFlow();
53659d1ed5bSDimitry Andric 
53759d1ed5bSDimitry Andric       // The increment is essentially part of the body but it needs to include
53859d1ed5bSDimitry Andric       // the count for all the continue statements.
53959d1ed5bSDimitry Andric       if (S->getInc()) {
54059d1ed5bSDimitry Andric         Cnt.setCurrentRegionCount(PGO.getCurrentRegionCount() +
54159d1ed5bSDimitry Andric                                   BreakContinueStack.back().ContinueCount);
54259d1ed5bSDimitry Andric         CountMap[S->getInc()] = PGO.getCurrentRegionCount();
54359d1ed5bSDimitry Andric         Visit(S->getInc());
54459d1ed5bSDimitry Andric         Cnt.adjustForControlFlow();
54559d1ed5bSDimitry Andric       }
54659d1ed5bSDimitry Andric 
54759d1ed5bSDimitry Andric       BreakContinue BC = BreakContinueStack.pop_back_val();
54859d1ed5bSDimitry Andric 
54959d1ed5bSDimitry Andric       // ...then go back and propagate counts through the condition.
55059d1ed5bSDimitry Andric       if (S->getCond()) {
55159d1ed5bSDimitry Andric         Cnt.setCurrentRegionCount(Cnt.getParentCount() +
55259d1ed5bSDimitry Andric                                   Cnt.getAdjustedCount() +
55359d1ed5bSDimitry Andric                                   BC.ContinueCount);
55459d1ed5bSDimitry Andric         CountMap[S->getCond()] = PGO.getCurrentRegionCount();
55559d1ed5bSDimitry Andric         Visit(S->getCond());
55659d1ed5bSDimitry Andric         Cnt.adjustForControlFlow();
55759d1ed5bSDimitry Andric       }
55859d1ed5bSDimitry Andric       Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
55959d1ed5bSDimitry Andric       RecordNextStmtCount = true;
56059d1ed5bSDimitry Andric     }
56159d1ed5bSDimitry Andric 
56259d1ed5bSDimitry Andric     void VisitCXXForRangeStmt(const CXXForRangeStmt *S) {
56359d1ed5bSDimitry Andric       RecordStmtCount(S);
56459d1ed5bSDimitry Andric       Visit(S->getRangeStmt());
56559d1ed5bSDimitry Andric       Visit(S->getBeginEndStmt());
56659d1ed5bSDimitry Andric       // Counter tracks the body of the loop.
56759d1ed5bSDimitry Andric       RegionCounter Cnt(PGO, S);
56859d1ed5bSDimitry Andric       BreakContinueStack.push_back(BreakContinue());
56959d1ed5bSDimitry Andric       // Visit the body region first. (This is basically the same as a while
57059d1ed5bSDimitry Andric       // loop; see further comments in VisitWhileStmt.)
57159d1ed5bSDimitry Andric       Cnt.beginRegion();
57259d1ed5bSDimitry Andric       CountMap[S->getLoopVarStmt()] = PGO.getCurrentRegionCount();
57359d1ed5bSDimitry Andric       Visit(S->getLoopVarStmt());
57459d1ed5bSDimitry Andric       Visit(S->getBody());
57559d1ed5bSDimitry Andric       Cnt.adjustForControlFlow();
57659d1ed5bSDimitry Andric 
57759d1ed5bSDimitry Andric       // The increment is essentially part of the body but it needs to include
57859d1ed5bSDimitry Andric       // the count for all the continue statements.
57959d1ed5bSDimitry Andric       Cnt.setCurrentRegionCount(PGO.getCurrentRegionCount() +
58059d1ed5bSDimitry Andric                                 BreakContinueStack.back().ContinueCount);
58159d1ed5bSDimitry Andric       CountMap[S->getInc()] = PGO.getCurrentRegionCount();
58259d1ed5bSDimitry Andric       Visit(S->getInc());
58359d1ed5bSDimitry Andric       Cnt.adjustForControlFlow();
58459d1ed5bSDimitry Andric 
58559d1ed5bSDimitry Andric       BreakContinue BC = BreakContinueStack.pop_back_val();
58659d1ed5bSDimitry Andric 
58759d1ed5bSDimitry Andric       // ...then go back and propagate counts through the condition.
58859d1ed5bSDimitry Andric       Cnt.setCurrentRegionCount(Cnt.getParentCount() +
58959d1ed5bSDimitry Andric                                 Cnt.getAdjustedCount() +
59059d1ed5bSDimitry Andric                                 BC.ContinueCount);
59159d1ed5bSDimitry Andric       CountMap[S->getCond()] = PGO.getCurrentRegionCount();
59259d1ed5bSDimitry Andric       Visit(S->getCond());
59359d1ed5bSDimitry Andric       Cnt.adjustForControlFlow();
59459d1ed5bSDimitry Andric       Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
59559d1ed5bSDimitry Andric       RecordNextStmtCount = true;
59659d1ed5bSDimitry Andric     }
59759d1ed5bSDimitry Andric 
59859d1ed5bSDimitry Andric     void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) {
59959d1ed5bSDimitry Andric       RecordStmtCount(S);
60059d1ed5bSDimitry Andric       Visit(S->getElement());
60159d1ed5bSDimitry Andric       // Counter tracks the body of the loop.
60259d1ed5bSDimitry Andric       RegionCounter Cnt(PGO, S);
60359d1ed5bSDimitry Andric       BreakContinueStack.push_back(BreakContinue());
60459d1ed5bSDimitry Andric       Cnt.beginRegion();
60559d1ed5bSDimitry Andric       CountMap[S->getBody()] = PGO.getCurrentRegionCount();
60659d1ed5bSDimitry Andric       Visit(S->getBody());
60759d1ed5bSDimitry Andric       BreakContinue BC = BreakContinueStack.pop_back_val();
60859d1ed5bSDimitry Andric       Cnt.adjustForControlFlow();
60959d1ed5bSDimitry Andric       Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount);
61059d1ed5bSDimitry Andric       RecordNextStmtCount = true;
61159d1ed5bSDimitry Andric     }
61259d1ed5bSDimitry Andric 
61359d1ed5bSDimitry Andric     void VisitSwitchStmt(const SwitchStmt *S) {
61459d1ed5bSDimitry Andric       RecordStmtCount(S);
61559d1ed5bSDimitry Andric       Visit(S->getCond());
61659d1ed5bSDimitry Andric       PGO.setCurrentRegionUnreachable();
61759d1ed5bSDimitry Andric       BreakContinueStack.push_back(BreakContinue());
61859d1ed5bSDimitry Andric       Visit(S->getBody());
61959d1ed5bSDimitry Andric       // If the switch is inside a loop, add the continue counts.
62059d1ed5bSDimitry Andric       BreakContinue BC = BreakContinueStack.pop_back_val();
62159d1ed5bSDimitry Andric       if (!BreakContinueStack.empty())
62259d1ed5bSDimitry Andric         BreakContinueStack.back().ContinueCount += BC.ContinueCount;
62359d1ed5bSDimitry Andric       // Counter tracks the exit block of the switch.
62459d1ed5bSDimitry Andric       RegionCounter ExitCnt(PGO, S);
62559d1ed5bSDimitry Andric       ExitCnt.beginRegion();
62659d1ed5bSDimitry Andric       RecordNextStmtCount = true;
62759d1ed5bSDimitry Andric     }
62859d1ed5bSDimitry Andric 
62959d1ed5bSDimitry Andric     void VisitCaseStmt(const CaseStmt *S) {
63059d1ed5bSDimitry Andric       RecordNextStmtCount = false;
63159d1ed5bSDimitry Andric       // Counter for this particular case. This counts only jumps from the
63259d1ed5bSDimitry Andric       // switch header and does not include fallthrough from the case before
63359d1ed5bSDimitry Andric       // this one.
63459d1ed5bSDimitry Andric       RegionCounter Cnt(PGO, S);
63559d1ed5bSDimitry Andric       Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
63659d1ed5bSDimitry Andric       CountMap[S] = Cnt.getCount();
63759d1ed5bSDimitry Andric       RecordNextStmtCount = true;
63859d1ed5bSDimitry Andric       Visit(S->getSubStmt());
63959d1ed5bSDimitry Andric     }
64059d1ed5bSDimitry Andric 
64159d1ed5bSDimitry Andric     void VisitDefaultStmt(const DefaultStmt *S) {
64259d1ed5bSDimitry Andric       RecordNextStmtCount = false;
64359d1ed5bSDimitry Andric       // Counter for this default case. This does not include fallthrough from
64459d1ed5bSDimitry Andric       // the previous case.
64559d1ed5bSDimitry Andric       RegionCounter Cnt(PGO, S);
64659d1ed5bSDimitry Andric       Cnt.beginRegion(/*AddIncomingFallThrough=*/true);
64759d1ed5bSDimitry Andric       CountMap[S] = Cnt.getCount();
64859d1ed5bSDimitry Andric       RecordNextStmtCount = true;
64959d1ed5bSDimitry Andric       Visit(S->getSubStmt());
65059d1ed5bSDimitry Andric     }
65159d1ed5bSDimitry Andric 
65259d1ed5bSDimitry Andric     void VisitIfStmt(const IfStmt *S) {
65359d1ed5bSDimitry Andric       RecordStmtCount(S);
65459d1ed5bSDimitry Andric       // Counter tracks the "then" part of an if statement. The count for
65559d1ed5bSDimitry Andric       // the "else" part, if it exists, will be calculated from this counter.
65659d1ed5bSDimitry Andric       RegionCounter Cnt(PGO, S);
65759d1ed5bSDimitry Andric       Visit(S->getCond());
65859d1ed5bSDimitry Andric 
65959d1ed5bSDimitry Andric       Cnt.beginRegion();
66059d1ed5bSDimitry Andric       CountMap[S->getThen()] = PGO.getCurrentRegionCount();
66159d1ed5bSDimitry Andric       Visit(S->getThen());
66259d1ed5bSDimitry Andric       Cnt.adjustForControlFlow();
66359d1ed5bSDimitry Andric 
66459d1ed5bSDimitry Andric       if (S->getElse()) {
66559d1ed5bSDimitry Andric         Cnt.beginElseRegion();
66659d1ed5bSDimitry Andric         CountMap[S->getElse()] = PGO.getCurrentRegionCount();
66759d1ed5bSDimitry Andric         Visit(S->getElse());
66859d1ed5bSDimitry Andric         Cnt.adjustForControlFlow();
66959d1ed5bSDimitry Andric       }
67059d1ed5bSDimitry Andric       Cnt.applyAdjustmentsToRegion(0);
67159d1ed5bSDimitry Andric       RecordNextStmtCount = true;
67259d1ed5bSDimitry Andric     }
67359d1ed5bSDimitry Andric 
67459d1ed5bSDimitry Andric     void VisitCXXTryStmt(const CXXTryStmt *S) {
67559d1ed5bSDimitry Andric       RecordStmtCount(S);
67659d1ed5bSDimitry Andric       Visit(S->getTryBlock());
67759d1ed5bSDimitry Andric       for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I)
67859d1ed5bSDimitry Andric         Visit(S->getHandler(I));
67959d1ed5bSDimitry Andric       // Counter tracks the continuation block of the try statement.
68059d1ed5bSDimitry Andric       RegionCounter Cnt(PGO, S);
68159d1ed5bSDimitry Andric       Cnt.beginRegion();
68259d1ed5bSDimitry Andric       RecordNextStmtCount = true;
68359d1ed5bSDimitry Andric     }
68459d1ed5bSDimitry Andric 
68559d1ed5bSDimitry Andric     void VisitCXXCatchStmt(const CXXCatchStmt *S) {
68659d1ed5bSDimitry Andric       RecordNextStmtCount = false;
68759d1ed5bSDimitry Andric       // Counter tracks the catch statement's handler block.
68859d1ed5bSDimitry Andric       RegionCounter Cnt(PGO, S);
68959d1ed5bSDimitry Andric       Cnt.beginRegion();
69059d1ed5bSDimitry Andric       CountMap[S] = PGO.getCurrentRegionCount();
69159d1ed5bSDimitry Andric       Visit(S->getHandlerBlock());
69259d1ed5bSDimitry Andric     }
69359d1ed5bSDimitry Andric 
69459d1ed5bSDimitry Andric     void VisitAbstractConditionalOperator(
69559d1ed5bSDimitry Andric         const AbstractConditionalOperator *E) {
69659d1ed5bSDimitry Andric       RecordStmtCount(E);
69759d1ed5bSDimitry Andric       // Counter tracks the "true" part of a conditional operator. The
69859d1ed5bSDimitry Andric       // count in the "false" part will be calculated from this counter.
69959d1ed5bSDimitry Andric       RegionCounter Cnt(PGO, E);
70059d1ed5bSDimitry Andric       Visit(E->getCond());
70159d1ed5bSDimitry Andric 
70259d1ed5bSDimitry Andric       Cnt.beginRegion();
70359d1ed5bSDimitry Andric       CountMap[E->getTrueExpr()] = PGO.getCurrentRegionCount();
70459d1ed5bSDimitry Andric       Visit(E->getTrueExpr());
70559d1ed5bSDimitry Andric       Cnt.adjustForControlFlow();
70659d1ed5bSDimitry Andric 
70759d1ed5bSDimitry Andric       Cnt.beginElseRegion();
70859d1ed5bSDimitry Andric       CountMap[E->getFalseExpr()] = PGO.getCurrentRegionCount();
70959d1ed5bSDimitry Andric       Visit(E->getFalseExpr());
71059d1ed5bSDimitry Andric       Cnt.adjustForControlFlow();
71159d1ed5bSDimitry Andric 
71259d1ed5bSDimitry Andric       Cnt.applyAdjustmentsToRegion(0);
71359d1ed5bSDimitry Andric       RecordNextStmtCount = true;
71459d1ed5bSDimitry Andric     }
71559d1ed5bSDimitry Andric 
71659d1ed5bSDimitry Andric     void VisitBinLAnd(const BinaryOperator *E) {
71759d1ed5bSDimitry Andric       RecordStmtCount(E);
71859d1ed5bSDimitry Andric       // Counter tracks the right hand side of a logical and operator.
71959d1ed5bSDimitry Andric       RegionCounter Cnt(PGO, E);
72059d1ed5bSDimitry Andric       Visit(E->getLHS());
72159d1ed5bSDimitry Andric       Cnt.beginRegion();
72259d1ed5bSDimitry Andric       CountMap[E->getRHS()] = PGO.getCurrentRegionCount();
72359d1ed5bSDimitry Andric       Visit(E->getRHS());
72459d1ed5bSDimitry Andric       Cnt.adjustForControlFlow();
72559d1ed5bSDimitry Andric       Cnt.applyAdjustmentsToRegion(0);
72659d1ed5bSDimitry Andric       RecordNextStmtCount = true;
72759d1ed5bSDimitry Andric     }
72859d1ed5bSDimitry Andric 
72959d1ed5bSDimitry Andric     void VisitBinLOr(const BinaryOperator *E) {
73059d1ed5bSDimitry Andric       RecordStmtCount(E);
73159d1ed5bSDimitry Andric       // Counter tracks the right hand side of a logical or operator.
73259d1ed5bSDimitry Andric       RegionCounter Cnt(PGO, E);
73359d1ed5bSDimitry Andric       Visit(E->getLHS());
73459d1ed5bSDimitry Andric       Cnt.beginRegion();
73559d1ed5bSDimitry Andric       CountMap[E->getRHS()] = PGO.getCurrentRegionCount();
73659d1ed5bSDimitry Andric       Visit(E->getRHS());
73759d1ed5bSDimitry Andric       Cnt.adjustForControlFlow();
73859d1ed5bSDimitry Andric       Cnt.applyAdjustmentsToRegion(0);
73959d1ed5bSDimitry Andric       RecordNextStmtCount = true;
74059d1ed5bSDimitry Andric     }
74159d1ed5bSDimitry Andric   };
74259d1ed5bSDimitry Andric }
74359d1ed5bSDimitry Andric 
74459d1ed5bSDimitry Andric void PGOHash::combine(HashType Type) {
74559d1ed5bSDimitry Andric   // Check that we never combine 0 and only have six bits.
74659d1ed5bSDimitry Andric   assert(Type && "Hash is invalid: unexpected type 0");
74759d1ed5bSDimitry Andric   assert(unsigned(Type) < TooBig && "Hash is invalid: too many types");
74859d1ed5bSDimitry Andric 
74959d1ed5bSDimitry Andric   // Pass through MD5 if enough work has built up.
75059d1ed5bSDimitry Andric   if (Count && Count % NumTypesPerWord == 0) {
75159d1ed5bSDimitry Andric     using namespace llvm::support;
75259d1ed5bSDimitry Andric     uint64_t Swapped = endian::byte_swap<uint64_t, little>(Working);
75359d1ed5bSDimitry Andric     MD5.update(llvm::makeArrayRef((uint8_t *)&Swapped, sizeof(Swapped)));
75459d1ed5bSDimitry Andric     Working = 0;
75559d1ed5bSDimitry Andric   }
75659d1ed5bSDimitry Andric 
75759d1ed5bSDimitry Andric   // Accumulate the current type.
75859d1ed5bSDimitry Andric   ++Count;
75959d1ed5bSDimitry Andric   Working = Working << NumBitsPerType | Type;
76059d1ed5bSDimitry Andric }
76159d1ed5bSDimitry Andric 
76259d1ed5bSDimitry Andric uint64_t PGOHash::finalize() {
76359d1ed5bSDimitry Andric   // Use Working as the hash directly if we never used MD5.
76459d1ed5bSDimitry Andric   if (Count <= NumTypesPerWord)
76559d1ed5bSDimitry Andric     // No need to byte swap here, since none of the math was endian-dependent.
76659d1ed5bSDimitry Andric     // This number will be byte-swapped as required on endianness transitions,
76759d1ed5bSDimitry Andric     // so we will see the same value on the other side.
76859d1ed5bSDimitry Andric     return Working;
76959d1ed5bSDimitry Andric 
77059d1ed5bSDimitry Andric   // Check for remaining work in Working.
77159d1ed5bSDimitry Andric   if (Working)
77259d1ed5bSDimitry Andric     MD5.update(Working);
77359d1ed5bSDimitry Andric 
77459d1ed5bSDimitry Andric   // Finalize the MD5 and return the hash.
77559d1ed5bSDimitry Andric   llvm::MD5::MD5Result Result;
77659d1ed5bSDimitry Andric   MD5.final(Result);
77759d1ed5bSDimitry Andric   using namespace llvm::support;
77859d1ed5bSDimitry Andric   return endian::read<uint64_t, little, unaligned>(Result);
77959d1ed5bSDimitry Andric }
78059d1ed5bSDimitry Andric 
78159d1ed5bSDimitry Andric static void emitRuntimeHook(CodeGenModule &CGM) {
78259d1ed5bSDimitry Andric   const char *const RuntimeVarName = "__llvm_profile_runtime";
78359d1ed5bSDimitry Andric   const char *const RuntimeUserName = "__llvm_profile_runtime_user";
78459d1ed5bSDimitry Andric   if (CGM.getModule().getGlobalVariable(RuntimeVarName))
78559d1ed5bSDimitry Andric     return;
78659d1ed5bSDimitry Andric 
78759d1ed5bSDimitry Andric   // Declare the runtime hook.
78859d1ed5bSDimitry Andric   llvm::LLVMContext &Ctx = CGM.getLLVMContext();
78959d1ed5bSDimitry Andric   auto *Int32Ty = llvm::Type::getInt32Ty(Ctx);
79059d1ed5bSDimitry Andric   auto *Var = new llvm::GlobalVariable(CGM.getModule(), Int32Ty, false,
79159d1ed5bSDimitry Andric                                        llvm::GlobalValue::ExternalLinkage,
79259d1ed5bSDimitry Andric                                        nullptr, RuntimeVarName);
79359d1ed5bSDimitry Andric 
79459d1ed5bSDimitry Andric   // Make a function that uses it.
79559d1ed5bSDimitry Andric   auto *User = llvm::Function::Create(llvm::FunctionType::get(Int32Ty, false),
79659d1ed5bSDimitry Andric                                       llvm::GlobalValue::LinkOnceODRLinkage,
79759d1ed5bSDimitry Andric                                       RuntimeUserName, &CGM.getModule());
79859d1ed5bSDimitry Andric   User->addFnAttr(llvm::Attribute::NoInline);
79959d1ed5bSDimitry Andric   if (CGM.getCodeGenOpts().DisableRedZone)
80059d1ed5bSDimitry Andric     User->addFnAttr(llvm::Attribute::NoRedZone);
80159d1ed5bSDimitry Andric   CGBuilderTy Builder(llvm::BasicBlock::Create(CGM.getLLVMContext(), "", User));
80259d1ed5bSDimitry Andric   auto *Load = Builder.CreateLoad(Var);
80359d1ed5bSDimitry Andric   Builder.CreateRet(Load);
80459d1ed5bSDimitry Andric 
80559d1ed5bSDimitry Andric   // Create a use of the function.  Now the definition of the runtime variable
80659d1ed5bSDimitry Andric   // should get pulled in, along with any static initializears.
80759d1ed5bSDimitry Andric   CGM.addUsedGlobal(User);
80859d1ed5bSDimitry Andric }
80959d1ed5bSDimitry Andric 
81059d1ed5bSDimitry Andric void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) {
81159d1ed5bSDimitry Andric   bool InstrumentRegions = CGM.getCodeGenOpts().ProfileInstrGenerate;
81259d1ed5bSDimitry Andric   llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader();
81359d1ed5bSDimitry Andric   if (!InstrumentRegions && !PGOReader)
81459d1ed5bSDimitry Andric     return;
81559d1ed5bSDimitry Andric   if (D->isImplicit())
81659d1ed5bSDimitry Andric     return;
81759d1ed5bSDimitry Andric   setFuncName(Fn);
81859d1ed5bSDimitry Andric 
81959d1ed5bSDimitry Andric   // Set the linkage for variables based on the function linkage.  Usually, we
82059d1ed5bSDimitry Andric   // want to match it, but available_externally and extern_weak both have the
82159d1ed5bSDimitry Andric   // wrong semantics.
82259d1ed5bSDimitry Andric   VarLinkage = Fn->getLinkage();
82359d1ed5bSDimitry Andric   switch (VarLinkage) {
82459d1ed5bSDimitry Andric   case llvm::GlobalValue::ExternalWeakLinkage:
82559d1ed5bSDimitry Andric     VarLinkage = llvm::GlobalValue::LinkOnceAnyLinkage;
82659d1ed5bSDimitry Andric     break;
82759d1ed5bSDimitry Andric   case llvm::GlobalValue::AvailableExternallyLinkage:
82859d1ed5bSDimitry Andric     VarLinkage = llvm::GlobalValue::LinkOnceODRLinkage;
82959d1ed5bSDimitry Andric     break;
83059d1ed5bSDimitry Andric   default:
83159d1ed5bSDimitry Andric     break;
83259d1ed5bSDimitry Andric   }
83359d1ed5bSDimitry Andric 
83459d1ed5bSDimitry Andric   mapRegionCounters(D);
83559d1ed5bSDimitry Andric   if (InstrumentRegions) {
83659d1ed5bSDimitry Andric     emitRuntimeHook(CGM);
83759d1ed5bSDimitry Andric     emitCounterVariables();
83859d1ed5bSDimitry Andric   }
83959d1ed5bSDimitry Andric   if (PGOReader) {
84059d1ed5bSDimitry Andric     SourceManager &SM = CGM.getContext().getSourceManager();
84159d1ed5bSDimitry Andric     loadRegionCounts(PGOReader, SM.isInMainFile(D->getLocation()));
84259d1ed5bSDimitry Andric     computeRegionCounts(D);
84359d1ed5bSDimitry Andric     applyFunctionAttributes(PGOReader, Fn);
84459d1ed5bSDimitry Andric   }
84559d1ed5bSDimitry Andric }
84659d1ed5bSDimitry Andric 
84759d1ed5bSDimitry Andric void CodeGenPGO::mapRegionCounters(const Decl *D) {
84859d1ed5bSDimitry Andric   RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>);
84959d1ed5bSDimitry Andric   MapRegionCounters Walker(*RegionCounterMap);
85059d1ed5bSDimitry Andric   if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
85159d1ed5bSDimitry Andric     Walker.TraverseDecl(const_cast<FunctionDecl *>(FD));
85259d1ed5bSDimitry Andric   else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
85359d1ed5bSDimitry Andric     Walker.TraverseDecl(const_cast<ObjCMethodDecl *>(MD));
85459d1ed5bSDimitry Andric   else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
85559d1ed5bSDimitry Andric     Walker.TraverseDecl(const_cast<BlockDecl *>(BD));
85659d1ed5bSDimitry Andric   else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
85759d1ed5bSDimitry Andric     Walker.TraverseDecl(const_cast<CapturedDecl *>(CD));
85859d1ed5bSDimitry Andric   assert(Walker.NextCounter > 0 && "no entry counter mapped for decl");
85959d1ed5bSDimitry Andric   NumRegionCounters = Walker.NextCounter;
86059d1ed5bSDimitry Andric   FunctionHash = Walker.Hash.finalize();
86159d1ed5bSDimitry Andric }
86259d1ed5bSDimitry Andric 
86359d1ed5bSDimitry Andric void CodeGenPGO::computeRegionCounts(const Decl *D) {
86459d1ed5bSDimitry Andric   StmtCountMap.reset(new llvm::DenseMap<const Stmt *, uint64_t>);
86559d1ed5bSDimitry Andric   ComputeRegionCounts Walker(*StmtCountMap, *this);
86659d1ed5bSDimitry Andric   if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D))
86759d1ed5bSDimitry Andric     Walker.VisitFunctionDecl(FD);
86859d1ed5bSDimitry Andric   else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
86959d1ed5bSDimitry Andric     Walker.VisitObjCMethodDecl(MD);
87059d1ed5bSDimitry Andric   else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D))
87159d1ed5bSDimitry Andric     Walker.VisitBlockDecl(BD);
87259d1ed5bSDimitry Andric   else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D))
87359d1ed5bSDimitry Andric     Walker.VisitCapturedDecl(const_cast<CapturedDecl *>(CD));
87459d1ed5bSDimitry Andric }
87559d1ed5bSDimitry Andric 
87659d1ed5bSDimitry Andric void
87759d1ed5bSDimitry Andric CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader,
87859d1ed5bSDimitry Andric                                     llvm::Function *Fn) {
87959d1ed5bSDimitry Andric   if (!haveRegionCounts())
88059d1ed5bSDimitry Andric     return;
88159d1ed5bSDimitry Andric 
88259d1ed5bSDimitry Andric   uint64_t MaxFunctionCount = PGOReader->getMaximumFunctionCount();
88359d1ed5bSDimitry Andric   uint64_t FunctionCount = getRegionCount(0);
88459d1ed5bSDimitry Andric   if (FunctionCount >= (uint64_t)(0.3 * (double)MaxFunctionCount))
88559d1ed5bSDimitry Andric     // Turn on InlineHint attribute for hot functions.
88659d1ed5bSDimitry Andric     // FIXME: 30% is from preliminary tuning on SPEC, it may not be optimal.
88759d1ed5bSDimitry Andric     Fn->addFnAttr(llvm::Attribute::InlineHint);
88859d1ed5bSDimitry Andric   else if (FunctionCount <= (uint64_t)(0.01 * (double)MaxFunctionCount))
88959d1ed5bSDimitry Andric     // Turn on Cold attribute for cold functions.
89059d1ed5bSDimitry Andric     // FIXME: 1% is from preliminary tuning on SPEC, it may not be optimal.
89159d1ed5bSDimitry Andric     Fn->addFnAttr(llvm::Attribute::Cold);
89259d1ed5bSDimitry Andric }
89359d1ed5bSDimitry Andric 
89459d1ed5bSDimitry Andric void CodeGenPGO::emitCounterVariables() {
89559d1ed5bSDimitry Andric   llvm::LLVMContext &Ctx = CGM.getLLVMContext();
89659d1ed5bSDimitry Andric   llvm::ArrayType *CounterTy = llvm::ArrayType::get(llvm::Type::getInt64Ty(Ctx),
89759d1ed5bSDimitry Andric                                                     NumRegionCounters);
89859d1ed5bSDimitry Andric   RegionCounters =
89959d1ed5bSDimitry Andric     new llvm::GlobalVariable(CGM.getModule(), CounterTy, false, VarLinkage,
90059d1ed5bSDimitry Andric                              llvm::Constant::getNullValue(CounterTy),
90159d1ed5bSDimitry Andric                              getFuncVarName("counters"));
90259d1ed5bSDimitry Andric   RegionCounters->setAlignment(8);
90359d1ed5bSDimitry Andric   RegionCounters->setSection(getCountersSection(CGM));
90459d1ed5bSDimitry Andric }
90559d1ed5bSDimitry Andric 
90659d1ed5bSDimitry Andric void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, unsigned Counter) {
90759d1ed5bSDimitry Andric   if (!RegionCounters)
90859d1ed5bSDimitry Andric     return;
90959d1ed5bSDimitry Andric   llvm::Value *Addr =
91059d1ed5bSDimitry Andric     Builder.CreateConstInBoundsGEP2_64(RegionCounters, 0, Counter);
91159d1ed5bSDimitry Andric   llvm::Value *Count = Builder.CreateLoad(Addr, "pgocount");
91259d1ed5bSDimitry Andric   Count = Builder.CreateAdd(Count, Builder.getInt64(1));
91359d1ed5bSDimitry Andric   Builder.CreateStore(Count, Addr);
91459d1ed5bSDimitry Andric }
91559d1ed5bSDimitry Andric 
91659d1ed5bSDimitry Andric void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader,
91759d1ed5bSDimitry Andric                                   bool IsInMainFile) {
91859d1ed5bSDimitry Andric   CGM.getPGOStats().addVisited(IsInMainFile);
91959d1ed5bSDimitry Andric   RegionCounts.reset(new std::vector<uint64_t>);
92059d1ed5bSDimitry Andric   uint64_t Hash;
92159d1ed5bSDimitry Andric   if (PGOReader->getFunctionCounts(getFuncName(), Hash, *RegionCounts)) {
92259d1ed5bSDimitry Andric     CGM.getPGOStats().addMissing(IsInMainFile);
92359d1ed5bSDimitry Andric     RegionCounts.reset();
92459d1ed5bSDimitry Andric   } else if (Hash != FunctionHash ||
92559d1ed5bSDimitry Andric              RegionCounts->size() != NumRegionCounters) {
92659d1ed5bSDimitry Andric     CGM.getPGOStats().addMismatched(IsInMainFile);
92759d1ed5bSDimitry Andric     RegionCounts.reset();
92859d1ed5bSDimitry Andric   }
92959d1ed5bSDimitry Andric }
93059d1ed5bSDimitry Andric 
93159d1ed5bSDimitry Andric void CodeGenPGO::destroyRegionCounters() {
93259d1ed5bSDimitry Andric   RegionCounterMap.reset();
93359d1ed5bSDimitry Andric   StmtCountMap.reset();
93459d1ed5bSDimitry Andric   RegionCounts.reset();
93559d1ed5bSDimitry Andric   RegionCounters = nullptr;
93659d1ed5bSDimitry Andric }
93759d1ed5bSDimitry Andric 
93859d1ed5bSDimitry Andric /// \brief Calculate what to divide by to scale weights.
93959d1ed5bSDimitry Andric ///
94059d1ed5bSDimitry Andric /// Given the maximum weight, calculate a divisor that will scale all the
94159d1ed5bSDimitry Andric /// weights to strictly less than UINT32_MAX.
94259d1ed5bSDimitry Andric static uint64_t calculateWeightScale(uint64_t MaxWeight) {
94359d1ed5bSDimitry Andric   return MaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1;
94459d1ed5bSDimitry Andric }
94559d1ed5bSDimitry Andric 
94659d1ed5bSDimitry Andric /// \brief Scale an individual branch weight (and add 1).
94759d1ed5bSDimitry Andric ///
94859d1ed5bSDimitry Andric /// Scale a 64-bit weight down to 32-bits using \c Scale.
94959d1ed5bSDimitry Andric ///
95059d1ed5bSDimitry Andric /// According to Laplace's Rule of Succession, it is better to compute the
95159d1ed5bSDimitry Andric /// weight based on the count plus 1, so universally add 1 to the value.
95259d1ed5bSDimitry Andric ///
95359d1ed5bSDimitry Andric /// \pre \c Scale was calculated by \a calculateWeightScale() with a weight no
95459d1ed5bSDimitry Andric /// greater than \c Weight.
95559d1ed5bSDimitry Andric static uint32_t scaleBranchWeight(uint64_t Weight, uint64_t Scale) {
95659d1ed5bSDimitry Andric   assert(Scale && "scale by 0?");
95759d1ed5bSDimitry Andric   uint64_t Scaled = Weight / Scale + 1;
95859d1ed5bSDimitry Andric   assert(Scaled <= UINT32_MAX && "overflow 32-bits");
95959d1ed5bSDimitry Andric   return Scaled;
96059d1ed5bSDimitry Andric }
96159d1ed5bSDimitry Andric 
96259d1ed5bSDimitry Andric llvm::MDNode *CodeGenPGO::createBranchWeights(uint64_t TrueCount,
96359d1ed5bSDimitry Andric                                               uint64_t FalseCount) {
96459d1ed5bSDimitry Andric   // Check for empty weights.
96559d1ed5bSDimitry Andric   if (!TrueCount && !FalseCount)
96659d1ed5bSDimitry Andric     return nullptr;
96759d1ed5bSDimitry Andric 
96859d1ed5bSDimitry Andric   // Calculate how to scale down to 32-bits.
96959d1ed5bSDimitry Andric   uint64_t Scale = calculateWeightScale(std::max(TrueCount, FalseCount));
97059d1ed5bSDimitry Andric 
97159d1ed5bSDimitry Andric   llvm::MDBuilder MDHelper(CGM.getLLVMContext());
97259d1ed5bSDimitry Andric   return MDHelper.createBranchWeights(scaleBranchWeight(TrueCount, Scale),
97359d1ed5bSDimitry Andric                                       scaleBranchWeight(FalseCount, Scale));
97459d1ed5bSDimitry Andric }
97559d1ed5bSDimitry Andric 
97659d1ed5bSDimitry Andric llvm::MDNode *CodeGenPGO::createBranchWeights(ArrayRef<uint64_t> Weights) {
97759d1ed5bSDimitry Andric   // We need at least two elements to create meaningful weights.
97859d1ed5bSDimitry Andric   if (Weights.size() < 2)
97959d1ed5bSDimitry Andric     return nullptr;
98059d1ed5bSDimitry Andric 
98159d1ed5bSDimitry Andric   // Check for empty weights.
98259d1ed5bSDimitry Andric   uint64_t MaxWeight = *std::max_element(Weights.begin(), Weights.end());
98359d1ed5bSDimitry Andric   if (MaxWeight == 0)
98459d1ed5bSDimitry Andric     return nullptr;
98559d1ed5bSDimitry Andric 
98659d1ed5bSDimitry Andric   // Calculate how to scale down to 32-bits.
98759d1ed5bSDimitry Andric   uint64_t Scale = calculateWeightScale(MaxWeight);
98859d1ed5bSDimitry Andric 
98959d1ed5bSDimitry Andric   SmallVector<uint32_t, 16> ScaledWeights;
99059d1ed5bSDimitry Andric   ScaledWeights.reserve(Weights.size());
99159d1ed5bSDimitry Andric   for (uint64_t W : Weights)
99259d1ed5bSDimitry Andric     ScaledWeights.push_back(scaleBranchWeight(W, Scale));
99359d1ed5bSDimitry Andric 
99459d1ed5bSDimitry Andric   llvm::MDBuilder MDHelper(CGM.getLLVMContext());
99559d1ed5bSDimitry Andric   return MDHelper.createBranchWeights(ScaledWeights);
99659d1ed5bSDimitry Andric }
99759d1ed5bSDimitry Andric 
99859d1ed5bSDimitry Andric llvm::MDNode *CodeGenPGO::createLoopWeights(const Stmt *Cond,
99959d1ed5bSDimitry Andric                                             RegionCounter &Cnt) {
100059d1ed5bSDimitry Andric   if (!haveRegionCounts())
100159d1ed5bSDimitry Andric     return nullptr;
100259d1ed5bSDimitry Andric   uint64_t LoopCount = Cnt.getCount();
100359d1ed5bSDimitry Andric   uint64_t CondCount = 0;
100459d1ed5bSDimitry Andric   bool Found = getStmtCount(Cond, CondCount);
100559d1ed5bSDimitry Andric   assert(Found && "missing expected loop condition count");
100659d1ed5bSDimitry Andric   (void)Found;
100759d1ed5bSDimitry Andric   if (CondCount == 0)
100859d1ed5bSDimitry Andric     return nullptr;
100959d1ed5bSDimitry Andric   return createBranchWeights(LoopCount,
101059d1ed5bSDimitry Andric                              std::max(CondCount, LoopCount) - LoopCount);
101159d1ed5bSDimitry Andric }
1012