1ef512b99SJustin Bogner //===--- CodeGenPGO.cpp - PGO Instrumentation for LLVM CodeGen --*- C++ -*-===// 2ef512b99SJustin Bogner // 3ef512b99SJustin Bogner // The LLVM Compiler Infrastructure 4ef512b99SJustin Bogner // 5ef512b99SJustin Bogner // This file is distributed under the University of Illinois Open Source 6ef512b99SJustin Bogner // License. See LICENSE.TXT for details. 7ef512b99SJustin Bogner // 8ef512b99SJustin Bogner //===----------------------------------------------------------------------===// 9ef512b99SJustin Bogner // 10ef512b99SJustin Bogner // Instrumentation-based profile-guided optimization 11ef512b99SJustin Bogner // 12ef512b99SJustin Bogner //===----------------------------------------------------------------------===// 13ef512b99SJustin Bogner 14ef512b99SJustin Bogner #include "CodeGenPGO.h" 15ef512b99SJustin Bogner #include "CodeGenFunction.h" 16*ee02499aSAlex Lorenz #include "CoverageMappingGen.h" 17ef512b99SJustin Bogner #include "clang/AST/RecursiveASTVisitor.h" 18ef512b99SJustin Bogner #include "clang/AST/StmtVisitor.h" 19ef512b99SJustin Bogner #include "llvm/IR/MDBuilder.h" 20837a6f6fSJustin Bogner #include "llvm/ProfileData/InstrProfReader.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 25ef512b99SJustin Bogner using namespace clang; 26ef512b99SJustin Bogner using namespace CodeGen; 27ef512b99SJustin Bogner 28*ee02499aSAlex Lorenz void CodeGenPGO::setFuncName(StringRef Name, 29*ee02499aSAlex Lorenz llvm::GlobalValue::LinkageTypes Linkage) { 30*ee02499aSAlex Lorenz RawFuncName = Name; 31da1ebedeSBob Wilson 32da1ebedeSBob Wilson // Function names may be prefixed with a binary '1' to indicate 33da1ebedeSBob Wilson // that the backend should not modify the symbols due to any platform 34da1ebedeSBob Wilson // naming convention. Do not include that '1' in the PGO profile name. 352fe531cbSDuncan P. N. Exon Smith if (RawFuncName[0] == '\1') 362fe531cbSDuncan P. N. Exon Smith RawFuncName = RawFuncName.substr(1); 37da1ebedeSBob Wilson 38*ee02499aSAlex Lorenz if (!llvm::GlobalValue::isLocalLinkage(Linkage)) { 391b67cfd4SDuncan P. N. Exon Smith PrefixedFuncName.reset(new std::string(RawFuncName)); 40da1ebedeSBob Wilson return; 41da1ebedeSBob Wilson } 42da1ebedeSBob Wilson 43da1ebedeSBob Wilson // For local symbols, prepend the main file name to distinguish them. 44da1ebedeSBob Wilson // Do not include the full path in the file name since there's no guarantee 45da1ebedeSBob Wilson // that it will stay the same, e.g., if the files are checked out from 46da1ebedeSBob Wilson // version control in different locations. 471b67cfd4SDuncan P. N. Exon Smith PrefixedFuncName.reset(new std::string(CGM.getCodeGenOpts().MainFileName)); 482fe531cbSDuncan P. N. Exon Smith if (PrefixedFuncName->empty()) 492fe531cbSDuncan P. N. Exon Smith PrefixedFuncName->assign("<unknown>"); 502fe531cbSDuncan P. N. Exon Smith PrefixedFuncName->append(":"); 512fe531cbSDuncan P. N. Exon Smith PrefixedFuncName->append(RawFuncName); 52da1ebedeSBob Wilson } 53da1ebedeSBob Wilson 54*ee02499aSAlex Lorenz void CodeGenPGO::setFuncName(llvm::Function *Fn) { 55*ee02499aSAlex Lorenz setFuncName(Fn->getName(), Fn->getLinkage()); 56*ee02499aSAlex Lorenz } 57*ee02499aSAlex Lorenz 58*ee02499aSAlex Lorenz void CodeGenPGO::setVarLinkage(llvm::GlobalValue::LinkageTypes Linkage) { 59*ee02499aSAlex Lorenz // Set the linkage for variables based on the function linkage. Usually, we 60*ee02499aSAlex Lorenz // want to match it, but available_externally and extern_weak both have the 61*ee02499aSAlex Lorenz // wrong semantics. 62*ee02499aSAlex Lorenz VarLinkage = Linkage; 63*ee02499aSAlex Lorenz switch (VarLinkage) { 64*ee02499aSAlex Lorenz case llvm::GlobalValue::ExternalWeakLinkage: 65*ee02499aSAlex Lorenz VarLinkage = llvm::GlobalValue::LinkOnceAnyLinkage; 66*ee02499aSAlex Lorenz break; 67*ee02499aSAlex Lorenz case llvm::GlobalValue::AvailableExternallyLinkage: 68*ee02499aSAlex Lorenz VarLinkage = llvm::GlobalValue::LinkOnceODRLinkage; 69*ee02499aSAlex Lorenz break; 70*ee02499aSAlex Lorenz default: 71*ee02499aSAlex Lorenz break; 72*ee02499aSAlex Lorenz } 73*ee02499aSAlex Lorenz } 74*ee02499aSAlex Lorenz 752fe531cbSDuncan P. N. Exon Smith static llvm::Function *getRegisterFunc(CodeGenModule &CGM) { 76a7807637SDuncan P. N. Exon Smith return CGM.getModule().getFunction("__llvm_profile_register_functions"); 772fe531cbSDuncan P. N. Exon Smith } 782fe531cbSDuncan P. N. Exon Smith 792fe531cbSDuncan P. N. Exon Smith static llvm::BasicBlock *getOrInsertRegisterBB(CodeGenModule &CGM) { 80780443e8SDuncan P. N. Exon Smith // Don't do this for Darwin. compiler-rt uses linker magic. 81780443e8SDuncan P. N. Exon Smith if (CGM.getTarget().getTriple().isOSDarwin()) 82780443e8SDuncan P. N. Exon Smith return nullptr; 83780443e8SDuncan P. N. Exon Smith 842fe531cbSDuncan P. N. Exon Smith // Only need to insert this once per module. 852fe531cbSDuncan P. N. Exon Smith if (llvm::Function *RegisterF = getRegisterFunc(CGM)) 862fe531cbSDuncan P. N. Exon Smith return &RegisterF->getEntryBlock(); 872fe531cbSDuncan P. N. Exon Smith 882fe531cbSDuncan P. N. Exon Smith // Construct the function. 892fe531cbSDuncan P. N. Exon Smith auto *VoidTy = llvm::Type::getVoidTy(CGM.getLLVMContext()); 902fe531cbSDuncan P. N. Exon Smith auto *RegisterFTy = llvm::FunctionType::get(VoidTy, false); 912fe531cbSDuncan P. N. Exon Smith auto *RegisterF = llvm::Function::Create(RegisterFTy, 922fe531cbSDuncan P. N. Exon Smith llvm::GlobalValue::InternalLinkage, 93a7807637SDuncan P. N. Exon Smith "__llvm_profile_register_functions", 942fe531cbSDuncan P. N. Exon Smith &CGM.getModule()); 952fe531cbSDuncan P. N. Exon Smith RegisterF->setUnnamedAddr(true); 962fe531cbSDuncan P. N. Exon Smith if (CGM.getCodeGenOpts().DisableRedZone) 972fe531cbSDuncan P. N. Exon Smith RegisterF->addFnAttr(llvm::Attribute::NoRedZone); 982fe531cbSDuncan P. N. Exon Smith 992fe531cbSDuncan P. N. Exon Smith // Construct and return the entry block. 1002fe531cbSDuncan P. N. Exon Smith auto *BB = llvm::BasicBlock::Create(CGM.getLLVMContext(), "", RegisterF); 1012fe531cbSDuncan P. N. Exon Smith CGBuilderTy Builder(BB); 1022fe531cbSDuncan P. N. Exon Smith Builder.CreateRetVoid(); 1032fe531cbSDuncan P. N. Exon Smith return BB; 1042fe531cbSDuncan P. N. Exon Smith } 1052fe531cbSDuncan P. N. Exon Smith 1062fe531cbSDuncan P. N. Exon Smith static llvm::Constant *getOrInsertRuntimeRegister(CodeGenModule &CGM) { 1072fe531cbSDuncan P. N. Exon Smith auto *VoidTy = llvm::Type::getVoidTy(CGM.getLLVMContext()); 1082fe531cbSDuncan P. N. Exon Smith auto *VoidPtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); 1092fe531cbSDuncan P. N. Exon Smith auto *RuntimeRegisterTy = llvm::FunctionType::get(VoidTy, VoidPtrTy, false); 110a7807637SDuncan P. N. Exon Smith return CGM.getModule().getOrInsertFunction("__llvm_profile_register_function", 1112fe531cbSDuncan P. N. Exon Smith RuntimeRegisterTy); 1122fe531cbSDuncan P. N. Exon Smith } 1132fe531cbSDuncan P. N. Exon Smith 1147134d47dSDuncan P. N. Exon Smith static bool isMachO(const CodeGenModule &CGM) { 1157134d47dSDuncan P. N. Exon Smith return CGM.getTarget().getTriple().isOSBinFormatMachO(); 1167134d47dSDuncan P. N. Exon Smith } 1177134d47dSDuncan P. N. Exon Smith 1182fe531cbSDuncan P. N. Exon Smith static StringRef getCountersSection(const CodeGenModule &CGM) { 119a7807637SDuncan P. N. Exon Smith return isMachO(CGM) ? "__DATA,__llvm_prf_cnts" : "__llvm_prf_cnts"; 1202fe531cbSDuncan P. N. Exon Smith } 1212fe531cbSDuncan P. N. Exon Smith 1222fe531cbSDuncan P. N. Exon Smith static StringRef getNameSection(const CodeGenModule &CGM) { 123a7807637SDuncan P. N. Exon Smith return isMachO(CGM) ? "__DATA,__llvm_prf_names" : "__llvm_prf_names"; 1242fe531cbSDuncan P. N. Exon Smith } 1252fe531cbSDuncan P. N. Exon Smith 1262fe531cbSDuncan P. N. Exon Smith static StringRef getDataSection(const CodeGenModule &CGM) { 127a7807637SDuncan P. N. Exon Smith return isMachO(CGM) ? "__DATA,__llvm_prf_data" : "__llvm_prf_data"; 1282fe531cbSDuncan P. N. Exon Smith } 1292fe531cbSDuncan P. N. Exon Smith 1302fe531cbSDuncan P. N. Exon Smith llvm::GlobalVariable *CodeGenPGO::buildDataVar() { 1312fe531cbSDuncan P. N. Exon Smith // Create name variable. 1322fe531cbSDuncan P. N. Exon Smith llvm::LLVMContext &Ctx = CGM.getLLVMContext(); 1332fe531cbSDuncan P. N. Exon Smith auto *VarName = llvm::ConstantDataArray::getString(Ctx, getFuncName(), 1342fe531cbSDuncan P. N. Exon Smith false); 1352fe531cbSDuncan P. N. Exon Smith auto *Name = new llvm::GlobalVariable(CGM.getModule(), VarName->getType(), 13673f78627SDuncan P. N. Exon Smith true, VarLinkage, VarName, 1372fe531cbSDuncan P. N. Exon Smith getFuncVarName("name")); 1382fe531cbSDuncan P. N. Exon Smith Name->setSection(getNameSection(CGM)); 1392fe531cbSDuncan P. N. Exon Smith Name->setAlignment(1); 1402fe531cbSDuncan P. N. Exon Smith 1412fe531cbSDuncan P. N. Exon Smith // Create data variable. 1422fe531cbSDuncan P. N. Exon Smith auto *Int32Ty = llvm::Type::getInt32Ty(Ctx); 143b4416f58SJustin Bogner auto *Int64Ty = llvm::Type::getInt64Ty(Ctx); 1442fe531cbSDuncan P. N. Exon Smith auto *Int8PtrTy = llvm::Type::getInt8PtrTy(Ctx); 1452fe531cbSDuncan P. N. Exon Smith auto *Int64PtrTy = llvm::Type::getInt64PtrTy(Ctx); 146*ee02499aSAlex Lorenz llvm::GlobalVariable *Data = nullptr; 147*ee02499aSAlex Lorenz if (RegionCounters) { 1482fe531cbSDuncan P. N. Exon Smith llvm::Type *DataTypes[] = { 149b4416f58SJustin Bogner Int32Ty, Int32Ty, Int64Ty, Int8PtrTy, Int64PtrTy 1502fe531cbSDuncan P. N. Exon Smith }; 1512fe531cbSDuncan P. N. Exon Smith auto *DataTy = llvm::StructType::get(Ctx, makeArrayRef(DataTypes)); 1522fe531cbSDuncan P. N. Exon Smith llvm::Constant *DataVals[] = { 1532fe531cbSDuncan P. N. Exon Smith llvm::ConstantInt::get(Int32Ty, getFuncName().size()), 1542fe531cbSDuncan P. N. Exon Smith llvm::ConstantInt::get(Int32Ty, NumRegionCounters), 155b4416f58SJustin Bogner llvm::ConstantInt::get(Int64Ty, FunctionHash), 1562fe531cbSDuncan P. N. Exon Smith llvm::ConstantExpr::getBitCast(Name, Int8PtrTy), 1572fe531cbSDuncan P. N. Exon Smith llvm::ConstantExpr::getBitCast(RegionCounters, Int64PtrTy) 1582fe531cbSDuncan P. N. Exon Smith }; 159*ee02499aSAlex Lorenz Data = 16073f78627SDuncan P. N. Exon Smith new llvm::GlobalVariable(CGM.getModule(), DataTy, true, VarLinkage, 1612fe531cbSDuncan P. N. Exon Smith llvm::ConstantStruct::get(DataTy, DataVals), 1622fe531cbSDuncan P. N. Exon Smith getFuncVarName("data")); 1632fe531cbSDuncan P. N. Exon Smith 1642fe531cbSDuncan P. N. Exon Smith // All the data should be packed into an array in its own section. 1652fe531cbSDuncan P. N. Exon Smith Data->setSection(getDataSection(CGM)); 1662fe531cbSDuncan P. N. Exon Smith Data->setAlignment(8); 167*ee02499aSAlex Lorenz } 168*ee02499aSAlex Lorenz 169*ee02499aSAlex Lorenz // Create coverage mapping data variable. 170*ee02499aSAlex Lorenz if (!CoverageMapping.empty()) 171*ee02499aSAlex Lorenz CGM.getCoverageMapping()->addFunctionMappingRecord(Name, 172*ee02499aSAlex Lorenz getFuncName().size(), 173*ee02499aSAlex Lorenz CoverageMapping); 1742fe531cbSDuncan P. N. Exon Smith 17591212208SDuncan P. N. Exon Smith // Hide all these symbols so that we correctly get a copy for each 17691212208SDuncan P. N. Exon Smith // executable. The profile format expects names and counters to be 17791212208SDuncan P. N. Exon Smith // contiguous, so references into shared objects would be invalid. 17891212208SDuncan P. N. Exon Smith if (!llvm::GlobalValue::isLocalLinkage(VarLinkage)) { 17991212208SDuncan P. N. Exon Smith Name->setVisibility(llvm::GlobalValue::HiddenVisibility); 180*ee02499aSAlex Lorenz if (Data) { 18191212208SDuncan P. N. Exon Smith Data->setVisibility(llvm::GlobalValue::HiddenVisibility); 18291212208SDuncan P. N. Exon Smith RegionCounters->setVisibility(llvm::GlobalValue::HiddenVisibility); 18391212208SDuncan P. N. Exon Smith } 184*ee02499aSAlex Lorenz } 18591212208SDuncan P. N. Exon Smith 1862fe531cbSDuncan P. N. Exon Smith // Make sure the data doesn't get deleted. 187*ee02499aSAlex Lorenz if (Data) CGM.addUsedGlobal(Data); 1882fe531cbSDuncan P. N. Exon Smith return Data; 1892fe531cbSDuncan P. N. Exon Smith } 1902fe531cbSDuncan P. N. Exon Smith 1912fe531cbSDuncan P. N. Exon Smith void CodeGenPGO::emitInstrumentationData() { 1923212b18bSJustin Bogner if (!RegionCounters) 193ef512b99SJustin Bogner return; 194ef512b99SJustin Bogner 1952fe531cbSDuncan P. N. Exon Smith // Build the data. 1962fe531cbSDuncan P. N. Exon Smith auto *Data = buildDataVar(); 197ef512b99SJustin Bogner 1982fe531cbSDuncan P. N. Exon Smith // Register the data. 199780443e8SDuncan P. N. Exon Smith auto *RegisterBB = getOrInsertRegisterBB(CGM); 200780443e8SDuncan P. N. Exon Smith if (!RegisterBB) 201780443e8SDuncan P. N. Exon Smith return; 202780443e8SDuncan P. N. Exon Smith CGBuilderTy Builder(RegisterBB->getTerminator()); 2032fe531cbSDuncan P. N. Exon Smith auto *VoidPtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); 2042fe531cbSDuncan P. N. Exon Smith Builder.CreateCall(getOrInsertRuntimeRegister(CGM), 2052fe531cbSDuncan P. N. Exon Smith Builder.CreateBitCast(Data, VoidPtrTy)); 206ef512b99SJustin Bogner } 207ef512b99SJustin Bogner 208ef512b99SJustin Bogner llvm::Function *CodeGenPGO::emitInitialization(CodeGenModule &CGM) { 2092fe531cbSDuncan P. N. Exon Smith if (!CGM.getCodeGenOpts().ProfileInstrGenerate) 210a5f804a7SDuncan P. N. Exon Smith return nullptr; 211ef512b99SJustin Bogner 212f2ea775eSJustin Bogner assert(CGM.getModule().getFunction("__llvm_profile_init") == nullptr && 213f2ea775eSJustin Bogner "profile initialization already emitted"); 214ef512b99SJustin Bogner 2155188e91cSDuncan P. N. Exon Smith // Get the function to call at initialization. 2162fe531cbSDuncan P. N. Exon Smith llvm::Constant *RegisterF = getRegisterFunc(CGM); 2175188e91cSDuncan P. N. Exon Smith if (!RegisterF) 218a5f804a7SDuncan P. N. Exon Smith return nullptr; 2192fe531cbSDuncan P. N. Exon Smith 2202fe531cbSDuncan P. N. Exon Smith // Create the initialization function. 2212fe531cbSDuncan P. N. Exon Smith auto *VoidTy = llvm::Type::getVoidTy(CGM.getLLVMContext()); 2222fe531cbSDuncan P. N. Exon Smith auto *F = llvm::Function::Create(llvm::FunctionType::get(VoidTy, false), 2232fe531cbSDuncan P. N. Exon Smith llvm::GlobalValue::InternalLinkage, 224a7807637SDuncan P. N. Exon Smith "__llvm_profile_init", &CGM.getModule()); 225ef512b99SJustin Bogner F->setUnnamedAddr(true); 226ef512b99SJustin Bogner F->addFnAttr(llvm::Attribute::NoInline); 227ef512b99SJustin Bogner if (CGM.getCodeGenOpts().DisableRedZone) 228ef512b99SJustin Bogner F->addFnAttr(llvm::Attribute::NoRedZone); 229ef512b99SJustin Bogner 2302fe531cbSDuncan P. N. Exon Smith // Add the basic block and the necessary calls. 2312fe531cbSDuncan P. N. Exon Smith CGBuilderTy Builder(llvm::BasicBlock::Create(CGM.getLLVMContext(), "", F)); 2322fe531cbSDuncan P. N. Exon Smith Builder.CreateCall(RegisterF); 2332fe531cbSDuncan P. N. Exon Smith Builder.CreateRetVoid(); 234ef512b99SJustin Bogner 235ef512b99SJustin Bogner return F; 236ef512b99SJustin Bogner } 237ef512b99SJustin Bogner 238ef512b99SJustin Bogner namespace { 2394bc7731aSDuncan P. N. Exon Smith /// \brief Stable hasher for PGO region counters. 2404bc7731aSDuncan P. N. Exon Smith /// 2414bc7731aSDuncan P. N. Exon Smith /// PGOHash produces a stable hash of a given function's control flow. 2424bc7731aSDuncan P. N. Exon Smith /// 2434bc7731aSDuncan P. N. Exon Smith /// Changing the output of this hash will invalidate all previously generated 2444bc7731aSDuncan P. N. Exon Smith /// profiles -- i.e., don't do it. 2454bc7731aSDuncan P. N. Exon Smith /// 2464bc7731aSDuncan P. N. Exon Smith /// \note When this hash does eventually change (years?), we still need to 2474bc7731aSDuncan P. N. Exon Smith /// support old hashes. We'll need to pull in the version number from the 2484bc7731aSDuncan P. N. Exon Smith /// profile data format and use the matching hash function. 2494bc7731aSDuncan P. N. Exon Smith class PGOHash { 2504bc7731aSDuncan P. N. Exon Smith uint64_t Working; 2514bc7731aSDuncan P. N. Exon Smith unsigned Count; 2524bc7731aSDuncan P. N. Exon Smith llvm::MD5 MD5; 2534bc7731aSDuncan P. N. Exon Smith 2544bc7731aSDuncan P. N. Exon Smith static const int NumBitsPerType = 6; 2554bc7731aSDuncan P. N. Exon Smith static const unsigned NumTypesPerWord = sizeof(uint64_t) * 8 / NumBitsPerType; 2564bc7731aSDuncan P. N. Exon Smith static const unsigned TooBig = 1u << NumBitsPerType; 2574bc7731aSDuncan P. N. Exon Smith 2584bc7731aSDuncan P. N. Exon Smith public: 2594bc7731aSDuncan P. N. Exon Smith /// \brief Hash values for AST nodes. 2604bc7731aSDuncan P. N. Exon Smith /// 2614bc7731aSDuncan P. N. Exon Smith /// Distinct values for AST nodes that have region counters attached. 2624bc7731aSDuncan P. N. Exon Smith /// 2634bc7731aSDuncan P. N. Exon Smith /// These values must be stable. All new members must be added at the end, 2644bc7731aSDuncan P. N. Exon Smith /// and no members should be removed. Changing the enumeration value for an 2654bc7731aSDuncan P. N. Exon Smith /// AST node will affect the hash of every function that contains that node. 2664bc7731aSDuncan P. N. Exon Smith enum HashType : unsigned char { 2674bc7731aSDuncan P. N. Exon Smith None = 0, 2684bc7731aSDuncan P. N. Exon Smith LabelStmt = 1, 2694bc7731aSDuncan P. N. Exon Smith WhileStmt, 2704bc7731aSDuncan P. N. Exon Smith DoStmt, 2714bc7731aSDuncan P. N. Exon Smith ForStmt, 2724bc7731aSDuncan P. N. Exon Smith CXXForRangeStmt, 2734bc7731aSDuncan P. N. Exon Smith ObjCForCollectionStmt, 2744bc7731aSDuncan P. N. Exon Smith SwitchStmt, 2754bc7731aSDuncan P. N. Exon Smith CaseStmt, 2764bc7731aSDuncan P. N. Exon Smith DefaultStmt, 2774bc7731aSDuncan P. N. Exon Smith IfStmt, 2784bc7731aSDuncan P. N. Exon Smith CXXTryStmt, 2794bc7731aSDuncan P. N. Exon Smith CXXCatchStmt, 2804bc7731aSDuncan P. N. Exon Smith ConditionalOperator, 2814bc7731aSDuncan P. N. Exon Smith BinaryOperatorLAnd, 2824bc7731aSDuncan P. N. Exon Smith BinaryOperatorLOr, 2834bc7731aSDuncan P. N. Exon Smith BinaryConditionalOperator, 2844bc7731aSDuncan P. N. Exon Smith 2854bc7731aSDuncan P. N. Exon Smith // Keep this last. It's for the static assert that follows. 2864bc7731aSDuncan P. N. Exon Smith LastHashType 2874bc7731aSDuncan P. N. Exon Smith }; 2884bc7731aSDuncan P. N. Exon Smith static_assert(LastHashType <= TooBig, "Too many types in HashType"); 2894bc7731aSDuncan P. N. Exon Smith 2904bc7731aSDuncan P. N. Exon Smith // TODO: When this format changes, take in a version number here, and use the 2914bc7731aSDuncan P. N. Exon Smith // old hash calculation for file formats that used the old hash. 2924bc7731aSDuncan P. N. Exon Smith PGOHash() : Working(0), Count(0) {} 2934bc7731aSDuncan P. N. Exon Smith void combine(HashType Type); 2944bc7731aSDuncan P. N. Exon Smith uint64_t finalize(); 2954bc7731aSDuncan P. N. Exon Smith }; 2964bc7731aSDuncan P. N. Exon Smith const int PGOHash::NumBitsPerType; 2974bc7731aSDuncan P. N. Exon Smith const unsigned PGOHash::NumTypesPerWord; 2984bc7731aSDuncan P. N. Exon Smith const unsigned PGOHash::TooBig; 2994bc7731aSDuncan P. N. Exon Smith 300d8931425SBob Wilson /// A RecursiveASTVisitor that fills a map of statements to PGO counters. 301d8931425SBob Wilson struct MapRegionCounters : public RecursiveASTVisitor<MapRegionCounters> { 302ef512b99SJustin Bogner /// The next counter value to assign. 303ef512b99SJustin Bogner unsigned NextCounter; 3044bc7731aSDuncan P. N. Exon Smith /// The function hash. 3054bc7731aSDuncan P. N. Exon Smith PGOHash Hash; 306ef512b99SJustin Bogner /// The map of statements to counters. 3073586be72SDuncan P. N. Exon Smith llvm::DenseMap<const Stmt *, unsigned> &CounterMap; 308ef512b99SJustin Bogner 3093586be72SDuncan P. N. Exon Smith MapRegionCounters(llvm::DenseMap<const Stmt *, unsigned> &CounterMap) 3103586be72SDuncan P. N. Exon Smith : NextCounter(0), CounterMap(CounterMap) {} 311ef512b99SJustin Bogner 312191ec63bSJustin Bogner // Blocks and lambdas are handled as separate functions, so we need not 313191ec63bSJustin Bogner // traverse them in the parent context. 314191ec63bSJustin Bogner bool TraverseBlockExpr(BlockExpr *BE) { return true; } 315191ec63bSJustin Bogner bool TraverseLambdaBody(LambdaExpr *LE) { return true; } 31681ab90f7SJustin Bogner bool TraverseCapturedStmt(CapturedStmt *CS) { return true; } 317ef512b99SJustin Bogner 318d8931425SBob Wilson bool VisitDecl(const Decl *D) { 319d8931425SBob Wilson switch (D->getKind()) { 320d8931425SBob Wilson default: 321d8931425SBob Wilson break; 322d8931425SBob Wilson case Decl::Function: 323d8931425SBob Wilson case Decl::CXXMethod: 324d8931425SBob Wilson case Decl::CXXConstructor: 325d8931425SBob Wilson case Decl::CXXDestructor: 326d8931425SBob Wilson case Decl::CXXConversion: 327d8931425SBob Wilson case Decl::ObjCMethod: 328d8931425SBob Wilson case Decl::Block: 32981ab90f7SJustin Bogner case Decl::Captured: 3304a2f5ae8SDuncan P. N. Exon Smith CounterMap[D->getBody()] = NextCounter++; 331d8931425SBob Wilson break; 332ef512b99SJustin Bogner } 333d8931425SBob Wilson return true; 3345ec8fe19SBob Wilson } 335d8931425SBob Wilson 336d8931425SBob Wilson bool VisitStmt(const Stmt *S) { 3374bc7731aSDuncan P. N. Exon Smith auto Type = getHashType(S); 3384bc7731aSDuncan P. N. Exon Smith if (Type == PGOHash::None) 3394bc7731aSDuncan P. N. Exon Smith return true; 3404bc7731aSDuncan P. N. Exon Smith 3414bc7731aSDuncan P. N. Exon Smith CounterMap[S] = NextCounter++; 3424bc7731aSDuncan P. N. Exon Smith Hash.combine(Type); 3434bc7731aSDuncan P. N. Exon Smith return true; 3444bc7731aSDuncan P. N. Exon Smith } 3454bc7731aSDuncan P. N. Exon Smith PGOHash::HashType getHashType(const Stmt *S) { 346d8931425SBob Wilson switch (S->getStmtClass()) { 347d8931425SBob Wilson default: 348d8931425SBob Wilson break; 349d8931425SBob Wilson case Stmt::LabelStmtClass: 3504bc7731aSDuncan P. N. Exon Smith return PGOHash::LabelStmt; 351d8931425SBob Wilson case Stmt::WhileStmtClass: 3524bc7731aSDuncan P. N. Exon Smith return PGOHash::WhileStmt; 353d8931425SBob Wilson case Stmt::DoStmtClass: 3544bc7731aSDuncan P. N. Exon Smith return PGOHash::DoStmt; 355d8931425SBob Wilson case Stmt::ForStmtClass: 3564bc7731aSDuncan P. N. Exon Smith return PGOHash::ForStmt; 357d8931425SBob Wilson case Stmt::CXXForRangeStmtClass: 3584bc7731aSDuncan P. N. Exon Smith return PGOHash::CXXForRangeStmt; 359d8931425SBob Wilson case Stmt::ObjCForCollectionStmtClass: 3604bc7731aSDuncan P. N. Exon Smith return PGOHash::ObjCForCollectionStmt; 361d8931425SBob Wilson case Stmt::SwitchStmtClass: 3624bc7731aSDuncan P. N. Exon Smith return PGOHash::SwitchStmt; 363d8931425SBob Wilson case Stmt::CaseStmtClass: 3644bc7731aSDuncan P. N. Exon Smith return PGOHash::CaseStmt; 365d8931425SBob Wilson case Stmt::DefaultStmtClass: 3664bc7731aSDuncan P. N. Exon Smith return PGOHash::DefaultStmt; 367d8931425SBob Wilson case Stmt::IfStmtClass: 3684bc7731aSDuncan P. N. Exon Smith return PGOHash::IfStmt; 369d8931425SBob Wilson case Stmt::CXXTryStmtClass: 3704bc7731aSDuncan P. N. Exon Smith return PGOHash::CXXTryStmt; 371d8931425SBob Wilson case Stmt::CXXCatchStmtClass: 3724bc7731aSDuncan P. N. Exon Smith return PGOHash::CXXCatchStmt; 373d8931425SBob Wilson case Stmt::ConditionalOperatorClass: 3744bc7731aSDuncan P. N. Exon Smith return PGOHash::ConditionalOperator; 375d8931425SBob Wilson case Stmt::BinaryConditionalOperatorClass: 3764bc7731aSDuncan P. N. Exon Smith return PGOHash::BinaryConditionalOperator; 377d8931425SBob Wilson case Stmt::BinaryOperatorClass: { 378d8931425SBob Wilson const BinaryOperator *BO = cast<BinaryOperator>(S); 3794bc7731aSDuncan P. N. Exon Smith if (BO->getOpcode() == BO_LAnd) 3804bc7731aSDuncan P. N. Exon Smith return PGOHash::BinaryOperatorLAnd; 3814bc7731aSDuncan P. N. Exon Smith if (BO->getOpcode() == BO_LOr) 3824bc7731aSDuncan P. N. Exon Smith return PGOHash::BinaryOperatorLOr; 383d8931425SBob Wilson break; 384ef512b99SJustin Bogner } 385ef512b99SJustin Bogner } 3864bc7731aSDuncan P. N. Exon Smith return PGOHash::None; 387ef512b99SJustin Bogner } 388ef512b99SJustin Bogner }; 389bf854f0fSBob Wilson 390bf854f0fSBob Wilson /// A StmtVisitor that propagates the raw counts through the AST and 391bf854f0fSBob Wilson /// records the count at statements where the value may change. 392bf854f0fSBob Wilson struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> { 393bf854f0fSBob Wilson /// PGO state. 394bf854f0fSBob Wilson CodeGenPGO &PGO; 395bf854f0fSBob Wilson 396bf854f0fSBob Wilson /// A flag that is set when the current count should be recorded on the 397bf854f0fSBob Wilson /// next statement, such as at the exit of a loop. 398bf854f0fSBob Wilson bool RecordNextStmtCount; 399bf854f0fSBob Wilson 400bf854f0fSBob Wilson /// The map of statements to count values. 4013586be72SDuncan P. N. Exon Smith llvm::DenseMap<const Stmt *, uint64_t> &CountMap; 402bf854f0fSBob Wilson 403bf854f0fSBob Wilson /// BreakContinueStack - Keep counts of breaks and continues inside loops. 404bf854f0fSBob Wilson struct BreakContinue { 405bf854f0fSBob Wilson uint64_t BreakCount; 406bf854f0fSBob Wilson uint64_t ContinueCount; 407bf854f0fSBob Wilson BreakContinue() : BreakCount(0), ContinueCount(0) {} 408bf854f0fSBob Wilson }; 409bf854f0fSBob Wilson SmallVector<BreakContinue, 8> BreakContinueStack; 410bf854f0fSBob Wilson 4113586be72SDuncan P. N. Exon Smith ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &CountMap, 4123586be72SDuncan P. N. Exon Smith CodeGenPGO &PGO) 4133586be72SDuncan P. N. Exon Smith : PGO(PGO), RecordNextStmtCount(false), CountMap(CountMap) {} 414bf854f0fSBob Wilson 415bf854f0fSBob Wilson void RecordStmtCount(const Stmt *S) { 416bf854f0fSBob Wilson if (RecordNextStmtCount) { 4173586be72SDuncan P. N. Exon Smith CountMap[S] = PGO.getCurrentRegionCount(); 418bf854f0fSBob Wilson RecordNextStmtCount = false; 419bf854f0fSBob Wilson } 420bf854f0fSBob Wilson } 421bf854f0fSBob Wilson 422bf854f0fSBob Wilson void VisitStmt(const Stmt *S) { 423bf854f0fSBob Wilson RecordStmtCount(S); 424bf854f0fSBob Wilson for (Stmt::const_child_range I = S->children(); I; ++I) { 425bf854f0fSBob Wilson if (*I) 426bf854f0fSBob Wilson this->Visit(*I); 427bf854f0fSBob Wilson } 428bf854f0fSBob Wilson } 429bf854f0fSBob Wilson 4304a2f5ae8SDuncan P. N. Exon Smith void VisitFunctionDecl(const FunctionDecl *D) { 431d8931425SBob Wilson // Counter tracks entry to the function body. 4324a2f5ae8SDuncan P. N. Exon Smith RegionCounter Cnt(PGO, D->getBody()); 433bf854f0fSBob Wilson Cnt.beginRegion(); 4344a2f5ae8SDuncan P. N. Exon Smith CountMap[D->getBody()] = PGO.getCurrentRegionCount(); 4354a2f5ae8SDuncan P. N. Exon Smith Visit(D->getBody()); 436bf854f0fSBob Wilson } 437bf854f0fSBob Wilson 438191ec63bSJustin Bogner // Skip lambda expressions. We visit these as FunctionDecls when we're 439191ec63bSJustin Bogner // generating them and aren't interested in the body when generating a 440191ec63bSJustin Bogner // parent context. 441191ec63bSJustin Bogner void VisitLambdaExpr(const LambdaExpr *LE) {} 442191ec63bSJustin Bogner 44381ab90f7SJustin Bogner void VisitCapturedDecl(const CapturedDecl *D) { 44481ab90f7SJustin Bogner // Counter tracks entry to the capture body. 44581ab90f7SJustin Bogner RegionCounter Cnt(PGO, D->getBody()); 44681ab90f7SJustin Bogner Cnt.beginRegion(); 44781ab90f7SJustin Bogner CountMap[D->getBody()] = PGO.getCurrentRegionCount(); 44881ab90f7SJustin Bogner Visit(D->getBody()); 44981ab90f7SJustin Bogner } 45081ab90f7SJustin Bogner 4514a2f5ae8SDuncan P. N. Exon Smith void VisitObjCMethodDecl(const ObjCMethodDecl *D) { 452d8931425SBob Wilson // Counter tracks entry to the method body. 4534a2f5ae8SDuncan P. N. Exon Smith RegionCounter Cnt(PGO, D->getBody()); 4545ec8fe19SBob Wilson Cnt.beginRegion(); 4554a2f5ae8SDuncan P. N. Exon Smith CountMap[D->getBody()] = PGO.getCurrentRegionCount(); 4564a2f5ae8SDuncan P. N. Exon Smith Visit(D->getBody()); 4575ec8fe19SBob Wilson } 4585ec8fe19SBob Wilson 4594a2f5ae8SDuncan P. N. Exon Smith void VisitBlockDecl(const BlockDecl *D) { 460d8931425SBob Wilson // Counter tracks entry to the block body. 4614a2f5ae8SDuncan P. N. Exon Smith RegionCounter Cnt(PGO, D->getBody()); 462c845c00aSBob Wilson Cnt.beginRegion(); 4634a2f5ae8SDuncan P. N. Exon Smith CountMap[D->getBody()] = PGO.getCurrentRegionCount(); 4644a2f5ae8SDuncan P. N. Exon Smith Visit(D->getBody()); 465c845c00aSBob Wilson } 466c845c00aSBob Wilson 467bf854f0fSBob Wilson void VisitReturnStmt(const ReturnStmt *S) { 468bf854f0fSBob Wilson RecordStmtCount(S); 469bf854f0fSBob Wilson if (S->getRetValue()) 470bf854f0fSBob Wilson Visit(S->getRetValue()); 471bf854f0fSBob Wilson PGO.setCurrentRegionUnreachable(); 472bf854f0fSBob Wilson RecordNextStmtCount = true; 473bf854f0fSBob Wilson } 474bf854f0fSBob Wilson 475bf854f0fSBob Wilson void VisitGotoStmt(const GotoStmt *S) { 476bf854f0fSBob Wilson RecordStmtCount(S); 477bf854f0fSBob Wilson PGO.setCurrentRegionUnreachable(); 478bf854f0fSBob Wilson RecordNextStmtCount = true; 479bf854f0fSBob Wilson } 480bf854f0fSBob Wilson 481bf854f0fSBob Wilson void VisitLabelStmt(const LabelStmt *S) { 482bf854f0fSBob Wilson RecordNextStmtCount = false; 483d8931425SBob Wilson // Counter tracks the block following the label. 484bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 485bf854f0fSBob Wilson Cnt.beginRegion(); 4863586be72SDuncan P. N. Exon Smith CountMap[S] = PGO.getCurrentRegionCount(); 487bf854f0fSBob Wilson Visit(S->getSubStmt()); 488bf854f0fSBob Wilson } 489bf854f0fSBob Wilson 490bf854f0fSBob Wilson void VisitBreakStmt(const BreakStmt *S) { 491bf854f0fSBob Wilson RecordStmtCount(S); 492bf854f0fSBob Wilson assert(!BreakContinueStack.empty() && "break not in a loop or switch!"); 493bf854f0fSBob Wilson BreakContinueStack.back().BreakCount += PGO.getCurrentRegionCount(); 494bf854f0fSBob Wilson PGO.setCurrentRegionUnreachable(); 495bf854f0fSBob Wilson RecordNextStmtCount = true; 496bf854f0fSBob Wilson } 497bf854f0fSBob Wilson 498bf854f0fSBob Wilson void VisitContinueStmt(const ContinueStmt *S) { 499bf854f0fSBob Wilson RecordStmtCount(S); 500bf854f0fSBob Wilson assert(!BreakContinueStack.empty() && "continue stmt not in a loop!"); 501bf854f0fSBob Wilson BreakContinueStack.back().ContinueCount += PGO.getCurrentRegionCount(); 502bf854f0fSBob Wilson PGO.setCurrentRegionUnreachable(); 503bf854f0fSBob Wilson RecordNextStmtCount = true; 504bf854f0fSBob Wilson } 505bf854f0fSBob Wilson 506bf854f0fSBob Wilson void VisitWhileStmt(const WhileStmt *S) { 507bf854f0fSBob Wilson RecordStmtCount(S); 508d8931425SBob Wilson // Counter tracks the body of the loop. 509bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 510bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue()); 511bf854f0fSBob Wilson // Visit the body region first so the break/continue adjustments can be 512bf854f0fSBob Wilson // included when visiting the condition. 513bf854f0fSBob Wilson Cnt.beginRegion(); 5143586be72SDuncan P. N. Exon Smith CountMap[S->getBody()] = PGO.getCurrentRegionCount(); 515bf854f0fSBob Wilson Visit(S->getBody()); 516bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 517bf854f0fSBob Wilson 518bf854f0fSBob Wilson // ...then go back and propagate counts through the condition. The count 519bf854f0fSBob Wilson // at the start of the condition is the sum of the incoming edges, 520bf854f0fSBob Wilson // the backedge from the end of the loop body, and the edges from 521bf854f0fSBob Wilson // continue statements. 522bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val(); 523bf854f0fSBob Wilson Cnt.setCurrentRegionCount(Cnt.getParentCount() + 524bf854f0fSBob Wilson Cnt.getAdjustedCount() + BC.ContinueCount); 5253586be72SDuncan P. N. Exon Smith CountMap[S->getCond()] = PGO.getCurrentRegionCount(); 526bf854f0fSBob Wilson Visit(S->getCond()); 527bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 528bf854f0fSBob Wilson Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount); 529bf854f0fSBob Wilson RecordNextStmtCount = true; 530bf854f0fSBob Wilson } 531bf854f0fSBob Wilson 532bf854f0fSBob Wilson void VisitDoStmt(const DoStmt *S) { 533bf854f0fSBob Wilson RecordStmtCount(S); 534d8931425SBob Wilson // Counter tracks the body of the loop. 535bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 536bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue()); 537bf854f0fSBob Wilson Cnt.beginRegion(/*AddIncomingFallThrough=*/true); 5383586be72SDuncan P. N. Exon Smith CountMap[S->getBody()] = PGO.getCurrentRegionCount(); 539bf854f0fSBob Wilson Visit(S->getBody()); 540bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 541bf854f0fSBob Wilson 542bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val(); 543bf854f0fSBob Wilson // The count at the start of the condition is equal to the count at the 544bf854f0fSBob Wilson // end of the body. The adjusted count does not include either the 545bf854f0fSBob Wilson // fall-through count coming into the loop or the continue count, so add 546bf854f0fSBob Wilson // both of those separately. This is coincidentally the same equation as 547bf854f0fSBob Wilson // with while loops but for different reasons. 548bf854f0fSBob Wilson Cnt.setCurrentRegionCount(Cnt.getParentCount() + 549bf854f0fSBob Wilson Cnt.getAdjustedCount() + BC.ContinueCount); 5503586be72SDuncan P. N. Exon Smith CountMap[S->getCond()] = PGO.getCurrentRegionCount(); 551bf854f0fSBob Wilson Visit(S->getCond()); 552bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 553bf854f0fSBob Wilson Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount); 554bf854f0fSBob Wilson RecordNextStmtCount = true; 555bf854f0fSBob Wilson } 556bf854f0fSBob Wilson 557bf854f0fSBob Wilson void VisitForStmt(const ForStmt *S) { 558bf854f0fSBob Wilson RecordStmtCount(S); 559bf854f0fSBob Wilson if (S->getInit()) 560bf854f0fSBob Wilson Visit(S->getInit()); 561d8931425SBob Wilson // Counter tracks the body of the loop. 562bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 563bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue()); 564bf854f0fSBob Wilson // Visit the body region first. (This is basically the same as a while 565bf854f0fSBob Wilson // loop; see further comments in VisitWhileStmt.) 566bf854f0fSBob Wilson Cnt.beginRegion(); 5673586be72SDuncan P. N. Exon Smith CountMap[S->getBody()] = PGO.getCurrentRegionCount(); 568bf854f0fSBob Wilson Visit(S->getBody()); 569bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 570bf854f0fSBob Wilson 571bf854f0fSBob Wilson // The increment is essentially part of the body but it needs to include 572bf854f0fSBob Wilson // the count for all the continue statements. 573bf854f0fSBob Wilson if (S->getInc()) { 574bf854f0fSBob Wilson Cnt.setCurrentRegionCount(PGO.getCurrentRegionCount() + 575bf854f0fSBob Wilson BreakContinueStack.back().ContinueCount); 5763586be72SDuncan P. N. Exon Smith CountMap[S->getInc()] = PGO.getCurrentRegionCount(); 577bf854f0fSBob Wilson Visit(S->getInc()); 578bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 579bf854f0fSBob Wilson } 580bf854f0fSBob Wilson 581bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val(); 582bf854f0fSBob Wilson 583bf854f0fSBob Wilson // ...then go back and propagate counts through the condition. 584bf854f0fSBob Wilson if (S->getCond()) { 585bf854f0fSBob Wilson Cnt.setCurrentRegionCount(Cnt.getParentCount() + 586bf854f0fSBob Wilson Cnt.getAdjustedCount() + 587bf854f0fSBob Wilson BC.ContinueCount); 5883586be72SDuncan P. N. Exon Smith CountMap[S->getCond()] = PGO.getCurrentRegionCount(); 589bf854f0fSBob Wilson Visit(S->getCond()); 590bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 591bf854f0fSBob Wilson } 592bf854f0fSBob Wilson Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount); 593bf854f0fSBob Wilson RecordNextStmtCount = true; 594bf854f0fSBob Wilson } 595bf854f0fSBob Wilson 596bf854f0fSBob Wilson void VisitCXXForRangeStmt(const CXXForRangeStmt *S) { 597bf854f0fSBob Wilson RecordStmtCount(S); 598bf854f0fSBob Wilson Visit(S->getRangeStmt()); 599bf854f0fSBob Wilson Visit(S->getBeginEndStmt()); 600d8931425SBob Wilson // Counter tracks the body of the loop. 601bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 602bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue()); 603bf854f0fSBob Wilson // Visit the body region first. (This is basically the same as a while 604bf854f0fSBob Wilson // loop; see further comments in VisitWhileStmt.) 605bf854f0fSBob Wilson Cnt.beginRegion(); 6063586be72SDuncan P. N. Exon Smith CountMap[S->getLoopVarStmt()] = PGO.getCurrentRegionCount(); 607bf854f0fSBob Wilson Visit(S->getLoopVarStmt()); 608bf854f0fSBob Wilson Visit(S->getBody()); 609bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 610bf854f0fSBob Wilson 611bf854f0fSBob Wilson // The increment is essentially part of the body but it needs to include 612bf854f0fSBob Wilson // the count for all the continue statements. 613bf854f0fSBob Wilson Cnt.setCurrentRegionCount(PGO.getCurrentRegionCount() + 614bf854f0fSBob Wilson BreakContinueStack.back().ContinueCount); 6153586be72SDuncan P. N. Exon Smith CountMap[S->getInc()] = PGO.getCurrentRegionCount(); 616bf854f0fSBob Wilson Visit(S->getInc()); 617bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 618bf854f0fSBob Wilson 619bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val(); 620bf854f0fSBob Wilson 621bf854f0fSBob Wilson // ...then go back and propagate counts through the condition. 622bf854f0fSBob Wilson Cnt.setCurrentRegionCount(Cnt.getParentCount() + 623bf854f0fSBob Wilson Cnt.getAdjustedCount() + 624bf854f0fSBob Wilson BC.ContinueCount); 6253586be72SDuncan P. N. Exon Smith CountMap[S->getCond()] = PGO.getCurrentRegionCount(); 626bf854f0fSBob Wilson Visit(S->getCond()); 627bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 628bf854f0fSBob Wilson Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount); 629bf854f0fSBob Wilson RecordNextStmtCount = true; 630bf854f0fSBob Wilson } 631bf854f0fSBob Wilson 632bf854f0fSBob Wilson void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) { 633bf854f0fSBob Wilson RecordStmtCount(S); 634bf854f0fSBob Wilson Visit(S->getElement()); 635d8931425SBob Wilson // Counter tracks the body of the loop. 636bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 637bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue()); 638bf854f0fSBob Wilson Cnt.beginRegion(); 6393586be72SDuncan P. N. Exon Smith CountMap[S->getBody()] = PGO.getCurrentRegionCount(); 640bf854f0fSBob Wilson Visit(S->getBody()); 641bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val(); 642bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 643bf854f0fSBob Wilson Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount); 644bf854f0fSBob Wilson RecordNextStmtCount = true; 645bf854f0fSBob Wilson } 646bf854f0fSBob Wilson 647bf854f0fSBob Wilson void VisitSwitchStmt(const SwitchStmt *S) { 648bf854f0fSBob Wilson RecordStmtCount(S); 649bf854f0fSBob Wilson Visit(S->getCond()); 650bf854f0fSBob Wilson PGO.setCurrentRegionUnreachable(); 651bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue()); 652bf854f0fSBob Wilson Visit(S->getBody()); 653bf854f0fSBob Wilson // If the switch is inside a loop, add the continue counts. 654bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val(); 655bf854f0fSBob Wilson if (!BreakContinueStack.empty()) 656bf854f0fSBob Wilson BreakContinueStack.back().ContinueCount += BC.ContinueCount; 657d8931425SBob Wilson // Counter tracks the exit block of the switch. 658bf854f0fSBob Wilson RegionCounter ExitCnt(PGO, S); 659bf854f0fSBob Wilson ExitCnt.beginRegion(); 660bf854f0fSBob Wilson RecordNextStmtCount = true; 661bf854f0fSBob Wilson } 662bf854f0fSBob Wilson 663bf854f0fSBob Wilson void VisitCaseStmt(const CaseStmt *S) { 664bf854f0fSBob Wilson RecordNextStmtCount = false; 665d8931425SBob Wilson // Counter for this particular case. This counts only jumps from the 666d8931425SBob Wilson // switch header and does not include fallthrough from the case before 667d8931425SBob Wilson // this one. 668bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 669bf854f0fSBob Wilson Cnt.beginRegion(/*AddIncomingFallThrough=*/true); 6703586be72SDuncan P. N. Exon Smith CountMap[S] = Cnt.getCount(); 671bf854f0fSBob Wilson RecordNextStmtCount = true; 672bf854f0fSBob Wilson Visit(S->getSubStmt()); 673bf854f0fSBob Wilson } 674bf854f0fSBob Wilson 675bf854f0fSBob Wilson void VisitDefaultStmt(const DefaultStmt *S) { 676bf854f0fSBob Wilson RecordNextStmtCount = false; 677d8931425SBob Wilson // Counter for this default case. This does not include fallthrough from 678d8931425SBob Wilson // the previous case. 679bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 680bf854f0fSBob Wilson Cnt.beginRegion(/*AddIncomingFallThrough=*/true); 6813586be72SDuncan P. N. Exon Smith CountMap[S] = Cnt.getCount(); 682bf854f0fSBob Wilson RecordNextStmtCount = true; 683bf854f0fSBob Wilson Visit(S->getSubStmt()); 684bf854f0fSBob Wilson } 685bf854f0fSBob Wilson 686bf854f0fSBob Wilson void VisitIfStmt(const IfStmt *S) { 687bf854f0fSBob Wilson RecordStmtCount(S); 688d8931425SBob Wilson // Counter tracks the "then" part of an if statement. The count for 689d8931425SBob Wilson // the "else" part, if it exists, will be calculated from this counter. 690bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 691bf854f0fSBob Wilson Visit(S->getCond()); 692bf854f0fSBob Wilson 693bf854f0fSBob Wilson Cnt.beginRegion(); 6943586be72SDuncan P. N. Exon Smith CountMap[S->getThen()] = PGO.getCurrentRegionCount(); 695bf854f0fSBob Wilson Visit(S->getThen()); 696bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 697bf854f0fSBob Wilson 698bf854f0fSBob Wilson if (S->getElse()) { 699bf854f0fSBob Wilson Cnt.beginElseRegion(); 7003586be72SDuncan P. N. Exon Smith CountMap[S->getElse()] = PGO.getCurrentRegionCount(); 701bf854f0fSBob Wilson Visit(S->getElse()); 702bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 703bf854f0fSBob Wilson } 704bf854f0fSBob Wilson Cnt.applyAdjustmentsToRegion(0); 705bf854f0fSBob Wilson RecordNextStmtCount = true; 706bf854f0fSBob Wilson } 707bf854f0fSBob Wilson 708bf854f0fSBob Wilson void VisitCXXTryStmt(const CXXTryStmt *S) { 709bf854f0fSBob Wilson RecordStmtCount(S); 710bf854f0fSBob Wilson Visit(S->getTryBlock()); 711bf854f0fSBob Wilson for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I) 712bf854f0fSBob Wilson Visit(S->getHandler(I)); 713d8931425SBob Wilson // Counter tracks the continuation block of the try statement. 714bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 715bf854f0fSBob Wilson Cnt.beginRegion(); 716bf854f0fSBob Wilson RecordNextStmtCount = true; 717bf854f0fSBob Wilson } 718bf854f0fSBob Wilson 719bf854f0fSBob Wilson void VisitCXXCatchStmt(const CXXCatchStmt *S) { 720bf854f0fSBob Wilson RecordNextStmtCount = false; 721d8931425SBob Wilson // Counter tracks the catch statement's handler block. 722bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 723bf854f0fSBob Wilson Cnt.beginRegion(); 7243586be72SDuncan P. N. Exon Smith CountMap[S] = PGO.getCurrentRegionCount(); 725bf854f0fSBob Wilson Visit(S->getHandlerBlock()); 726bf854f0fSBob Wilson } 727bf854f0fSBob Wilson 72853c55d99SJustin Bogner void VisitAbstractConditionalOperator( 72953c55d99SJustin Bogner const AbstractConditionalOperator *E) { 730bf854f0fSBob Wilson RecordStmtCount(E); 731d8931425SBob Wilson // Counter tracks the "true" part of a conditional operator. The 732d8931425SBob Wilson // count in the "false" part will be calculated from this counter. 733bf854f0fSBob Wilson RegionCounter Cnt(PGO, E); 734bf854f0fSBob Wilson Visit(E->getCond()); 735bf854f0fSBob Wilson 736bf854f0fSBob Wilson Cnt.beginRegion(); 7373586be72SDuncan P. N. Exon Smith CountMap[E->getTrueExpr()] = PGO.getCurrentRegionCount(); 738bf854f0fSBob Wilson Visit(E->getTrueExpr()); 739bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 740bf854f0fSBob Wilson 741bf854f0fSBob Wilson Cnt.beginElseRegion(); 7423586be72SDuncan P. N. Exon Smith CountMap[E->getFalseExpr()] = PGO.getCurrentRegionCount(); 743bf854f0fSBob Wilson Visit(E->getFalseExpr()); 744bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 745bf854f0fSBob Wilson 746bf854f0fSBob Wilson Cnt.applyAdjustmentsToRegion(0); 747bf854f0fSBob Wilson RecordNextStmtCount = true; 748bf854f0fSBob Wilson } 749bf854f0fSBob Wilson 750bf854f0fSBob Wilson void VisitBinLAnd(const BinaryOperator *E) { 751bf854f0fSBob Wilson RecordStmtCount(E); 752d8931425SBob Wilson // Counter tracks the right hand side of a logical and operator. 753bf854f0fSBob Wilson RegionCounter Cnt(PGO, E); 754bf854f0fSBob Wilson Visit(E->getLHS()); 755bf854f0fSBob Wilson Cnt.beginRegion(); 7563586be72SDuncan P. N. Exon Smith CountMap[E->getRHS()] = PGO.getCurrentRegionCount(); 757bf854f0fSBob Wilson Visit(E->getRHS()); 758bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 759bf854f0fSBob Wilson Cnt.applyAdjustmentsToRegion(0); 760bf854f0fSBob Wilson RecordNextStmtCount = true; 761bf854f0fSBob Wilson } 762bf854f0fSBob Wilson 763bf854f0fSBob Wilson void VisitBinLOr(const BinaryOperator *E) { 764bf854f0fSBob Wilson RecordStmtCount(E); 765d8931425SBob Wilson // Counter tracks the right hand side of a logical or operator. 766bf854f0fSBob Wilson RegionCounter Cnt(PGO, E); 767bf854f0fSBob Wilson Visit(E->getLHS()); 768bf854f0fSBob Wilson Cnt.beginRegion(); 7693586be72SDuncan P. N. Exon Smith CountMap[E->getRHS()] = PGO.getCurrentRegionCount(); 770bf854f0fSBob Wilson Visit(E->getRHS()); 771bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 772bf854f0fSBob Wilson Cnt.applyAdjustmentsToRegion(0); 773bf854f0fSBob Wilson RecordNextStmtCount = true; 774bf854f0fSBob Wilson } 775bf854f0fSBob Wilson }; 776ef512b99SJustin Bogner } 777ef512b99SJustin Bogner 7784bc7731aSDuncan P. N. Exon Smith void PGOHash::combine(HashType Type) { 7794bc7731aSDuncan P. N. Exon Smith // Check that we never combine 0 and only have six bits. 7804bc7731aSDuncan P. N. Exon Smith assert(Type && "Hash is invalid: unexpected type 0"); 7814bc7731aSDuncan P. N. Exon Smith assert(unsigned(Type) < TooBig && "Hash is invalid: too many types"); 7824bc7731aSDuncan P. N. Exon Smith 7834bc7731aSDuncan P. N. Exon Smith // Pass through MD5 if enough work has built up. 7844bc7731aSDuncan P. N. Exon Smith if (Count && Count % NumTypesPerWord == 0) { 7854bc7731aSDuncan P. N. Exon Smith using namespace llvm::support; 7864bc7731aSDuncan P. N. Exon Smith uint64_t Swapped = endian::byte_swap<uint64_t, little>(Working); 7874bc7731aSDuncan P. N. Exon Smith MD5.update(llvm::makeArrayRef((uint8_t *)&Swapped, sizeof(Swapped))); 7884bc7731aSDuncan P. N. Exon Smith Working = 0; 7894bc7731aSDuncan P. N. Exon Smith } 7904bc7731aSDuncan P. N. Exon Smith 7914bc7731aSDuncan P. N. Exon Smith // Accumulate the current type. 7924bc7731aSDuncan P. N. Exon Smith ++Count; 7934bc7731aSDuncan P. N. Exon Smith Working = Working << NumBitsPerType | Type; 7944bc7731aSDuncan P. N. Exon Smith } 7954bc7731aSDuncan P. N. Exon Smith 7964bc7731aSDuncan P. N. Exon Smith uint64_t PGOHash::finalize() { 7974bc7731aSDuncan P. N. Exon Smith // Use Working as the hash directly if we never used MD5. 7984bc7731aSDuncan P. N. Exon Smith if (Count <= NumTypesPerWord) 7994bc7731aSDuncan P. N. Exon Smith // No need to byte swap here, since none of the math was endian-dependent. 8004bc7731aSDuncan P. N. Exon Smith // This number will be byte-swapped as required on endianness transitions, 8014bc7731aSDuncan P. N. Exon Smith // so we will see the same value on the other side. 8024bc7731aSDuncan P. N. Exon Smith return Working; 8034bc7731aSDuncan P. N. Exon Smith 8044bc7731aSDuncan P. N. Exon Smith // Check for remaining work in Working. 8054bc7731aSDuncan P. N. Exon Smith if (Working) 8064bc7731aSDuncan P. N. Exon Smith MD5.update(Working); 8074bc7731aSDuncan P. N. Exon Smith 8084bc7731aSDuncan P. N. Exon Smith // Finalize the MD5 and return the hash. 8094bc7731aSDuncan P. N. Exon Smith llvm::MD5::MD5Result Result; 8104bc7731aSDuncan P. N. Exon Smith MD5.final(Result); 8114bc7731aSDuncan P. N. Exon Smith using namespace llvm::support; 8124bc7731aSDuncan P. N. Exon Smith return endian::read<uint64_t, little, unaligned>(Result); 8134bc7731aSDuncan P. N. Exon Smith } 8144bc7731aSDuncan P. N. Exon Smith 815d971cd1bSDuncan P. N. Exon Smith static void emitRuntimeHook(CodeGenModule &CGM) { 8163fefedb2SDuncan P. N. Exon Smith const char *const RuntimeVarName = "__llvm_profile_runtime"; 8173fefedb2SDuncan P. N. Exon Smith const char *const RuntimeUserName = "__llvm_profile_runtime_user"; 818d971cd1bSDuncan P. N. Exon Smith if (CGM.getModule().getGlobalVariable(RuntimeVarName)) 819d971cd1bSDuncan P. N. Exon Smith return; 820d971cd1bSDuncan P. N. Exon Smith 821d971cd1bSDuncan P. N. Exon Smith // Declare the runtime hook. 822d971cd1bSDuncan P. N. Exon Smith llvm::LLVMContext &Ctx = CGM.getLLVMContext(); 823d971cd1bSDuncan P. N. Exon Smith auto *Int32Ty = llvm::Type::getInt32Ty(Ctx); 824d971cd1bSDuncan P. N. Exon Smith auto *Var = new llvm::GlobalVariable(CGM.getModule(), Int32Ty, false, 825d971cd1bSDuncan P. N. Exon Smith llvm::GlobalValue::ExternalLinkage, 826d971cd1bSDuncan P. N. Exon Smith nullptr, RuntimeVarName); 827d971cd1bSDuncan P. N. Exon Smith 828d971cd1bSDuncan P. N. Exon Smith // Make a function that uses it. 829d971cd1bSDuncan P. N. Exon Smith auto *User = llvm::Function::Create(llvm::FunctionType::get(Int32Ty, false), 830d971cd1bSDuncan P. N. Exon Smith llvm::GlobalValue::LinkOnceODRLinkage, 831d971cd1bSDuncan P. N. Exon Smith RuntimeUserName, &CGM.getModule()); 832d971cd1bSDuncan P. N. Exon Smith User->addFnAttr(llvm::Attribute::NoInline); 833d971cd1bSDuncan P. N. Exon Smith if (CGM.getCodeGenOpts().DisableRedZone) 834d971cd1bSDuncan P. N. Exon Smith User->addFnAttr(llvm::Attribute::NoRedZone); 835d971cd1bSDuncan P. N. Exon Smith CGBuilderTy Builder(llvm::BasicBlock::Create(CGM.getLLVMContext(), "", User)); 836d971cd1bSDuncan P. N. Exon Smith auto *Load = Builder.CreateLoad(Var); 837d971cd1bSDuncan P. N. Exon Smith Builder.CreateRet(Load); 838d971cd1bSDuncan P. N. Exon Smith 839d971cd1bSDuncan P. N. Exon Smith // Create a use of the function. Now the definition of the runtime variable 840d971cd1bSDuncan P. N. Exon Smith // should get pulled in, along with any static initializears. 841d971cd1bSDuncan P. N. Exon Smith CGM.addUsedGlobal(User); 842d971cd1bSDuncan P. N. Exon Smith } 843d971cd1bSDuncan P. N. Exon Smith 844*ee02499aSAlex Lorenz void CodeGenPGO::checkGlobalDecl(GlobalDecl GD) { 845*ee02499aSAlex Lorenz // Make sure we only emit coverage mapping for one constructor/destructor. 846*ee02499aSAlex Lorenz // Clang emits several functions for the constructor and the destructor of 847*ee02499aSAlex Lorenz // a class. Every function is instrumented, but we only want to provide 848*ee02499aSAlex Lorenz // coverage for one of them. Because of that we only emit the coverage mapping 849*ee02499aSAlex Lorenz // for the base constructor/destructor. 850*ee02499aSAlex Lorenz if ((isa<CXXConstructorDecl>(GD.getDecl()) && 851*ee02499aSAlex Lorenz GD.getCtorType() != Ctor_Base) || 852*ee02499aSAlex Lorenz (isa<CXXDestructorDecl>(GD.getDecl()) && 853*ee02499aSAlex Lorenz GD.getDtorType() != Dtor_Base)) { 854*ee02499aSAlex Lorenz SkipCoverageMapping = true; 855*ee02499aSAlex Lorenz } 856*ee02499aSAlex Lorenz } 857*ee02499aSAlex Lorenz 858da1ebedeSBob Wilson void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) { 859ef512b99SJustin Bogner bool InstrumentRegions = CGM.getCodeGenOpts().ProfileInstrGenerate; 860837a6f6fSJustin Bogner llvm::IndexedInstrProfReader *PGOReader = CGM.getPGOReader(); 861837a6f6fSJustin Bogner if (!InstrumentRegions && !PGOReader) 862ef512b99SJustin Bogner return; 8633212b18bSJustin Bogner if (D->isImplicit()) 864ef512b99SJustin Bogner return; 865*ee02499aSAlex Lorenz CGM.ClearUnusedCoverageMapping(D); 866da1ebedeSBob Wilson setFuncName(Fn); 867*ee02499aSAlex Lorenz setVarLinkage(Fn->getLinkage()); 8687c41451bSDuncan P. N. Exon Smith 869ef512b99SJustin Bogner mapRegionCounters(D); 870d971cd1bSDuncan P. N. Exon Smith if (InstrumentRegions) { 871d971cd1bSDuncan P. N. Exon Smith emitRuntimeHook(CGM); 872ef512b99SJustin Bogner emitCounterVariables(); 873*ee02499aSAlex Lorenz if (CGM.getCodeGenOpts().CoverageMapping) 874*ee02499aSAlex Lorenz emitCounterRegionMapping(D); 875d971cd1bSDuncan P. N. Exon Smith } 876837a6f6fSJustin Bogner if (PGOReader) { 87740b8ba14SJustin Bogner SourceManager &SM = CGM.getContext().getSourceManager(); 87840b8ba14SJustin Bogner loadRegionCounts(PGOReader, SM.isInMainFile(D->getLocation())); 879bf854f0fSBob Wilson computeRegionCounts(D); 880837a6f6fSJustin Bogner applyFunctionAttributes(PGOReader, Fn); 881bf854f0fSBob Wilson } 882ef512b99SJustin Bogner } 883ef512b99SJustin Bogner 884ef512b99SJustin Bogner void CodeGenPGO::mapRegionCounters(const Decl *D) { 8851b67cfd4SDuncan P. N. Exon Smith RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>); 8863586be72SDuncan P. N. Exon Smith MapRegionCounters Walker(*RegionCounterMap); 887ef512b99SJustin Bogner if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) 888d8931425SBob Wilson Walker.TraverseDecl(const_cast<FunctionDecl *>(FD)); 8895ec8fe19SBob Wilson else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D)) 890d8931425SBob Wilson Walker.TraverseDecl(const_cast<ObjCMethodDecl *>(MD)); 891c845c00aSBob Wilson else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D)) 892d8931425SBob Wilson Walker.TraverseDecl(const_cast<BlockDecl *>(BD)); 89381ab90f7SJustin Bogner else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D)) 89481ab90f7SJustin Bogner Walker.TraverseDecl(const_cast<CapturedDecl *>(CD)); 8953212b18bSJustin Bogner assert(Walker.NextCounter > 0 && "no entry counter mapped for decl"); 896ef512b99SJustin Bogner NumRegionCounters = Walker.NextCounter; 8974bc7731aSDuncan P. N. Exon Smith FunctionHash = Walker.Hash.finalize(); 898ef512b99SJustin Bogner } 899ef512b99SJustin Bogner 900*ee02499aSAlex Lorenz void CodeGenPGO::emitCounterRegionMapping(const Decl *D) { 901*ee02499aSAlex Lorenz if (SkipCoverageMapping) 902*ee02499aSAlex Lorenz return; 903*ee02499aSAlex Lorenz // Don't map the functions inside the system headers 904*ee02499aSAlex Lorenz auto Loc = D->getBody()->getLocStart(); 905*ee02499aSAlex Lorenz if (CGM.getContext().getSourceManager().isInSystemHeader(Loc)) 906*ee02499aSAlex Lorenz return; 907*ee02499aSAlex Lorenz 908*ee02499aSAlex Lorenz llvm::raw_string_ostream OS(CoverageMapping); 909*ee02499aSAlex Lorenz CoverageMappingGen MappingGen(*CGM.getCoverageMapping(), 910*ee02499aSAlex Lorenz CGM.getContext().getSourceManager(), 911*ee02499aSAlex Lorenz CGM.getLangOpts(), RegionCounterMap.get(), 912*ee02499aSAlex Lorenz NumRegionCounters); 913*ee02499aSAlex Lorenz MappingGen.emitCounterMapping(D, OS); 914*ee02499aSAlex Lorenz OS.flush(); 915*ee02499aSAlex Lorenz } 916*ee02499aSAlex Lorenz 917*ee02499aSAlex Lorenz void 918*ee02499aSAlex Lorenz CodeGenPGO::emitEmptyCounterMapping(const Decl *D, StringRef FuncName, 919*ee02499aSAlex Lorenz llvm::GlobalValue::LinkageTypes Linkage) { 920*ee02499aSAlex Lorenz if (SkipCoverageMapping) 921*ee02499aSAlex Lorenz return; 922*ee02499aSAlex Lorenz setFuncName(FuncName, Linkage); 923*ee02499aSAlex Lorenz setVarLinkage(Linkage); 924*ee02499aSAlex Lorenz 925*ee02499aSAlex Lorenz // Don't map the functions inside the system headers 926*ee02499aSAlex Lorenz auto Loc = D->getBody()->getLocStart(); 927*ee02499aSAlex Lorenz if (CGM.getContext().getSourceManager().isInSystemHeader(Loc)) 928*ee02499aSAlex Lorenz return; 929*ee02499aSAlex Lorenz 930*ee02499aSAlex Lorenz llvm::raw_string_ostream OS(CoverageMapping); 931*ee02499aSAlex Lorenz CoverageMappingGen MappingGen(*CGM.getCoverageMapping(), 932*ee02499aSAlex Lorenz CGM.getContext().getSourceManager(), 933*ee02499aSAlex Lorenz CGM.getLangOpts()); 934*ee02499aSAlex Lorenz MappingGen.emitEmptyMapping(D, OS); 935*ee02499aSAlex Lorenz OS.flush(); 936*ee02499aSAlex Lorenz buildDataVar(); 937*ee02499aSAlex Lorenz } 938*ee02499aSAlex Lorenz 939bf854f0fSBob Wilson void CodeGenPGO::computeRegionCounts(const Decl *D) { 9401b67cfd4SDuncan P. N. Exon Smith StmtCountMap.reset(new llvm::DenseMap<const Stmt *, uint64_t>); 9413586be72SDuncan P. N. Exon Smith ComputeRegionCounts Walker(*StmtCountMap, *this); 942bf854f0fSBob Wilson if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) 943bf854f0fSBob Wilson Walker.VisitFunctionDecl(FD); 9445ec8fe19SBob Wilson else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D)) 9455ec8fe19SBob Wilson Walker.VisitObjCMethodDecl(MD); 946c845c00aSBob Wilson else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D)) 947c845c00aSBob Wilson Walker.VisitBlockDecl(BD); 94881ab90f7SJustin Bogner else if (const CapturedDecl *CD = dyn_cast_or_null<CapturedDecl>(D)) 94981ab90f7SJustin Bogner Walker.VisitCapturedDecl(const_cast<CapturedDecl *>(CD)); 950bf854f0fSBob Wilson } 951bf854f0fSBob Wilson 952837a6f6fSJustin Bogner void 953837a6f6fSJustin Bogner CodeGenPGO::applyFunctionAttributes(llvm::IndexedInstrProfReader *PGOReader, 9544c9c45c0SJustin Bogner llvm::Function *Fn) { 9554c9c45c0SJustin Bogner if (!haveRegionCounts()) 9564c9c45c0SJustin Bogner return; 9574c9c45c0SJustin Bogner 958837a6f6fSJustin Bogner uint64_t MaxFunctionCount = PGOReader->getMaximumFunctionCount(); 9594c9c45c0SJustin Bogner uint64_t FunctionCount = getRegionCount(0); 9604c9c45c0SJustin Bogner if (FunctionCount >= (uint64_t)(0.3 * (double)MaxFunctionCount)) 9614c9c45c0SJustin Bogner // Turn on InlineHint attribute for hot functions. 9624c9c45c0SJustin Bogner // FIXME: 30% is from preliminary tuning on SPEC, it may not be optimal. 9634c9c45c0SJustin Bogner Fn->addFnAttr(llvm::Attribute::InlineHint); 9644c9c45c0SJustin Bogner else if (FunctionCount <= (uint64_t)(0.01 * (double)MaxFunctionCount)) 9654c9c45c0SJustin Bogner // Turn on Cold attribute for cold functions. 9664c9c45c0SJustin Bogner // FIXME: 1% is from preliminary tuning on SPEC, it may not be optimal. 9674c9c45c0SJustin Bogner Fn->addFnAttr(llvm::Attribute::Cold); 9684c9c45c0SJustin Bogner } 9694c9c45c0SJustin Bogner 970ef512b99SJustin Bogner void CodeGenPGO::emitCounterVariables() { 971ef512b99SJustin Bogner llvm::LLVMContext &Ctx = CGM.getLLVMContext(); 972ef512b99SJustin Bogner llvm::ArrayType *CounterTy = llvm::ArrayType::get(llvm::Type::getInt64Ty(Ctx), 973ef512b99SJustin Bogner NumRegionCounters); 974ef512b99SJustin Bogner RegionCounters = 97573f78627SDuncan P. N. Exon Smith new llvm::GlobalVariable(CGM.getModule(), CounterTy, false, VarLinkage, 976ef512b99SJustin Bogner llvm::Constant::getNullValue(CounterTy), 9772fe531cbSDuncan P. N. Exon Smith getFuncVarName("counters")); 9782fe531cbSDuncan P. N. Exon Smith RegionCounters->setAlignment(8); 9792fe531cbSDuncan P. N. Exon Smith RegionCounters->setSection(getCountersSection(CGM)); 980ef512b99SJustin Bogner } 981ef512b99SJustin Bogner 982ef512b99SJustin Bogner void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, unsigned Counter) { 983749ebc7fSBob Wilson if (!RegionCounters) 984ef512b99SJustin Bogner return; 985ef512b99SJustin Bogner llvm::Value *Addr = 986ef512b99SJustin Bogner Builder.CreateConstInBoundsGEP2_64(RegionCounters, 0, Counter); 987ef512b99SJustin Bogner llvm::Value *Count = Builder.CreateLoad(Addr, "pgocount"); 988ef512b99SJustin Bogner Count = Builder.CreateAdd(Count, Builder.getInt64(1)); 989ef512b99SJustin Bogner Builder.CreateStore(Count, Addr); 990ef512b99SJustin Bogner } 991ef512b99SJustin Bogner 99240b8ba14SJustin Bogner void CodeGenPGO::loadRegionCounts(llvm::IndexedInstrProfReader *PGOReader, 99340b8ba14SJustin Bogner bool IsInMainFile) { 99440b8ba14SJustin Bogner CGM.getPGOStats().addVisited(IsInMainFile); 9951b67cfd4SDuncan P. N. Exon Smith RegionCounts.reset(new std::vector<uint64_t>); 9969c6818efSJustin Bogner if (std::error_code EC = PGOReader->getFunctionCounts( 9979c6818efSJustin Bogner getFuncName(), FunctionHash, *RegionCounts)) { 9989c6818efSJustin Bogner if (EC == llvm::instrprof_error::unknown_function) 99940b8ba14SJustin Bogner CGM.getPGOStats().addMissing(IsInMainFile); 10009c6818efSJustin Bogner else if (EC == llvm::instrprof_error::hash_mismatch) 10019c6818efSJustin Bogner CGM.getPGOStats().addMismatched(IsInMainFile); 10029c6818efSJustin Bogner else if (EC == llvm::instrprof_error::malformed) 10039c6818efSJustin Bogner // TODO: Consider a more specific warning for this case. 100440b8ba14SJustin Bogner CGM.getPGOStats().addMismatched(IsInMainFile); 1005e2ef2a09SJustin Bogner RegionCounts.reset(); 1006e2ef2a09SJustin Bogner } 1007ef512b99SJustin Bogner } 1008ef512b99SJustin Bogner 1009ef512b99SJustin Bogner void CodeGenPGO::destroyRegionCounters() { 10101b67cfd4SDuncan P. N. Exon Smith RegionCounterMap.reset(); 10111b67cfd4SDuncan P. N. Exon Smith StmtCountMap.reset(); 10121b67cfd4SDuncan P. N. Exon Smith RegionCounts.reset(); 10133212b18bSJustin Bogner RegionCounters = nullptr; 1014ef512b99SJustin Bogner } 1015ef512b99SJustin Bogner 101638402dc9SDuncan P. N. Exon Smith /// \brief Calculate what to divide by to scale weights. 101738402dc9SDuncan P. N. Exon Smith /// 101838402dc9SDuncan P. N. Exon Smith /// Given the maximum weight, calculate a divisor that will scale all the 101938402dc9SDuncan P. N. Exon Smith /// weights to strictly less than UINT32_MAX. 102038402dc9SDuncan P. N. Exon Smith static uint64_t calculateWeightScale(uint64_t MaxWeight) { 102138402dc9SDuncan P. N. Exon Smith return MaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1; 102238402dc9SDuncan P. N. Exon Smith } 102338402dc9SDuncan P. N. Exon Smith 102438402dc9SDuncan P. N. Exon Smith /// \brief Scale an individual branch weight (and add 1). 102538402dc9SDuncan P. N. Exon Smith /// 102638402dc9SDuncan P. N. Exon Smith /// Scale a 64-bit weight down to 32-bits using \c Scale. 102738402dc9SDuncan P. N. Exon Smith /// 102838402dc9SDuncan P. N. Exon Smith /// According to Laplace's Rule of Succession, it is better to compute the 102938402dc9SDuncan P. N. Exon Smith /// weight based on the count plus 1, so universally add 1 to the value. 103038402dc9SDuncan P. N. Exon Smith /// 103138402dc9SDuncan P. N. Exon Smith /// \pre \c Scale was calculated by \a calculateWeightScale() with a weight no 103238402dc9SDuncan P. N. Exon Smith /// greater than \c Weight. 103338402dc9SDuncan P. N. Exon Smith static uint32_t scaleBranchWeight(uint64_t Weight, uint64_t Scale) { 103438402dc9SDuncan P. N. Exon Smith assert(Scale && "scale by 0?"); 103538402dc9SDuncan P. N. Exon Smith uint64_t Scaled = Weight / Scale + 1; 103638402dc9SDuncan P. N. Exon Smith assert(Scaled <= UINT32_MAX && "overflow 32-bits"); 103738402dc9SDuncan P. N. Exon Smith return Scaled; 103838402dc9SDuncan P. N. Exon Smith } 103938402dc9SDuncan P. N. Exon Smith 1040ef512b99SJustin Bogner llvm::MDNode *CodeGenPGO::createBranchWeights(uint64_t TrueCount, 1041ef512b99SJustin Bogner uint64_t FalseCount) { 104238402dc9SDuncan P. N. Exon Smith // Check for empty weights. 1043ef512b99SJustin Bogner if (!TrueCount && !FalseCount) 1044a5f804a7SDuncan P. N. Exon Smith return nullptr; 1045ef512b99SJustin Bogner 104638402dc9SDuncan P. N. Exon Smith // Calculate how to scale down to 32-bits. 104738402dc9SDuncan P. N. Exon Smith uint64_t Scale = calculateWeightScale(std::max(TrueCount, FalseCount)); 104838402dc9SDuncan P. N. Exon Smith 1049ef512b99SJustin Bogner llvm::MDBuilder MDHelper(CGM.getLLVMContext()); 105038402dc9SDuncan P. N. Exon Smith return MDHelper.createBranchWeights(scaleBranchWeight(TrueCount, Scale), 105138402dc9SDuncan P. N. Exon Smith scaleBranchWeight(FalseCount, Scale)); 1052ef512b99SJustin Bogner } 1053ef512b99SJustin Bogner 105495a27b0eSBob Wilson llvm::MDNode *CodeGenPGO::createBranchWeights(ArrayRef<uint64_t> Weights) { 105538402dc9SDuncan P. N. Exon Smith // We need at least two elements to create meaningful weights. 105638402dc9SDuncan P. N. Exon Smith if (Weights.size() < 2) 1057a5f804a7SDuncan P. N. Exon Smith return nullptr; 105838402dc9SDuncan P. N. Exon Smith 1059f3aefca7SJustin Bogner // Check for empty weights. 1060f3aefca7SJustin Bogner uint64_t MaxWeight = *std::max_element(Weights.begin(), Weights.end()); 1061f3aefca7SJustin Bogner if (MaxWeight == 0) 1062f3aefca7SJustin Bogner return nullptr; 1063f3aefca7SJustin Bogner 106438402dc9SDuncan P. N. Exon Smith // Calculate how to scale down to 32-bits. 1065f3aefca7SJustin Bogner uint64_t Scale = calculateWeightScale(MaxWeight); 106638402dc9SDuncan P. N. Exon Smith 1067ef512b99SJustin Bogner SmallVector<uint32_t, 16> ScaledWeights; 1068ef512b99SJustin Bogner ScaledWeights.reserve(Weights.size()); 106938402dc9SDuncan P. N. Exon Smith for (uint64_t W : Weights) 107038402dc9SDuncan P. N. Exon Smith ScaledWeights.push_back(scaleBranchWeight(W, Scale)); 107138402dc9SDuncan P. N. Exon Smith 107238402dc9SDuncan P. N. Exon Smith llvm::MDBuilder MDHelper(CGM.getLLVMContext()); 1073ef512b99SJustin Bogner return MDHelper.createBranchWeights(ScaledWeights); 1074ef512b99SJustin Bogner } 1075bf854f0fSBob Wilson 1076bf854f0fSBob Wilson llvm::MDNode *CodeGenPGO::createLoopWeights(const Stmt *Cond, 1077bf854f0fSBob Wilson RegionCounter &Cnt) { 1078bf854f0fSBob Wilson if (!haveRegionCounts()) 1079a5f804a7SDuncan P. N. Exon Smith return nullptr; 1080bf854f0fSBob Wilson uint64_t LoopCount = Cnt.getCount(); 1081bf854f0fSBob Wilson uint64_t CondCount = 0; 1082bf854f0fSBob Wilson bool Found = getStmtCount(Cond, CondCount); 1083bf854f0fSBob Wilson assert(Found && "missing expected loop condition count"); 1084bf854f0fSBob Wilson (void)Found; 1085bf854f0fSBob Wilson if (CondCount == 0) 1086a5f804a7SDuncan P. N. Exon Smith return nullptr; 1087bf854f0fSBob Wilson return createBranchWeights(LoopCount, 1088bf854f0fSBob Wilson std::max(CondCount, LoopCount) - LoopCount); 1089bf854f0fSBob Wilson } 1090