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" 16ef512b99SJustin Bogner #include "clang/AST/RecursiveASTVisitor.h" 17ef512b99SJustin Bogner #include "clang/AST/StmtVisitor.h" 18e9624291SDuncan P. N. Exon Smith #include "llvm/Config/config.h" // for strtoull()/strtoul() define 19ef512b99SJustin Bogner #include "llvm/IR/MDBuilder.h" 20ef512b99SJustin Bogner #include "llvm/Support/FileSystem.h" 21ef512b99SJustin Bogner 22ef512b99SJustin Bogner using namespace clang; 23ef512b99SJustin Bogner using namespace CodeGen; 24ef512b99SJustin Bogner 25d66a17d0SJustin Bogner static void ReportBadPGOData(CodeGenModule &CGM, const char *Message) { 26d66a17d0SJustin Bogner DiagnosticsEngine &Diags = CGM.getDiags(); 27d66a17d0SJustin Bogner unsigned diagID = Diags.getCustomDiagID(DiagnosticsEngine::Error, "%0"); 28d66a17d0SJustin Bogner Diags.Report(diagID) << Message; 29d66a17d0SJustin Bogner } 30d66a17d0SJustin Bogner 31d66a17d0SJustin Bogner PGOProfileData::PGOProfileData(CodeGenModule &CGM, std::string Path) 32d66a17d0SJustin Bogner : CGM(CGM) { 33d66a17d0SJustin Bogner if (llvm::MemoryBuffer::getFile(Path, DataBuffer)) { 34d66a17d0SJustin Bogner ReportBadPGOData(CGM, "failed to open pgo data file"); 35d66a17d0SJustin Bogner return; 36d66a17d0SJustin Bogner } 37d66a17d0SJustin Bogner 38d66a17d0SJustin Bogner if (DataBuffer->getBufferSize() > std::numeric_limits<unsigned>::max()) { 39d66a17d0SJustin Bogner ReportBadPGOData(CGM, "pgo data file too big"); 40d66a17d0SJustin Bogner return; 41d66a17d0SJustin Bogner } 42d66a17d0SJustin Bogner 43d66a17d0SJustin Bogner // Scan through the data file and map each function to the corresponding 44d66a17d0SJustin Bogner // file offset where its counts are stored. 45d66a17d0SJustin Bogner const char *BufferStart = DataBuffer->getBufferStart(); 46d66a17d0SJustin Bogner const char *BufferEnd = DataBuffer->getBufferEnd(); 47d66a17d0SJustin Bogner const char *CurPtr = BufferStart; 48d66a17d0SJustin Bogner uint64_t MaxCount = 0; 49d66a17d0SJustin Bogner while (CurPtr < BufferEnd) { 50d66a17d0SJustin Bogner // Read the function name. 51d66a17d0SJustin Bogner const char *FuncStart = CurPtr; 52d66a17d0SJustin Bogner // For Objective-C methods, the name may include whitespace, so search 53d66a17d0SJustin Bogner // backward from the end of the line to find the space that separates the 54d66a17d0SJustin Bogner // name from the number of counters. (This is a temporary hack since we are 55d66a17d0SJustin Bogner // going to completely replace this file format in the near future.) 56d66a17d0SJustin Bogner CurPtr = strchr(CurPtr, '\n'); 57d66a17d0SJustin Bogner if (!CurPtr) { 58d66a17d0SJustin Bogner ReportBadPGOData(CGM, "pgo data file has malformed function entry"); 59d66a17d0SJustin Bogner return; 60d66a17d0SJustin Bogner } 61d66a17d0SJustin Bogner StringRef FuncName(FuncStart, CurPtr - FuncStart); 62d66a17d0SJustin Bogner 63b4416f58SJustin Bogner // Skip over the function hash. 64b4416f58SJustin Bogner CurPtr = strchr(++CurPtr, '\n'); 65b4416f58SJustin Bogner if (!CurPtr) { 66b4416f58SJustin Bogner ReportBadPGOData(CGM, "pgo data file is missing the function hash"); 67b4416f58SJustin Bogner return; 68b4416f58SJustin Bogner } 69b4416f58SJustin Bogner 70d66a17d0SJustin Bogner // Read the number of counters. 71d66a17d0SJustin Bogner char *EndPtr; 72e9624291SDuncan P. N. Exon Smith unsigned NumCounters = strtoul(++CurPtr, &EndPtr, 10); 73d66a17d0SJustin Bogner if (EndPtr == CurPtr || *EndPtr != '\n' || NumCounters <= 0) { 74d66a17d0SJustin Bogner ReportBadPGOData(CGM, "pgo data file has unexpected number of counters"); 75d66a17d0SJustin Bogner return; 76d66a17d0SJustin Bogner } 77d66a17d0SJustin Bogner CurPtr = EndPtr; 78d66a17d0SJustin Bogner 79d66a17d0SJustin Bogner // Read function count. 80e9624291SDuncan P. N. Exon Smith uint64_t Count = strtoull(CurPtr, &EndPtr, 10); 81d66a17d0SJustin Bogner if (EndPtr == CurPtr || *EndPtr != '\n') { 82d66a17d0SJustin Bogner ReportBadPGOData(CGM, "pgo-data file has bad count value"); 83d66a17d0SJustin Bogner return; 84d66a17d0SJustin Bogner } 85d66a17d0SJustin Bogner CurPtr = EndPtr; // Point to '\n'. 86d66a17d0SJustin Bogner FunctionCounts[FuncName] = Count; 87d66a17d0SJustin Bogner MaxCount = Count > MaxCount ? Count : MaxCount; 88d66a17d0SJustin Bogner 89d66a17d0SJustin Bogner // There is one line for each counter; skip over those lines. 90d66a17d0SJustin Bogner // Since function count is already read, we start the loop from 1. 91d66a17d0SJustin Bogner for (unsigned N = 1; N < NumCounters; ++N) { 92d66a17d0SJustin Bogner CurPtr = strchr(++CurPtr, '\n'); 93d66a17d0SJustin Bogner if (!CurPtr) { 94d66a17d0SJustin Bogner ReportBadPGOData(CGM, "pgo data file is missing some counter info"); 95d66a17d0SJustin Bogner return; 96d66a17d0SJustin Bogner } 97d66a17d0SJustin Bogner } 98d66a17d0SJustin Bogner 99d66a17d0SJustin Bogner // Skip over the blank line separating functions. 100d66a17d0SJustin Bogner CurPtr += 2; 101d66a17d0SJustin Bogner 102d66a17d0SJustin Bogner DataOffsets[FuncName] = FuncStart - BufferStart; 103d66a17d0SJustin Bogner } 104d66a17d0SJustin Bogner MaxFunctionCount = MaxCount; 105d66a17d0SJustin Bogner } 106d66a17d0SJustin Bogner 107b4416f58SJustin Bogner bool PGOProfileData::getFunctionCounts(StringRef FuncName, uint64_t &FuncHash, 108d66a17d0SJustin Bogner std::vector<uint64_t> &Counts) { 109d66a17d0SJustin Bogner // Find the relevant section of the pgo-data file. 110d66a17d0SJustin Bogner llvm::StringMap<unsigned>::const_iterator OffsetIter = 111d66a17d0SJustin Bogner DataOffsets.find(FuncName); 112d66a17d0SJustin Bogner if (OffsetIter == DataOffsets.end()) 113d66a17d0SJustin Bogner return true; 114d66a17d0SJustin Bogner const char *CurPtr = DataBuffer->getBufferStart() + OffsetIter->getValue(); 115d66a17d0SJustin Bogner 116d66a17d0SJustin Bogner // Skip over the function name. 117d66a17d0SJustin Bogner CurPtr = strchr(CurPtr, '\n'); 118d66a17d0SJustin Bogner assert(CurPtr && "pgo-data has corrupted function entry"); 119b4416f58SJustin Bogner 120b4416f58SJustin Bogner char *EndPtr; 121b4416f58SJustin Bogner // Read the function hash. 122e9624291SDuncan P. N. Exon Smith FuncHash = strtoull(++CurPtr, &EndPtr, 10); 123b4416f58SJustin Bogner assert(EndPtr != CurPtr && *EndPtr == '\n' && 124b4416f58SJustin Bogner "pgo-data file has corrupted function hash"); 125b4416f58SJustin Bogner CurPtr = EndPtr; 126d66a17d0SJustin Bogner 127d66a17d0SJustin Bogner // Read the number of counters. 128e9624291SDuncan P. N. Exon Smith unsigned NumCounters = strtoul(++CurPtr, &EndPtr, 10); 129d66a17d0SJustin Bogner assert(EndPtr != CurPtr && *EndPtr == '\n' && NumCounters > 0 && 130d66a17d0SJustin Bogner "pgo-data file has corrupted number of counters"); 131d66a17d0SJustin Bogner CurPtr = EndPtr; 132d66a17d0SJustin Bogner 133d66a17d0SJustin Bogner Counts.reserve(NumCounters); 134d66a17d0SJustin Bogner 135d66a17d0SJustin Bogner for (unsigned N = 0; N < NumCounters; ++N) { 136d66a17d0SJustin Bogner // Read the count value. 137e9624291SDuncan P. N. Exon Smith uint64_t Count = strtoull(CurPtr, &EndPtr, 10); 138d66a17d0SJustin Bogner if (EndPtr == CurPtr || *EndPtr != '\n') { 139d66a17d0SJustin Bogner ReportBadPGOData(CGM, "pgo-data file has bad count value"); 140d66a17d0SJustin Bogner return true; 141d66a17d0SJustin Bogner } 142d66a17d0SJustin Bogner Counts.push_back(Count); 143d66a17d0SJustin Bogner CurPtr = EndPtr + 1; 144d66a17d0SJustin Bogner } 145d66a17d0SJustin Bogner 146d66a17d0SJustin Bogner // Make sure the number of counters matches up. 147d66a17d0SJustin Bogner if (Counts.size() != NumCounters) { 148d66a17d0SJustin Bogner ReportBadPGOData(CGM, "pgo-data file has inconsistent counters"); 149d66a17d0SJustin Bogner return true; 150d66a17d0SJustin Bogner } 151d66a17d0SJustin Bogner 152d66a17d0SJustin Bogner return false; 153d66a17d0SJustin Bogner } 154d66a17d0SJustin Bogner 155da1ebedeSBob Wilson void CodeGenPGO::setFuncName(llvm::Function *Fn) { 1562fe531cbSDuncan P. N. Exon Smith RawFuncName = Fn->getName(); 157da1ebedeSBob Wilson 158da1ebedeSBob Wilson // Function names may be prefixed with a binary '1' to indicate 159da1ebedeSBob Wilson // that the backend should not modify the symbols due to any platform 160da1ebedeSBob Wilson // naming convention. Do not include that '1' in the PGO profile name. 1612fe531cbSDuncan P. N. Exon Smith if (RawFuncName[0] == '\1') 1622fe531cbSDuncan P. N. Exon Smith RawFuncName = RawFuncName.substr(1); 163da1ebedeSBob Wilson 164da1ebedeSBob Wilson if (!Fn->hasLocalLinkage()) { 1651b67cfd4SDuncan P. N. Exon Smith PrefixedFuncName.reset(new std::string(RawFuncName)); 166da1ebedeSBob Wilson return; 167da1ebedeSBob Wilson } 168da1ebedeSBob Wilson 169da1ebedeSBob Wilson // For local symbols, prepend the main file name to distinguish them. 170da1ebedeSBob Wilson // Do not include the full path in the file name since there's no guarantee 171da1ebedeSBob Wilson // that it will stay the same, e.g., if the files are checked out from 172da1ebedeSBob Wilson // version control in different locations. 1731b67cfd4SDuncan P. N. Exon Smith PrefixedFuncName.reset(new std::string(CGM.getCodeGenOpts().MainFileName)); 1742fe531cbSDuncan P. N. Exon Smith if (PrefixedFuncName->empty()) 1752fe531cbSDuncan P. N. Exon Smith PrefixedFuncName->assign("<unknown>"); 1762fe531cbSDuncan P. N. Exon Smith PrefixedFuncName->append(":"); 1772fe531cbSDuncan P. N. Exon Smith PrefixedFuncName->append(RawFuncName); 178da1ebedeSBob Wilson } 179da1ebedeSBob Wilson 1802fe531cbSDuncan P. N. Exon Smith static llvm::Function *getRegisterFunc(CodeGenModule &CGM) { 181a7807637SDuncan P. N. Exon Smith return CGM.getModule().getFunction("__llvm_profile_register_functions"); 1822fe531cbSDuncan P. N. Exon Smith } 1832fe531cbSDuncan P. N. Exon Smith 1842fe531cbSDuncan P. N. Exon Smith static llvm::BasicBlock *getOrInsertRegisterBB(CodeGenModule &CGM) { 185780443e8SDuncan P. N. Exon Smith // Don't do this for Darwin. compiler-rt uses linker magic. 186780443e8SDuncan P. N. Exon Smith if (CGM.getTarget().getTriple().isOSDarwin()) 187780443e8SDuncan P. N. Exon Smith return nullptr; 188780443e8SDuncan P. N. Exon Smith 1892fe531cbSDuncan P. N. Exon Smith // Only need to insert this once per module. 1902fe531cbSDuncan P. N. Exon Smith if (llvm::Function *RegisterF = getRegisterFunc(CGM)) 1912fe531cbSDuncan P. N. Exon Smith return &RegisterF->getEntryBlock(); 1922fe531cbSDuncan P. N. Exon Smith 1932fe531cbSDuncan P. N. Exon Smith // Construct the function. 1942fe531cbSDuncan P. N. Exon Smith auto *VoidTy = llvm::Type::getVoidTy(CGM.getLLVMContext()); 1952fe531cbSDuncan P. N. Exon Smith auto *RegisterFTy = llvm::FunctionType::get(VoidTy, false); 1962fe531cbSDuncan P. N. Exon Smith auto *RegisterF = llvm::Function::Create(RegisterFTy, 1972fe531cbSDuncan P. N. Exon Smith llvm::GlobalValue::InternalLinkage, 198a7807637SDuncan P. N. Exon Smith "__llvm_profile_register_functions", 1992fe531cbSDuncan P. N. Exon Smith &CGM.getModule()); 2002fe531cbSDuncan P. N. Exon Smith RegisterF->setUnnamedAddr(true); 2012fe531cbSDuncan P. N. Exon Smith if (CGM.getCodeGenOpts().DisableRedZone) 2022fe531cbSDuncan P. N. Exon Smith RegisterF->addFnAttr(llvm::Attribute::NoRedZone); 2032fe531cbSDuncan P. N. Exon Smith 2042fe531cbSDuncan P. N. Exon Smith // Construct and return the entry block. 2052fe531cbSDuncan P. N. Exon Smith auto *BB = llvm::BasicBlock::Create(CGM.getLLVMContext(), "", RegisterF); 2062fe531cbSDuncan P. N. Exon Smith CGBuilderTy Builder(BB); 2072fe531cbSDuncan P. N. Exon Smith Builder.CreateRetVoid(); 2082fe531cbSDuncan P. N. Exon Smith return BB; 2092fe531cbSDuncan P. N. Exon Smith } 2102fe531cbSDuncan P. N. Exon Smith 2112fe531cbSDuncan P. N. Exon Smith static llvm::Constant *getOrInsertRuntimeRegister(CodeGenModule &CGM) { 2122fe531cbSDuncan P. N. Exon Smith auto *VoidTy = llvm::Type::getVoidTy(CGM.getLLVMContext()); 2132fe531cbSDuncan P. N. Exon Smith auto *VoidPtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); 2142fe531cbSDuncan P. N. Exon Smith auto *RuntimeRegisterTy = llvm::FunctionType::get(VoidTy, VoidPtrTy, false); 215a7807637SDuncan P. N. Exon Smith return CGM.getModule().getOrInsertFunction("__llvm_profile_register_function", 2162fe531cbSDuncan P. N. Exon Smith RuntimeRegisterTy); 2172fe531cbSDuncan P. N. Exon Smith } 2182fe531cbSDuncan P. N. Exon Smith 2197134d47dSDuncan P. N. Exon Smith static bool isMachO(const CodeGenModule &CGM) { 2207134d47dSDuncan P. N. Exon Smith return CGM.getTarget().getTriple().isOSBinFormatMachO(); 2217134d47dSDuncan P. N. Exon Smith } 2227134d47dSDuncan P. N. Exon Smith 2232fe531cbSDuncan P. N. Exon Smith static StringRef getCountersSection(const CodeGenModule &CGM) { 224a7807637SDuncan P. N. Exon Smith return isMachO(CGM) ? "__DATA,__llvm_prf_cnts" : "__llvm_prf_cnts"; 2252fe531cbSDuncan P. N. Exon Smith } 2262fe531cbSDuncan P. N. Exon Smith 2272fe531cbSDuncan P. N. Exon Smith static StringRef getNameSection(const CodeGenModule &CGM) { 228a7807637SDuncan P. N. Exon Smith return isMachO(CGM) ? "__DATA,__llvm_prf_names" : "__llvm_prf_names"; 2292fe531cbSDuncan P. N. Exon Smith } 2302fe531cbSDuncan P. N. Exon Smith 2312fe531cbSDuncan P. N. Exon Smith static StringRef getDataSection(const CodeGenModule &CGM) { 232a7807637SDuncan P. N. Exon Smith return isMachO(CGM) ? "__DATA,__llvm_prf_data" : "__llvm_prf_data"; 2332fe531cbSDuncan P. N. Exon Smith } 2342fe531cbSDuncan P. N. Exon Smith 2352fe531cbSDuncan P. N. Exon Smith llvm::GlobalVariable *CodeGenPGO::buildDataVar() { 2362fe531cbSDuncan P. N. Exon Smith // Create name variable. 2372fe531cbSDuncan P. N. Exon Smith llvm::LLVMContext &Ctx = CGM.getLLVMContext(); 2382fe531cbSDuncan P. N. Exon Smith auto *VarName = llvm::ConstantDataArray::getString(Ctx, getFuncName(), 2392fe531cbSDuncan P. N. Exon Smith false); 2402fe531cbSDuncan P. N. Exon Smith auto *Name = new llvm::GlobalVariable(CGM.getModule(), VarName->getType(), 24173f78627SDuncan P. N. Exon Smith true, VarLinkage, VarName, 2422fe531cbSDuncan P. N. Exon Smith getFuncVarName("name")); 2432fe531cbSDuncan P. N. Exon Smith Name->setSection(getNameSection(CGM)); 2442fe531cbSDuncan P. N. Exon Smith Name->setAlignment(1); 2452fe531cbSDuncan P. N. Exon Smith 2462fe531cbSDuncan P. N. Exon Smith // Create data variable. 2472fe531cbSDuncan P. N. Exon Smith auto *Int32Ty = llvm::Type::getInt32Ty(Ctx); 248b4416f58SJustin Bogner auto *Int64Ty = llvm::Type::getInt64Ty(Ctx); 2492fe531cbSDuncan P. N. Exon Smith auto *Int8PtrTy = llvm::Type::getInt8PtrTy(Ctx); 2502fe531cbSDuncan P. N. Exon Smith auto *Int64PtrTy = llvm::Type::getInt64PtrTy(Ctx); 2512fe531cbSDuncan P. N. Exon Smith llvm::Type *DataTypes[] = { 252b4416f58SJustin Bogner Int32Ty, Int32Ty, Int64Ty, Int8PtrTy, Int64PtrTy 2532fe531cbSDuncan P. N. Exon Smith }; 2542fe531cbSDuncan P. N. Exon Smith auto *DataTy = llvm::StructType::get(Ctx, makeArrayRef(DataTypes)); 2552fe531cbSDuncan P. N. Exon Smith llvm::Constant *DataVals[] = { 2562fe531cbSDuncan P. N. Exon Smith llvm::ConstantInt::get(Int32Ty, getFuncName().size()), 2572fe531cbSDuncan P. N. Exon Smith llvm::ConstantInt::get(Int32Ty, NumRegionCounters), 258b4416f58SJustin Bogner llvm::ConstantInt::get(Int64Ty, FunctionHash), 2592fe531cbSDuncan P. N. Exon Smith llvm::ConstantExpr::getBitCast(Name, Int8PtrTy), 2602fe531cbSDuncan P. N. Exon Smith llvm::ConstantExpr::getBitCast(RegionCounters, Int64PtrTy) 2612fe531cbSDuncan P. N. Exon Smith }; 2622fe531cbSDuncan P. N. Exon Smith auto *Data = 26373f78627SDuncan P. N. Exon Smith new llvm::GlobalVariable(CGM.getModule(), DataTy, true, VarLinkage, 2642fe531cbSDuncan P. N. Exon Smith llvm::ConstantStruct::get(DataTy, DataVals), 2652fe531cbSDuncan P. N. Exon Smith getFuncVarName("data")); 2662fe531cbSDuncan P. N. Exon Smith 2672fe531cbSDuncan P. N. Exon Smith // All the data should be packed into an array in its own section. 2682fe531cbSDuncan P. N. Exon Smith Data->setSection(getDataSection(CGM)); 2692fe531cbSDuncan P. N. Exon Smith Data->setAlignment(8); 2702fe531cbSDuncan P. N. Exon Smith 2712fe531cbSDuncan P. N. Exon Smith // Make sure the data doesn't get deleted. 2722fe531cbSDuncan P. N. Exon Smith CGM.addUsedGlobal(Data); 2732fe531cbSDuncan P. N. Exon Smith return Data; 2742fe531cbSDuncan P. N. Exon Smith } 2752fe531cbSDuncan P. N. Exon Smith 2762fe531cbSDuncan P. N. Exon Smith void CodeGenPGO::emitInstrumentationData() { 277ef512b99SJustin Bogner if (!CGM.getCodeGenOpts().ProfileInstrGenerate) 278ef512b99SJustin Bogner return; 279ef512b99SJustin Bogner 2802fe531cbSDuncan P. N. Exon Smith // Build the data. 2812fe531cbSDuncan P. N. Exon Smith auto *Data = buildDataVar(); 282ef512b99SJustin Bogner 2832fe531cbSDuncan P. N. Exon Smith // Register the data. 284780443e8SDuncan P. N. Exon Smith auto *RegisterBB = getOrInsertRegisterBB(CGM); 285780443e8SDuncan P. N. Exon Smith if (!RegisterBB) 286780443e8SDuncan P. N. Exon Smith return; 287780443e8SDuncan P. N. Exon Smith CGBuilderTy Builder(RegisterBB->getTerminator()); 2882fe531cbSDuncan P. N. Exon Smith auto *VoidPtrTy = llvm::Type::getInt8PtrTy(CGM.getLLVMContext()); 2892fe531cbSDuncan P. N. Exon Smith Builder.CreateCall(getOrInsertRuntimeRegister(CGM), 2902fe531cbSDuncan P. N. Exon Smith Builder.CreateBitCast(Data, VoidPtrTy)); 291ef512b99SJustin Bogner } 292ef512b99SJustin Bogner 293ef512b99SJustin Bogner llvm::Function *CodeGenPGO::emitInitialization(CodeGenModule &CGM) { 2942fe531cbSDuncan P. N. Exon Smith if (!CGM.getCodeGenOpts().ProfileInstrGenerate) 295a5f804a7SDuncan P. N. Exon Smith return nullptr; 296ef512b99SJustin Bogner 297f2ea775eSJustin Bogner assert(CGM.getModule().getFunction("__llvm_profile_init") == nullptr && 298f2ea775eSJustin Bogner "profile initialization already emitted"); 299ef512b99SJustin Bogner 3005188e91cSDuncan P. N. Exon Smith // Get the function to call at initialization. 3012fe531cbSDuncan P. N. Exon Smith llvm::Constant *RegisterF = getRegisterFunc(CGM); 3025188e91cSDuncan P. N. Exon Smith if (!RegisterF) 303a5f804a7SDuncan P. N. Exon Smith return nullptr; 3042fe531cbSDuncan P. N. Exon Smith 3052fe531cbSDuncan P. N. Exon Smith // Create the initialization function. 3062fe531cbSDuncan P. N. Exon Smith auto *VoidTy = llvm::Type::getVoidTy(CGM.getLLVMContext()); 3072fe531cbSDuncan P. N. Exon Smith auto *F = llvm::Function::Create(llvm::FunctionType::get(VoidTy, false), 3082fe531cbSDuncan P. N. Exon Smith llvm::GlobalValue::InternalLinkage, 309a7807637SDuncan P. N. Exon Smith "__llvm_profile_init", &CGM.getModule()); 310ef512b99SJustin Bogner F->setUnnamedAddr(true); 311ef512b99SJustin Bogner F->addFnAttr(llvm::Attribute::NoInline); 312ef512b99SJustin Bogner if (CGM.getCodeGenOpts().DisableRedZone) 313ef512b99SJustin Bogner F->addFnAttr(llvm::Attribute::NoRedZone); 314ef512b99SJustin Bogner 3152fe531cbSDuncan P. N. Exon Smith // Add the basic block and the necessary calls. 3162fe531cbSDuncan P. N. Exon Smith CGBuilderTy Builder(llvm::BasicBlock::Create(CGM.getLLVMContext(), "", F)); 3172fe531cbSDuncan P. N. Exon Smith Builder.CreateCall(RegisterF); 3182fe531cbSDuncan P. N. Exon Smith Builder.CreateRetVoid(); 319ef512b99SJustin Bogner 320ef512b99SJustin Bogner return F; 321ef512b99SJustin Bogner } 322ef512b99SJustin Bogner 323ef512b99SJustin Bogner namespace { 324ef512b99SJustin Bogner /// A StmtVisitor that fills a map of statements to PGO counters. 325ef512b99SJustin Bogner struct MapRegionCounters : public ConstStmtVisitor<MapRegionCounters> { 326ef512b99SJustin Bogner /// The next counter value to assign. 327ef512b99SJustin Bogner unsigned NextCounter; 328ef512b99SJustin Bogner /// The map of statements to counters. 3293586be72SDuncan P. N. Exon Smith llvm::DenseMap<const Stmt *, unsigned> &CounterMap; 330ef512b99SJustin Bogner 3313586be72SDuncan P. N. Exon Smith MapRegionCounters(llvm::DenseMap<const Stmt *, unsigned> &CounterMap) 3323586be72SDuncan P. N. Exon Smith : NextCounter(0), CounterMap(CounterMap) {} 333ef512b99SJustin Bogner 334ef512b99SJustin Bogner void VisitChildren(const Stmt *S) { 335ef512b99SJustin Bogner for (Stmt::const_child_range I = S->children(); I; ++I) 336ef512b99SJustin Bogner if (*I) 337ef512b99SJustin Bogner this->Visit(*I); 338ef512b99SJustin Bogner } 339ef512b99SJustin Bogner void VisitStmt(const Stmt *S) { VisitChildren(S); } 340ef512b99SJustin Bogner 341ea278c32SJustin Bogner /// Assign a counter to track entry to the function body. 3424a2f5ae8SDuncan P. N. Exon Smith void VisitFunctionDecl(const FunctionDecl *D) { 3434a2f5ae8SDuncan P. N. Exon Smith CounterMap[D->getBody()] = NextCounter++; 3444a2f5ae8SDuncan P. N. Exon Smith Visit(D->getBody()); 345ef512b99SJustin Bogner } 3464a2f5ae8SDuncan P. N. Exon Smith void VisitObjCMethodDecl(const ObjCMethodDecl *D) { 3474a2f5ae8SDuncan P. N. Exon Smith CounterMap[D->getBody()] = NextCounter++; 3484a2f5ae8SDuncan P. N. Exon Smith Visit(D->getBody()); 3495ec8fe19SBob Wilson } 3504a2f5ae8SDuncan P. N. Exon Smith void VisitBlockDecl(const BlockDecl *D) { 3514a2f5ae8SDuncan P. N. Exon Smith CounterMap[D->getBody()] = NextCounter++; 3524a2f5ae8SDuncan P. N. Exon Smith Visit(D->getBody()); 353c845c00aSBob Wilson } 354ea278c32SJustin Bogner /// Assign a counter to track the block following a label. 355ef512b99SJustin Bogner void VisitLabelStmt(const LabelStmt *S) { 3563586be72SDuncan P. N. Exon Smith CounterMap[S] = NextCounter++; 357ef512b99SJustin Bogner Visit(S->getSubStmt()); 358ef512b99SJustin Bogner } 359bf854f0fSBob Wilson /// Assign a counter for the body of a while loop. 360ef512b99SJustin Bogner void VisitWhileStmt(const WhileStmt *S) { 3613586be72SDuncan P. N. Exon Smith CounterMap[S] = NextCounter++; 362ef512b99SJustin Bogner Visit(S->getCond()); 363ef512b99SJustin Bogner Visit(S->getBody()); 364ef512b99SJustin Bogner } 365bf854f0fSBob Wilson /// Assign a counter for the body of a do-while loop. 366ef512b99SJustin Bogner void VisitDoStmt(const DoStmt *S) { 3673586be72SDuncan P. N. Exon Smith CounterMap[S] = NextCounter++; 368ef512b99SJustin Bogner Visit(S->getBody()); 369ef512b99SJustin Bogner Visit(S->getCond()); 370ef512b99SJustin Bogner } 371bf854f0fSBob Wilson /// Assign a counter for the body of a for loop. 372ef512b99SJustin Bogner void VisitForStmt(const ForStmt *S) { 3733586be72SDuncan P. N. Exon Smith CounterMap[S] = NextCounter++; 374bf854f0fSBob Wilson if (S->getInit()) 375bf854f0fSBob Wilson Visit(S->getInit()); 376ef512b99SJustin Bogner const Expr *E; 377ef512b99SJustin Bogner if ((E = S->getCond())) 378ef512b99SJustin Bogner Visit(E); 379ef512b99SJustin Bogner if ((E = S->getInc())) 380ef512b99SJustin Bogner Visit(E); 381bf854f0fSBob Wilson Visit(S->getBody()); 382ef512b99SJustin Bogner } 383bf854f0fSBob Wilson /// Assign a counter for the body of a for-range loop. 384ef512b99SJustin Bogner void VisitCXXForRangeStmt(const CXXForRangeStmt *S) { 3853586be72SDuncan P. N. Exon Smith CounterMap[S] = NextCounter++; 386bf854f0fSBob Wilson Visit(S->getRangeStmt()); 387bf854f0fSBob Wilson Visit(S->getBeginEndStmt()); 388bf854f0fSBob Wilson Visit(S->getCond()); 389bf854f0fSBob Wilson Visit(S->getLoopVarStmt()); 390ef512b99SJustin Bogner Visit(S->getBody()); 391bf854f0fSBob Wilson Visit(S->getInc()); 392ef512b99SJustin Bogner } 393bf854f0fSBob Wilson /// Assign a counter for the body of a for-collection loop. 394ef512b99SJustin Bogner void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) { 3953586be72SDuncan P. N. Exon Smith CounterMap[S] = NextCounter++; 396ef512b99SJustin Bogner Visit(S->getElement()); 397ef512b99SJustin Bogner Visit(S->getBody()); 398ef512b99SJustin Bogner } 399ef512b99SJustin Bogner /// Assign a counter for the exit block of the switch statement. 400ef512b99SJustin Bogner void VisitSwitchStmt(const SwitchStmt *S) { 4013586be72SDuncan P. N. Exon Smith CounterMap[S] = NextCounter++; 402ef512b99SJustin Bogner Visit(S->getCond()); 403ef512b99SJustin Bogner Visit(S->getBody()); 404ef512b99SJustin Bogner } 405ef512b99SJustin Bogner /// Assign a counter for a particular case in a switch. This counts jumps 406ef512b99SJustin Bogner /// from the switch header as well as fallthrough from the case before this 407ef512b99SJustin Bogner /// one. 408ef512b99SJustin Bogner void VisitCaseStmt(const CaseStmt *S) { 4093586be72SDuncan P. N. Exon Smith CounterMap[S] = NextCounter++; 410ef512b99SJustin Bogner Visit(S->getSubStmt()); 411ef512b99SJustin Bogner } 412ef512b99SJustin Bogner /// Assign a counter for the default case of a switch statement. The count 413ef512b99SJustin Bogner /// is the number of branches from the loop header to the default, and does 414ef512b99SJustin Bogner /// not include fallthrough from previous cases. If we have multiple 415ef512b99SJustin Bogner /// conditional branch blocks from the switch instruction to the default 416ef512b99SJustin Bogner /// block, as with large GNU case ranges, this is the counter for the last 417ef512b99SJustin Bogner /// edge in that series, rather than the first. 418ef512b99SJustin Bogner void VisitDefaultStmt(const DefaultStmt *S) { 4193586be72SDuncan P. N. Exon Smith CounterMap[S] = NextCounter++; 420ef512b99SJustin Bogner Visit(S->getSubStmt()); 421ef512b99SJustin Bogner } 422ef512b99SJustin Bogner /// Assign a counter for the "then" part of an if statement. The count for 423ef512b99SJustin Bogner /// the "else" part, if it exists, will be calculated from this counter. 424ef512b99SJustin Bogner void VisitIfStmt(const IfStmt *S) { 4253586be72SDuncan P. N. Exon Smith CounterMap[S] = NextCounter++; 426ef512b99SJustin Bogner Visit(S->getCond()); 427ef512b99SJustin Bogner Visit(S->getThen()); 428ef512b99SJustin Bogner if (S->getElse()) 429ef512b99SJustin Bogner Visit(S->getElse()); 430ef512b99SJustin Bogner } 431ef512b99SJustin Bogner /// Assign a counter for the continuation block of a C++ try statement. 432ef512b99SJustin Bogner void VisitCXXTryStmt(const CXXTryStmt *S) { 4333586be72SDuncan P. N. Exon Smith CounterMap[S] = NextCounter++; 434ef512b99SJustin Bogner Visit(S->getTryBlock()); 435ef512b99SJustin Bogner for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I) 436ef512b99SJustin Bogner Visit(S->getHandler(I)); 437ef512b99SJustin Bogner } 438ef512b99SJustin Bogner /// Assign a counter for a catch statement's handler block. 439ef512b99SJustin Bogner void VisitCXXCatchStmt(const CXXCatchStmt *S) { 4403586be72SDuncan P. N. Exon Smith CounterMap[S] = NextCounter++; 441ef512b99SJustin Bogner Visit(S->getHandlerBlock()); 442ef512b99SJustin Bogner } 443ef512b99SJustin Bogner /// Assign a counter for the "true" part of a conditional operator. The 444ef512b99SJustin Bogner /// count in the "false" part will be calculated from this counter. 445ef512b99SJustin Bogner void VisitConditionalOperator(const ConditionalOperator *E) { 4463586be72SDuncan P. N. Exon Smith CounterMap[E] = NextCounter++; 447ef512b99SJustin Bogner Visit(E->getCond()); 448ef512b99SJustin Bogner Visit(E->getTrueExpr()); 449ef512b99SJustin Bogner Visit(E->getFalseExpr()); 450ef512b99SJustin Bogner } 451ef512b99SJustin Bogner /// Assign a counter for the right hand side of a logical and operator. 452ef512b99SJustin Bogner void VisitBinLAnd(const BinaryOperator *E) { 4533586be72SDuncan P. N. Exon Smith CounterMap[E] = NextCounter++; 454ef512b99SJustin Bogner Visit(E->getLHS()); 455ef512b99SJustin Bogner Visit(E->getRHS()); 456ef512b99SJustin Bogner } 457ef512b99SJustin Bogner /// Assign a counter for the right hand side of a logical or operator. 458ef512b99SJustin Bogner void VisitBinLOr(const BinaryOperator *E) { 4593586be72SDuncan P. N. Exon Smith CounterMap[E] = NextCounter++; 460ef512b99SJustin Bogner Visit(E->getLHS()); 461ef512b99SJustin Bogner Visit(E->getRHS()); 462ef512b99SJustin Bogner } 463ef512b99SJustin Bogner }; 464bf854f0fSBob Wilson 465bf854f0fSBob Wilson /// A StmtVisitor that propagates the raw counts through the AST and 466bf854f0fSBob Wilson /// records the count at statements where the value may change. 467bf854f0fSBob Wilson struct ComputeRegionCounts : public ConstStmtVisitor<ComputeRegionCounts> { 468bf854f0fSBob Wilson /// PGO state. 469bf854f0fSBob Wilson CodeGenPGO &PGO; 470bf854f0fSBob Wilson 471bf854f0fSBob Wilson /// A flag that is set when the current count should be recorded on the 472bf854f0fSBob Wilson /// next statement, such as at the exit of a loop. 473bf854f0fSBob Wilson bool RecordNextStmtCount; 474bf854f0fSBob Wilson 475bf854f0fSBob Wilson /// The map of statements to count values. 4763586be72SDuncan P. N. Exon Smith llvm::DenseMap<const Stmt *, uint64_t> &CountMap; 477bf854f0fSBob Wilson 478bf854f0fSBob Wilson /// BreakContinueStack - Keep counts of breaks and continues inside loops. 479bf854f0fSBob Wilson struct BreakContinue { 480bf854f0fSBob Wilson uint64_t BreakCount; 481bf854f0fSBob Wilson uint64_t ContinueCount; 482bf854f0fSBob Wilson BreakContinue() : BreakCount(0), ContinueCount(0) {} 483bf854f0fSBob Wilson }; 484bf854f0fSBob Wilson SmallVector<BreakContinue, 8> BreakContinueStack; 485bf854f0fSBob Wilson 4863586be72SDuncan P. N. Exon Smith ComputeRegionCounts(llvm::DenseMap<const Stmt *, uint64_t> &CountMap, 4873586be72SDuncan P. N. Exon Smith CodeGenPGO &PGO) 4883586be72SDuncan P. N. Exon Smith : PGO(PGO), RecordNextStmtCount(false), CountMap(CountMap) {} 489bf854f0fSBob Wilson 490bf854f0fSBob Wilson void RecordStmtCount(const Stmt *S) { 491bf854f0fSBob Wilson if (RecordNextStmtCount) { 4923586be72SDuncan P. N. Exon Smith CountMap[S] = PGO.getCurrentRegionCount(); 493bf854f0fSBob Wilson RecordNextStmtCount = false; 494bf854f0fSBob Wilson } 495bf854f0fSBob Wilson } 496bf854f0fSBob Wilson 497bf854f0fSBob Wilson void VisitStmt(const Stmt *S) { 498bf854f0fSBob Wilson RecordStmtCount(S); 499bf854f0fSBob Wilson for (Stmt::const_child_range I = S->children(); I; ++I) { 500bf854f0fSBob Wilson if (*I) 501bf854f0fSBob Wilson this->Visit(*I); 502bf854f0fSBob Wilson } 503bf854f0fSBob Wilson } 504bf854f0fSBob Wilson 5054a2f5ae8SDuncan P. N. Exon Smith void VisitFunctionDecl(const FunctionDecl *D) { 5064a2f5ae8SDuncan P. N. Exon Smith RegionCounter Cnt(PGO, D->getBody()); 507bf854f0fSBob Wilson Cnt.beginRegion(); 5084a2f5ae8SDuncan P. N. Exon Smith CountMap[D->getBody()] = PGO.getCurrentRegionCount(); 5094a2f5ae8SDuncan P. N. Exon Smith Visit(D->getBody()); 510bf854f0fSBob Wilson } 511bf854f0fSBob Wilson 5124a2f5ae8SDuncan P. N. Exon Smith void VisitObjCMethodDecl(const ObjCMethodDecl *D) { 5134a2f5ae8SDuncan P. N. Exon Smith RegionCounter Cnt(PGO, D->getBody()); 5145ec8fe19SBob Wilson Cnt.beginRegion(); 5154a2f5ae8SDuncan P. N. Exon Smith CountMap[D->getBody()] = PGO.getCurrentRegionCount(); 5164a2f5ae8SDuncan P. N. Exon Smith Visit(D->getBody()); 5175ec8fe19SBob Wilson } 5185ec8fe19SBob Wilson 5194a2f5ae8SDuncan P. N. Exon Smith void VisitBlockDecl(const BlockDecl *D) { 5204a2f5ae8SDuncan P. N. Exon Smith RegionCounter Cnt(PGO, D->getBody()); 521c845c00aSBob Wilson Cnt.beginRegion(); 5224a2f5ae8SDuncan P. N. Exon Smith CountMap[D->getBody()] = PGO.getCurrentRegionCount(); 5234a2f5ae8SDuncan P. N. Exon Smith Visit(D->getBody()); 524c845c00aSBob Wilson } 525c845c00aSBob Wilson 526bf854f0fSBob Wilson void VisitReturnStmt(const ReturnStmt *S) { 527bf854f0fSBob Wilson RecordStmtCount(S); 528bf854f0fSBob Wilson if (S->getRetValue()) 529bf854f0fSBob Wilson Visit(S->getRetValue()); 530bf854f0fSBob Wilson PGO.setCurrentRegionUnreachable(); 531bf854f0fSBob Wilson RecordNextStmtCount = true; 532bf854f0fSBob Wilson } 533bf854f0fSBob Wilson 534bf854f0fSBob Wilson void VisitGotoStmt(const GotoStmt *S) { 535bf854f0fSBob Wilson RecordStmtCount(S); 536bf854f0fSBob Wilson PGO.setCurrentRegionUnreachable(); 537bf854f0fSBob Wilson RecordNextStmtCount = true; 538bf854f0fSBob Wilson } 539bf854f0fSBob Wilson 540bf854f0fSBob Wilson void VisitLabelStmt(const LabelStmt *S) { 541bf854f0fSBob Wilson RecordNextStmtCount = false; 542bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 543bf854f0fSBob Wilson Cnt.beginRegion(); 5443586be72SDuncan P. N. Exon Smith CountMap[S] = PGO.getCurrentRegionCount(); 545bf854f0fSBob Wilson Visit(S->getSubStmt()); 546bf854f0fSBob Wilson } 547bf854f0fSBob Wilson 548bf854f0fSBob Wilson void VisitBreakStmt(const BreakStmt *S) { 549bf854f0fSBob Wilson RecordStmtCount(S); 550bf854f0fSBob Wilson assert(!BreakContinueStack.empty() && "break not in a loop or switch!"); 551bf854f0fSBob Wilson BreakContinueStack.back().BreakCount += PGO.getCurrentRegionCount(); 552bf854f0fSBob Wilson PGO.setCurrentRegionUnreachable(); 553bf854f0fSBob Wilson RecordNextStmtCount = true; 554bf854f0fSBob Wilson } 555bf854f0fSBob Wilson 556bf854f0fSBob Wilson void VisitContinueStmt(const ContinueStmt *S) { 557bf854f0fSBob Wilson RecordStmtCount(S); 558bf854f0fSBob Wilson assert(!BreakContinueStack.empty() && "continue stmt not in a loop!"); 559bf854f0fSBob Wilson BreakContinueStack.back().ContinueCount += PGO.getCurrentRegionCount(); 560bf854f0fSBob Wilson PGO.setCurrentRegionUnreachable(); 561bf854f0fSBob Wilson RecordNextStmtCount = true; 562bf854f0fSBob Wilson } 563bf854f0fSBob Wilson 564bf854f0fSBob Wilson void VisitWhileStmt(const WhileStmt *S) { 565bf854f0fSBob Wilson RecordStmtCount(S); 566bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 567bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue()); 568bf854f0fSBob Wilson // Visit the body region first so the break/continue adjustments can be 569bf854f0fSBob Wilson // included when visiting the condition. 570bf854f0fSBob Wilson Cnt.beginRegion(); 5713586be72SDuncan P. N. Exon Smith CountMap[S->getBody()] = PGO.getCurrentRegionCount(); 572bf854f0fSBob Wilson Visit(S->getBody()); 573bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 574bf854f0fSBob Wilson 575bf854f0fSBob Wilson // ...then go back and propagate counts through the condition. The count 576bf854f0fSBob Wilson // at the start of the condition is the sum of the incoming edges, 577bf854f0fSBob Wilson // the backedge from the end of the loop body, and the edges from 578bf854f0fSBob Wilson // continue statements. 579bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val(); 580bf854f0fSBob Wilson Cnt.setCurrentRegionCount(Cnt.getParentCount() + 581bf854f0fSBob Wilson Cnt.getAdjustedCount() + BC.ContinueCount); 5823586be72SDuncan P. N. Exon Smith CountMap[S->getCond()] = PGO.getCurrentRegionCount(); 583bf854f0fSBob Wilson Visit(S->getCond()); 584bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 585bf854f0fSBob Wilson Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount); 586bf854f0fSBob Wilson RecordNextStmtCount = true; 587bf854f0fSBob Wilson } 588bf854f0fSBob Wilson 589bf854f0fSBob Wilson void VisitDoStmt(const DoStmt *S) { 590bf854f0fSBob Wilson RecordStmtCount(S); 591bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 592bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue()); 593bf854f0fSBob Wilson Cnt.beginRegion(/*AddIncomingFallThrough=*/true); 5943586be72SDuncan P. N. Exon Smith CountMap[S->getBody()] = PGO.getCurrentRegionCount(); 595bf854f0fSBob Wilson Visit(S->getBody()); 596bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 597bf854f0fSBob Wilson 598bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val(); 599bf854f0fSBob Wilson // The count at the start of the condition is equal to the count at the 600bf854f0fSBob Wilson // end of the body. The adjusted count does not include either the 601bf854f0fSBob Wilson // fall-through count coming into the loop or the continue count, so add 602bf854f0fSBob Wilson // both of those separately. This is coincidentally the same equation as 603bf854f0fSBob Wilson // with while loops but for different reasons. 604bf854f0fSBob Wilson Cnt.setCurrentRegionCount(Cnt.getParentCount() + 605bf854f0fSBob Wilson Cnt.getAdjustedCount() + BC.ContinueCount); 6063586be72SDuncan P. N. Exon Smith CountMap[S->getCond()] = PGO.getCurrentRegionCount(); 607bf854f0fSBob Wilson Visit(S->getCond()); 608bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 609bf854f0fSBob Wilson Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount); 610bf854f0fSBob Wilson RecordNextStmtCount = true; 611bf854f0fSBob Wilson } 612bf854f0fSBob Wilson 613bf854f0fSBob Wilson void VisitForStmt(const ForStmt *S) { 614bf854f0fSBob Wilson RecordStmtCount(S); 615bf854f0fSBob Wilson if (S->getInit()) 616bf854f0fSBob Wilson Visit(S->getInit()); 617bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 618bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue()); 619bf854f0fSBob Wilson // Visit the body region first. (This is basically the same as a while 620bf854f0fSBob Wilson // loop; see further comments in VisitWhileStmt.) 621bf854f0fSBob Wilson Cnt.beginRegion(); 6223586be72SDuncan P. N. Exon Smith CountMap[S->getBody()] = PGO.getCurrentRegionCount(); 623bf854f0fSBob Wilson Visit(S->getBody()); 624bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 625bf854f0fSBob Wilson 626bf854f0fSBob Wilson // The increment is essentially part of the body but it needs to include 627bf854f0fSBob Wilson // the count for all the continue statements. 628bf854f0fSBob Wilson if (S->getInc()) { 629bf854f0fSBob Wilson Cnt.setCurrentRegionCount(PGO.getCurrentRegionCount() + 630bf854f0fSBob Wilson BreakContinueStack.back().ContinueCount); 6313586be72SDuncan P. N. Exon Smith CountMap[S->getInc()] = PGO.getCurrentRegionCount(); 632bf854f0fSBob Wilson Visit(S->getInc()); 633bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 634bf854f0fSBob Wilson } 635bf854f0fSBob Wilson 636bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val(); 637bf854f0fSBob Wilson 638bf854f0fSBob Wilson // ...then go back and propagate counts through the condition. 639bf854f0fSBob Wilson if (S->getCond()) { 640bf854f0fSBob Wilson Cnt.setCurrentRegionCount(Cnt.getParentCount() + 641bf854f0fSBob Wilson Cnt.getAdjustedCount() + 642bf854f0fSBob Wilson BC.ContinueCount); 6433586be72SDuncan P. N. Exon Smith CountMap[S->getCond()] = PGO.getCurrentRegionCount(); 644bf854f0fSBob Wilson Visit(S->getCond()); 645bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 646bf854f0fSBob Wilson } 647bf854f0fSBob Wilson Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount); 648bf854f0fSBob Wilson RecordNextStmtCount = true; 649bf854f0fSBob Wilson } 650bf854f0fSBob Wilson 651bf854f0fSBob Wilson void VisitCXXForRangeStmt(const CXXForRangeStmt *S) { 652bf854f0fSBob Wilson RecordStmtCount(S); 653bf854f0fSBob Wilson Visit(S->getRangeStmt()); 654bf854f0fSBob Wilson Visit(S->getBeginEndStmt()); 655bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 656bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue()); 657bf854f0fSBob Wilson // Visit the body region first. (This is basically the same as a while 658bf854f0fSBob Wilson // loop; see further comments in VisitWhileStmt.) 659bf854f0fSBob Wilson Cnt.beginRegion(); 6603586be72SDuncan P. N. Exon Smith CountMap[S->getLoopVarStmt()] = PGO.getCurrentRegionCount(); 661bf854f0fSBob Wilson Visit(S->getLoopVarStmt()); 662bf854f0fSBob Wilson Visit(S->getBody()); 663bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 664bf854f0fSBob Wilson 665bf854f0fSBob Wilson // The increment is essentially part of the body but it needs to include 666bf854f0fSBob Wilson // the count for all the continue statements. 667bf854f0fSBob Wilson Cnt.setCurrentRegionCount(PGO.getCurrentRegionCount() + 668bf854f0fSBob Wilson BreakContinueStack.back().ContinueCount); 6693586be72SDuncan P. N. Exon Smith CountMap[S->getInc()] = PGO.getCurrentRegionCount(); 670bf854f0fSBob Wilson Visit(S->getInc()); 671bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 672bf854f0fSBob Wilson 673bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val(); 674bf854f0fSBob Wilson 675bf854f0fSBob Wilson // ...then go back and propagate counts through the condition. 676bf854f0fSBob Wilson Cnt.setCurrentRegionCount(Cnt.getParentCount() + 677bf854f0fSBob Wilson Cnt.getAdjustedCount() + 678bf854f0fSBob Wilson BC.ContinueCount); 6793586be72SDuncan P. N. Exon Smith CountMap[S->getCond()] = PGO.getCurrentRegionCount(); 680bf854f0fSBob Wilson Visit(S->getCond()); 681bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 682bf854f0fSBob Wilson Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount); 683bf854f0fSBob Wilson RecordNextStmtCount = true; 684bf854f0fSBob Wilson } 685bf854f0fSBob Wilson 686bf854f0fSBob Wilson void VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S) { 687bf854f0fSBob Wilson RecordStmtCount(S); 688bf854f0fSBob Wilson Visit(S->getElement()); 689bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 690bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue()); 691bf854f0fSBob Wilson Cnt.beginRegion(); 6923586be72SDuncan P. N. Exon Smith CountMap[S->getBody()] = PGO.getCurrentRegionCount(); 693bf854f0fSBob Wilson Visit(S->getBody()); 694bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val(); 695bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 696bf854f0fSBob Wilson Cnt.applyAdjustmentsToRegion(BC.BreakCount + BC.ContinueCount); 697bf854f0fSBob Wilson RecordNextStmtCount = true; 698bf854f0fSBob Wilson } 699bf854f0fSBob Wilson 700bf854f0fSBob Wilson void VisitSwitchStmt(const SwitchStmt *S) { 701bf854f0fSBob Wilson RecordStmtCount(S); 702bf854f0fSBob Wilson Visit(S->getCond()); 703bf854f0fSBob Wilson PGO.setCurrentRegionUnreachable(); 704bf854f0fSBob Wilson BreakContinueStack.push_back(BreakContinue()); 705bf854f0fSBob Wilson Visit(S->getBody()); 706bf854f0fSBob Wilson // If the switch is inside a loop, add the continue counts. 707bf854f0fSBob Wilson BreakContinue BC = BreakContinueStack.pop_back_val(); 708bf854f0fSBob Wilson if (!BreakContinueStack.empty()) 709bf854f0fSBob Wilson BreakContinueStack.back().ContinueCount += BC.ContinueCount; 710bf854f0fSBob Wilson RegionCounter ExitCnt(PGO, S); 711bf854f0fSBob Wilson ExitCnt.beginRegion(); 712bf854f0fSBob Wilson RecordNextStmtCount = true; 713bf854f0fSBob Wilson } 714bf854f0fSBob Wilson 715bf854f0fSBob Wilson void VisitCaseStmt(const CaseStmt *S) { 716bf854f0fSBob Wilson RecordNextStmtCount = false; 717bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 718bf854f0fSBob Wilson Cnt.beginRegion(/*AddIncomingFallThrough=*/true); 7193586be72SDuncan P. N. Exon Smith CountMap[S] = Cnt.getCount(); 720bf854f0fSBob Wilson RecordNextStmtCount = true; 721bf854f0fSBob Wilson Visit(S->getSubStmt()); 722bf854f0fSBob Wilson } 723bf854f0fSBob Wilson 724bf854f0fSBob Wilson void VisitDefaultStmt(const DefaultStmt *S) { 725bf854f0fSBob Wilson RecordNextStmtCount = false; 726bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 727bf854f0fSBob Wilson Cnt.beginRegion(/*AddIncomingFallThrough=*/true); 7283586be72SDuncan P. N. Exon Smith CountMap[S] = Cnt.getCount(); 729bf854f0fSBob Wilson RecordNextStmtCount = true; 730bf854f0fSBob Wilson Visit(S->getSubStmt()); 731bf854f0fSBob Wilson } 732bf854f0fSBob Wilson 733bf854f0fSBob Wilson void VisitIfStmt(const IfStmt *S) { 734bf854f0fSBob Wilson RecordStmtCount(S); 735bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 736bf854f0fSBob Wilson Visit(S->getCond()); 737bf854f0fSBob Wilson 738bf854f0fSBob Wilson Cnt.beginRegion(); 7393586be72SDuncan P. N. Exon Smith CountMap[S->getThen()] = PGO.getCurrentRegionCount(); 740bf854f0fSBob Wilson Visit(S->getThen()); 741bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 742bf854f0fSBob Wilson 743bf854f0fSBob Wilson if (S->getElse()) { 744bf854f0fSBob Wilson Cnt.beginElseRegion(); 7453586be72SDuncan P. N. Exon Smith CountMap[S->getElse()] = PGO.getCurrentRegionCount(); 746bf854f0fSBob Wilson Visit(S->getElse()); 747bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 748bf854f0fSBob Wilson } 749bf854f0fSBob Wilson Cnt.applyAdjustmentsToRegion(0); 750bf854f0fSBob Wilson RecordNextStmtCount = true; 751bf854f0fSBob Wilson } 752bf854f0fSBob Wilson 753bf854f0fSBob Wilson void VisitCXXTryStmt(const CXXTryStmt *S) { 754bf854f0fSBob Wilson RecordStmtCount(S); 755bf854f0fSBob Wilson Visit(S->getTryBlock()); 756bf854f0fSBob Wilson for (unsigned I = 0, E = S->getNumHandlers(); I < E; ++I) 757bf854f0fSBob Wilson Visit(S->getHandler(I)); 758bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 759bf854f0fSBob Wilson Cnt.beginRegion(); 760bf854f0fSBob Wilson RecordNextStmtCount = true; 761bf854f0fSBob Wilson } 762bf854f0fSBob Wilson 763bf854f0fSBob Wilson void VisitCXXCatchStmt(const CXXCatchStmt *S) { 764bf854f0fSBob Wilson RecordNextStmtCount = false; 765bf854f0fSBob Wilson RegionCounter Cnt(PGO, S); 766bf854f0fSBob Wilson Cnt.beginRegion(); 7673586be72SDuncan P. N. Exon Smith CountMap[S] = PGO.getCurrentRegionCount(); 768bf854f0fSBob Wilson Visit(S->getHandlerBlock()); 769bf854f0fSBob Wilson } 770bf854f0fSBob Wilson 771bf854f0fSBob Wilson void VisitConditionalOperator(const ConditionalOperator *E) { 772bf854f0fSBob Wilson RecordStmtCount(E); 773bf854f0fSBob Wilson RegionCounter Cnt(PGO, E); 774bf854f0fSBob Wilson Visit(E->getCond()); 775bf854f0fSBob Wilson 776bf854f0fSBob Wilson Cnt.beginRegion(); 7773586be72SDuncan P. N. Exon Smith CountMap[E->getTrueExpr()] = PGO.getCurrentRegionCount(); 778bf854f0fSBob Wilson Visit(E->getTrueExpr()); 779bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 780bf854f0fSBob Wilson 781bf854f0fSBob Wilson Cnt.beginElseRegion(); 7823586be72SDuncan P. N. Exon Smith CountMap[E->getFalseExpr()] = PGO.getCurrentRegionCount(); 783bf854f0fSBob Wilson Visit(E->getFalseExpr()); 784bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 785bf854f0fSBob Wilson 786bf854f0fSBob Wilson Cnt.applyAdjustmentsToRegion(0); 787bf854f0fSBob Wilson RecordNextStmtCount = true; 788bf854f0fSBob Wilson } 789bf854f0fSBob Wilson 790bf854f0fSBob Wilson void VisitBinLAnd(const BinaryOperator *E) { 791bf854f0fSBob Wilson RecordStmtCount(E); 792bf854f0fSBob Wilson RegionCounter Cnt(PGO, E); 793bf854f0fSBob Wilson Visit(E->getLHS()); 794bf854f0fSBob Wilson Cnt.beginRegion(); 7953586be72SDuncan P. N. Exon Smith CountMap[E->getRHS()] = PGO.getCurrentRegionCount(); 796bf854f0fSBob Wilson Visit(E->getRHS()); 797bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 798bf854f0fSBob Wilson Cnt.applyAdjustmentsToRegion(0); 799bf854f0fSBob Wilson RecordNextStmtCount = true; 800bf854f0fSBob Wilson } 801bf854f0fSBob Wilson 802bf854f0fSBob Wilson void VisitBinLOr(const BinaryOperator *E) { 803bf854f0fSBob Wilson RecordStmtCount(E); 804bf854f0fSBob Wilson RegionCounter Cnt(PGO, E); 805bf854f0fSBob Wilson Visit(E->getLHS()); 806bf854f0fSBob Wilson Cnt.beginRegion(); 8073586be72SDuncan P. N. Exon Smith CountMap[E->getRHS()] = PGO.getCurrentRegionCount(); 808bf854f0fSBob Wilson Visit(E->getRHS()); 809bf854f0fSBob Wilson Cnt.adjustForControlFlow(); 810bf854f0fSBob Wilson Cnt.applyAdjustmentsToRegion(0); 811bf854f0fSBob Wilson RecordNextStmtCount = true; 812bf854f0fSBob Wilson } 813bf854f0fSBob Wilson }; 814ef512b99SJustin Bogner } 815ef512b99SJustin Bogner 816d971cd1bSDuncan P. N. Exon Smith static void emitRuntimeHook(CodeGenModule &CGM) { 817*3fefedb2SDuncan P. N. Exon Smith const char *const RuntimeVarName = "__llvm_profile_runtime"; 818*3fefedb2SDuncan P. N. Exon Smith const char *const RuntimeUserName = "__llvm_profile_runtime_user"; 819d971cd1bSDuncan P. N. Exon Smith if (CGM.getModule().getGlobalVariable(RuntimeVarName)) 820d971cd1bSDuncan P. N. Exon Smith return; 821d971cd1bSDuncan P. N. Exon Smith 822d971cd1bSDuncan P. N. Exon Smith // Declare the runtime hook. 823d971cd1bSDuncan P. N. Exon Smith llvm::LLVMContext &Ctx = CGM.getLLVMContext(); 824d971cd1bSDuncan P. N. Exon Smith auto *Int32Ty = llvm::Type::getInt32Ty(Ctx); 825d971cd1bSDuncan P. N. Exon Smith auto *Var = new llvm::GlobalVariable(CGM.getModule(), Int32Ty, false, 826d971cd1bSDuncan P. N. Exon Smith llvm::GlobalValue::ExternalLinkage, 827d971cd1bSDuncan P. N. Exon Smith nullptr, RuntimeVarName); 828d971cd1bSDuncan P. N. Exon Smith 829d971cd1bSDuncan P. N. Exon Smith // Make a function that uses it. 830d971cd1bSDuncan P. N. Exon Smith auto *User = llvm::Function::Create(llvm::FunctionType::get(Int32Ty, false), 831d971cd1bSDuncan P. N. Exon Smith llvm::GlobalValue::LinkOnceODRLinkage, 832d971cd1bSDuncan P. N. Exon Smith RuntimeUserName, &CGM.getModule()); 833d971cd1bSDuncan P. N. Exon Smith User->addFnAttr(llvm::Attribute::NoInline); 834d971cd1bSDuncan P. N. Exon Smith if (CGM.getCodeGenOpts().DisableRedZone) 835d971cd1bSDuncan P. N. Exon Smith User->addFnAttr(llvm::Attribute::NoRedZone); 836d971cd1bSDuncan P. N. Exon Smith CGBuilderTy Builder(llvm::BasicBlock::Create(CGM.getLLVMContext(), "", User)); 837d971cd1bSDuncan P. N. Exon Smith auto *Load = Builder.CreateLoad(Var); 838d971cd1bSDuncan P. N. Exon Smith Builder.CreateRet(Load); 839d971cd1bSDuncan P. N. Exon Smith 840d971cd1bSDuncan P. N. Exon Smith // Create a use of the function. Now the definition of the runtime variable 841d971cd1bSDuncan P. N. Exon Smith // should get pulled in, along with any static initializears. 842d971cd1bSDuncan P. N. Exon Smith CGM.addUsedGlobal(User); 843d971cd1bSDuncan P. N. Exon Smith } 844d971cd1bSDuncan P. N. Exon Smith 845da1ebedeSBob Wilson void CodeGenPGO::assignRegionCounters(const Decl *D, llvm::Function *Fn) { 846ef512b99SJustin Bogner bool InstrumentRegions = CGM.getCodeGenOpts().ProfileInstrGenerate; 847d66a17d0SJustin Bogner PGOProfileData *PGOData = CGM.getPGOData(); 848d66a17d0SJustin Bogner if (!InstrumentRegions && !PGOData) 849ef512b99SJustin Bogner return; 850ef512b99SJustin Bogner if (!D) 851ef512b99SJustin Bogner return; 852da1ebedeSBob Wilson setFuncName(Fn); 8537c41451bSDuncan P. N. Exon Smith 8547c41451bSDuncan P. N. Exon Smith // Set the linkage for variables based on the function linkage. Usually, we 8557c41451bSDuncan P. N. Exon Smith // want to match it, but available_externally and extern_weak both have the 8567c41451bSDuncan P. N. Exon Smith // wrong semantics. 85773f78627SDuncan P. N. Exon Smith VarLinkage = Fn->getLinkage(); 8587c41451bSDuncan P. N. Exon Smith switch (VarLinkage) { 8597c41451bSDuncan P. N. Exon Smith case llvm::GlobalValue::ExternalWeakLinkage: 8607c41451bSDuncan P. N. Exon Smith VarLinkage = llvm::GlobalValue::LinkOnceAnyLinkage; 8617c41451bSDuncan P. N. Exon Smith break; 8627c41451bSDuncan P. N. Exon Smith case llvm::GlobalValue::AvailableExternallyLinkage: 8637c41451bSDuncan P. N. Exon Smith VarLinkage = llvm::GlobalValue::LinkOnceODRLinkage; 8647c41451bSDuncan P. N. Exon Smith break; 8657c41451bSDuncan P. N. Exon Smith default: 8667c41451bSDuncan P. N. Exon Smith break; 8677c41451bSDuncan P. N. Exon Smith } 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(); 873d971cd1bSDuncan P. N. Exon Smith } 874d66a17d0SJustin Bogner if (PGOData) { 875d66a17d0SJustin Bogner loadRegionCounts(PGOData); 876bf854f0fSBob Wilson computeRegionCounts(D); 877d66a17d0SJustin Bogner applyFunctionAttributes(PGOData, Fn); 878bf854f0fSBob Wilson } 879ef512b99SJustin Bogner } 880ef512b99SJustin Bogner 881ef512b99SJustin Bogner void CodeGenPGO::mapRegionCounters(const Decl *D) { 8821b67cfd4SDuncan P. N. Exon Smith RegionCounterMap.reset(new llvm::DenseMap<const Stmt *, unsigned>); 8833586be72SDuncan P. N. Exon Smith MapRegionCounters Walker(*RegionCounterMap); 884ef512b99SJustin Bogner if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) 885ef512b99SJustin Bogner Walker.VisitFunctionDecl(FD); 8865ec8fe19SBob Wilson else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D)) 8875ec8fe19SBob Wilson Walker.VisitObjCMethodDecl(MD); 888c845c00aSBob Wilson else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D)) 889c845c00aSBob Wilson Walker.VisitBlockDecl(BD); 890ef512b99SJustin Bogner NumRegionCounters = Walker.NextCounter; 891b4416f58SJustin Bogner // FIXME: The number of counters isn't sufficient for the hash 892b4416f58SJustin Bogner FunctionHash = NumRegionCounters; 893ef512b99SJustin Bogner } 894ef512b99SJustin Bogner 895bf854f0fSBob Wilson void CodeGenPGO::computeRegionCounts(const Decl *D) { 8961b67cfd4SDuncan P. N. Exon Smith StmtCountMap.reset(new llvm::DenseMap<const Stmt *, uint64_t>); 8973586be72SDuncan P. N. Exon Smith ComputeRegionCounts Walker(*StmtCountMap, *this); 898bf854f0fSBob Wilson if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(D)) 899bf854f0fSBob Wilson Walker.VisitFunctionDecl(FD); 9005ec8fe19SBob Wilson else if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D)) 9015ec8fe19SBob Wilson Walker.VisitObjCMethodDecl(MD); 902c845c00aSBob Wilson else if (const BlockDecl *BD = dyn_cast_or_null<BlockDecl>(D)) 903c845c00aSBob Wilson Walker.VisitBlockDecl(BD); 904bf854f0fSBob Wilson } 905bf854f0fSBob Wilson 906d66a17d0SJustin Bogner void CodeGenPGO::applyFunctionAttributes(PGOProfileData *PGOData, 9074c9c45c0SJustin Bogner llvm::Function *Fn) { 9084c9c45c0SJustin Bogner if (!haveRegionCounts()) 9094c9c45c0SJustin Bogner return; 9104c9c45c0SJustin Bogner 911d66a17d0SJustin Bogner uint64_t MaxFunctionCount = PGOData->getMaximumFunctionCount(); 9124c9c45c0SJustin Bogner uint64_t FunctionCount = getRegionCount(0); 9134c9c45c0SJustin Bogner if (FunctionCount >= (uint64_t)(0.3 * (double)MaxFunctionCount)) 9144c9c45c0SJustin Bogner // Turn on InlineHint attribute for hot functions. 9154c9c45c0SJustin Bogner // FIXME: 30% is from preliminary tuning on SPEC, it may not be optimal. 9164c9c45c0SJustin Bogner Fn->addFnAttr(llvm::Attribute::InlineHint); 9174c9c45c0SJustin Bogner else if (FunctionCount <= (uint64_t)(0.01 * (double)MaxFunctionCount)) 9184c9c45c0SJustin Bogner // Turn on Cold attribute for cold functions. 9194c9c45c0SJustin Bogner // FIXME: 1% is from preliminary tuning on SPEC, it may not be optimal. 9204c9c45c0SJustin Bogner Fn->addFnAttr(llvm::Attribute::Cold); 9214c9c45c0SJustin Bogner } 9224c9c45c0SJustin Bogner 923ef512b99SJustin Bogner void CodeGenPGO::emitCounterVariables() { 924ef512b99SJustin Bogner llvm::LLVMContext &Ctx = CGM.getLLVMContext(); 925ef512b99SJustin Bogner llvm::ArrayType *CounterTy = llvm::ArrayType::get(llvm::Type::getInt64Ty(Ctx), 926ef512b99SJustin Bogner NumRegionCounters); 927ef512b99SJustin Bogner RegionCounters = 92873f78627SDuncan P. N. Exon Smith new llvm::GlobalVariable(CGM.getModule(), CounterTy, false, VarLinkage, 929ef512b99SJustin Bogner llvm::Constant::getNullValue(CounterTy), 9302fe531cbSDuncan P. N. Exon Smith getFuncVarName("counters")); 9312fe531cbSDuncan P. N. Exon Smith RegionCounters->setAlignment(8); 9322fe531cbSDuncan P. N. Exon Smith RegionCounters->setSection(getCountersSection(CGM)); 933ef512b99SJustin Bogner } 934ef512b99SJustin Bogner 935ef512b99SJustin Bogner void CodeGenPGO::emitCounterIncrement(CGBuilderTy &Builder, unsigned Counter) { 936749ebc7fSBob Wilson if (!RegionCounters) 937ef512b99SJustin Bogner return; 938ef512b99SJustin Bogner llvm::Value *Addr = 939ef512b99SJustin Bogner Builder.CreateConstInBoundsGEP2_64(RegionCounters, 0, Counter); 940ef512b99SJustin Bogner llvm::Value *Count = Builder.CreateLoad(Addr, "pgocount"); 941ef512b99SJustin Bogner Count = Builder.CreateAdd(Count, Builder.getInt64(1)); 942ef512b99SJustin Bogner Builder.CreateStore(Count, Addr); 943ef512b99SJustin Bogner } 944ef512b99SJustin Bogner 945d66a17d0SJustin Bogner void CodeGenPGO::loadRegionCounts(PGOProfileData *PGOData) { 946ef512b99SJustin Bogner // For now, ignore the counts from the PGO data file only if the number of 947ef512b99SJustin Bogner // counters does not match. This could be tightened down in the future to 948ef512b99SJustin Bogner // ignore counts when the input changes in various ways, e.g., by comparing a 949ef512b99SJustin Bogner // hash value based on some characteristics of the input. 9501b67cfd4SDuncan P. N. Exon Smith RegionCounts.reset(new std::vector<uint64_t>); 951b4416f58SJustin Bogner uint64_t Hash; 952b4416f58SJustin Bogner if (PGOData->getFunctionCounts(getFuncName(), Hash, *RegionCounts) || 9531b67cfd4SDuncan P. N. Exon Smith Hash != FunctionHash || RegionCounts->size() != NumRegionCounters) 9541b67cfd4SDuncan P. N. Exon Smith RegionCounts.reset(); 955ef512b99SJustin Bogner } 956ef512b99SJustin Bogner 957ef512b99SJustin Bogner void CodeGenPGO::destroyRegionCounters() { 9581b67cfd4SDuncan P. N. Exon Smith RegionCounterMap.reset(); 9591b67cfd4SDuncan P. N. Exon Smith StmtCountMap.reset(); 9601b67cfd4SDuncan P. N. Exon Smith RegionCounts.reset(); 961ef512b99SJustin Bogner } 962ef512b99SJustin Bogner 96338402dc9SDuncan P. N. Exon Smith /// \brief Calculate what to divide by to scale weights. 96438402dc9SDuncan P. N. Exon Smith /// 96538402dc9SDuncan P. N. Exon Smith /// Given the maximum weight, calculate a divisor that will scale all the 96638402dc9SDuncan P. N. Exon Smith /// weights to strictly less than UINT32_MAX. 96738402dc9SDuncan P. N. Exon Smith static uint64_t calculateWeightScale(uint64_t MaxWeight) { 96838402dc9SDuncan P. N. Exon Smith return MaxWeight < UINT32_MAX ? 1 : MaxWeight / UINT32_MAX + 1; 96938402dc9SDuncan P. N. Exon Smith } 97038402dc9SDuncan P. N. Exon Smith 97138402dc9SDuncan P. N. Exon Smith /// \brief Scale an individual branch weight (and add 1). 97238402dc9SDuncan P. N. Exon Smith /// 97338402dc9SDuncan P. N. Exon Smith /// Scale a 64-bit weight down to 32-bits using \c Scale. 97438402dc9SDuncan P. N. Exon Smith /// 97538402dc9SDuncan P. N. Exon Smith /// According to Laplace's Rule of Succession, it is better to compute the 97638402dc9SDuncan P. N. Exon Smith /// weight based on the count plus 1, so universally add 1 to the value. 97738402dc9SDuncan P. N. Exon Smith /// 97838402dc9SDuncan P. N. Exon Smith /// \pre \c Scale was calculated by \a calculateWeightScale() with a weight no 97938402dc9SDuncan P. N. Exon Smith /// greater than \c Weight. 98038402dc9SDuncan P. N. Exon Smith static uint32_t scaleBranchWeight(uint64_t Weight, uint64_t Scale) { 98138402dc9SDuncan P. N. Exon Smith assert(Scale && "scale by 0?"); 98238402dc9SDuncan P. N. Exon Smith uint64_t Scaled = Weight / Scale + 1; 98338402dc9SDuncan P. N. Exon Smith assert(Scaled <= UINT32_MAX && "overflow 32-bits"); 98438402dc9SDuncan P. N. Exon Smith return Scaled; 98538402dc9SDuncan P. N. Exon Smith } 98638402dc9SDuncan P. N. Exon Smith 987ef512b99SJustin Bogner llvm::MDNode *CodeGenPGO::createBranchWeights(uint64_t TrueCount, 988ef512b99SJustin Bogner uint64_t FalseCount) { 98938402dc9SDuncan P. N. Exon Smith // Check for empty weights. 990ef512b99SJustin Bogner if (!TrueCount && !FalseCount) 991a5f804a7SDuncan P. N. Exon Smith return nullptr; 992ef512b99SJustin Bogner 99338402dc9SDuncan P. N. Exon Smith // Calculate how to scale down to 32-bits. 99438402dc9SDuncan P. N. Exon Smith uint64_t Scale = calculateWeightScale(std::max(TrueCount, FalseCount)); 99538402dc9SDuncan P. N. Exon Smith 996ef512b99SJustin Bogner llvm::MDBuilder MDHelper(CGM.getLLVMContext()); 99738402dc9SDuncan P. N. Exon Smith return MDHelper.createBranchWeights(scaleBranchWeight(TrueCount, Scale), 99838402dc9SDuncan P. N. Exon Smith scaleBranchWeight(FalseCount, Scale)); 999ef512b99SJustin Bogner } 1000ef512b99SJustin Bogner 100195a27b0eSBob Wilson llvm::MDNode *CodeGenPGO::createBranchWeights(ArrayRef<uint64_t> Weights) { 100238402dc9SDuncan P. N. Exon Smith // We need at least two elements to create meaningful weights. 100338402dc9SDuncan P. N. Exon Smith if (Weights.size() < 2) 1004a5f804a7SDuncan P. N. Exon Smith return nullptr; 100538402dc9SDuncan P. N. Exon Smith 1006f3aefca7SJustin Bogner // Check for empty weights. 1007f3aefca7SJustin Bogner uint64_t MaxWeight = *std::max_element(Weights.begin(), Weights.end()); 1008f3aefca7SJustin Bogner if (MaxWeight == 0) 1009f3aefca7SJustin Bogner return nullptr; 1010f3aefca7SJustin Bogner 101138402dc9SDuncan P. N. Exon Smith // Calculate how to scale down to 32-bits. 1012f3aefca7SJustin Bogner uint64_t Scale = calculateWeightScale(MaxWeight); 101338402dc9SDuncan P. N. Exon Smith 1014ef512b99SJustin Bogner SmallVector<uint32_t, 16> ScaledWeights; 1015ef512b99SJustin Bogner ScaledWeights.reserve(Weights.size()); 101638402dc9SDuncan P. N. Exon Smith for (uint64_t W : Weights) 101738402dc9SDuncan P. N. Exon Smith ScaledWeights.push_back(scaleBranchWeight(W, Scale)); 101838402dc9SDuncan P. N. Exon Smith 101938402dc9SDuncan P. N. Exon Smith llvm::MDBuilder MDHelper(CGM.getLLVMContext()); 1020ef512b99SJustin Bogner return MDHelper.createBranchWeights(ScaledWeights); 1021ef512b99SJustin Bogner } 1022bf854f0fSBob Wilson 1023bf854f0fSBob Wilson llvm::MDNode *CodeGenPGO::createLoopWeights(const Stmt *Cond, 1024bf854f0fSBob Wilson RegionCounter &Cnt) { 1025bf854f0fSBob Wilson if (!haveRegionCounts()) 1026a5f804a7SDuncan P. N. Exon Smith return nullptr; 1027bf854f0fSBob Wilson uint64_t LoopCount = Cnt.getCount(); 1028bf854f0fSBob Wilson uint64_t CondCount = 0; 1029bf854f0fSBob Wilson bool Found = getStmtCount(Cond, CondCount); 1030bf854f0fSBob Wilson assert(Found && "missing expected loop condition count"); 1031bf854f0fSBob Wilson (void)Found; 1032bf854f0fSBob Wilson if (CondCount == 0) 1033a5f804a7SDuncan P. N. Exon Smith return nullptr; 1034bf854f0fSBob Wilson return createBranchWeights(LoopCount, 1035bf854f0fSBob Wilson std::max(CondCount, LoopCount) - LoopCount); 1036bf854f0fSBob Wilson } 1037