LLVM 24.0.0git
MemProfUse.cpp
Go to the documentation of this file.
1//===- MemProfUse.cpp - memory allocation profile use pass --*- C++ -*-===//
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 MemProfUsePass which reads memory profiling data
10// and uses it to add metadata to instructions to guide optimization.
11//
12//===----------------------------------------------------------------------===//
13
16#include "llvm/ADT/DenseSet.h"
18#include "llvm/ADT/Statistic.h"
19#include "llvm/ADT/StringRef.h"
25#include "llvm/IR/Function.h"
27#include "llvm/IR/Module.h"
32#include "llvm/Support/BLAKE3.h"
34#include "llvm/Support/Debug.h"
36#include "llvm/Support/MD5.h"
39#include <map>
40#include <set>
41
42using namespace llvm;
43using namespace llvm::memprof;
44
45#define DEBUG_TYPE "memprof"
46
47namespace llvm {
50} // namespace llvm
51
52// Matching statistics
53STATISTIC(NumOfMemProfMissing, "Number of functions without memory profile.");
54STATISTIC(NumOfMemProfMismatch,
55 "Number of functions having mismatched memory profile hash.");
56STATISTIC(NumOfMemProfFunc, "Number of functions having valid memory profile.");
57STATISTIC(NumOfMemProfAllocContextProfiles,
58 "Number of alloc contexts in memory profile.");
59STATISTIC(NumOfMemProfCallSiteProfiles,
60 "Number of callsites in memory profile.");
61STATISTIC(NumOfMemProfMatchedAllocContexts,
62 "Number of matched memory profile alloc contexts.");
63STATISTIC(NumOfMemProfMatchedAllocs,
64 "Number of matched memory profile allocs.");
65STATISTIC(NumOfMemProfMatchedCallSites,
66 "Number of matched memory profile callsites.");
67STATISTIC(NumOfMemProfHotGlobalVars,
68 "Number of global vars annotated with 'hot' section prefix.");
69STATISTIC(NumOfMemProfColdGlobalVars,
70 "Number of global vars annotated with 'unlikely' section prefix.");
71STATISTIC(NumOfMemProfUnknownGlobalVars,
72 "Number of global vars with unknown hotness (no section prefix).");
73STATISTIC(NumOfMemProfExplicitSectionGlobalVars,
74 "Number of global vars with user-specified section (not annotated).");
75
77 ArrayRef<uint64_t> InlinedCallStack,
78 LLVMContext &Ctx) {
79 I.setMetadata(LLVMContext::MD_callsite,
80 buildCallstackMetadata(InlinedCallStack, Ctx));
81}
82
84 uint32_t Column) {
87 HashBuilder.add(Function, LineOffset, Column);
89 uint64_t Id;
90 std::memcpy(&Id, Hash.data(), sizeof(Hash));
91 return Id;
92}
93
97
98// Compute the line offset of a debug location relative to the start line of
99// its enclosing subprogram, clamped at 0 as the profile reader does (e.g. for
100// locations without debug info whose line is 0).
102 unsigned Line = DIL->getLine();
103 unsigned SubprogramLine = DIL->getScope()->getSubprogram()->getLine();
104 if (Line < SubprogramLine)
105 return 0;
106 return Line - SubprogramLine;
107}
108
110 return getAllocType(AllocInfo->Info.getTotalLifetimeAccessDensity(),
111 AllocInfo->Info.getAllocCount(),
112 AllocInfo->Info.getTotalLifetime());
113}
114
117 uint64_t FullStackId) {
118 SmallVector<uint64_t> StackIds;
119 for (const auto &StackFrame : AllocInfo->CallStack)
120 StackIds.push_back(computeStackId(StackFrame));
122 std::vector<ContextTotalSize> ContextSizeInfo;
124 auto TotalSize = AllocInfo->Info.getTotalSize();
125 assert(TotalSize);
126 assert(FullStackId != 0);
127 ContextSizeInfo.push_back({FullStackId, TotalSize});
128 }
129 AllocTrie.addCallStack(AllocType, StackIds, std::move(ContextSizeInfo));
130 return AllocType;
131}
132
133// Return true if InlinedCallStack, computed from a call instruction's debug
134// info, is a prefix of ProfileCallStack, a list of Frames from profile data
135// (either the allocation data or a callsite).
136static bool
138 ArrayRef<uint64_t> InlinedCallStack) {
139 return ProfileCallStack.size() >= InlinedCallStack.size() &&
140 llvm::equal(ProfileCallStack.take_front(InlinedCallStack.size()),
141 InlinedCallStack, [](const Frame &F, uint64_t StackId) {
142 return computeStackId(F) == StackId;
143 });
144}
145
146static bool isAllocationWithHotColdVariant(const InstrumentationOptions &Opts,
147 const Function *Callee,
148 const TargetLibraryInfo &TLI) {
149 if (!Callee)
150 return false;
151 LibFunc Func = TLI.getLibFunc(*Callee);
152 if (Func == NotLibFunc)
153 return false;
154 switch (Func) {
155 case LibFunc_Znwm:
156 case LibFunc_ZnwmRKSt9nothrow_t:
157 case LibFunc_ZnwmSt11align_val_t:
158 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t:
159 case LibFunc_Znam:
160 case LibFunc_ZnamRKSt9nothrow_t:
161 case LibFunc_ZnamSt11align_val_t:
162 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t:
163 case LibFunc_size_returning_new:
164 case LibFunc_size_returning_new_aligned:
165 return true;
166 case LibFunc_Znwm12__hot_cold_t:
167 case LibFunc_ZnwmRKSt9nothrow_t12__hot_cold_t:
168 case LibFunc_ZnwmSt11align_val_t12__hot_cold_t:
169 case LibFunc_ZnwmSt11align_val_tRKSt9nothrow_t12__hot_cold_t:
170 case LibFunc_Znam12__hot_cold_t:
171 case LibFunc_ZnamRKSt9nothrow_t12__hot_cold_t:
172 case LibFunc_ZnamSt11align_val_t12__hot_cold_t:
173 case LibFunc_ZnamSt11align_val_tRKSt9nothrow_t12__hot_cold_t:
174 case LibFunc_size_returning_new_hot_cold:
175 case LibFunc_size_returning_new_aligned_hot_cold:
176 return Opts.memprof_match_hot_cold_new;
177 default:
178 return false;
179 }
180}
181
183 AnnotationKind Kind) {
185 "Should not handle AnnotationOK here");
186 SmallString<32> Reason;
187 switch (Kind) {
189 ++NumOfMemProfExplicitSectionGlobalVars;
190 Reason.append("explicit section name");
191 break;
193 Reason.append("linker declaration");
194 break;
196 Reason.append("name starts with `llvm.`");
197 break;
198 default:
199 llvm_unreachable("Unexpected annotation kind");
200 }
201 LLVM_DEBUG(dbgs() << "Skip annotation for " << GVar.getName() << " due to "
202 << Reason << ".\n");
203}
204
205// Computes the LLVM version of MD5 hash for the content of a string
206// literal.
207static std::optional<uint64_t>
209 auto *Initializer = GVar.getInitializer();
210 if (!Initializer)
211 return std::nullopt;
212 if (auto *C = dyn_cast<ConstantDataSequential>(Initializer))
213 if (C->isString()) {
214 // Note the hash computed for the literal would include the null byte.
215 return llvm::MD5Hash(C->getAsString());
216 }
217 return std::nullopt;
218}
219
220// Structure for tracking info about matched allocation contexts for use with
221// -memprof-print-match-info and -memprof-print-matched-alloc-stack.
223 // Total size in bytes of matched context.
224 uint64_t TotalSize = 0;
225 // Matched allocation's type.
227 // Number of frames matched to the allocation itself (values will be >1 in
228 // cases where allocation was already inlined). Use a set because there can
229 // be multiple inlined instances and each may have a different inline depth.
230 // Use std::set to iterate in sorted order when printing.
231 std::set<unsigned> MatchedFramesSet;
232 // The full call stack of the allocation, for cases where requested via
233 // -memprof-print-matched-alloc-stack.
234 std::vector<Frame> CallStack;
235
236 // Caller responsible for inserting the matched frames and the call stack when
237 // appropriate.
240};
241
244 function_ref<bool(uint64_t)> IsPresentInProfile) {
246
247 for (Function &F : M) {
248 if (F.isDeclaration())
249 continue;
250
251 for (auto &BB : F) {
252 for (auto &I : BB) {
254 continue;
255
256 auto *CB = dyn_cast<CallBase>(&I);
257 auto *CalledFunction = CB->getCalledFunction();
258 // Disregard indirect calls and intrinsics.
259 if (!CalledFunction || CalledFunction->isIntrinsic())
260 continue;
261
262 StringRef CalleeName = CalledFunction->getName();
263 // True if we are calling a heap allocation function that supports
264 // hot/cold variants.
265 bool IsAlloc = isAllocationWithHotColdVariant(
266 InstrumentationOptions::Global, CalledFunction, TLI);
267 // True for the first iteration below, indicating that we are looking at
268 // a leaf node.
269 bool IsLeaf = true;
270 for (const DILocation *DIL = I.getDebugLoc(); DIL;
271 DIL = DIL->getInlinedAt()) {
272 StringRef CallerName = DIL->getSubprogramLinkageName();
273 assert(!CallerName.empty() &&
274 "Be sure to enable -fdebug-info-for-profiling");
275 uint64_t CallerGUID = memprof::getGUID(CallerName);
276 uint64_t CalleeGUID = memprof::getGUID(CalleeName);
277 // Pretend that we are calling a function with GUID == 0 if we are
278 // in the inline stack leading to a heap allocation function.
279 if (IsAlloc) {
280 if (IsLeaf) {
281 // For leaf nodes, set CalleeGUID to 0 without consulting
282 // IsPresentInProfile.
283 CalleeGUID = 0;
284 } else if (!IsPresentInProfile(CalleeGUID)) {
285 // In addition to the leaf case above, continue to set CalleeGUID
286 // to 0 as long as we don't see CalleeGUID in the profile.
287 CalleeGUID = 0;
288 } else {
289 // Once we encounter a callee that exists in the profile, stop
290 // setting CalleeGUID to 0.
291 IsAlloc = false;
292 }
293 }
294
295 LineLocation Loc = {getLineOffset(DIL), DIL->getColumn()};
296 Calls[CallerGUID].emplace_back(Loc, CalleeGUID);
297 CalleeName = CallerName;
298 IsLeaf = false;
299 }
300 }
301 }
302 }
303
304 // Sort each call list by the source location.
305 for (auto &[CallerGUID, CallList] : Calls) {
306 llvm::sort(CallList);
307 CallList.erase(llvm::unique(CallList), CallList.end());
308 }
309
310 return Calls;
311}
312
315 const TargetLibraryInfo &TLI) {
317
319 MemProfReader->getMemProfCallerCalleePairs();
321 extractCallsFromIR(M, TLI, [&](uint64_t GUID) {
322 return CallsFromProfile.contains(GUID);
323 });
324
325 // Compute an undrift map for each CallerGUID.
326 for (const auto &[CallerGUID, IRAnchors] : CallsFromIR) {
327 auto It = CallsFromProfile.find(CallerGUID);
328 if (It == CallsFromProfile.end())
329 continue;
330 const auto &ProfileAnchors = It->second;
331
332 LocToLocMap Matchings;
334 ProfileAnchors, IRAnchors, std::equal_to<GlobalValue::GUID>(),
335 [&](LineLocation A, LineLocation B) { Matchings.try_emplace(A, B); });
336 [[maybe_unused]] bool Inserted =
337 UndriftMaps.try_emplace(CallerGUID, std::move(Matchings)).second;
338
339 // The insertion must succeed because we visit each GUID exactly once.
340 assert(Inserted);
341 }
342
343 return UndriftMaps;
344}
345
346// Given a MemProfRecord, undrift all the source locations present in the
347// record in place.
348static void
350 memprof::MemProfRecord &MemProfRec) {
351 // Undrift a call stack in place.
352 auto UndriftCallStack = [&](std::vector<Frame> &CallStack) {
353 for (auto &F : CallStack) {
354 auto I = UndriftMaps.find(F.Function);
355 if (I == UndriftMaps.end())
356 continue;
357 auto J = I->second.find(LineLocation(F.LineOffset, F.Column));
358 if (J == I->second.end())
359 continue;
360 auto &NewLoc = J->second;
361 F.LineOffset = NewLoc.LineOffset;
362 F.Column = NewLoc.Column;
363 }
364 };
365
366 for (auto &AS : MemProfRec.AllocSites)
367 UndriftCallStack(AS.CallStack);
368
369 for (auto &CS : MemProfRec.CallSites)
370 UndriftCallStack(CS.Frames);
371}
372
373// Helper function to process CalleeGuids and create value profile metadata
374static void addVPMetadata(const InstrumentationOptions &Opts, Module &M,
375 Instruction &I,
376 ArrayRef<GlobalValue::GUID> CalleeGuids) {
377 if (!Opts.memprof_attach_calleeguids || CalleeGuids.empty())
378 return;
379
380 // Prepare the vector of value data, initializing from any existing
381 // value-profile metadata present on the instruction so that we merge the
382 // new CalleeGuids into the existing entries.
384 uint64_t TotalCount = 0;
385
386 if (I.getMetadata(LLVMContext::MD_prof)) {
387 // Read all existing entries so we can merge them. Use a large
388 // MaxNumValueData to retrieve all existing entries.
389 VDs = getValueProfDataFromInst(I, IPVK_IndirectCallTarget,
390 /*MaxNumValueData=*/UINT32_MAX, TotalCount);
391 }
392
393 // Save the original size for use later in detecting whether any were added.
394 const size_t OriginalSize = VDs.size();
395
396 // Initialize the set of existing guids with the original list.
397 DenseSet<uint64_t> ExistingValues(
400 VDs, [](const InstrProfValueData &Entry) { return Entry.Value; }));
401
402 // Merge CalleeGuids into list of existing VDs, by appending any that are not
403 // already included.
404 VDs.reserve(OriginalSize + CalleeGuids.size());
405 for (auto G : CalleeGuids) {
406 if (!ExistingValues.insert(G).second)
407 continue;
408 InstrProfValueData NewEntry;
409 NewEntry.Value = G;
410 // For MemProf, we don't have actual call counts, so we assign
411 // a weight of 1 to each potential target.
412 // TODO: Consider making this weight configurable or increasing it to
413 // improve effectiveness for ICP.
414 NewEntry.Count = 1;
415 TotalCount += NewEntry.Count;
416 VDs.push_back(NewEntry);
417 }
418
419 // Update the VP metadata if we added any new callee GUIDs to the list.
420 assert(VDs.size() >= OriginalSize);
421 if (VDs.size() == OriginalSize)
422 return;
423
424 // First clear the existing !prof.
425 I.setMetadata(LLVMContext::MD_prof, nullptr);
426
427 // No need to sort the updated VDs as all appended entries have the same count
428 // of 1, which is no larger than any existing entries. The incoming list of
429 // CalleeGuids should already be deterministic for a given profile.
430 annotateValueSite(M, I, VDs, TotalCount, IPVK_IndirectCallTarget, VDs.size());
431}
432
433static void handleAllocSite(
434 const InstrumentationOptions &Opts, Instruction &I, CallBase *CI,
435 ArrayRef<uint64_t> InlinedCallStack, LLVMContext &Ctx,
436 OptimizationRemarkEmitter &ORE, uint64_t MaxColdSize,
437 const std::set<const AllocationInfo *> &AllocInfoSet,
438 std::map<uint64_t, AllocMatchInfo> &FullStackIdToAllocMatchInfo) {
439 // TODO: Remove this once the profile creation logic deduplicates contexts
440 // that are the same other than the IsInlineFrame bool. Until then, keep the
441 // largest.
442 DenseMap<uint64_t, const AllocationInfo *> UniqueFullContextIdAllocInfo;
443 for (auto *AllocInfo : AllocInfoSet) {
444 auto FullStackId = computeFullStackId(AllocInfo->CallStack);
445 auto [It, Inserted] =
446 UniqueFullContextIdAllocInfo.insert({FullStackId, AllocInfo});
447 // If inserted entry, done.
448 if (Inserted)
449 continue;
450 // Keep the larger one, or the noncold one if they are the same size.
451 auto CurSize = It->second->Info.getTotalSize();
452 auto NewSize = AllocInfo->Info.getTotalSize();
453 if ((CurSize > NewSize) ||
454 (CurSize == NewSize &&
456 continue;
457 It->second = AllocInfo;
458 }
459 // We may match this instruction's location list to multiple MIB
460 // contexts. Add them to a Trie specialized for trimming the contexts to
461 // the minimal needed to disambiguate contexts with unique behavior.
462 CallStackTrie AllocTrie(&ORE, MaxColdSize);
463 uint64_t TotalSize = 0;
464 uint64_t TotalColdSize = 0;
465 for (auto &[FullStackId, AllocInfo] : UniqueFullContextIdAllocInfo) {
466 // Check the full inlined call stack against this one.
467 // If we found and thus matched all frames on the call, include
468 // this MIB.
470 InlinedCallStack)) {
471 NumOfMemProfMatchedAllocContexts++;
472 auto AllocType = addCallStack(AllocTrie, AllocInfo, FullStackId);
473 TotalSize += AllocInfo->Info.getTotalSize();
475 TotalColdSize += AllocInfo->Info.getTotalSize();
476 // Record information about the allocation if match info printing
477 // was requested.
478 if (Opts.memprof_print_match_info) {
479 assert(FullStackId != 0);
480 auto [Iter, Inserted] = FullStackIdToAllocMatchInfo.try_emplace(
481 FullStackId,
482 AllocMatchInfo(AllocInfo->Info.getTotalSize(), AllocType));
483 // Always insert the new matched frame count, since it may differ.
484 Iter->second.MatchedFramesSet.insert(InlinedCallStack.size());
485 if (Inserted && Opts.memprof_print_matched_alloc_stack)
486 Iter->second.CallStack.insert(Iter->second.CallStack.begin(),
487 AllocInfo->CallStack.begin(),
488 AllocInfo->CallStack.end());
489 }
490 ORE.emit(
491 OptimizationRemark(DEBUG_TYPE, "MemProfUse", CI)
492 << ore::NV("AllocationCall", CI) << " in function "
493 << ore::NV("Caller", CI->getFunction())
494 << " matched alloc context with alloc type "
496 << " total size " << ore::NV("Size", AllocInfo->Info.getTotalSize())
497 << " full context id " << ore::NV("Context", FullStackId)
498 << " frame count " << ore::NV("Frames", InlinedCallStack.size()));
499 }
500 }
501 // If the threshold for the percent of cold bytes is less than 100%,
502 // and not all bytes are cold, see if we should still hint this
503 // allocation as cold without context sensitivity.
504 if (TotalColdSize < TotalSize && Opts.memprof_matching_cold_threshold < 100 &&
505 TotalColdSize * 100 >= Opts.memprof_matching_cold_threshold * TotalSize) {
506 AllocTrie.addSingleAllocTypeAttribute(CI, AllocationType::Cold, "dominant");
507 return;
508 }
509
510 // We might not have matched any to the full inlined call stack.
511 // But if we did, create and attach metadata, or a function attribute if
512 // all contexts have identical profiled behavior.
513 if (!AllocTrie.empty()) {
514 NumOfMemProfMatchedAllocs++;
515 // MemprofMDAttached will be false if a function attribute was
516 // attached.
517 bool MemprofMDAttached = AllocTrie.buildAndAttachMIBMetadata(CI);
518 assert(MemprofMDAttached == I.hasMetadata(LLVMContext::MD_memprof));
519 if (MemprofMDAttached) {
520 // Add callsite metadata for the instruction's location list so that
521 // it simpler later on to identify which part of the MIB contexts
522 // are from this particular instruction (including during inlining,
523 // when the callsite metadata will be updated appropriately).
524 // FIXME: can this be changed to strip out the matching stack
525 // context ids from the MIB contexts and not add any callsite
526 // metadata here to save space?
527 addCallsiteMetadata(I, InlinedCallStack, Ctx);
528 }
529 }
530}
531
532// Helper struct for maintaining refs to callsite data. As an alternative we
533// could store a pointer to the CallSiteInfo struct but we also need the frame
534// index. Using ArrayRefs instead makes it a little easier to read.
536 // Subset of frames for the corresponding CallSiteInfo.
538 // Potential targets for indirect calls.
540};
541
542static void handleCallSite(const InstrumentationOptions &Opts, Instruction &I,
543 const Function *CalledFunction,
544 ArrayRef<uint64_t> InlinedCallStack,
545 const std::vector<CallSiteEntry> &CallSiteEntries,
546 Module &M,
547 std::set<std::vector<uint64_t>> &MatchedCallSites,
549 auto &Ctx = M.getContext();
550 // Set of Callee GUIDs to attach to indirect calls. We accumulate all of them
551 // to support cases where the instuction's inlined frames match multiple call
552 // site entries, which can happen if the profile was collected from a binary
553 // where this instruction was eventually inlined into multiple callers.
555 bool CallsiteMDAdded = false;
556 for (const auto &CallSiteEntry : CallSiteEntries) {
557 // If we found and thus matched all frames on the call, create and
558 // attach call stack metadata.
560 InlinedCallStack)) {
561 NumOfMemProfMatchedCallSites++;
562 // Only need to find one with a matching call stack and add a single
563 // callsite metadata.
564 if (!CallsiteMDAdded) {
565 addCallsiteMetadata(I, InlinedCallStack, Ctx);
566
567 // Accumulate call site matching information upon request.
568 if (Opts.memprof_print_match_info) {
569 std::vector<uint64_t> CallStack;
570 append_range(CallStack, InlinedCallStack);
571 MatchedCallSites.insert(std::move(CallStack));
572 }
573 OptimizationRemark Remark(DEBUG_TYPE, "MemProfUse", &I);
574 Remark << ore::NV("CallSite", &I) << " in function "
575 << ore::NV("Caller", I.getFunction())
576 << " matched callsite with frame count "
577 << ore::NV("Frames", InlinedCallStack.size())
578 << " and stack ids";
579 for (uint64_t StackId : InlinedCallStack)
580 Remark << " " << ore::NV("StackId", StackId);
581 ORE.emit(Remark);
582
583 // If this is a direct call, we're done.
584 if (CalledFunction)
585 break;
586 CallsiteMDAdded = true;
587 }
588
589 assert(!CalledFunction && "Didn't expect direct call");
590
591 // Collect Callee GUIDs from all matching CallSiteEntries.
594 }
595 }
596 // Try to attach indirect call metadata if possible.
597 addVPMetadata(Opts, M, I, CalleeGuids.getArrayRef());
598}
599
600// Dump inline call stack for debugging purposes.
603 DenseSet<uint64_t> &SeenFrames,
604 DenseSet<uint64_t> &SeenStacks,
605 bool ProfileHasColumns) {
606 // Dump frame info. Frames are deduplicated using FrameID.
607 std::string CallStack;
608 raw_string_ostream CallStackOS(CallStack);
609 bool First = true;
610 for (const DILocation *DIL = I.getDebugLoc(); DIL;
611 DIL = DIL->getInlinedAt()) {
612 StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName();
613 if (Name.empty())
614 Name = DIL->getScope()->getSubprogram()->getName();
615 auto CalleeGUID = Function::getGUIDAssumingExternalLinkage(Name);
616 uint64_t FrameID = computeStackId(CalleeGUID, getLineOffset(DIL),
617 ProfileHasColumns ? DIL->getColumn() : 0);
618 if (SeenFrames.insert(FrameID).second) {
619 std::string DictMsg;
620 raw_string_ostream DictOS(DictMsg);
621 DictOS << "frame: " << FrameID << " " << Name << ":" << getLineOffset(DIL)
622 << ":" << (ProfileHasColumns ? DIL->getColumn() : 0);
623 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "MemProfUse", CI)
624 << DictOS.str());
625 }
626
627 if (First)
628 First = false;
629 else
630 CallStackOS << ",";
631 CallStackOS << FrameID;
632 }
633
634 // Dump inline call stack info. Stacks are deduplicated using StackHash.
635 uint64_t StackHash = llvm::MD5Hash(CallStack);
636 if (SeenStacks.insert(StackHash).second) {
637 std::string Msg;
639 OS << "inline call stack: " << CallStack;
640 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "MemProfUse", CI)
641 << OS.str());
642 }
643}
644
645static void
646readMemprof(const InstrumentationOptions &Opts, Module &M, Function &F,
648 std::map<uint64_t, AllocMatchInfo> &FullStackIdToAllocMatchInfo,
649 std::set<std::vector<uint64_t>> &MatchedCallSites,
651 OptimizationRemarkEmitter &ORE, uint64_t MaxColdSize,
652 DenseSet<uint64_t> &SeenStacks, DenseSet<uint64_t> &SeenFrames) {
653 auto &Ctx = M.getContext();
654 // Previously we used getIRPGOObjectName() here. If F is local linkage,
655 // getIRPGOObjectName() returns FuncName with prefix 'FileName;'. But
656 // llvm-profdata uses FuncName in dwarf to create GUID which doesn't
657 // contain FileName's prefix. It caused local linkage function can't
658 // find MemProfRecord. So we use getName() now.
659 // 'unique-internal-linkage-names' can make MemProf work better for local
660 // linkage function.
661 auto FuncName = F.getName();
662 auto FuncGUID = Function::getGUIDAssumingExternalLinkage(FuncName);
663 if (Opts.memprof_print_function_guids)
664 errs() << "MemProf: Function GUID " << FuncGUID << " is " << FuncName
665 << "\n";
666 std::optional<memprof::MemProfRecord> MemProfRec;
667 auto Err = MemProfReader->getMemProfRecord(FuncGUID).moveInto(MemProfRec);
668 if (Err) {
669 handleAllErrors(std::move(Err), [&](const InstrProfError &IPE) {
670 auto Err = IPE.get();
671 bool SkipWarning = false;
672 LLVM_DEBUG(dbgs() << "Error in reading profile for Func " << FuncName
673 << ": ");
675 NumOfMemProfMissing++;
676 SkipWarning = !Opts.pgo_warn_missing_function;
677 LLVM_DEBUG(dbgs() << "unknown function");
678 } else if (Err == instrprof_error::hash_mismatch) {
679 NumOfMemProfMismatch++;
680 SkipWarning =
682 (Opts.no_pgo_warn_mismatch_comdat_weak &&
683 (F.hasComdat() ||
685 LLVM_DEBUG(dbgs() << "hash mismatch (skip=" << SkipWarning << ")");
686 }
687
688 if (SkipWarning)
689 return;
690
691 std::string Msg = (IPE.message() + Twine(" ") + F.getName().str() +
692 Twine(" Hash = ") + std::to_string(FuncGUID))
693 .str();
694
695 Ctx.diagnose(
696 DiagnosticInfoPGOProfile(M.getName().data(), Msg, DS_Warning));
697 });
698 return;
699 }
700
701 NumOfMemProfFunc++;
702
703 // If requested, undrfit MemProfRecord so that the source locations in it
704 // match those in the IR.
705 if (Opts.memprof_salvage_stale_profile)
706 undriftMemProfRecord(UndriftMaps, *MemProfRec);
707
708 // Detect if there are non-zero column numbers in the profile. If not,
709 // treat all column numbers as 0 when matching (i.e. ignore any non-zero
710 // columns in the IR). The profiled binary might have been built with
711 // column numbers disabled, for example.
712 bool ProfileHasColumns = false;
713
714 // Build maps of the location hash to all profile data with that leaf location
715 // (allocation info and the callsites).
716 std::map<uint64_t, std::set<const AllocationInfo *>> LocHashToAllocInfo;
717
718 // For the callsites we need to record slices of the frame array (see comments
719 // below where the map entries are added) along with their CalleeGuids.
720 std::map<uint64_t, std::vector<CallSiteEntry>> LocHashToCallSites;
721 for (auto &AI : MemProfRec->AllocSites) {
722 NumOfMemProfAllocContextProfiles++;
723 // Associate the allocation info with the leaf frame. The later matching
724 // code will match any inlined call sequences in the IR with a longer prefix
725 // of call stack frames.
726 uint64_t StackId = computeStackId(AI.CallStack[0]);
727 LocHashToAllocInfo[StackId].insert(&AI);
728 ProfileHasColumns |= AI.CallStack[0].Column;
729 }
730 for (auto &CS : MemProfRec->CallSites) {
731 NumOfMemProfCallSiteProfiles++;
732 // Need to record all frames from leaf up to and including this function,
733 // as any of these may or may not have been inlined at this point.
734 unsigned Idx = 0;
735 for (auto &StackFrame : CS.Frames) {
736 uint64_t StackId = computeStackId(StackFrame);
737 ArrayRef<Frame> FrameSlice = ArrayRef<Frame>(CS.Frames).drop_front(Idx++);
738 // The callee guids for the slice containing all frames (due to the
739 // increment above Idx is now 1) comes from the CalleeGuids recorded in
740 // the CallSite. For the slices not containing the leaf-most frame, the
741 // callee guid is simply the function GUID of the prior frame.
742 LocHashToCallSites[StackId].push_back(
743 {FrameSlice, (Idx == 1 ? CS.CalleeGuids
745 CS.Frames[Idx - 2].Function))});
746
747 ProfileHasColumns |= StackFrame.Column;
748 // Once we find this function, we can stop recording.
749 if (StackFrame.Function == FuncGUID)
750 break;
751 }
752 assert(Idx <= CS.Frames.size() && CS.Frames[Idx - 1].Function == FuncGUID);
753 }
754
755 // Now walk the instructions, looking up the associated profile data using
756 // debug locations.
757 for (auto &BB : F) {
758 for (auto &I : BB) {
759 if (I.isDebugOrPseudoInst())
760 continue;
761 // We are only interested in calls (allocation or interior call stack
762 // context calls).
763 auto *CI = dyn_cast<CallBase>(&I);
764 if (!CI)
765 continue;
766 auto *CalledFunction = CI->getCalledFunction();
767 if (CalledFunction && CalledFunction->isIntrinsic())
768 continue;
769
771 dumpInlineCallStack(I, CI, ORE, SeenFrames, SeenStacks,
772 ProfileHasColumns);
773
774 // List of call stack ids computed from the location hashes on debug
775 // locations (leaf to inlined at root).
776 SmallVector<uint64_t, 8> InlinedCallStack;
777 // Was the leaf location found in one of the profile maps?
778 bool LeafFound = false;
779 // If leaf was found in a map, iterators pointing to its location in both
780 // of the maps. It might exist in neither, one, or both (the latter case
781 // can happen because we don't currently have discriminators to
782 // distinguish the case when a single line/col maps to both an allocation
783 // and another callsite).
784 auto AllocInfoIter = LocHashToAllocInfo.end();
785 auto CallSitesIter = LocHashToCallSites.end();
786 for (const DILocation *DIL = I.getDebugLoc(); DIL != nullptr;
787 DIL = DIL->getInlinedAt()) {
788 // Use C++ linkage name if possible. Need to compile with
789 // -fdebug-info-for-profiling to get linkage name.
790 StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName();
791 if (Name.empty())
792 Name = DIL->getScope()->getSubprogram()->getName();
793 auto CalleeGUID = Function::getGUIDAssumingExternalLinkage(Name);
794 auto StackId = computeStackId(CalleeGUID, getLineOffset(DIL),
795 ProfileHasColumns ? DIL->getColumn() : 0);
796 // Check if we have found the profile's leaf frame. If yes, collect
797 // the rest of the call's inlined context starting here. If not, see if
798 // we find a match further up the inlined context (in case the profile
799 // was missing debug frames at the leaf).
800 if (!LeafFound) {
801 AllocInfoIter = LocHashToAllocInfo.find(StackId);
802 CallSitesIter = LocHashToCallSites.find(StackId);
803 if (AllocInfoIter != LocHashToAllocInfo.end() ||
804 CallSitesIter != LocHashToCallSites.end())
805 LeafFound = true;
806 }
807 if (LeafFound)
808 InlinedCallStack.push_back(StackId);
809 }
810 // If leaf not in either of the maps, skip inst.
811 if (!LeafFound)
812 continue;
813
814 // First add !memprof metadata from allocation info, if we found the
815 // instruction's leaf location in that map, and if the rest of the
816 // instruction's locations match the prefix Frame locations on an
817 // allocation context with the same leaf.
818 if (AllocInfoIter != LocHashToAllocInfo.end() &&
819 // Only consider allocations which support hinting.
820 isAllocationWithHotColdVariant(Opts, CI->getCalledFunction(), TLI))
821 handleAllocSite(Opts, I, CI, InlinedCallStack, Ctx, ORE, MaxColdSize,
822 AllocInfoIter->second, FullStackIdToAllocMatchInfo);
823 else if (CallSitesIter != LocHashToCallSites.end())
824 // Otherwise, add callsite metadata. If we reach here then we found the
825 // instruction's leaf location in the callsites map and not the
826 // allocation map.
827 handleCallSite(Opts, I, CalledFunction, InlinedCallStack,
828 CallSitesIter->second, M, MatchedCallSites, ORE);
829 }
830 }
831}
832
833MemProfUsePass::MemProfUsePass(std::string MemoryProfileFile,
835 : MemoryProfileFileName(MemoryProfileFile), FS(FS) {
836 if (!FS)
837 this->FS = vfs::getRealFileSystem();
838}
839
841 const InstrumentationOptions &Opts = InstrumentationOptions::Global;
842 // Return immediately if the module doesn't contain any function or global
843 // variables.
844 if (M.empty() && M.globals().empty())
845 return PreservedAnalyses::all();
846
847 LLVM_DEBUG(dbgs() << "Read in memory profile:\n");
848 auto &Ctx = M.getContext();
849 auto ReaderOrErr = IndexedInstrProfReader::create(MemoryProfileFileName, *FS);
850 if (Error E = ReaderOrErr.takeError()) {
851 handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) {
852 Ctx.diagnose(
853 DiagnosticInfoPGOProfile(MemoryProfileFileName.data(), EI.message()));
854 });
855 return PreservedAnalyses::all();
856 }
857
858 std::unique_ptr<IndexedInstrProfReader> MemProfReader =
859 std::move(ReaderOrErr.get());
860 if (!MemProfReader) {
861 Ctx.diagnose(DiagnosticInfoPGOProfile(
862 MemoryProfileFileName.data(), StringRef("Cannot get MemProfReader")));
863 return PreservedAnalyses::all();
864 }
865
866 if (!MemProfReader->hasMemoryProfile()) {
867 Ctx.diagnose(DiagnosticInfoPGOProfile(MemoryProfileFileName.data(),
868 "Not a memory profile"));
869 return PreservedAnalyses::all();
870 }
871
872 const bool Changed =
873 Opts.memprof_annotate_static_data_prefix &&
874 annotateGlobalVariables(M, MemProfReader->getDataAccessProfileData());
875
876 // If the module doesn't contain any function, return after we process all
877 // global variables.
878 if (M.empty())
880
881 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
882
883 TargetLibraryInfo &TLI = FAM.getResult<TargetLibraryAnalysis>(*M.begin());
885 if (Opts.memprof_salvage_stale_profile)
886 UndriftMaps = computeUndriftMap(M, MemProfReader.get(), TLI);
887
888 // Map from the stack hash of each matched allocation context in the function
889 // profiles to match info such as the total profiled size (bytes), allocation
890 // type, number of frames matched to the allocation itself, and the full array
891 // of call stack ids.
892 std::map<uint64_t, AllocMatchInfo> FullStackIdToAllocMatchInfo;
893
894 // Set of the matched call sites, each expressed as a sequence of an inline
895 // call stack.
896 std::set<std::vector<uint64_t>> MatchedCallSites;
897
898 DenseSet<uint64_t> SeenStacks;
899 DenseSet<uint64_t> SeenFrames;
900
901 uint64_t MaxColdSize = 0;
902 if (auto *MemProfSum = MemProfReader->getMemProfSummary())
903 MaxColdSize = MemProfSum->getMaxColdTotalSize();
904
905 for (auto &F : M) {
906 if (F.isDeclaration())
907 continue;
908
909 const TargetLibraryInfo &TLI = FAM.getResult<TargetLibraryAnalysis>(F);
910 auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
911 readMemprof(Opts, M, F, MemProfReader.get(), TLI,
912 FullStackIdToAllocMatchInfo, MatchedCallSites, UndriftMaps, ORE,
913 MaxColdSize, SeenStacks, SeenFrames);
914 }
915
916 if (Opts.memprof_print_match_info) {
917 for (const auto &[Id, Info] : FullStackIdToAllocMatchInfo) {
918 for (auto Frames : Info.MatchedFramesSet) {
919 // TODO: To reduce verbosity, should we change the existing message
920 // so that we emit a list of matched frame counts in a single message
921 // about the context (instead of one message per frame count?
922 errs() << "MemProf " << getAllocTypeAttributeString(Info.AllocType)
923 << " context with id " << Id << " has total profiled size "
924 << Info.TotalSize << " is matched with " << Frames << " frames";
925 if (Opts.memprof_print_matched_alloc_stack) {
926 errs() << " and call stack";
927 for (auto &F : Info.CallStack)
928 errs() << " " << computeStackId(F);
929 }
930 errs() << "\n";
931 }
932 }
933
934 for (const auto &CallStack : MatchedCallSites) {
935 errs() << "MemProf callsite match for inline call stack";
936 for (uint64_t StackId : CallStack)
937 errs() << " " << StackId;
938 errs() << "\n";
939 }
940 }
941
943}
944
945bool MemProfUsePass::annotateGlobalVariables(
946 Module &M, const memprof::DataAccessProfData *DataAccessProf) {
947 if (M.globals().empty())
948 return false;
949
950 if (!DataAccessProf) {
951 M.addModuleFlag(Module::Warning, "EnableDataAccessProf", 0U);
952 // FIXME: Add a diagnostic message without failing the compilation when
953 // data access profile payload is not available.
954 return false;
955 }
956 M.addModuleFlag(Module::Warning, "EnableDataAccessProf", 1U);
957
958 bool Changed = false;
959 // Iterate all global variables in the module and annotate them based on
960 // data access profiles. Note it's up to the linker to decide how to map input
961 // sections to output sections, and one conservative practice is to map
962 // unlikely-prefixed ones to unlikely output section, and map the rest
963 // (hot-prefixed or prefix-less) to the canonical output section.
964 for (GlobalVariable &GVar : M.globals()) {
965 assert(!GVar.getSectionPrefix().has_value() &&
966 "GVar shouldn't have section prefix yet");
967 auto Kind = llvm::memprof::getAnnotationKind(GVar);
970 continue;
971 }
972
973 StringRef Name = GVar.getName();
974 SymbolHandleRef Handle = SymbolHandleRef(Name);
975 // Skip string literals as their mangled names don't stay stable across
976 // binary releases.
978 if (Name.starts_with(".str"))
979 continue;
980
981 if (Name.starts_with(".str")) {
982 std::optional<uint64_t> Hash = getStringContentHash(GVar);
983 if (!Hash) {
984 LLVM_DEBUG(dbgs() << "Cannot compute content hash for string literal "
985 << Name << "\n");
986 continue;
987 }
988 Handle = SymbolHandleRef(Hash.value());
989 }
990
991 // DataAccessProfRecord's get* methods will canonicalize the name under the
992 // hood before looking it up, so optimizer doesn't need to do it.
993 std::optional<DataAccessProfRecord> Record =
994 DataAccessProf->getProfileRecord(Handle);
995 // Annotate a global variable as hot if it has non-zero sampled count, and
996 // annotate it as cold if it's seen in the profiled binary
997 // file but doesn't have any access sample.
998 // For logging, optimization remark emitter requires a llvm::Function, but
999 // it's not well defined how to associate a global variable with a function.
1000 // So we just print out the static data section prefix in LLVM_DEBUG.
1001 if (Record && Record->AccessCount > 0) {
1002 ++NumOfMemProfHotGlobalVars;
1003 Changed |= GVar.setSectionPrefix("hot");
1004 LLVM_DEBUG(dbgs() << "Global variable " << Name
1005 << " is annotated as hot\n");
1006 } else if (DataAccessProf->isKnownColdSymbol(Handle)) {
1007 ++NumOfMemProfColdGlobalVars;
1008 Changed |= GVar.setSectionPrefix("unlikely");
1009 Changed = true;
1010 LLVM_DEBUG(dbgs() << "Global variable " << Name
1011 << " is annotated as unlikely\n");
1012 } else {
1013 ++NumOfMemProfUnknownGlobalVars;
1014 LLVM_DEBUG(dbgs() << "Global variable " << Name << " is not annotated\n");
1015 }
1016 }
1017
1018 return Changed;
1019}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
unsigned 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")
This file defines the DenseSet and SmallDenseSet classes.
#define DEBUG_TYPE
Module.h This file contains the declarations for the Module class.
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define G(x, y, z)
Definition MD5.cpp:55
static std::optional< uint64_t > getStringContentHash(const GlobalVariable &GVar)
static void addVPMetadata(const InstrumentationOptions &Opts, Module &M, Instruction &I, ArrayRef< GlobalValue::GUID > CalleeGuids)
static void addCallsiteMetadata(Instruction &I, ArrayRef< uint64_t > InlinedCallStack, LLVMContext &Ctx)
static void HandleUnsupportedAnnotationKinds(GlobalVariable &GVar, AnnotationKind Kind)
static void undriftMemProfRecord(const DenseMap< uint64_t, LocToLocMap > &UndriftMaps, memprof::MemProfRecord &MemProfRec)
static uint64_t computeStackId(GlobalValue::GUID Function, uint32_t LineOffset, uint32_t Column)
static uint32_t getLineOffset(const DILocation *DIL)
static void readMemprof(const InstrumentationOptions &Opts, Module &M, Function &F, IndexedInstrProfReader *MemProfReader, const TargetLibraryInfo &TLI, std::map< uint64_t, AllocMatchInfo > &FullStackIdToAllocMatchInfo, std::set< std::vector< uint64_t > > &MatchedCallSites, DenseMap< uint64_t, LocToLocMap > &UndriftMaps, OptimizationRemarkEmitter &ORE, uint64_t MaxColdSize, DenseSet< uint64_t > &SeenStacks, DenseSet< uint64_t > &SeenFrames)
static bool isAllocationWithHotColdVariant(const InstrumentationOptions &Opts, const Function *Callee, const TargetLibraryInfo &TLI)
static void dumpInlineCallStack(Instruction &I, CallBase *CI, OptimizationRemarkEmitter &ORE, DenseSet< uint64_t > &SeenFrames, DenseSet< uint64_t > &SeenStacks, bool ProfileHasColumns)
static AllocationType addCallStack(CallStackTrie &AllocTrie, const AllocationInfo *AllocInfo, uint64_t FullStackId)
static void handleAllocSite(const InstrumentationOptions &Opts, Instruction &I, CallBase *CI, ArrayRef< uint64_t > InlinedCallStack, LLVMContext &Ctx, OptimizationRemarkEmitter &ORE, uint64_t MaxColdSize, const std::set< const AllocationInfo * > &AllocInfoSet, std::map< uint64_t, AllocMatchInfo > &FullStackIdToAllocMatchInfo)
static bool stackFrameIncludesInlinedCallStack(ArrayRef< Frame > ProfileCallStack, ArrayRef< uint64_t > InlinedCallStack)
static void handleCallSite(const InstrumentationOptions &Opts, Instruction &I, const Function *CalledFunction, ArrayRef< uint64_t > InlinedCallStack, const std::vector< CallSiteEntry > &CallSiteEntries, Module &M, std::set< std::vector< uint64_t > > &MatchedCallSites, OptimizationRemarkEmitter &ORE)
AllocType
FunctionAnalysisManager FAM
const char * Msg
This file defines the SmallVector class.
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
Defines the virtual file system interface vfs::FileSystem.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
ArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
Definition ArrayRef.h:218
ArrayRef< T > drop_front(size_t N=1) const
Drop the first N elements of the array.
Definition ArrayRef.h:194
iterator end() const
Definition ArrayRef.h:130
size_t size() const
Get the array size.
Definition ArrayRef.h:141
iterator begin() const
Definition ArrayRef.h:129
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Definition DenseMap.h:758
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:767
iterator end()
Definition DenseMap.h:687
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:828
std::pair< iterator, bool > try_emplace(KeyT &&Key, Ts &&...Args)
Definition DenseMap.h:857
Implements a dense probed hash-table based set.
Definition DenseSet.h:281
Diagnostic information for the PGO profiler.
Base class for error info classes.
Definition Error.h:44
virtual std::string message() const
Return the error message as a string.
Definition Error.h:52
Lightweight error class with error context and mandatory checking.
Definition Error.h:159
static LLVM_ABI GUID getGUIDAssumingExternalLinkage(StringRef GlobalName)
Return a 64-bit global unique ID constructed from the name of a global symbol.
Definition Globals.cpp:80
uint64_t GUID
Declare a type to represent a global unique identifier for a global value.
@ AvailableExternallyLinkage
Available for inspection, not emission.
Definition GlobalValue.h:54
const Constant * getInitializer() const
getInitializer - Return the initializer for this global variable.
HashResultTy< HasherT_ > final()
Forward to HasherT::final() if available.
Definition HashBuilder.h:64
Interface to help hash various types through a hasher type.
std::enable_if_t< hashbuilder_detail::IsHashableData< T >::value, HashBuilder & > add(T Value)
Implement hashing for hashable data types, e.g. integral or enum values.
Reader for the indexed binary instrprof format.
static Expected< std::unique_ptr< IndexedInstrProfReader > > create(const Twine &Path, vfs::FileSystem &FS, const Twine &RemappingPath="")
Factory method to create an indexed reader.
instrprof_error get() const
Definition InstrProf.h:459
std::string message() const override
Return the error message as a string.
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
A smart pointer to a reference-counted object that inherits from RefCountedBase or ThreadSafeRefCount...
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:68
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
LLVM_ABI MemProfUsePass(std::string MemoryProfileFile, IntrusiveRefCntPtr< vfs::FileSystem > FS=nullptr)
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
@ Warning
Emits a warning if two values disagree.
Definition Module.h:125
Diagnostic information for optimization analysis remarks.
The optimization diagnostic interface.
bool allowExtraAnalysis(StringRef PassName) const
Whether we allow for extra compile-time budget to perform more analysis to produce fewer false positi...
LLVM_ABI void emit(DiagnosticInfoOptimizationBase &OptDiag)
Output the remark via the diagnostic handler and to the optimization record file.
Diagnostic information for applied optimization remarks.
A set of analyses that are preserved following a run of a transformation pass.
Definition Analysis.h:112
static PreservedAnalyses none()
Convenience factory function for the empty preserved set.
Definition Analysis.h:115
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
A vector that has set insertion semantics.
Definition SetVector.h:57
ArrayRef< value_type > getArrayRef() const
Definition SetVector.h:91
bool insert(const value_type &X)
Insert a new element into the SetVector.
Definition SetVector.h:157
SmallString - A SmallString is just a SmallVector with methods and accessors that make it work better...
Definition SmallString.h:26
void append(StringRef RHS)
Append from a StringRef.
Definition SmallString.h:68
void reserve(size_type N)
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
constexpr bool empty() const
Check if the string is empty.
Definition StringRef.h:141
Analysis pass providing the TargetLibraryInfo.
Provides information about what library functions are available for the current target.
LibFunc getLibFunc(StringRef funcName) const
Searches for a particular function name.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM_ABI StringRef getName() const
Return a constant reference to the value's name.
Definition Value.cpp:319
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:209
An efficient, type-erasing, non-owning reference to a callable.
Class to build a trie of call stack contexts for a particular profiled allocation call,...
LLVM_ABI void addCallStack(AllocationType AllocType, ArrayRef< uint64_t > StackIds, std::vector< ContextTotalSize > ContextSizeInfo={})
Add a call stack context with the given allocation type to the Trie.
LLVM_ABI void addSingleAllocTypeAttribute(CallBase *CI, AllocationType AT, StringRef Descriptor)
Add an attribute for the given allocation type to the call instruction.
LLVM_ABI bool buildAndAttachMIBMetadata(CallBase *CI)
Build and attach the minimal necessary MIB metadata.
Helper class to iterate through stack ids in both metadata (memprof MIB and callsite) and the corresp...
Encapsulates the data access profile data and the methods to operate on it.
LLVM_ABI std::optional< DataAccessProfRecord > getProfileRecord(const SymbolHandleRef SymID) const
Returns a profile record for SymbolID, or std::nullopt if there isn't a record.
LLVM_ABI bool isKnownColdSymbol(const SymbolHandleRef SymID) const
Returns true if SymID is seen in profiled binaries and cold.
A raw_ostream that writes to an std::string.
std::string & str()
Returns the string's reference.
Changed
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
LLVM_ABI DenseMap< uint64_t, LocToLocMap > computeUndriftMap(Module &M, IndexedInstrProfReader *MemProfReader, const TargetLibraryInfo &TLI)
DenseMap< LineLocation, LineLocation > LocToLocMap
Definition MemProfUse.h:54
LLVM_ABI MDNode * buildCallstackMetadata(ArrayRef< uint64_t > CallStack, LLVMContext &Ctx)
Build callstack metadata from the provided list of call stack ids.
LLVM_ABI AllocationType getAllocType(uint64_t TotalLifetimeAccessDensity, uint64_t AllocCount, uint64_t TotalLifetime)
Return the allocation type for a given set of memory profile values.
LLVM_ABI bool recordContextSizeInfoForAnalysis()
Whether we need to record the context size info in the alloc trie used to build metadata.
LLVM_ABI uint64_t computeFullStackId(ArrayRef< Frame > CallStack)
Helper to generate a single hash id for a given callstack, used for emitting matching statistics and ...
std::variant< StringRef, uint64_t > SymbolHandleRef
LLVM_ABI DenseMap< uint64_t, SmallVector< CallEdgeTy, 0 > > extractCallsFromIR(Module &M, const TargetLibraryInfo &TLI, function_ref< bool(uint64_t)> IsPresentInProfile=[](uint64_t) { return true;})
LLVM_ABI AnnotationKind getAnnotationKind(const GlobalVariable &GV)
Returns the annotation kind of the global variable GV.
LLVM_ABI GlobalValue::GUID getGUID(const StringRef FunctionName)
Definition MemProf.cpp:262
LLVM_ABI std::string getAllocTypeAttributeString(AllocationType Type)
Returns the string to use in attributes with the given type.
DiagnosticInfoOptimizationBase::Argument NV
uint64_t MD5Hash(const FunctionId &Obj)
Definition FunctionId.h:167
LLVM_ABI IntrusiveRefCntPtr< FileSystem > getRealFileSystem()
Gets an vfs::FileSystem for the 'real' file system, as seen by the operating system.
This is an optimization pass for GlobalISel generic memory operations.
std::array< uint8_t, NumBytes > BLAKE3Result
The constant LLVM_BLAKE3_OUT_LEN provides the default output length, 32 bytes, which is recommended f...
Definition BLAKE3.h:35
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
void handleAllErrors(Error E, HandlerTs &&... Handlers)
Behaves the same as handleErrors, except that by contract all errors must be handled by the given han...
Definition Error.h:1013
constexpr from_range_t from_range
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
auto unique(Range &&R, Predicate P)
Definition STLExtras.h:2150
auto map_range(ContainerTy &&C, FuncTy F)
Return a range that applies F to the elements of C.
Definition STLExtras.h:366
LLVM_ABI void annotateValueSite(Module &M, Instruction &Inst, const InstrProfRecord &InstrProfR, InstrProfValueKind ValueKind, uint32_t SiteIndx, uint32_t MaxMDCount=3)
Get the value profile data for value site SiteIdx from InstrProfR and annotate the instruction Inst w...
void sort(IteratorTy Start, IteratorTy End)
Definition STLExtras.h:1652
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
cl::opt< bool > AnnotateStringLiteralSectionPrefix("memprof-annotate-string-literal-section-prefix", cl::init(true), cl::Hidden, cl::desc("If true, annotate the string literal data section prefix"))
LLVM_ABI SmallVector< InstrProfValueData, 4 > getValueProfDataFromInst(const Instruction &Inst, InstrProfValueKind ValueKind, uint32_t MaxNumValueData, uint64_t &TotalC, bool GetNoICPValue=false)
Extract the value profile data from Inst and returns them if Inst is annotated with value profile dat...
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
cl::opt< bool > NoPGOWarnMismatch
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
@ First
Helpers to iterate all locations in the MemoryEffectsBase class.
Definition ModRef.h:74
void longestCommonSequence(AnchorList AnchorList1, AnchorList AnchorList2, llvm::function_ref< bool(const Function &, const Function &)> FunctionMatchesProfile, llvm::function_ref< void(Loc, Loc)> InsertMatching)
ArrayRef(const T &OneElt) -> ArrayRef< T >
bool equal(L &&LRange, R &&RRange)
Wrapper function around std::equal to detect if pair-wise elements between two ranges are the same.
Definition STLExtras.h:2162
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
std::set< unsigned > MatchedFramesSet
uint64_t TotalSize
std::vector< Frame > CallStack
AllocMatchInfo(uint64_t TotalSize, AllocationType AllocType)
AllocationType AllocType
ArrayRef< GlobalValue::GUID > CalleeGuids
ArrayRef< Frame > Frames
Summary of memprof metadata on allocations.
GlobalValue::GUID Function
Definition MemProf.h:243
uint32_t LineOffset
Definition MemProf.h:248
llvm::SmallVector< CallSiteInfo > CallSites
Definition MemProf.h:523
llvm::SmallVector< AllocationInfo > AllocSites
Definition MemProf.h:521