LLVM 24.0.0git
SampleProfileMatcher.cpp
Go to the documentation of this file.
1//===- SampleProfileMatcher.cpp - Sampling-based Stale Profile Matcher ----===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file implements the SampleProfileMatcher used for stale
10// profile matching.
11//
12//===----------------------------------------------------------------------===//
13
15#include "IPOOptions.h"
16#include "llvm/ADT/STLExtras.h"
17#include "llvm/ADT/Statistic.h"
20#include "llvm/IR/MDBuilder.h"
22
23using namespace llvm;
24using namespace sampleprof;
25
26#define DEBUG_TYPE "sample-profile-matcher"
27
28STATISTIC(NumDirectProfileMatch,
29 "Number of functions matched by demangled basename");
30
31namespace llvm {
32
33
34} // end namespace llvm
35
36void SampleProfileMatcher::findIRAnchors(const Function &F,
37 AnchorMap &IRAnchors) const {
38 // For inlined code, recover the original callsite and callee by finding the
39 // top-level inline frame. e.g. For frame stack "main:1 @ foo:2 @ bar:3", the
40 // top-level frame is "main:1", the callsite is "1" and the callee is "foo".
41 auto FindTopLevelInlinedCallsite = [](const DILocation *DIL) {
42 assert((DIL && DIL->getInlinedAt()) && "No inlined callsite");
43 const DILocation *PrevDIL = nullptr;
44 do {
45 PrevDIL = DIL;
46 DIL = DIL->getInlinedAt();
47 } while (DIL->getInlinedAt());
48
49 LineLocation Callsite = FunctionSamples::getCallSiteIdentifier(
51 StringRef CalleeName = PrevDIL->getSubprogramLinkageName();
52 return std::make_pair(Callsite, FunctionId(CalleeName));
53 };
54
55 auto GetCanonicalCalleeName = [](const CallBase *CB) {
56 StringRef CalleeName = UnknownIndirectCallee;
57 if (Function *Callee = CB->getCalledFunction())
58 CalleeName = FunctionSamples::getCanonicalFnName(Callee->getName());
59 return CalleeName;
60 };
61
62 // Extract profile matching anchors in the IR.
63 for (auto &BB : F) {
64 for (auto &I : BB) {
65 DILocation *DIL = I.getDebugLoc();
66 if (!DIL)
67 continue;
68
70 if (auto Probe = extractProbe(I)) {
71 // Flatten inlined IR for the matching.
72 if (DIL->getInlinedAt()) {
73 IRAnchors.emplace(FindTopLevelInlinedCallsite(DIL));
74 } else {
75 // Use empty StringRef for basic block probe.
76 StringRef CalleeName;
77 if (const auto *CB = dyn_cast<CallBase>(&I)) {
78 // Skip the probe inst whose callee name is "llvm.pseudoprobe".
79 if (!isa<IntrinsicInst>(&I))
80 CalleeName = GetCanonicalCalleeName(CB);
81 }
82 LineLocation Loc = LineLocation(Probe->Id, 0);
83 IRAnchors.emplace(Loc, FunctionId(CalleeName));
84 }
85 }
86 } else {
87 // TODO: For line-number based profile(AutoFDO), currently only support
88 // find callsite anchors. In future, we need to parse all the non-call
89 // instructions to extract the line locations for profile matching.
91 continue;
92
93 if (DIL->getInlinedAt()) {
94 IRAnchors.emplace(FindTopLevelInlinedCallsite(DIL));
95 } else {
96 LineLocation Callsite = FunctionSamples::getCallSiteIdentifier(
98 StringRef CalleeName = GetCanonicalCalleeName(dyn_cast<CallBase>(&I));
99 IRAnchors.emplace(Callsite, FunctionId(CalleeName));
100 }
101 }
102 }
103 }
104}
105
106void SampleProfileMatcher::findProfileAnchors(const FunctionSamples &FS,
107 AnchorMap &ProfileAnchors) const {
108 auto isInvalidLineOffset = [](uint32_t LineOffset) {
109 return LineOffset & 0x8000;
110 };
111
112 auto InsertAnchor = [](const LineLocation &Loc, const FunctionId &CalleeName,
113 AnchorMap &ProfileAnchors) {
114 auto Ret = ProfileAnchors.try_emplace(Loc, CalleeName);
115 if (!Ret.second) {
116 // For multiple callees, which indicates it's an indirect call, we use a
117 // dummy name(UnknownIndirectCallee) as the indrect callee name.
118 Ret.first->second = FunctionId(UnknownIndirectCallee);
119 }
120 };
121
122 for (const auto &I : FS.getBodySamples()) {
123 const LineLocation &Loc = I.first;
124 if (isInvalidLineOffset(Loc.LineOffset))
125 continue;
126
127 const auto &CallTargets = I.second.getCallTargets();
128 const bool HasSampledTarget =
129 llvm::any_of(CallTargets, [](const auto &C) { return C.second != 0; });
130 for (const auto &C : CallTargets) {
131 // Zero-count targets remain meaningful in the profile, but should not
132 // obscure a uniquely sampled callee when choosing a matching anchor.
133 // Ignore them here when sampled targets exist; retain all-zero locations.
134 if (HasSampledTarget && C.second == 0)
135 continue;
136 InsertAnchor(Loc, C.first, ProfileAnchors);
137 }
138 }
139
140 for (const auto &I : FS.getCallsiteSamples()) {
141 const LineLocation &Loc = I.first;
142 if (isInvalidLineOffset(Loc.LineOffset))
143 continue;
144
145 const auto &Callees = I.second;
146 const bool HasSampledCallee = llvm::any_of(
147 Callees, [](const auto &C) { return C.second.getTotalSamples() != 0; });
148 for (const auto &C : Callees) {
149 // Apply the same anchor selection policy to inline callees, preserving
150 // zero-sample frames in the profile.
151 if (HasSampledCallee && C.second.getTotalSamples() == 0)
152 continue;
153 InsertAnchor(Loc, C.first, ProfileAnchors);
154 }
155 }
156}
157
158bool SampleProfileMatcher::anchorsMatch(const FunctionId &IRAnchor,
159 const FunctionId &ProfileAnchor) const {
160 // Check whether the callees at an already-aligned location are compatible.
161 // An indirect IR call has no statically known callee, so any profiled target
162 // is compatible. The reverse is not true: multiple sampled profile targets
163 // cannot match a direct IR call. This is only a compatibility test; an
164 // indirect anchor carries no callee identity and must not be used to
165 // establish the location alignment itself.
166 return IRAnchor == ProfileAnchor ||
167 IRAnchor == FunctionId(UnknownIndirectCallee);
168}
169
170bool SampleProfileMatcher::functionHasProfile(const FunctionId &IRFuncName,
171 Function *&FuncWithoutProfile) {
172 FuncWithoutProfile = nullptr;
173 auto R = FunctionsWithoutProfile.find(IRFuncName);
174 if (R != FunctionsWithoutProfile.end())
175 FuncWithoutProfile = R->second;
176 return !FuncWithoutProfile;
177}
178
179bool SampleProfileMatcher::isProfileUnused(const FunctionId &ProfileFuncName) {
180 // In post-link, the profiled function may have been optimized away from the
181 // module. Check if the function name exists in the pseudo_probe descriptors.
182 return (SymbolMap->find(ProfileFuncName) == SymbolMap->end()) &&
185 !ProfileFuncName.isStringRef() ||
186 (ProbeManager->getDesc(ProfileFuncName.stringRef()) == nullptr));
187}
188
189bool SampleProfileMatcher::functionMatchesProfile(
190 const FunctionId &IRFuncName, const FunctionId &ProfileFuncName,
191 bool FindMatchedProfileOnly) {
192 if (IRFuncName == ProfileFuncName)
193 return true;
194 if (!SalvageUnusedProfile)
195 return false;
196
197 // If IR function doesn't have profile and the profile is unused, try
198 // matching them.
199 Function *IRFunc = nullptr;
200 if (functionHasProfile(IRFuncName, IRFunc) ||
201 !isProfileUnused(ProfileFuncName))
202 return false;
203
204 assert(FunctionId(IRFunc->getName()) != ProfileFuncName &&
205 "IR function should be different from profile function to match");
206 return functionMatchesProfile(*IRFunc, ProfileFuncName,
207 FindMatchedProfileOnly);
208}
209
211SampleProfileMatcher::longestCommonSequence(const AnchorList &AnchorList1,
212 const AnchorList &AnchorList2,
213 bool MatchUnusedFunction) {
214 LocToLocMap MatchedAnchors;
216 AnchorList1, AnchorList2,
217 [&](const FunctionId &A, const FunctionId &B) {
218 return functionMatchesProfile(
219 A, B,
220 !MatchUnusedFunction // Find matched function only
221 );
222 },
223 [&](LineLocation A, LineLocation B) {
224 MatchedAnchors.try_emplace(A, B);
225 });
226 return MatchedAnchors;
227}
228
229void SampleProfileMatcher::matchNonCallsiteLocs(
230 const LocToLocMap &MatchedAnchors, const AnchorMap &IRAnchors,
231 LocToLocMap &IRToProfileLocationMap) {
232 auto UpdateMatching = [&](const LineLocation &From, const LineLocation &To) {
233 // Skip the unchanged location mapping to save memory.
234 if (From != To)
235 IRToProfileLocationMap.insert_or_assign(From, To);
236 else
237 IRToProfileLocationMap.erase(From);
238 };
239
240 // Use function's beginning location as the initial anchor.
241 int32_t LocationDelta = 0;
242 SmallVector<LineLocation> LastMatchedNonAnchors;
243 for (const auto &IR : IRAnchors) {
244 const auto &Loc = IR.first;
245 bool IsMatchedAnchor = false;
246 // Match the anchor location in lexical order.
247 auto R = MatchedAnchors.find(Loc);
248 if (R != MatchedAnchors.end()) {
249 const auto &Candidate = R->second;
250 UpdateMatching(Loc, Candidate);
251 LLVM_DEBUG(dbgs() << "Callsite with callee:" << IR.second.stringRef()
252 << " is matched from " << Loc << " to " << Candidate
253 << "\n");
254 LocationDelta = Candidate.LineOffset - Loc.LineOffset;
255
256 // Match backwards for non-anchor locations.
257 // The locations in LastMatchedNonAnchors have been matched forwards
258 // based on the previous anchor, split it evenly and overwrite the
259 // second half based on the current anchor.
260 for (size_t I = (LastMatchedNonAnchors.size() + 1) / 2;
261 I < LastMatchedNonAnchors.size(); I++) {
262 const auto &L = LastMatchedNonAnchors[I];
263 uint32_t CandidateLineOffset = L.LineOffset + LocationDelta;
264 LineLocation Candidate(CandidateLineOffset, L.Discriminator);
265 UpdateMatching(L, Candidate);
266 LLVM_DEBUG(dbgs() << "Location is rematched backwards from " << L
267 << " to " << Candidate << "\n");
268 }
269
270 IsMatchedAnchor = true;
271 LastMatchedNonAnchors.clear();
272 }
273
274 // Match forwards for non-anchor locations.
275 if (!IsMatchedAnchor) {
276 uint32_t CandidateLineOffset = Loc.LineOffset + LocationDelta;
277 LineLocation Candidate(CandidateLineOffset, Loc.Discriminator);
278 UpdateMatching(Loc, Candidate);
279 LLVM_DEBUG(dbgs() << "Location is matched from " << Loc << " to "
280 << Candidate << "\n");
281 LastMatchedNonAnchors.emplace_back(Loc);
282 }
283 }
284}
285
286// Filter the non-call locations from IRAnchors and ProfileAnchors and write
287// them into a list for random access later.
288void SampleProfileMatcher::getFilteredAnchorList(
289 const AnchorMap &IRAnchors, const AnchorMap &ProfileAnchors,
290 AnchorList &FilteredIRAnchorsList, AnchorList &FilteredProfileAnchorList) {
291 for (const auto &I : IRAnchors) {
292 if (I.second.stringRef().empty())
293 continue;
294 FilteredIRAnchorsList.emplace_back(I);
295 }
296
297 for (const auto &I : ProfileAnchors)
298 FilteredProfileAnchorList.emplace_back(I);
299}
300
301// Call target name anchor based profile fuzzy matching.
302// Input:
303// For IR locations, the anchor is the callee name of direct callsite; For
304// profile locations, it's the call target name for BodySamples or inlinee's
305// profile name for CallsiteSamples.
306// Matching heuristic:
307// First match all the anchors using the diff algorithm, then split the
308// non-anchor locations between the two anchors evenly, first half are matched
309// based on the start anchor, second half are matched based on the end anchor.
310// For example, given:
311// IR locations: [1, 2(foo), 3, 5, 6(bar), 7]
312// Profile locations: [1, 2, 3(foo), 4, 7, 8(bar), 9]
313// The matching gives:
314// [1, 2(foo), 3, 5, 6(bar), 7]
315// | | | | | |
316// [1, 2, 3(foo), 4, 7, 8(bar), 9]
317// The output mapping: [2->3, 3->4, 5->7, 6->8, 7->9].
318void SampleProfileMatcher::runStaleProfileMatching(
319 const Function &F, const AnchorMap &IRAnchors,
320 const AnchorMap &ProfileAnchors, LocToLocMap &IRToProfileLocationMap,
321 bool RunCFGMatching, bool RunCGMatching) {
322 if (!RunCFGMatching && !RunCGMatching)
323 return;
324 LLVM_DEBUG(dbgs() << "Run stale profile matching for " << F.getName()
325 << "\n");
326 assert(IRToProfileLocationMap.empty() &&
327 "Run stale profile matching only once per function");
328
329 AnchorList FilteredProfileAnchorList;
330 AnchorList FilteredIRAnchorsList;
331 getFilteredAnchorList(IRAnchors, ProfileAnchors, FilteredIRAnchorsList,
332 FilteredProfileAnchorList);
333
334 if (FilteredIRAnchorsList.empty() || FilteredProfileAnchorList.empty())
335 return;
336
337 if (FilteredIRAnchorsList.size() > Opts.salvage_stale_profile_max_callsites ||
338 FilteredProfileAnchorList.size() >
339 Opts.salvage_stale_profile_max_callsites) {
340 LLVM_DEBUG(dbgs() << "Skip stale profile matching for " << F.getName()
341 << " because the number of callsites in the IR is "
342 << FilteredIRAnchorsList.size()
343 << " and in the profile is "
344 << FilteredProfileAnchorList.size() << "\n");
345 return;
346 }
347
348 // Match the callsite anchors by finding the longest common subsequence
349 // between IR and profile.
350 // Define a match between two anchors as follows:
351 // 1) The function names of anchors are the same.
352 // 2) The similarity between the anchor functions is above a threshold if
353 // RunCGMatching is set.
354 // For 2), we only consider the anchor functions from IR and profile don't
355 // appear on either side to reduce the matching scope. Note that we need to
356 // use IR anchor as base(A side) to align with the order of
357 // IRToProfileLocationMap.
358 LocToLocMap MatchedAnchors =
359 longestCommonSequence(FilteredIRAnchorsList, FilteredProfileAnchorList,
360 RunCGMatching /* Match unused functions */);
361
362 // Scan through the matched anchors to make sure functions and profiles are
363 // 1:1 mapped. If the profile has already been mapped to another function
364 // during previous fuzzy matching, create a new profile with the same sample
365 // counts and assumed to be pre-inlined.
366 for (const auto &IR : IRAnchors) {
367 bool ProfileConflicted = false;
368 const auto &Loc = IR.first;
369 Function *Callee = M.getFunction(IR.second.stringRef());
370 if (!Callee)
371 continue;
372 FunctionId ProfAnchor;
373 auto AnchorLoc = MatchedAnchors.find(Loc);
374 if (AnchorLoc == MatchedAnchors.end()) {
375 // Search within the module and find if we have conflicts in pre-matched
376 // profiles for this anchor
377 auto PreMatched = FuncToProfileNameMap.find(Callee);
378 if (PreMatched == FuncToProfileNameMap.end())
379 continue;
380 ProfAnchor = PreMatched->second;
381 } else {
382 const auto &Prof = ProfileAnchors.find(AnchorLoc->second);
383 if (Prof == ProfileAnchors.end())
384 continue;
385 ProfAnchor = Prof->second;
386 }
387
388 // Conflicting profile previously matched
389 auto Cached = MatchedAnchorCache.find(ProfAnchor);
390 if (Cached == MatchedAnchorCache.end())
391 MatchedAnchorCache[ProfAnchor] = Callee;
392 else if (Cached->second != Callee)
393 ProfileConflicted = true;
394
395 if (ProfileConflicted) {
396 // Create a flattened profile using the IR function name to avoid profile
397 // name conflicts
398 const auto *FSForMatching = getFlattenedSamplesFor(ProfAnchor);
399 if (!FSForMatching)
400 FSForMatching = Reader.getSamplesFor(ProfAnchor.stringRef());
401 if (!FSForMatching)
402 continue;
403
404 FunctionId NewAnchor(
405 FunctionSamples::getCanonicalFnName(IR.second.stringRef()));
406 auto R = FuncProfileMatchCache.find({Callee, NewAnchor});
407 if (R != FuncProfileMatchCache.end() && R->second)
408 continue;
409 FunctionSamples &NewFS = FlattenedProfiles.create(NewAnchor);
410 NewFS.merge(*FSForMatching);
411 FuncToProfileNameMap[Callee] = NewAnchor;
412 FuncProfileMatchCache[{Callee, NewAnchor}] = true;
413
414 // Update profile in the sample profile reader
415 SampleProfileMap &Profiles = Reader.getProfiles();
416 SampleContext FContext(NewAnchor);
417 auto Res = Profiles.try_emplace(FContext.getHashCode(), FContext, NewFS);
418 FunctionSamples &FProfile = Res.first->second;
419 FProfile.setContext(FContext);
420 }
421 }
422
423 // CFG level matching:
424 // Apply the callsite matchings to infer matching for the basic
425 // block(non-callsite) locations and write the result to
426 // IRToProfileLocationMap.
427 if (RunCFGMatching)
428 matchNonCallsiteLocs(MatchedAnchors, IRAnchors, IRToProfileLocationMap);
429}
430
431void SampleProfileMatcher::runOnFunction(Function &F) {
432 // We need to use flattened function samples for matching.
433 // Unlike IR, which includes all callsites from the source code, the callsites
434 // in profile only show up when they are hit by samples, i,e. the profile
435 // callsites in one context may differ from those in another context. To get
436 // the maximum number of callsites, we merge the function profiles from all
437 // contexts, aka, the flattened profile to find profile anchors.
438 const auto *FSForMatching = getFlattenedSamplesFor(F);
439 if (SalvageUnusedProfile && !FSForMatching) {
440 // Apply the matching in place to find the new function's matched profile.
441 auto R = FuncToProfileNameMap.find(&F);
442 if (R != FuncToProfileNameMap.end()) {
443 FSForMatching = getFlattenedSamplesFor(R->second);
444 // Fallback for profiles loaded by functionMatchesProfileHelper but not
445 // yet in FlattenedProfiles. This should be rare now that
446 // functionMatchesProfileHelper flattens after loading.
447 if (!FSForMatching && Opts.load_func_profile_for_cg_matching)
448 FSForMatching = Reader.getSamplesFor(R->second.stringRef());
449 }
450 }
451 if (!FSForMatching)
452 return;
453
454 // Anchors for IR. It's a map from IR location to callee name, callee name is
455 // empty for non-call instruction and use a dummy name(UnknownIndirectCallee)
456 // for unknown indrect callee name.
457 AnchorMap IRAnchors;
458 findIRAnchors(F, IRAnchors);
459 // Anchors for profile. It's a map from callsite location to a set of callee
460 // name.
461 AnchorMap ProfileAnchors;
462 findProfileAnchors(*FSForMatching, ProfileAnchors);
463
464 // Compute the callsite match states for profile staleness report.
465 if (Opts.report_profile_staleness || Opts.persist_profile_staleness)
466 recordCallsiteMatchStates(F, IRAnchors, ProfileAnchors, nullptr);
467
468 if (!SalvageStaleProfile)
469 return;
470 // For probe-based profiles, run matching only when profile checksum is
471 // mismatched.
472 bool ChecksumMismatch = FunctionSamples::ProfileIsProbeBased &&
473 !ProbeManager->profileIsValid(F, *FSForMatching);
474 bool RunCFGMatching =
475 !FunctionSamples::ProfileIsProbeBased || ChecksumMismatch;
476 bool RunCGMatching = SalvageUnusedProfile;
477 // For imported functions, the checksum metadata(pseudo_probe_desc) are
478 // dropped, so we leverage function attribute(profile-checksum-mismatch) to
479 // transfer the info: add the attribute during pre-link phase and check it
480 // during post-link phase(see "profileIsValid").
481 if (ChecksumMismatch && LTOPhase == ThinOrFullLTOPhase::ThinLTOPreLink)
482 F.addFnAttr("profile-checksum-mismatch");
483
484 // The matching result will be saved to IRToProfileLocationMap, create a
485 // new map for each function.
486 auto &IRToProfileLocationMap = getIRToProfileLocationMap(*FSForMatching);
487 runStaleProfileMatching(F, IRAnchors, ProfileAnchors, IRToProfileLocationMap,
488 RunCFGMatching, RunCGMatching);
489 // Find and update callsite match states after matching.
490 if (RunCFGMatching &&
491 (Opts.report_profile_staleness || Opts.persist_profile_staleness))
492 recordCallsiteMatchStates(F, IRAnchors, ProfileAnchors,
493 &IRToProfileLocationMap);
494}
495
496void SampleProfileMatcher::recordCallsiteMatchStates(
497 const Function &F, const AnchorMap &IRAnchors,
498 const AnchorMap &ProfileAnchors,
499 const LocToLocMap *IRToProfileLocationMap) {
500 bool IsPostMatch = IRToProfileLocationMap != nullptr;
501 auto &CallsiteMatchStates =
502 FuncCallsiteMatchStates[FunctionSamples::getCanonicalFnName(F.getName())];
503
504 auto MapIRLocToProfileLoc = [&](const LineLocation &IRLoc) {
505 // IRToProfileLocationMap is null in pre-match phrase.
506 if (!IRToProfileLocationMap)
507 return IRLoc;
508 const auto &ProfileLoc = IRToProfileLocationMap->find(IRLoc);
509 if (ProfileLoc != IRToProfileLocationMap->end())
510 return ProfileLoc->second;
511 else
512 return IRLoc;
513 };
514
515 for (const auto &I : IRAnchors) {
516 // After fuzzy profile matching, use the matching result to remap the
517 // current IR callsite.
518 const auto &ProfileLoc = MapIRLocToProfileLoc(I.first);
519 const auto &IRCalleeId = I.second;
520 const auto &It = ProfileAnchors.find(ProfileLoc);
521 if (It == ProfileAnchors.end())
522 continue;
523 const auto &ProfCalleeId = It->second;
524 if (anchorsMatch(IRCalleeId, ProfCalleeId)) {
525 auto It = CallsiteMatchStates.find(ProfileLoc);
526 if (It == CallsiteMatchStates.end())
527 CallsiteMatchStates.try_emplace(ProfileLoc, MatchState::InitialMatch);
528 else if (IsPostMatch) {
529 if (It->second == MatchState::InitialMatch)
530 It->second = MatchState::UnchangedMatch;
531 else if (It->second == MatchState::InitialMismatch)
532 It->second = MatchState::RecoveredMismatch;
533 }
534 }
535 }
536
537 // Check if there are any callsites in the profile that does not match to any
538 // IR callsites.
539 for (const auto &I : ProfileAnchors) {
540 const auto &Loc = I.first;
541 assert(!I.second.stringRef().empty() && "Callees should not be empty");
542 auto It = CallsiteMatchStates.find(Loc);
543 if (It == CallsiteMatchStates.end())
544 CallsiteMatchStates.try_emplace(Loc, MatchState::InitialMismatch);
545 else if (IsPostMatch) {
546 // Update the state if it's not matched(UnchangedMatch or
547 // RecoveredMismatch).
548 if (It->second == MatchState::InitialMismatch)
549 It->second = MatchState::UnchangedMismatch;
550 else if (It->second == MatchState::InitialMatch)
551 It->second = MatchState::RemovedMatch;
552 }
553 }
554}
555
556void SampleProfileMatcher::countMismatchedFuncSamples(const FunctionSamples &FS,
557 bool IsTopLevel) {
558 const auto *FuncDesc = ProbeManager->getDesc(FS.getGUID());
559 // Skip the function that is external or renamed.
560 if (!FuncDesc)
561 return;
562
563 if (ProbeManager->profileIsHashMismatched(*FuncDesc, FS)) {
564 if (IsTopLevel)
565 NumStaleProfileFunc++;
566 // Given currently all probe ids are after block probe ids, once the
567 // checksum is mismatched, it's likely all the callites are mismatched and
568 // dropped. We conservatively count all the samples as mismatched and stop
569 // counting the inlinees' profiles.
570 MismatchedFunctionSamples += FS.getTotalSamples();
571 return;
572 }
573
574 // Even the current-level function checksum is matched, it's possible that the
575 // nested inlinees' checksums are mismatched that affect the inlinee's sample
576 // loading, we need to go deeper to check the inlinees' function samples.
577 // Similarly, count all the samples as mismatched if the inlinee's checksum is
578 // mismatched using this recursive function.
579 for (const auto &I : FS.getCallsiteSamples())
580 for (const auto &CS : I.second)
581 countMismatchedFuncSamples(CS.second, false);
582}
583
584void SampleProfileMatcher::countMismatchedCallsiteSamples(
585 const FunctionSamples &FS) {
586 auto It = FuncCallsiteMatchStates.find(FS.getFuncName());
587 // Skip it if no mismatched callsite or this is an external function.
588 if (It == FuncCallsiteMatchStates.end() || It->second.empty())
589 return;
590 const auto &CallsiteMatchStates = It->second;
591
592 auto findMatchState = [&](const LineLocation &Loc) {
593 auto It = CallsiteMatchStates.find(Loc);
594 if (It == CallsiteMatchStates.end())
595 return MatchState::Unknown;
596 return It->second;
597 };
598
599 auto AttributeMismatchedSamples = [&](const enum MatchState &State,
600 uint64_t Samples) {
601 if (isMismatchState(State))
602 MismatchedCallsiteSamples += Samples;
603 else if (State == MatchState::RecoveredMismatch)
604 RecoveredCallsiteSamples += Samples;
605 };
606
607 // The non-inlined callsites are saved in the body samples of function
608 // profile, go through it to count the non-inlined callsite samples.
609 for (const auto &I : FS.getBodySamples())
610 AttributeMismatchedSamples(findMatchState(I.first), I.second.getSamples());
611
612 // Count the inlined callsite samples.
613 for (const auto &I : FS.getCallsiteSamples()) {
614 auto State = findMatchState(I.first);
615 uint64_t CallsiteSamples = 0;
616 for (const auto &CS : I.second)
617 CallsiteSamples += CS.second.getTotalSamples();
618 AttributeMismatchedSamples(State, CallsiteSamples);
619
620 if (isMismatchState(State))
621 continue;
622
623 // When the current level of inlined call site matches the profiled call
624 // site, we need to go deeper along the inline tree to count mismatches from
625 // lower level inlinees.
626 for (const auto &CS : I.second)
627 countMismatchedCallsiteSamples(CS.second);
628 }
629}
630
631void SampleProfileMatcher::countMismatchCallsites(const FunctionSamples &FS) {
632 auto It = FuncCallsiteMatchStates.find(FS.getFuncName());
633 // Skip it if no mismatched callsite or this is an external function.
634 if (It == FuncCallsiteMatchStates.end() || It->second.empty())
635 return;
636 const auto &MatchStates = It->second;
637 [[maybe_unused]] bool OnInitialState =
638 isInitialState(MatchStates.begin()->second);
639 for (const auto &I : MatchStates) {
640 TotalProfiledCallsites++;
641 assert(
642 (OnInitialState ? isInitialState(I.second) : isFinalState(I.second)) &&
643 "Profile matching state is inconsistent");
644
645 if (isMismatchState(I.second))
646 NumMismatchedCallsites++;
647 else if (I.second == MatchState::RecoveredMismatch)
648 NumRecoveredCallsites++;
649 }
650}
651
652void SampleProfileMatcher::countCallGraphRecoveredSamples(
653 const FunctionSamples &FS,
654 DenseSet<FunctionId> &CallGraphRecoveredProfiles) {
655 if (CallGraphRecoveredProfiles.count(FS.getFunction())) {
656 NumCallGraphRecoveredFuncSamples += FS.getTotalSamples();
657 return;
658 }
659
660 for (const auto &CM : FS.getCallsiteSamples()) {
661 for (const auto &CS : CM.second) {
662 countCallGraphRecoveredSamples(CS.second, CallGraphRecoveredProfiles);
663 }
664 }
665}
666
667void SampleProfileMatcher::computeAndReportProfileStaleness() {
668 if (!Opts.report_profile_staleness && !Opts.persist_profile_staleness)
669 return;
670
671 DenseSet<FunctionId> CallGraphRecoveredProfiles;
672 if (SalvageUnusedProfile) {
673 for (const auto &I : FuncToProfileNameMap) {
674 CallGraphRecoveredProfiles.insert(I.second);
675 if (GlobalValue::isAvailableExternallyLinkage(I.first->getLinkage()))
676 continue;
677 NumCallGraphRecoveredProfiledFunc++;
678 }
679 }
680
681 // Count profile mismatches for profile staleness report.
682 for (const auto &F : M) {
684 continue;
685 // As the stats will be merged by linker, skip reporting the metrics for
686 // imported functions to avoid repeated counting.
688 continue;
689 const auto *FS = Reader.getSamplesFor(F);
690 if (!FS)
691 continue;
692 TotalProfiledFunc++;
693 TotalFunctionSamples += FS->getTotalSamples();
694
695 if (SalvageUnusedProfile && !CallGraphRecoveredProfiles.empty())
696 countCallGraphRecoveredSamples(*FS, CallGraphRecoveredProfiles);
697
698 // Checksum mismatch is only used in pseudo-probe mode.
700 countMismatchedFuncSamples(*FS, true);
701
702 // Count mismatches and samples for calliste.
703 countMismatchCallsites(*FS);
704 countMismatchedCallsiteSamples(*FS);
705 }
706
707 if (Opts.report_profile_staleness) {
709 errs() << "(" << NumStaleProfileFunc << "/" << TotalProfiledFunc
710 << ") of functions' profile are invalid and ("
711 << MismatchedFunctionSamples << "/" << TotalFunctionSamples
712 << ") of samples are discarded due to function hash mismatch.\n";
713 }
714 if (SalvageUnusedProfile) {
715 errs() << "(" << NumCallGraphRecoveredProfiledFunc << "/"
716 << TotalProfiledFunc << ") of functions' profile are matched and ("
717 << NumCallGraphRecoveredFuncSamples << "/" << TotalFunctionSamples
718 << ") of samples are reused by call graph matching.\n";
719 }
720
721 errs() << "(" << (NumMismatchedCallsites + NumRecoveredCallsites) << "/"
722 << TotalProfiledCallsites
723 << ") of callsites' profile are invalid and ("
724 << (MismatchedCallsiteSamples + RecoveredCallsiteSamples) << "/"
725 << TotalFunctionSamples
726 << ") of samples are discarded due to callsite location mismatch.\n";
727 errs() << "(" << NumRecoveredCallsites << "/"
728 << (NumRecoveredCallsites + NumMismatchedCallsites)
729 << ") of callsites and (" << RecoveredCallsiteSamples << "/"
730 << (RecoveredCallsiteSamples + MismatchedCallsiteSamples)
731 << ") of samples are recovered by stale profile matching.\n";
732 }
733
734 if (Opts.persist_profile_staleness) {
735 LLVMContext &Ctx = M.getContext();
736 MDBuilder MDB(Ctx);
737
740 ProfStatsVec.emplace_back("NumStaleProfileFunc", NumStaleProfileFunc);
741 ProfStatsVec.emplace_back("TotalProfiledFunc", TotalProfiledFunc);
742 ProfStatsVec.emplace_back("MismatchedFunctionSamples",
743 MismatchedFunctionSamples);
744 ProfStatsVec.emplace_back("TotalFunctionSamples", TotalFunctionSamples);
745 }
746
747 if (SalvageUnusedProfile) {
748 ProfStatsVec.emplace_back("NumCallGraphRecoveredProfiledFunc",
749 NumCallGraphRecoveredProfiledFunc);
750 ProfStatsVec.emplace_back("NumCallGraphRecoveredFuncSamples",
751 NumCallGraphRecoveredFuncSamples);
752 }
753
754 ProfStatsVec.emplace_back("NumMismatchedCallsites", NumMismatchedCallsites);
755 ProfStatsVec.emplace_back("NumRecoveredCallsites", NumRecoveredCallsites);
756 ProfStatsVec.emplace_back("TotalProfiledCallsites", TotalProfiledCallsites);
757 ProfStatsVec.emplace_back("MismatchedCallsiteSamples",
758 MismatchedCallsiteSamples);
759 ProfStatsVec.emplace_back("RecoveredCallsiteSamples",
760 RecoveredCallsiteSamples);
761
762 auto *MD = MDB.createLLVMStats(ProfStatsVec);
763 auto *NMD = M.getOrInsertNamedMetadata("llvm.stats");
764 NMD->addOperand(MD);
765 }
766}
767
768void SampleProfileMatcher::findFunctionsWithoutProfile() {
769 // TODO: Support MD5 profile.
771 return;
772
773 for (auto &F : M) {
774 // Skip declarations, as even if the function can be matched, we have
775 // nothing to do with it.
776 if (F.isDeclaration())
777 continue;
778
779 StringRef CanonFName = FunctionSamples::getCanonicalFnName(F.getName());
780 const auto *FS = getFlattenedSamplesFor(F);
781 if (FS)
782 continue;
783
784 // For extended binary, functions fully inlined may not be loaded in the
785 // top-level profile, so check the NameTable which has the all symbol names
786 // in profile.
787 if (Reader.contains(CanonFName))
788 continue;
789
790 // For extended binary, non-profiled function symbols are in the profile
791 // symbol list table.
792 if (PSL && PSL->contains(CanonFName))
793 continue;
794
795 LLVM_DEBUG(dbgs() << "Function " << CanonFName
796 << " is not in profile or profile symbol list.\n");
797 FunctionsWithoutProfile[FunctionId(CanonFName)] = &F;
798 }
799}
800
801// Demangle \p FName and return the base function name (stripping namespaces,
802// templates, and parameter types). Returns an empty string on failure.
803static std::string getDemangledBaseName(ItaniumPartialDemangler &Demangler,
804 StringRef FName) {
805 auto FunctionName = FName.str();
806 if (Demangler.partialDemangle(FunctionName.c_str()))
807 return std::string();
808 size_t BaseNameSize = 0;
809 // The demangler API follows the __cxa_demangle one, and thus needs a
810 // pointer that originates from malloc (or nullptr) and the caller is
811 // responsible for free()-ing the buffer.
812 char *BaseNamePtr = Demangler.getFunctionBaseName(nullptr, &BaseNameSize);
813 std::string Result = (BaseNamePtr && BaseNameSize)
814 ? std::string(BaseNamePtr, BaseNameSize)
815 : std::string();
816 free(BaseNamePtr);
817 // Trim trailing whitespace/null — getFunctionBaseName may include trailing
818 // characters in the reported size.
819 while (!Result.empty() && (Result.back() == ' ' || Result.back() == '\0'))
820 Result.pop_back();
821 return Result;
822}
823
824void SampleProfileMatcher::matchFunctionsWithoutProfileByBasename() {
825 if (FunctionsWithoutProfile.empty() ||
826 !Opts.load_func_profile_for_cg_matching)
827 return;
828 auto NameTable = Reader.getNameTable();
829 if (NameTable.empty())
830 return;
831
832 ItaniumPartialDemangler Demangler;
833
834 // Build a map from demangled basename to orphan function. Only keep
835 // basenames that map to exactly one orphan — ambiguous basenames like
836 // "get" or "operator()" would produce false positives.
837 StringMap<Function *> OrphansByBaseName;
838 StringSet<> AmbiguousBaseNames;
839 for (auto &[FuncId, Func] : FunctionsWithoutProfile) {
840 std::string BaseName = getDemangledBaseName(Demangler, Func->getName());
841 if (BaseName.empty() || AmbiguousBaseNames.count(BaseName))
842 continue;
843 auto [It, Inserted] = OrphansByBaseName.try_emplace(BaseName, Func);
844 if (!Inserted) {
845 // More than one orphan shares this basename — mark ambiguous.
846 OrphansByBaseName.erase(It);
847 AmbiguousBaseNames.insert(BaseName);
848 }
849 }
850 if (OrphansByBaseName.empty())
851 return;
852
853 // Scan the profile NameTable for candidates whose demangled basename matches
854 // a unique orphan. Use a map to track exactly one candidate per basename.
855 StringMap<FunctionId> CandidateByBaseName;
856 for (FunctionId ProfileFuncId : NameTable) {
857 StringRef ProfName = ProfileFuncId.stringRef();
858 if (ProfName.empty())
859 continue;
860
861 std::string ProfBaseName = getDemangledBaseName(Demangler, ProfName);
862 if (ProfBaseName.empty())
863 continue;
864
865 if (OrphansByBaseName.count(ProfBaseName)) {
866 if (AmbiguousBaseNames.count(ProfBaseName))
867 continue;
868
869 auto [It, Inserted] =
870 CandidateByBaseName.try_emplace(ProfBaseName, ProfileFuncId);
871 if (!Inserted) {
872 // More than one profile entry shares this basename — mark ambiguous.
873 CandidateByBaseName.erase(It);
874 AmbiguousBaseNames.insert(ProfBaseName);
875 }
876 }
877 }
878
879 if (CandidateByBaseName.empty())
880 return;
881
882 // Load candidate profiles on demand, match, and flatten.
883 DenseSet<StringRef> ToLoad;
884 for (auto &[BaseName, ProfId] : CandidateByBaseName)
885 ToLoad.insert(ProfId.stringRef());
886 Reader.read(ToLoad);
887
888 unsigned MatchCount = 0;
889 SampleProfileMap NewlyLoadedProfiles;
890 for (auto &[BaseName, ProfId] : CandidateByBaseName) {
891 if (!isProfileUnused(ProfId))
892 continue;
893 Function *OrphanFunc = OrphansByBaseName.lookup(BaseName);
894 if (!OrphanFunc)
895 continue;
896
897 FuncToProfileNameMap[OrphanFunc] = ProfId;
898 MatchedAnchorCache[ProfId] = OrphanFunc;
899 if (const auto *FS = Reader.getSamplesFor(ProfId.stringRef()))
900 NewlyLoadedProfiles.create(FS->getFunction()).merge(*FS);
901 MatchCount++;
902 LLVM_DEBUG(dbgs() << "Direct basename match: " << OrphanFunc->getName()
903 << " (IR) -> " << ProfId << " (Profile)"
904 << " [basename: " << BaseName << "]\n");
905 }
906
907 // Flatten newly loaded profiles so inlined callees are available for
908 // subsequent LCS-based CG matching.
909 if (!NewlyLoadedProfiles.empty())
910 ProfileConverter::flattenProfile(NewlyLoadedProfiles, FlattenedProfiles,
912
913 NumDirectProfileMatch += MatchCount;
914 LLVM_DEBUG(dbgs() << "Direct basename matching found " << MatchCount
915 << " matches\n");
916}
917
918bool SampleProfileMatcher::functionMatchesProfileHelper(
919 const Function &IRFunc, const FunctionId &ProfFunc) {
920 // The value is in the range [0, 1]. The bigger the value is, the more similar
921 // two sequences are.
922 float Similarity = 0.0;
923
924 // Match the functions if they have the same base name(after demangling) and
925 // skip the similarity check.
926 ItaniumPartialDemangler Demangler;
927 auto IRBaseName = getDemangledBaseName(Demangler, IRFunc.getName());
928 auto ProfBaseName = getDemangledBaseName(Demangler, ProfFunc.stringRef());
929 if (!IRBaseName.empty() && IRBaseName == ProfBaseName) {
930 LLVM_DEBUG(dbgs() << "The functions " << IRFunc.getName() << "(IR) and "
931 << ProfFunc << "(Profile) share the same base name: "
932 << IRBaseName << ".\n");
933 return true;
934 }
935
936 const auto *FSForMatching = getFlattenedSamplesFor(ProfFunc);
937 // With extbinary profile format, initial profile loading only reads profile
938 // based on current function names in the module.
939 // However, if a function is renamed, sample loader skips to load its original
940 // profile(which has a different name), we will miss this case. To address
941 // this, we load the top-level profile candidate explicitly for the matching.
942 if (!FSForMatching && Opts.load_func_profile_for_cg_matching) {
943 DenseSet<StringRef> TopLevelFunc({ProfFunc.stringRef()});
944 if (std::error_code EC = Reader.read(TopLevelFunc))
945 return false;
946 FSForMatching = Reader.getSamplesFor(ProfFunc.stringRef());
947 // Flatten the newly loaded profile so its inlined callees get their own
948 // entries in FlattenedProfiles, making them discoverable by subsequent
949 // CG matching steps.
950 if (FSForMatching) {
951 SampleProfileMap TempProfiles;
952 TempProfiles.create(FSForMatching->getFunction()).merge(*FSForMatching);
953 ProfileConverter::flattenProfile(TempProfiles, FlattenedProfiles,
955 FSForMatching = getFlattenedSamplesFor(ProfFunc);
956 }
957 LLVM_DEBUG({
958 if (FSForMatching)
959 dbgs() << "Read top-level function " << ProfFunc
960 << " for call-graph matching\n";
961 });
962 }
963 if (!FSForMatching)
964 return false;
965 // The check for similarity or checksum may not be reliable if the function is
966 // tiny, we use the number of basic block as a proxy for the function
967 // complexity and skip the matching if it's too small.
968 if (IRFunc.size() < Opts.min_func_count_for_cg_matching ||
969 FSForMatching->getBodySamples().size() <
970 Opts.min_func_count_for_cg_matching)
971 return false;
972
973 // For probe-based function, we first trust the checksum info. If the checksum
974 // doesn't match, we continue checking for similarity.
976 const auto *FuncDesc = ProbeManager->getDesc(IRFunc);
977 if (FuncDesc &&
978 !ProbeManager->profileIsHashMismatched(*FuncDesc, *FSForMatching)) {
979 LLVM_DEBUG(dbgs() << "The checksums for " << IRFunc.getName()
980 << "(IR) and " << ProfFunc << "(Profile) match.\n");
981
982 return true;
983 }
984 }
985
986 AnchorMap IRAnchors;
987 findIRAnchors(IRFunc, IRAnchors);
988 AnchorMap ProfileAnchors;
989 findProfileAnchors(*FSForMatching, ProfileAnchors);
990
991 AnchorList FilteredIRAnchorsList;
992 AnchorList FilteredProfileAnchorList;
993 getFilteredAnchorList(IRAnchors, ProfileAnchors, FilteredIRAnchorsList,
994 FilteredProfileAnchorList);
995
996 // Similarly skip the matching if the num of anchors is not enough.
997 if (FilteredIRAnchorsList.size() < Opts.min_call_count_for_cg_matching ||
998 FilteredProfileAnchorList.size() < Opts.min_call_count_for_cg_matching)
999 return false;
1000
1001 // Use the diff algorithm to find the LCS between IR and profile.
1002
1003 // Don't recursively match the callee function to avoid infinite matching,
1004 // callee functions will be handled later since it's processed in top-down
1005 // order .
1006 LocToLocMap MatchedAnchors =
1007 longestCommonSequence(FilteredIRAnchorsList, FilteredProfileAnchorList,
1008 false /* Match unused functions */);
1009
1010 Similarity = static_cast<float>(MatchedAnchors.size()) /
1011 FilteredProfileAnchorList.size();
1012
1013 LLVM_DEBUG(dbgs() << "The similarity between " << IRFunc.getName()
1014 << "(IR) and " << ProfFunc << "(profile) is "
1015 << format("%.2f", Similarity) << "\n");
1016 assert((Similarity >= 0 && Similarity <= 1.0) &&
1017 "Similarity value should be in [0, 1]");
1018 return Similarity * 100 > Opts.func_profile_similarity_threshold;
1019}
1020
1021// If FindMatchedProfileOnly is set to true, only use the processed function
1022// results. This is used for skipping the repeated recursive matching.
1023bool SampleProfileMatcher::functionMatchesProfile(Function &IRFunc,
1024 const FunctionId &ProfFunc,
1025 bool FindMatchedProfileOnly) {
1026 auto R = FuncProfileMatchCache.find({&IRFunc, ProfFunc});
1027 if (R != FuncProfileMatchCache.end())
1028 return R->second;
1029
1030 if (FindMatchedProfileOnly)
1031 return false;
1032
1033 bool Matched = functionMatchesProfileHelper(IRFunc, ProfFunc);
1034 FuncProfileMatchCache[{&IRFunc, ProfFunc}] = Matched;
1035 if (Matched) {
1036 FuncToProfileNameMap[&IRFunc] = ProfFunc;
1037 LLVM_DEBUG(dbgs() << "Function:" << IRFunc.getName()
1038 << " matches profile:" << ProfFunc << "\n");
1039 }
1040
1041 return Matched;
1042}
1043
1044void SampleProfileMatcher::UpdateWithSalvagedProfiles() {
1045 DenseSet<StringRef> ProfileSalvagedFuncs;
1046 // Update FuncNameToProfNameMap and SymbolMap.
1047 for (auto &I : FuncToProfileNameMap) {
1048 assert(I.first && "New function is null");
1049 FunctionId FuncName(I.first->getName());
1050 ProfileSalvagedFuncs.insert(I.second.stringRef());
1051 FuncNameToProfNameMap->emplace(FuncName, I.second);
1052
1053 // We need to remove the old entry to avoid duplicating the function
1054 // processing.
1055 SymbolMap->erase(FuncName);
1056 [[maybe_unused]] auto Ret = SymbolMap->emplace(I.second, I.first);
1057 LLVM_DEBUG({
1058 if (!Ret.second)
1059 dbgs() << "Profile Function " << I.second
1060 << " has already been matched to another IR function.\n";
1061 });
1062 }
1063
1064 // With extbinary profile format, initial profile loading only reads profile
1065 // based on current function names in the module, so we need to load top-level
1066 // profiles for functions with different profile name explicitly after
1067 // function-profile name map is established with stale profile matching.
1068 Reader.read(ProfileSalvagedFuncs);
1069 Reader.setFuncNameToProfNameMap(*FuncNameToProfNameMap);
1070}
1071
1073 ProfileConverter::flattenProfile(Reader.getProfiles(), FlattenedProfiles,
1075 // Disable SalvageUnusedProfile if the module has an extremely large number of
1076 // functions to limit compile time.
1077 SalvageUnusedProfile = SalvageUnusedProfile &&
1078 M.size() < Opts.salvage_unused_profile_max_functions;
1079
1080 if (SalvageUnusedProfile) {
1081 findFunctionsWithoutProfile();
1082 matchFunctionsWithoutProfileByBasename();
1083 }
1084
1085 // Process the matching in top-down order so that the caller matching result
1086 // can be used to the callee matching.
1087 std::vector<Function *> TopDownFunctionList;
1088 TopDownFunctionList.reserve(M.size());
1089 buildTopDownFuncOrder(CG, TopDownFunctionList);
1090 for (auto *F : TopDownFunctionList) {
1092 continue;
1093 runOnFunction(*F);
1094 }
1095
1096 if (SalvageUnusedProfile)
1097 UpdateWithSalvagedProfiles();
1098
1099 if (SalvageStaleProfile)
1100 distributeIRToProfileLocationMap();
1101
1102 computeAndReportProfileStaleness();
1103}
1104
1105void SampleProfileMatcher::distributeIRToProfileLocationMap(
1106 FunctionSamples &FS) {
1107 const auto ProfileMappings = FuncMappings.find(FS.getFuncName());
1108 if (ProfileMappings != FuncMappings.end()) {
1109 FS.setIRToProfileLocationMap(&(ProfileMappings->second));
1110 }
1111
1112 for (auto &Callees :
1113 const_cast<CallsiteSampleMap &>(FS.getCallsiteSamples())) {
1114 for (auto &FS : Callees.second) {
1115 distributeIRToProfileLocationMap(FS.second);
1116 }
1117 }
1118}
1119
1120// Use a central place to distribute the matching results. Outlined and inlined
1121// profile with the function name will be set to the same pointer.
1122void SampleProfileMatcher::distributeIRToProfileLocationMap() {
1123 for (auto &I : Reader.getProfiles()) {
1124 distributeIRToProfileLocationMap(I.second);
1125 }
1126}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
uint64_t uint64_t
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
itanium_demangle::ManglingParser< DefaultAllocator > Demangler
Legalize the Machine IR a function s Machine IR
Definition Legalizer.cpp:85
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
This file contains some templates that are useful if you are working with the STL at all.
static std::string getDemangledBaseName(ItaniumPartialDemangler &Demangler, StringRef FName)
This file provides the interface for SampleProfileMatcher.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition Statistic.h:171
#define LLVM_DEBUG(...)
Definition Debug.h:119
bool empty() const
Definition DenseMap.h:716
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:766
std::pair< iterator, bool > insert_or_assign(const KeyT &Key, V &&Val)
Definition DenseMap.h:899
iterator end()
Definition DenseMap.h:686
unsigned size() const
Definition DenseMap.h:717
bool erase(const KeyT &Val)
Definition DenseMap.h:930
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:856
Implements a dense probed hash-table based set.
Definition DenseSet.h:283
size_t size() const
Definition Function.h:843
static bool isAvailableExternallyLinkage(LinkageTypes Linkage)
reference emplace_back(ArgTypes &&... Args)
bool empty() const
Definition StringMap.h:103
size_type count(StringRef Key) const
count - Return 1 if the element is in the map, 0 otherwise.
Definition StringMap.h:275
ValueTy lookup(StringRef Key) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
Definition StringMap.h:250
void erase(iterator I)
Definition StringMap.h:418
std::pair< iterator, bool > try_emplace(StringRef Key, ArgsTy &&...Args)
Emplace a new element for the specified key into the map if the key isn't already in the map.
Definition StringMap.h:370
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
std::string str() const
Get the contents as an std::string.
Definition StringRef.h:222
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
std::pair< typename Base::iterator, bool > insert(StringRef key)
Definition StringSet.h:41
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:314
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:210
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition DenseSet.h:188
This class represents a function that is read from a sample profile.
Definition FunctionId.h:36
StringRef stringRef() const
Convert to StringRef.
Definition FunctionId.h:108
bool isStringRef() const
Check if this object represents a StringRef, or a hash code.
Definition FunctionId.h:132
Representation of the samples collected for a function.
Definition SampleProf.h:854
static LLVM_ABI std::atomic< bool > ProfileIsFS
If this profile uses flow sensitive discriminators.
static LLVM_ABI std::atomic< bool > UseMD5
Whether the profile uses MD5 to represent string.
static StringRef getCanonicalFnName(const Function &F)
Return the canonical name for a function, taking into account suffix elision policy attributes.
static LLVM_ABI std::atomic< bool > ProfileIsProbeBased
sampleprof_error merge(const FunctionSamples &Other, uint64_t Weight=1)
Merge the samples in Other into this one.
void setContext(const SampleContext &FContext)
static LLVM_ABI std::atomic< bool > ProfileIsCS
static LLVM_ABI LineLocation getCallSiteIdentifier(const DILocation *DIL, bool ProfileIsFS=false)
Returns a unique call site identifier for a given debug location of a call instruction.
std::pair< iterator, bool > try_emplace(const key_type &Hash, const original_key_type &Key, Ts &&...Args)
Definition HashKeyMap.h:64
static void flattenProfile(SampleProfileMap &ProfileMap, bool ProfileIsCS=false)
mapped_type & create(const SampleContext &Ctx)
NodeAddr< FuncNode * > Func
Definition RDFGraph.h:393
std::map< LineLocation, FunctionSamplesMap > CallsiteSampleMap
Definition SampleProf.h:845
DenseMap< LineLocation, LineLocation > LocToLocMap
Definition SampleProf.h:847
This is an optimization pass for GlobalISel generic memory operations.
std::map< LineLocation, FunctionId > AnchorMap
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
static void buildTopDownFuncOrder(LazyCallGraph &CG, std::vector< Function * > &FunctionOrderList)
@ ThinLTOPreLink
ThinLTO prelink (summary) phase.
Definition Pass.h:79
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
LLVM_ABI std::optional< PseudoProbe > extractProbe(const Instruction &Inst)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition Format.h:102
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
void longestCommonSequence(AnchorList AnchorList1, AnchorList AnchorList2, llvm::function_ref< bool(const Function &, const Function &)> FunctionMatchesProfile, llvm::function_ref< void(Loc, Loc)> InsertMatching)
std::vector< std::pair< LineLocation, FunctionId > > AnchorList
static bool skipProfileForFunction(const Function &F)
"Partial" demangler.
Definition Demangle.h:102