12f09f445SMaksim Panchenko //===- bolt/Profile/YAMLProfileReader.cpp - YAML profile de-serializer ----===// 2a34c753fSRafael Auler // 3a34c753fSRafael Auler // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a34c753fSRafael Auler // See https://llvm.org/LICENSE.txt for license information. 5a34c753fSRafael Auler // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a34c753fSRafael Auler // 7a34c753fSRafael Auler //===----------------------------------------------------------------------===// 8a34c753fSRafael Auler 9a34c753fSRafael Auler #include "bolt/Profile/YAMLProfileReader.h" 10a34c753fSRafael Auler #include "bolt/Core/BinaryBasicBlock.h" 11a34c753fSRafael Auler #include "bolt/Core/BinaryFunction.h" 12a34c753fSRafael Auler #include "bolt/Passes/MCF.h" 13a34c753fSRafael Auler #include "bolt/Profile/ProfileYAMLMapping.h" 14a34c753fSRafael Auler #include "bolt/Utils/Utils.h" 15a34c753fSRafael Auler #include "llvm/Support/CommandLine.h" 16a34c753fSRafael Auler 17a34c753fSRafael Auler using namespace llvm; 18a34c753fSRafael Auler 19a34c753fSRafael Auler namespace opts { 20a34c753fSRafael Auler 21a34c753fSRafael Auler extern cl::opt<unsigned> Verbosity; 22a34c753fSRafael Auler extern cl::OptionCategory BoltOptCategory; 23a34c753fSRafael Auler 24a34c753fSRafael Auler static llvm::cl::opt<bool> 25a34c753fSRafael Auler IgnoreHash("profile-ignore-hash", 26a34c753fSRafael Auler cl::desc("ignore hash while reading function profile"), 27a34c753fSRafael Auler cl::init(false), 28a34c753fSRafael Auler cl::ZeroOrMore, 29a34c753fSRafael Auler cl::Hidden, 30a34c753fSRafael Auler cl::cat(BoltOptCategory)); 31a34c753fSRafael Auler 32a34c753fSRafael Auler } 33a34c753fSRafael Auler 34a34c753fSRafael Auler namespace llvm { 35a34c753fSRafael Auler namespace bolt { 36a34c753fSRafael Auler 37a34c753fSRafael Auler bool YAMLProfileReader::isYAML(const StringRef Filename) { 38a34c753fSRafael Auler ErrorOr<std::unique_ptr<MemoryBuffer>> MB = 39a34c753fSRafael Auler MemoryBuffer::getFileOrSTDIN(Filename); 40a34c753fSRafael Auler if (std::error_code EC = MB.getError()) 41a34c753fSRafael Auler report_error(Filename, EC); 42a34c753fSRafael Auler StringRef Buffer = MB.get()->getBuffer(); 43a34c753fSRafael Auler if (Buffer.startswith("---\n")) 44a34c753fSRafael Auler return true; 45a34c753fSRafael Auler return false; 46a34c753fSRafael Auler } 47a34c753fSRafael Auler 48a34c753fSRafael Auler void YAMLProfileReader::buildNameMaps( 49a34c753fSRafael Auler std::map<uint64_t, BinaryFunction> &Functions) { 50a34c753fSRafael Auler for (yaml::bolt::BinaryFunctionProfile &YamlBF : YamlBP.Functions) { 51a34c753fSRafael Auler StringRef Name = YamlBF.Name; 52a34c753fSRafael Auler const size_t Pos = Name.find("(*"); 53a34c753fSRafael Auler if (Pos != StringRef::npos) 54a34c753fSRafael Auler Name = Name.substr(0, Pos); 55a34c753fSRafael Auler ProfileNameToProfile[Name] = &YamlBF; 56*def464aaSAmir Ayupov if (const Optional<StringRef> CommonName = getLTOCommonName(Name)) 57a34c753fSRafael Auler LTOCommonNameMap[*CommonName].push_back(&YamlBF); 58a34c753fSRafael Auler } 59a34c753fSRafael Auler for (auto &BFI : Functions) { 60a34c753fSRafael Auler const BinaryFunction &Function = BFI.second; 61*def464aaSAmir Ayupov for (StringRef Name : Function.getNames()) 62*def464aaSAmir Ayupov if (const Optional<StringRef> CommonName = getLTOCommonName(Name)) 63a34c753fSRafael Auler LTOCommonNameFunctionMap[*CommonName].insert(&Function); 64a34c753fSRafael Auler } 65a34c753fSRafael Auler } 66a34c753fSRafael Auler 67a34c753fSRafael Auler bool YAMLProfileReader::hasLocalsWithFileName() const { 68a34c753fSRafael Auler for (const StringMapEntry<yaml::bolt::BinaryFunctionProfile *> &KV : 69a34c753fSRafael Auler ProfileNameToProfile) { 70a34c753fSRafael Auler const StringRef &FuncName = KV.getKey(); 71a34c753fSRafael Auler if (FuncName.count('/') == 2 && FuncName[0] != '/') 72a34c753fSRafael Auler return true; 73a34c753fSRafael Auler } 74a34c753fSRafael Auler return false; 75a34c753fSRafael Auler } 76a34c753fSRafael Auler 77a34c753fSRafael Auler bool YAMLProfileReader::parseFunctionProfile( 7840c2e0faSMaksim Panchenko BinaryFunction &BF, const yaml::bolt::BinaryFunctionProfile &YamlBF) { 79a34c753fSRafael Auler BinaryContext &BC = BF.getBinaryContext(); 80a34c753fSRafael Auler 81a34c753fSRafael Auler bool ProfileMatched = true; 82a34c753fSRafael Auler uint64_t MismatchedBlocks = 0; 83a34c753fSRafael Auler uint64_t MismatchedCalls = 0; 84a34c753fSRafael Auler uint64_t MismatchedEdges = 0; 85a34c753fSRafael Auler 86a34c753fSRafael Auler uint64_t FunctionExecutionCount = 0; 87a34c753fSRafael Auler 88a34c753fSRafael Auler BF.setExecutionCount(YamlBF.ExecCount); 89a34c753fSRafael Auler 90a34c753fSRafael Auler if (!opts::IgnoreHash && YamlBF.Hash != BF.computeHash(/*UseDFS=*/true)) { 91a34c753fSRafael Auler if (opts::Verbosity >= 1) 92a34c753fSRafael Auler errs() << "BOLT-WARNING: function hash mismatch\n"; 93a34c753fSRafael Auler ProfileMatched = false; 94a34c753fSRafael Auler } 95a34c753fSRafael Auler 96a34c753fSRafael Auler if (YamlBF.NumBasicBlocks != BF.size()) { 97a34c753fSRafael Auler if (opts::Verbosity >= 1) 98a34c753fSRafael Auler errs() << "BOLT-WARNING: number of basic blocks mismatch\n"; 99a34c753fSRafael Auler ProfileMatched = false; 100a34c753fSRafael Auler } 101a34c753fSRafael Auler 102ebe51c4dSMaksim Panchenko BinaryFunction::BasicBlockOrderType DFSOrder = BF.dfs(); 103a34c753fSRafael Auler 104a34c753fSRafael Auler for (const yaml::bolt::BinaryBasicBlockProfile &YamlBB : YamlBF.Blocks) { 105a34c753fSRafael Auler if (YamlBB.Index >= DFSOrder.size()) { 106a34c753fSRafael Auler if (opts::Verbosity >= 2) 107a34c753fSRafael Auler errs() << "BOLT-WARNING: index " << YamlBB.Index 108a34c753fSRafael Auler << " is out of bounds\n"; 109a34c753fSRafael Auler ++MismatchedBlocks; 110a34c753fSRafael Auler continue; 111a34c753fSRafael Auler } 112a34c753fSRafael Auler 113a34c753fSRafael Auler BinaryBasicBlock &BB = *DFSOrder[YamlBB.Index]; 114a34c753fSRafael Auler 115a34c753fSRafael Auler // Basic samples profile (without LBR) does not have branches information 116a34c753fSRafael Auler // and needs a special processing. 117a34c753fSRafael Auler if (YamlBP.Header.Flags & BinaryFunction::PF_SAMPLE) { 118a34c753fSRafael Auler if (!YamlBB.EventCount) { 119a34c753fSRafael Auler BB.setExecutionCount(0); 120a34c753fSRafael Auler continue; 121a34c753fSRafael Auler } 122a34c753fSRafael Auler uint64_t NumSamples = YamlBB.EventCount * 1000; 123*def464aaSAmir Ayupov if (NormalizeByInsnCount && BB.getNumNonPseudos()) 124a34c753fSRafael Auler NumSamples /= BB.getNumNonPseudos(); 125*def464aaSAmir Ayupov else if (NormalizeByCalls) 126a34c753fSRafael Auler NumSamples /= BB.getNumCalls() + 1; 127*def464aaSAmir Ayupov 128a34c753fSRafael Auler BB.setExecutionCount(NumSamples); 129a34c753fSRafael Auler if (BB.isEntryPoint()) 130a34c753fSRafael Auler FunctionExecutionCount += NumSamples; 131a34c753fSRafael Auler continue; 132a34c753fSRafael Auler } 133a34c753fSRafael Auler 134a34c753fSRafael Auler BB.setExecutionCount(YamlBB.ExecCount); 135a34c753fSRafael Auler 136a34c753fSRafael Auler for (const yaml::bolt::CallSiteInfo &YamlCSI : YamlBB.CallSites) { 137a34c753fSRafael Auler BinaryFunction *Callee = YamlCSI.DestId < YamlProfileToFunction.size() 138a34c753fSRafael Auler ? YamlProfileToFunction[YamlCSI.DestId] 139a34c753fSRafael Auler : nullptr; 140a34c753fSRafael Auler bool IsFunction = Callee ? true : false; 141a34c753fSRafael Auler MCSymbol *CalleeSymbol = nullptr; 142*def464aaSAmir Ayupov if (IsFunction) 143a34c753fSRafael Auler CalleeSymbol = Callee->getSymbolForEntryID(YamlCSI.EntryDiscriminator); 144*def464aaSAmir Ayupov 14540c2e0faSMaksim Panchenko BF.getAllCallSites().emplace_back(CalleeSymbol, YamlCSI.Count, 14640c2e0faSMaksim Panchenko YamlCSI.Mispreds, YamlCSI.Offset); 147a34c753fSRafael Auler 148a34c753fSRafael Auler if (YamlCSI.Offset >= BB.getOriginalSize()) { 149a34c753fSRafael Auler if (opts::Verbosity >= 2) 150a34c753fSRafael Auler errs() << "BOLT-WARNING: offset " << YamlCSI.Offset 151a34c753fSRafael Auler << " out of bounds in block " << BB.getName() << '\n'; 152a34c753fSRafael Auler ++MismatchedCalls; 153a34c753fSRafael Auler continue; 154a34c753fSRafael Auler } 155a34c753fSRafael Auler 156a34c753fSRafael Auler MCInst *Instr = 157a34c753fSRafael Auler BF.getInstructionAtOffset(BB.getInputOffset() + YamlCSI.Offset); 158a34c753fSRafael Auler if (!Instr) { 159a34c753fSRafael Auler if (opts::Verbosity >= 2) 160a34c753fSRafael Auler errs() << "BOLT-WARNING: no instruction at offset " << YamlCSI.Offset 161a34c753fSRafael Auler << " in block " << BB.getName() << '\n'; 162a34c753fSRafael Auler ++MismatchedCalls; 163a34c753fSRafael Auler continue; 164a34c753fSRafael Auler } 165a34c753fSRafael Auler if (!BC.MIB->isCall(*Instr) && !BC.MIB->isIndirectBranch(*Instr)) { 166a34c753fSRafael Auler if (opts::Verbosity >= 2) 167a34c753fSRafael Auler errs() << "BOLT-WARNING: expected call at offset " << YamlCSI.Offset 168a34c753fSRafael Auler << " in block " << BB.getName() << '\n'; 169a34c753fSRafael Auler ++MismatchedCalls; 170a34c753fSRafael Auler continue; 171a34c753fSRafael Auler } 172a34c753fSRafael Auler 173a34c753fSRafael Auler auto setAnnotation = [&](StringRef Name, uint64_t Count) { 174a34c753fSRafael Auler if (BC.MIB->hasAnnotation(*Instr, Name)) { 175a34c753fSRafael Auler if (opts::Verbosity >= 1) 176a34c753fSRafael Auler errs() << "BOLT-WARNING: ignoring duplicate " << Name 177a34c753fSRafael Auler << " info for offset 0x" << Twine::utohexstr(YamlCSI.Offset) 178a34c753fSRafael Auler << " in function " << BF << '\n'; 179a34c753fSRafael Auler return; 180a34c753fSRafael Auler } 181a34c753fSRafael Auler BC.MIB->addAnnotation(*Instr, Name, Count); 182a34c753fSRafael Auler }; 183a34c753fSRafael Auler 184a34c753fSRafael Auler if (BC.MIB->isIndirectCall(*Instr) || BC.MIB->isIndirectBranch(*Instr)) { 185a34c753fSRafael Auler auto &CSP = BC.MIB->getOrCreateAnnotationAs<IndirectCallSiteProfile>( 186a34c753fSRafael Auler *Instr, "CallProfile"); 187a34c753fSRafael Auler CSP.emplace_back(CalleeSymbol, YamlCSI.Count, YamlCSI.Mispreds); 188a34c753fSRafael Auler } else if (BC.MIB->getConditionalTailCall(*Instr)) { 189a34c753fSRafael Auler setAnnotation("CTCTakenCount", YamlCSI.Count); 190a34c753fSRafael Auler setAnnotation("CTCMispredCount", YamlCSI.Mispreds); 191a34c753fSRafael Auler } else { 192a34c753fSRafael Auler setAnnotation("Count", YamlCSI.Count); 193a34c753fSRafael Auler } 194a34c753fSRafael Auler } 195a34c753fSRafael Auler 196a34c753fSRafael Auler for (const yaml::bolt::SuccessorInfo &YamlSI : YamlBB.Successors) { 197a34c753fSRafael Auler if (YamlSI.Index >= DFSOrder.size()) { 198a34c753fSRafael Auler if (opts::Verbosity >= 1) 199a34c753fSRafael Auler errs() << "BOLT-WARNING: index out of bounds for profiled block\n"; 200a34c753fSRafael Auler ++MismatchedEdges; 201a34c753fSRafael Auler continue; 202a34c753fSRafael Auler } 203a34c753fSRafael Auler 204a34c753fSRafael Auler BinaryBasicBlock &SuccessorBB = *DFSOrder[YamlSI.Index]; 205a34c753fSRafael Auler if (!BB.getSuccessor(SuccessorBB.getLabel())) { 206a34c753fSRafael Auler if (opts::Verbosity >= 1) 207a34c753fSRafael Auler errs() << "BOLT-WARNING: no successor for block " << BB.getName() 208a34c753fSRafael Auler << " that matches index " << YamlSI.Index << " or block " 209a34c753fSRafael Auler << SuccessorBB.getName() << '\n'; 210a34c753fSRafael Auler ++MismatchedEdges; 211a34c753fSRafael Auler continue; 212a34c753fSRafael Auler } 213a34c753fSRafael Auler 214a34c753fSRafael Auler BinaryBasicBlock::BinaryBranchInfo &BI = BB.getBranchInfo(SuccessorBB); 215a34c753fSRafael Auler BI.Count += YamlSI.Count; 216a34c753fSRafael Auler BI.MispredictedCount += YamlSI.Mispreds; 217a34c753fSRafael Auler } 218a34c753fSRafael Auler } 219a34c753fSRafael Auler 220a34c753fSRafael Auler // If basic block profile wasn't read it should be 0. 221*def464aaSAmir Ayupov for (BinaryBasicBlock &BB : BF) 222a34c753fSRafael Auler if (BB.getExecutionCount() == BinaryBasicBlock::COUNT_NO_PROFILE) 223a34c753fSRafael Auler BB.setExecutionCount(0); 224a34c753fSRafael Auler 225a34c753fSRafael Auler if (YamlBP.Header.Flags & BinaryFunction::PF_SAMPLE) { 226a34c753fSRafael Auler BF.setExecutionCount(FunctionExecutionCount); 227a34c753fSRafael Auler estimateEdgeCounts(BF); 228a34c753fSRafael Auler } 229a34c753fSRafael Auler 230a34c753fSRafael Auler ProfileMatched &= !MismatchedBlocks && !MismatchedCalls && !MismatchedEdges; 231a34c753fSRafael Auler 232a34c753fSRafael Auler if (ProfileMatched) 233a34c753fSRafael Auler BF.markProfiled(YamlBP.Header.Flags); 234a34c753fSRafael Auler 235*def464aaSAmir Ayupov if (!ProfileMatched && opts::Verbosity >= 1) 236a34c753fSRafael Auler errs() << "BOLT-WARNING: " << MismatchedBlocks << " blocks, " 237a34c753fSRafael Auler << MismatchedCalls << " calls, and " << MismatchedEdges 238a34c753fSRafael Auler << " edges in profile did not match function " << BF << '\n'; 239a34c753fSRafael Auler 240a34c753fSRafael Auler return ProfileMatched; 241a34c753fSRafael Auler } 242a34c753fSRafael Auler 243a34c753fSRafael Auler Error YAMLProfileReader::preprocessProfile(BinaryContext &BC) { 244a34c753fSRafael Auler ErrorOr<std::unique_ptr<MemoryBuffer>> MB = 245a34c753fSRafael Auler MemoryBuffer::getFileOrSTDIN(Filename); 246a34c753fSRafael Auler if (std::error_code EC = MB.getError()) { 247a34c753fSRafael Auler errs() << "ERROR: cannot open " << Filename << ": " << EC.message() << "\n"; 248a34c753fSRafael Auler return errorCodeToError(EC); 249a34c753fSRafael Auler } 250a34c753fSRafael Auler yaml::Input YamlInput(MB.get()->getBuffer()); 251a34c753fSRafael Auler 252a34c753fSRafael Auler // Consume YAML file. 253a34c753fSRafael Auler YamlInput >> YamlBP; 254a34c753fSRafael Auler if (YamlInput.error()) { 255a34c753fSRafael Auler errs() << "BOLT-ERROR: syntax error parsing profile in " << Filename 256a34c753fSRafael Auler << " : " << YamlInput.error().message() << '\n'; 257a34c753fSRafael Auler return errorCodeToError(YamlInput.error()); 258a34c753fSRafael Auler } 259a34c753fSRafael Auler 260a34c753fSRafael Auler // Sanity check. 261*def464aaSAmir Ayupov if (YamlBP.Header.Version != 1) 262a34c753fSRafael Auler return make_error<StringError>( 263a34c753fSRafael Auler Twine("cannot read profile : unsupported version"), 264a34c753fSRafael Auler inconvertibleErrorCode()); 265*def464aaSAmir Ayupov 266*def464aaSAmir Ayupov if (YamlBP.Header.EventNames.find(',') != StringRef::npos) 267a34c753fSRafael Auler return make_error<StringError>( 268a34c753fSRafael Auler Twine("multiple events in profile are not supported"), 269a34c753fSRafael Auler inconvertibleErrorCode()); 270a34c753fSRafael Auler 271a34c753fSRafael Auler // Match profile to function based on a function name. 272a34c753fSRafael Auler buildNameMaps(BC.getBinaryFunctions()); 273a34c753fSRafael Auler 274a34c753fSRafael Auler // Preliminary assign function execution count. 275a34c753fSRafael Auler for (auto &KV : BC.getBinaryFunctions()) { 276a34c753fSRafael Auler BinaryFunction &BF = KV.second; 277a34c753fSRafael Auler for (StringRef Name : BF.getNames()) { 278a34c753fSRafael Auler auto PI = ProfileNameToProfile.find(Name); 279a34c753fSRafael Auler if (PI != ProfileNameToProfile.end()) { 280a34c753fSRafael Auler yaml::bolt::BinaryFunctionProfile &YamlBF = *PI->getValue(); 281a34c753fSRafael Auler BF.setExecutionCount(YamlBF.ExecCount); 282a34c753fSRafael Auler break; 283a34c753fSRafael Auler } 284a34c753fSRafael Auler } 285a34c753fSRafael Auler } 286a34c753fSRafael Auler 287a34c753fSRafael Auler return Error::success(); 288a34c753fSRafael Auler } 289a34c753fSRafael Auler 290a34c753fSRafael Auler bool YAMLProfileReader::mayHaveProfileData(const BinaryFunction &BF) { 291a34c753fSRafael Auler for (StringRef Name : BF.getNames()) { 292a34c753fSRafael Auler if (ProfileNameToProfile.find(Name) != ProfileNameToProfile.end()) 293a34c753fSRafael Auler return true; 294a34c753fSRafael Auler if (const Optional<StringRef> CommonName = getLTOCommonName(Name)) { 295*def464aaSAmir Ayupov if (LTOCommonNameMap.find(*CommonName) != LTOCommonNameMap.end()) 296a34c753fSRafael Auler return true; 297a34c753fSRafael Auler } 298a34c753fSRafael Auler } 299a34c753fSRafael Auler 300a34c753fSRafael Auler return false; 301a34c753fSRafael Auler } 302a34c753fSRafael Auler 303a34c753fSRafael Auler Error YAMLProfileReader::readProfile(BinaryContext &BC) { 304a34c753fSRafael Auler YamlProfileToFunction.resize(YamlBP.Functions.size() + 1); 305a34c753fSRafael Auler 306a34c753fSRafael Auler auto profileMatches = [](const yaml::bolt::BinaryFunctionProfile &Profile, 307a34c753fSRafael Auler BinaryFunction &BF) { 308a34c753fSRafael Auler if (opts::IgnoreHash && Profile.NumBasicBlocks == BF.size()) 309a34c753fSRafael Auler return true; 310a34c753fSRafael Auler if (!opts::IgnoreHash && 311a34c753fSRafael Auler Profile.Hash == static_cast<uint64_t>(BF.getHash())) 312a34c753fSRafael Auler return true; 313a34c753fSRafael Auler return false; 314a34c753fSRafael Auler }; 315a34c753fSRafael Auler 316a34c753fSRafael Auler // We have to do 2 passes since LTO introduces an ambiguity in function 317a34c753fSRafael Auler // names. The first pass assigns profiles that match 100% by name and 318a34c753fSRafael Auler // by hash. The second pass allows name ambiguity for LTO private functions. 319a34c753fSRafael Auler for (auto &BFI : BC.getBinaryFunctions()) { 320a34c753fSRafael Auler BinaryFunction &Function = BFI.second; 321a34c753fSRafael Auler 322a34c753fSRafael Auler // Clear function call count that may have been set while pre-processing 323a34c753fSRafael Auler // the profile. 324a34c753fSRafael Auler Function.setExecutionCount(BinaryFunction::COUNT_NO_PROFILE); 325a34c753fSRafael Auler 326a34c753fSRafael Auler // Recompute hash once per function. 327a34c753fSRafael Auler if (!opts::IgnoreHash) 328a34c753fSRafael Auler Function.computeHash(/*UseDFS=*/true); 329a34c753fSRafael Auler 330a34c753fSRafael Auler for (StringRef FunctionName : Function.getNames()) { 331a34c753fSRafael Auler auto PI = ProfileNameToProfile.find(FunctionName); 332*def464aaSAmir Ayupov if (PI == ProfileNameToProfile.end()) 333a34c753fSRafael Auler continue; 334*def464aaSAmir Ayupov 335a34c753fSRafael Auler yaml::bolt::BinaryFunctionProfile &YamlBF = *PI->getValue(); 336a34c753fSRafael Auler if (profileMatches(YamlBF, Function)) 337a34c753fSRafael Auler matchProfileToFunction(YamlBF, Function); 338a34c753fSRafael Auler } 339a34c753fSRafael Auler } 340a34c753fSRafael Auler 341a34c753fSRafael Auler for (auto &BFI : BC.getBinaryFunctions()) { 342a34c753fSRafael Auler BinaryFunction &Function = BFI.second; 343a34c753fSRafael Auler 344a34c753fSRafael Auler if (ProfiledFunctions.count(&Function)) 345a34c753fSRafael Auler continue; 346a34c753fSRafael Auler 347a34c753fSRafael Auler for (StringRef FunctionName : Function.getNames()) { 348a34c753fSRafael Auler const Optional<StringRef> CommonName = getLTOCommonName(FunctionName); 349a34c753fSRafael Auler if (CommonName) { 350a34c753fSRafael Auler auto I = LTOCommonNameMap.find(*CommonName); 351a34c753fSRafael Auler if (I == LTOCommonNameMap.end()) 352a34c753fSRafael Auler continue; 353a34c753fSRafael Auler 354a34c753fSRafael Auler bool ProfileMatched = false; 355a34c753fSRafael Auler std::vector<yaml::bolt::BinaryFunctionProfile *> <OProfiles = 356a34c753fSRafael Auler I->getValue(); 357a34c753fSRafael Auler for (yaml::bolt::BinaryFunctionProfile *YamlBF : LTOProfiles) { 358a34c753fSRafael Auler if (YamlBF->Used) 359a34c753fSRafael Auler continue; 360a34c753fSRafael Auler if ((ProfileMatched = profileMatches(*YamlBF, Function))) { 361a34c753fSRafael Auler matchProfileToFunction(*YamlBF, Function); 362a34c753fSRafael Auler break; 363a34c753fSRafael Auler } 364a34c753fSRafael Auler } 365a34c753fSRafael Auler if (ProfileMatched) 366a34c753fSRafael Auler break; 367a34c753fSRafael Auler 368a34c753fSRafael Auler // If there's only one function with a given name, try to 369a34c753fSRafael Auler // match it partially. 370a34c753fSRafael Auler if (LTOProfiles.size() == 1 && 371a34c753fSRafael Auler LTOCommonNameFunctionMap[*CommonName].size() == 1 && 372a34c753fSRafael Auler !LTOProfiles.front()->Used) { 373a34c753fSRafael Auler matchProfileToFunction(*LTOProfiles.front(), Function); 374a34c753fSRafael Auler break; 375a34c753fSRafael Auler } 376a34c753fSRafael Auler } else { 377a34c753fSRafael Auler auto PI = ProfileNameToProfile.find(FunctionName); 378a34c753fSRafael Auler if (PI == ProfileNameToProfile.end()) 379a34c753fSRafael Auler continue; 380a34c753fSRafael Auler 381a34c753fSRafael Auler yaml::bolt::BinaryFunctionProfile &YamlBF = *PI->getValue(); 382a34c753fSRafael Auler if (!YamlBF.Used) { 383a34c753fSRafael Auler matchProfileToFunction(YamlBF, Function); 384a34c753fSRafael Auler break; 385a34c753fSRafael Auler } 386a34c753fSRafael Auler } 387a34c753fSRafael Auler } 388a34c753fSRafael Auler } 389a34c753fSRafael Auler 390*def464aaSAmir Ayupov for (yaml::bolt::BinaryFunctionProfile &YamlBF : YamlBP.Functions) 391*def464aaSAmir Ayupov if (!YamlBF.Used && opts::Verbosity >= 1) 392a34c753fSRafael Auler errs() << "BOLT-WARNING: profile ignored for function " << YamlBF.Name 393a34c753fSRafael Auler << '\n'; 394a34c753fSRafael Auler 395a34c753fSRafael Auler // Set for parseFunctionProfile(). 396a34c753fSRafael Auler NormalizeByInsnCount = usesEvent("cycles") || usesEvent("instructions"); 397a34c753fSRafael Auler NormalizeByCalls = usesEvent("branches"); 398a34c753fSRafael Auler 399a34c753fSRafael Auler uint64_t NumUnused = 0; 400a34c753fSRafael Auler for (yaml::bolt::BinaryFunctionProfile &YamlBF : YamlBP.Functions) { 401a34c753fSRafael Auler if (YamlBF.Id >= YamlProfileToFunction.size()) { 402a34c753fSRafael Auler // Such profile was ignored. 403a34c753fSRafael Auler ++NumUnused; 404a34c753fSRafael Auler continue; 405a34c753fSRafael Auler } 406*def464aaSAmir Ayupov if (BinaryFunction *BF = YamlProfileToFunction[YamlBF.Id]) 407a34c753fSRafael Auler parseFunctionProfile(*BF, YamlBF); 408*def464aaSAmir Ayupov else 409a34c753fSRafael Auler ++NumUnused; 410a34c753fSRafael Auler } 411a34c753fSRafael Auler 412a34c753fSRafael Auler BC.setNumUnusedProfiledObjects(NumUnused); 413a34c753fSRafael Auler 414a34c753fSRafael Auler return Error::success(); 415a34c753fSRafael Auler } 416a34c753fSRafael Auler 417a34c753fSRafael Auler bool YAMLProfileReader::usesEvent(StringRef Name) const { 418a34c753fSRafael Auler return YamlBP.Header.EventNames.find(std::string(Name)) != StringRef::npos; 419a34c753fSRafael Auler } 420a34c753fSRafael Auler 421a34c753fSRafael Auler } // end namespace bolt 422a34c753fSRafael Auler } // end namespace llvm 423