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