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