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