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 profile-guided memory
11// optimization (MemPGO).
12//
13//===----------------------------------------------------------------------===//
14
17#include "llvm/ADT/DenseSet.h"
19#include "llvm/ADT/Statistic.h"
20#include "llvm/ADT/StringRef.h"
26#include "llvm/IR/Function.h"
28#include "llvm/IR/Module.h"
33#include "llvm/Support/BLAKE3.h"
35#include "llvm/Support/Debug.h"
37#include "llvm/Support/MD5.h"
40#include <map>
41#include <set>
42
43using namespace llvm;
44using namespace llvm::memprof;
45
46#define DEBUG_TYPE "memprof"
47
48namespace 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) {
245 const InstrumentationOptions &Opts = getInstrumentationOptions(M);
247
248 for (Function &F : M) {
249 if (F.isDeclaration())
250 continue;
251
252 for (auto &BB : F) {
253 for (auto &I : BB) {
255 continue;
256
257 auto *CB = dyn_cast<CallBase>(&I);
258 auto *CalledFunction = CB->getCalledFunction();
259 // Disregard indirect calls and intrinsics.
260 if (!CalledFunction || CalledFunction->isIntrinsic())
261 continue;
262
263 StringRef CalleeName = CalledFunction->getName();
264 // True if we are calling a heap allocation function that supports
265 // hot/cold variants.
266 bool IsAlloc =
267 isAllocationWithHotColdVariant(Opts, CalledFunction, TLI);
268 // True for the first iteration below, indicating that we are looking at
269 // a leaf node.
270 bool IsLeaf = true;
271 for (const DILocation *DIL = I.getDebugLoc(); DIL;
272 DIL = DIL->getInlinedAt()) {
273 StringRef CallerName = DIL->getSubprogramLinkageName();
274 assert(!CallerName.empty() &&
275 "Be sure to enable -fdebug-info-for-profiling");
276 uint64_t CallerGUID = memprof::getGUID(CallerName);
277 uint64_t CalleeGUID = memprof::getGUID(CalleeName);
278 // Pretend that we are calling a function with GUID == 0 if we are
279 // in the inline stack leading to a heap allocation function.
280 if (IsAlloc) {
281 if (IsLeaf) {
282 // For leaf nodes, set CalleeGUID to 0 without consulting
283 // IsPresentInProfile.
284 CalleeGUID = 0;
285 } else if (!IsPresentInProfile(CalleeGUID)) {
286 // In addition to the leaf case above, continue to set CalleeGUID
287 // to 0 as long as we don't see CalleeGUID in the profile.
288 CalleeGUID = 0;
289 } else {
290 // Once we encounter a callee that exists in the profile, stop
291 // setting CalleeGUID to 0.
292 IsAlloc = false;
293 }
294 }
295
296 LineLocation Loc = {getLineOffset(DIL), DIL->getColumn()};
297 Calls[CallerGUID].emplace_back(Loc, CalleeGUID);
298 CalleeName = CallerName;
299 IsLeaf = false;
300 }
301 }
302 }
303 }
304
305 // Sort each call list by the source location.
306 for (auto &[CallerGUID, CallList] : Calls) {
307 llvm::sort(CallList);
308 CallList.erase(llvm::unique(CallList), CallList.end());
309 }
310
311 return Calls;
312}
313
316 const TargetLibraryInfo &TLI) {
318
320 MemProfReader->getMemProfCallerCalleePairs();
322 extractCallsFromIR(M, TLI, [&](uint64_t GUID) {
323 return CallsFromProfile.contains(GUID);
324 });
325
326 // Compute an undrift map for each CallerGUID.
327 for (const auto &[CallerGUID, IRAnchors] : CallsFromIR) {
328 auto It = CallsFromProfile.find(CallerGUID);
329 if (It == CallsFromProfile.end())
330 continue;
331 const auto &ProfileAnchors = It->second;
332
333 LocToLocMap Matchings;
335 ProfileAnchors, IRAnchors, std::equal_to<GlobalValue::GUID>(),
336 [&](LineLocation A, LineLocation B) { Matchings.try_emplace(A, B); });
337 [[maybe_unused]] bool Inserted =
338 UndriftMaps.try_emplace(CallerGUID, std::move(Matchings)).second;
339
340 // The insertion must succeed because we visit each GUID exactly once.
341 assert(Inserted);
342 }
343
344 return UndriftMaps;
345}
346
347// Given a MemProfRecord, undrift all the source locations present in the
348// record in place.
349static void
351 memprof::MemProfRecord &MemProfRec) {
352 // Undrift a call stack in place.
353 auto UndriftCallStack = [&](std::vector<Frame> &CallStack) {
354 for (auto &F : CallStack) {
355 auto I = UndriftMaps.find(F.Function);
356 if (I == UndriftMaps.end())
357 continue;
358 auto J = I->second.find(LineLocation(F.LineOffset, F.Column));
359 if (J == I->second.end())
360 continue;
361 auto &NewLoc = J->second;
362 F.LineOffset = NewLoc.LineOffset;
363 F.Column = NewLoc.Column;
364 }
365 };
366
367 for (auto &AS : MemProfRec.AllocSites)
368 UndriftCallStack(AS.CallStack);
369
370 for (auto &CS : MemProfRec.CallSites)
371 UndriftCallStack(CS.Frames);
372}
373
374// Helper function to process CalleeGuids and create value profile metadata
375static void addVPMetadata(const InstrumentationOptions &Opts, Module &M,
376 Instruction &I,
377 ArrayRef<GlobalValue::GUID> CalleeGuids) {
378 if (!Opts.memprof_attach_calleeguids || CalleeGuids.empty())
379 return;
380
381 // Prepare the vector of value data, initializing from any existing
382 // value-profile metadata present on the instruction so that we merge the
383 // new CalleeGuids into the existing entries.
385 uint64_t TotalCount = 0;
386
387 if (I.getMetadata(LLVMContext::MD_prof)) {
388 // Read all existing entries so we can merge them. Use a large
389 // MaxNumValueData to retrieve all existing entries.
390 VDs = getValueProfDataFromInst(I, IPVK_IndirectCallTarget,
391 /*MaxNumValueData=*/UINT32_MAX, TotalCount);
392 }
393
394 // Save the original size for use later in detecting whether any were added.
395 const size_t OriginalSize = VDs.size();
396
397 // Initialize the set of existing guids with the original list.
398 DenseSet<uint64_t> ExistingValues(
401 VDs, [](const InstrProfValueData &Entry) { return Entry.Value; }));
402
403 // Merge CalleeGuids into list of existing VDs, by appending any that are not
404 // already included.
405 VDs.reserve(OriginalSize + CalleeGuids.size());
406 for (auto G : CalleeGuids) {
407 if (!ExistingValues.insert(G).second)
408 continue;
409 InstrProfValueData NewEntry;
410 NewEntry.Value = G;
411 // For MemProf, we don't have actual call counts, so we assign
412 // a weight of 1 to each potential target.
413 // TODO: Consider making this weight configurable or increasing it to
414 // improve effectiveness for ICP.
415 NewEntry.Count = 1;
416 TotalCount += NewEntry.Count;
417 VDs.push_back(NewEntry);
418 }
419
420 // Update the VP metadata if we added any new callee GUIDs to the list.
421 assert(VDs.size() >= OriginalSize);
422 if (VDs.size() == OriginalSize)
423 return;
424
425 // First clear the existing !prof.
426 I.setMetadata(LLVMContext::MD_prof, nullptr);
427
428 // No need to sort the updated VDs as all appended entries have the same count
429 // of 1, which is no larger than any existing entries. The incoming list of
430 // CalleeGuids should already be deterministic for a given profile.
431 annotateValueSite(M, I, VDs, TotalCount, IPVK_IndirectCallTarget, VDs.size());
432}
433
434static void handleAllocSite(
435 const InstrumentationOptions &Opts, Instruction &I, CallBase *CI,
436 ArrayRef<uint64_t> InlinedCallStack, LLVMContext &Ctx,
437 OptimizationRemarkEmitter &ORE, uint64_t MaxColdSize,
438 const std::set<const AllocationInfo *> &AllocInfoSet,
439 std::map<uint64_t, AllocMatchInfo> &FullStackIdToAllocMatchInfo) {
440 // TODO: Remove this once the profile creation logic deduplicates contexts
441 // that are the same other than the IsInlineFrame bool. Until then, keep the
442 // largest.
443 DenseMap<uint64_t, const AllocationInfo *> UniqueFullContextIdAllocInfo;
444 for (auto *AllocInfo : AllocInfoSet) {
445 auto FullStackId = computeFullStackId(AllocInfo->CallStack);
446 auto [It, Inserted] =
447 UniqueFullContextIdAllocInfo.insert({FullStackId, AllocInfo});
448 // If inserted entry, done.
449 if (Inserted)
450 continue;
451 // Keep the larger one, or the noncold one if they are the same size.
452 auto CurSize = It->second->Info.getTotalSize();
453 auto NewSize = AllocInfo->Info.getTotalSize();
454 if ((CurSize > NewSize) ||
455 (CurSize == NewSize &&
457 continue;
458 It->second = AllocInfo;
459 }
460 // We may match this instruction's location list to multiple MIB
461 // contexts. Add them to a Trie specialized for trimming the contexts to
462 // the minimal needed to disambiguate contexts with unique behavior.
463 CallStackTrie AllocTrie(&ORE, MaxColdSize);
464 uint64_t TotalSize = 0;
465 uint64_t TotalColdSize = 0;
466 for (auto &[FullStackId, AllocInfo] : UniqueFullContextIdAllocInfo) {
467 // Check the full inlined call stack against this one.
468 // If we found and thus matched all frames on the call, include
469 // this MIB.
471 InlinedCallStack)) {
472 NumOfMemProfMatchedAllocContexts++;
473 auto AllocType = addCallStack(AllocTrie, AllocInfo, FullStackId);
474 TotalSize += AllocInfo->Info.getTotalSize();
476 TotalColdSize += AllocInfo->Info.getTotalSize();
477 // Record information about the allocation if match info printing
478 // was requested.
479 if (Opts.memprof_print_match_info) {
480 assert(FullStackId != 0);
481 auto [Iter, Inserted] = FullStackIdToAllocMatchInfo.try_emplace(
482 FullStackId,
483 AllocMatchInfo(AllocInfo->Info.getTotalSize(), AllocType));
484 // Always insert the new matched frame count, since it may differ.
485 Iter->second.MatchedFramesSet.insert(InlinedCallStack.size());
486 if (Inserted && Opts.memprof_print_matched_alloc_stack)
487 Iter->second.CallStack.insert(Iter->second.CallStack.begin(),
488 AllocInfo->CallStack.begin(),
489 AllocInfo->CallStack.end());
490 }
491 ORE.emit(
492 OptimizationRemark(DEBUG_TYPE, "MemProfUse", CI)
493 << ore::NV("AllocationCall", CI) << " in function "
494 << ore::NV("Caller", CI->getFunction())
495 << " matched alloc context with alloc type "
497 << " total size " << ore::NV("Size", AllocInfo->Info.getTotalSize())
498 << " full context id " << ore::NV("Context", FullStackId)
499 << " frame count " << ore::NV("Frames", InlinedCallStack.size()));
500 }
501 }
502 // If the threshold for the percent of cold bytes is less than 100%,
503 // and not all bytes are cold, see if we should still hint this
504 // allocation as cold without context sensitivity.
505 if (TotalColdSize < TotalSize && Opts.memprof_matching_cold_threshold < 100 &&
506 TotalColdSize * 100 >= Opts.memprof_matching_cold_threshold * TotalSize) {
507 AllocTrie.addSingleAllocTypeAttribute(CI, AllocationType::Cold, "dominant");
508 return;
509 }
510
511 // We might not have matched any to the full inlined call stack.
512 // But if we did, create and attach metadata, or a function attribute if
513 // all contexts have identical profiled behavior.
514 if (!AllocTrie.empty()) {
515 NumOfMemProfMatchedAllocs++;
516 // MemprofMDAttached will be false if a function attribute was
517 // attached.
518 bool MemprofMDAttached = AllocTrie.buildAndAttachMIBMetadata(CI);
519 assert(MemprofMDAttached == I.hasMetadata(LLVMContext::MD_memprof));
520 if (MemprofMDAttached) {
521 // Add callsite metadata for the instruction's location list so that
522 // it simpler later on to identify which part of the MIB contexts
523 // are from this particular instruction (including during inlining,
524 // when the callsite metadata will be updated appropriately).
525 // FIXME: can this be changed to strip out the matching stack
526 // context ids from the MIB contexts and not add any callsite
527 // metadata here to save space?
528 addCallsiteMetadata(I, InlinedCallStack, Ctx);
529 }
530 }
531}
532
533// Helper struct for maintaining refs to callsite data. As an alternative we
534// could store a pointer to the CallSiteInfo struct but we also need the frame
535// index. Using ArrayRefs instead makes it a little easier to read.
537 // Subset of frames for the corresponding CallSiteInfo.
539 // Potential targets for indirect calls.
541};
542
543static void handleCallSite(const InstrumentationOptions &Opts, Instruction &I,
544 const Function *CalledFunction,
545 ArrayRef<uint64_t> InlinedCallStack,
546 const std::vector<CallSiteEntry> &CallSiteEntries,
547 Module &M,
548 std::set<std::vector<uint64_t>> &MatchedCallSites,
550 auto &Ctx = M.getContext();
551 // Set of Callee GUIDs to attach to indirect calls. We accumulate all of them
552 // to support cases where the instruction's inlined frames match multiple call
553 // site entries, which can happen if the profile was collected from a binary
554 // where this instruction was eventually inlined into multiple callers.
556 bool CallsiteMDAdded = false;
557 for (const auto &CallSiteEntry : CallSiteEntries) {
558 // If we found and thus matched all frames on the call, create and
559 // attach call stack metadata.
561 InlinedCallStack)) {
562 NumOfMemProfMatchedCallSites++;
563 // Only need to find one with a matching call stack and add a single
564 // callsite metadata.
565 if (!CallsiteMDAdded) {
566 addCallsiteMetadata(I, InlinedCallStack, Ctx);
567
568 // Accumulate call site matching information upon request.
569 if (Opts.memprof_print_match_info) {
570 std::vector<uint64_t> CallStack;
571 append_range(CallStack, InlinedCallStack);
572 MatchedCallSites.insert(std::move(CallStack));
573 }
574 OptimizationRemark Remark(DEBUG_TYPE, "MemProfUse", &I);
575 Remark << ore::NV("CallSite", &I) << " in function "
576 << ore::NV("Caller", I.getFunction())
577 << " matched callsite with frame count "
578 << ore::NV("Frames", InlinedCallStack.size())
579 << " and stack ids";
580 for (uint64_t StackId : InlinedCallStack)
581 Remark << " " << ore::NV("StackId", StackId);
582 ORE.emit(Remark);
583
584 // If this is a direct call, we're done.
585 if (CalledFunction)
586 break;
587 CallsiteMDAdded = true;
588 }
589
590 assert(!CalledFunction && "Didn't expect direct call");
591
592 // Collect Callee GUIDs from all matching CallSiteEntries.
595 }
596 }
597 // Try to attach indirect call metadata if possible.
598 addVPMetadata(Opts, M, I, CalleeGuids.getArrayRef());
599}
600
601// Dump inline call stack for debugging purposes.
604 DenseSet<uint64_t> &SeenFrames,
605 DenseSet<uint64_t> &SeenStacks,
606 bool ProfileHasColumns) {
607 // Dump frame info. Frames are deduplicated using FrameID.
608 std::string CallStack;
609 raw_string_ostream CallStackOS(CallStack);
610 bool First = true;
611 for (const DILocation *DIL = I.getDebugLoc(); DIL;
612 DIL = DIL->getInlinedAt()) {
613 StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName();
614 if (Name.empty())
615 Name = DIL->getScope()->getSubprogram()->getName();
616 auto CalleeGUID = Function::getGUIDAssumingExternalLinkage(Name);
617 uint64_t FrameID = computeStackId(CalleeGUID, getLineOffset(DIL),
618 ProfileHasColumns ? DIL->getColumn() : 0);
619 if (SeenFrames.insert(FrameID).second) {
620 std::string DictMsg;
621 raw_string_ostream DictOS(DictMsg);
622 DictOS << "frame: " << FrameID << " " << Name << ":" << getLineOffset(DIL)
623 << ":" << (ProfileHasColumns ? DIL->getColumn() : 0);
624 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "MemProfUse", CI)
625 << DictOS.str());
626 }
627
628 if (First)
629 First = false;
630 else
631 CallStackOS << ",";
632 CallStackOS << FrameID;
633 }
634
635 // Dump inline call stack info. Stacks are deduplicated using StackHash.
636 uint64_t StackHash = llvm::MD5Hash(CallStack);
637 if (SeenStacks.insert(StackHash).second) {
638 std::string Msg;
640 OS << "inline call stack: " << CallStack;
641 ORE.emit(OptimizationRemarkAnalysis(DEBUG_TYPE, "MemProfUse", CI)
642 << OS.str());
643 }
644}
645
646static void
647readMemprof(const InstrumentationOptions &Opts, Module &M, Function &F,
649 std::map<uint64_t, AllocMatchInfo> &FullStackIdToAllocMatchInfo,
650 std::set<std::vector<uint64_t>> &MatchedCallSites,
652 OptimizationRemarkEmitter &ORE, uint64_t MaxColdSize,
653 DenseSet<uint64_t> &SeenStacks, DenseSet<uint64_t> &SeenFrames) {
654 auto &Ctx = M.getContext();
655 // Previously we used getIRPGOObjectName() here. If F is local linkage,
656 // getIRPGOObjectName() returns FuncName with prefix 'FileName;'. But
657 // llvm-profdata uses FuncName in dwarf to create GUID which doesn't
658 // contain FileName's prefix. It caused local linkage function can't
659 // find MemProfRecord. So we use getName() now.
660 // 'unique-internal-linkage-names' can make MemProf work better for local
661 // linkage function.
662 auto FuncName = F.getName();
663 auto FuncGUID = Function::getGUIDAssumingExternalLinkage(FuncName);
664 if (Opts.memprof_print_function_guids)
665 errs() << "MemProf: Function GUID " << FuncGUID << " is " << FuncName
666 << "\n";
667 std::optional<memprof::MemProfRecord> MemProfRec;
668 auto Err = MemProfReader->getMemProfRecord(FuncGUID).moveInto(MemProfRec);
669 if (Err) {
670 handleAllErrors(std::move(Err), [&](const InstrProfError &IPE) {
671 auto Err = IPE.get();
672 bool SkipWarning = false;
673 LLVM_DEBUG(dbgs() << "Error in reading profile for Func " << FuncName
674 << ": ");
676 NumOfMemProfMissing++;
677 SkipWarning = !Opts.pgo_warn_missing_function;
678 LLVM_DEBUG(dbgs() << "unknown function");
679 } else if (Err == instrprof_error::hash_mismatch) {
680 NumOfMemProfMismatch++;
681 SkipWarning =
683 (Opts.no_pgo_warn_mismatch_comdat_weak &&
684 (F.hasComdat() ||
686 LLVM_DEBUG(dbgs() << "hash mismatch (skip=" << SkipWarning << ")");
687 }
688
689 if (SkipWarning)
690 return;
691
692 std::string Msg = (IPE.message() + Twine(" ") + F.getName().str() +
693 Twine(" Hash = ") + std::to_string(FuncGUID))
694 .str();
695
696 Ctx.diagnose(
697 DiagnosticInfoPGOProfile(M.getName().data(), Msg, DS_Warning));
698 });
699 return;
700 }
701
702 NumOfMemProfFunc++;
703
704 // If requested, undrfit MemProfRecord so that the source locations in it
705 // match those in the IR.
706 if (Opts.memprof_salvage_stale_profile)
707 undriftMemProfRecord(UndriftMaps, *MemProfRec);
708
709 // Detect if there are non-zero column numbers in the profile. If not,
710 // treat all column numbers as 0 when matching (i.e. ignore any non-zero
711 // columns in the IR). The profiled binary might have been built with
712 // column numbers disabled, for example.
713 bool ProfileHasColumns = false;
714
715 // Build maps of the location hash to all profile data with that leaf location
716 // (allocation info and the callsites).
717 std::map<uint64_t, std::set<const AllocationInfo *>> LocHashToAllocInfo;
718
719 // For the callsites we need to record slices of the frame array (see comments
720 // below where the map entries are added) along with their CalleeGuids.
721 std::map<uint64_t, std::vector<CallSiteEntry>> LocHashToCallSites;
722 for (auto &AI : MemProfRec->AllocSites) {
723 NumOfMemProfAllocContextProfiles++;
724 // Associate the allocation info with the leaf frame. The later matching
725 // code will match any inlined call sequences in the IR with a longer prefix
726 // of call stack frames.
727 uint64_t StackId = computeStackId(AI.CallStack[0]);
728 LocHashToAllocInfo[StackId].insert(&AI);
729 ProfileHasColumns |= AI.CallStack[0].Column;
730 }
731 for (auto &CS : MemProfRec->CallSites) {
732 NumOfMemProfCallSiteProfiles++;
733 // Need to record all frames from leaf up to and including this function,
734 // as any of these may or may not have been inlined at this point.
735 unsigned Idx = 0;
736 for (auto &StackFrame : CS.Frames) {
737 uint64_t StackId = computeStackId(StackFrame);
738 ArrayRef<Frame> FrameSlice = ArrayRef<Frame>(CS.Frames).drop_front(Idx++);
739 // The callee guids for the slice containing all frames (due to the
740 // increment above Idx is now 1) comes from the CalleeGuids recorded in
741 // the CallSite. For the slices not containing the leaf-most frame, the
742 // callee guid is simply the function GUID of the prior frame.
743 LocHashToCallSites[StackId].push_back(
744 {FrameSlice, (Idx == 1 ? CS.CalleeGuids
746 CS.Frames[Idx - 2].Function))});
747
748 ProfileHasColumns |= StackFrame.Column;
749 // Once we find this function, we can stop recording.
750 if (StackFrame.Function == FuncGUID)
751 break;
752 }
753 assert(Idx <= CS.Frames.size() && CS.Frames[Idx - 1].Function == FuncGUID);
754 }
755
756 // Now walk the instructions, looking up the associated profile data using
757 // debug locations.
758 for (auto &BB : F) {
759 for (auto &I : BB) {
760 // We are only interested in calls (allocation or interior call stack
761 // context calls).
762 auto *CI = dyn_cast<CallBase>(&I);
763 if (!CI)
764 continue;
765 auto *CalledFunction = CI->getCalledFunction();
766 if (CalledFunction && CalledFunction->isIntrinsic())
767 continue;
768
770 dumpInlineCallStack(I, CI, ORE, SeenFrames, SeenStacks,
771 ProfileHasColumns);
772
773 // List of call stack ids computed from the location hashes on debug
774 // locations (leaf to inlined at root).
775 SmallVector<uint64_t, 8> InlinedCallStack;
776 // Was the leaf location found in one of the profile maps?
777 bool LeafFound = false;
778 // If leaf was found in a map, iterators pointing to its location in both
779 // of the maps. It might exist in neither, one, or both (the latter case
780 // can happen because we don't currently have discriminators to
781 // distinguish the case when a single line/col maps to both an allocation
782 // and another callsite).
783 auto AllocInfoIter = LocHashToAllocInfo.end();
784 auto CallSitesIter = LocHashToCallSites.end();
785 for (const DILocation *DIL = I.getDebugLoc(); DIL != nullptr;
786 DIL = DIL->getInlinedAt()) {
787 // Use C++ linkage name if possible. Need to compile with
788 // -fdebug-info-for-profiling to get linkage name.
789 StringRef Name = DIL->getScope()->getSubprogram()->getLinkageName();
790 if (Name.empty())
791 Name = DIL->getScope()->getSubprogram()->getName();
792 auto CalleeGUID = Function::getGUIDAssumingExternalLinkage(Name);
793 auto StackId = computeStackId(CalleeGUID, getLineOffset(DIL),
794 ProfileHasColumns ? DIL->getColumn() : 0);
795 // Check if we have found the profile's leaf frame. If yes, collect
796 // the rest of the call's inlined context starting here. If not, see if
797 // we find a match further up the inlined context (in case the profile
798 // was missing debug frames at the leaf).
799 if (!LeafFound) {
800 AllocInfoIter = LocHashToAllocInfo.find(StackId);
801 CallSitesIter = LocHashToCallSites.find(StackId);
802 if (AllocInfoIter != LocHashToAllocInfo.end() ||
803 CallSitesIter != LocHashToCallSites.end())
804 LeafFound = true;
805 }
806 if (LeafFound)
807 InlinedCallStack.push_back(StackId);
808 }
809 // If leaf not in either of the maps, skip inst.
810 if (!LeafFound)
811 continue;
812
813 // First add !memprof metadata from allocation info, if we found the
814 // instruction's leaf location in that map, and if the rest of the
815 // instruction's locations match the prefix Frame locations on an
816 // allocation context with the same leaf.
817 if (AllocInfoIter != LocHashToAllocInfo.end() &&
818 // Only consider allocations which support hinting.
819 isAllocationWithHotColdVariant(Opts, CI->getCalledFunction(), TLI))
820 handleAllocSite(Opts, I, CI, InlinedCallStack, Ctx, ORE, MaxColdSize,
821 AllocInfoIter->second, FullStackIdToAllocMatchInfo);
822 else if (CallSitesIter != LocHashToCallSites.end())
823 // Otherwise, add callsite metadata. If we reach here then we found the
824 // instruction's leaf location in the callsites map and not the
825 // allocation map.
826 handleCallSite(Opts, I, CalledFunction, InlinedCallStack,
827 CallSitesIter->second, M, MatchedCallSites, ORE);
828 }
829 }
830}
831
832MemProfUsePass::MemProfUsePass(std::string MemoryProfileFile,
834 : MemoryProfileFileName(MemoryProfileFile), FS(FS) {
835 if (!FS)
836 this->FS = vfs::getRealFileSystem();
837}
838
840 const InstrumentationOptions &Opts = getInstrumentationOptions(M);
841 // Return immediately if the module doesn't contain any function or global
842 // variables.
843 if (M.empty() && M.globals().empty())
844 return PreservedAnalyses::all();
845
846 LLVM_DEBUG(dbgs() << "Read in memory profile:\n");
847 auto &Ctx = M.getContext();
848 auto ReaderOrErr = IndexedInstrProfReader::create(MemoryProfileFileName, *FS);
849 if (Error E = ReaderOrErr.takeError()) {
850 handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) {
851 Ctx.diagnose(
852 DiagnosticInfoPGOProfile(MemoryProfileFileName.data(), EI.message()));
853 });
854 return PreservedAnalyses::all();
855 }
856
857 std::unique_ptr<IndexedInstrProfReader> MemProfReader =
858 std::move(ReaderOrErr.get());
859 if (!MemProfReader) {
860 Ctx.diagnose(DiagnosticInfoPGOProfile(
861 MemoryProfileFileName.data(), StringRef("Cannot get MemProfReader")));
862 return PreservedAnalyses::all();
863 }
864
865 if (!MemProfReader->hasMemoryProfile()) {
866 Ctx.diagnose(DiagnosticInfoPGOProfile(MemoryProfileFileName.data(),
867 "Not a memory profile"));
868 return PreservedAnalyses::all();
869 }
870
871 const bool Changed =
872 Opts.memprof_annotate_static_data_prefix &&
873 annotateGlobalVariables(M, MemProfReader->getDataAccessProfileData());
874
875 // If the module doesn't contain any function, return after we process all
876 // global variables.
877 if (M.empty())
879
880 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
881
882 TargetLibraryInfo &TLI = FAM.getResult<TargetLibraryAnalysis>(*M.begin());
884 if (Opts.memprof_salvage_stale_profile)
885 UndriftMaps = computeUndriftMap(M, MemProfReader.get(), TLI);
886
887 // Map from the stack hash of each matched allocation context in the function
888 // profiles to match info such as the total profiled size (bytes), allocation
889 // type, number of frames matched to the allocation itself, and the full array
890 // of call stack ids.
891 std::map<uint64_t, AllocMatchInfo> FullStackIdToAllocMatchInfo;
892
893 // Set of the matched call sites, each expressed as a sequence of an inline
894 // call stack.
895 std::set<std::vector<uint64_t>> MatchedCallSites;
896
897 DenseSet<uint64_t> SeenStacks;
898 DenseSet<uint64_t> SeenFrames;
899
900 uint64_t MaxColdSize = 0;
901 if (auto *MemProfSum = MemProfReader->getMemProfSummary())
902 MaxColdSize = MemProfSum->getMaxColdTotalSize();
903
904 for (auto &F : M) {
905 if (F.isDeclaration())
906 continue;
907
908 const TargetLibraryInfo &TLI = FAM.getResult<TargetLibraryAnalysis>(F);
909 auto &ORE = FAM.getResult<OptimizationRemarkEmitterAnalysis>(F);
910 readMemprof(Opts, M, F, MemProfReader.get(), TLI,
911 FullStackIdToAllocMatchInfo, MatchedCallSites, UndriftMaps, ORE,
912 MaxColdSize, SeenStacks, SeenFrames);
913 }
914
915 if (Opts.memprof_print_match_info) {
916 for (const auto &[Id, Info] : FullStackIdToAllocMatchInfo) {
917 for (auto Frames : Info.MatchedFramesSet) {
918 // TODO: To reduce verbosity, should we change the existing message
919 // so that we emit a list of matched frame counts in a single message
920 // about the context (instead of one message per frame count?
921 errs() << "MemProf " << getAllocTypeAttributeString(Info.AllocType)
922 << " context with id " << Id << " has total profiled size "
923 << Info.TotalSize << " is matched with " << Frames << " frames";
924 if (Opts.memprof_print_matched_alloc_stack) {
925 errs() << " and call stack";
926 for (auto &F : Info.CallStack)
927 errs() << " " << computeStackId(F);
928 }
929 errs() << "\n";
930 }
931 }
932
933 for (const auto &CallStack : MatchedCallSites) {
934 errs() << "MemProf callsite match for inline call stack";
935 for (uint64_t StackId : CallStack)
936 errs() << " " << StackId;
937 errs() << "\n";
938 }
939 }
940
942}
943
944bool MemProfUsePass::annotateGlobalVariables(
945 Module &M, const memprof::DataAccessProfData *DataAccessProf) {
946 if (M.globals().empty())
947 return false;
948
949 if (!DataAccessProf) {
950 M.addModuleFlag(Module::Warning, "EnableDataAccessProf", 0U);
951 // FIXME: Add a diagnostic message without failing the compilation when
952 // data access profile payload is not available.
953 return false;
954 }
955 M.addModuleFlag(Module::Warning, "EnableDataAccessProf", 1U);
956
957 bool Changed = false;
958 // Iterate all global variables in the module and annotate them based on
959 // data access profiles. Note it's up to the linker to decide how to map input
960 // sections to output sections, and one conservative practice is to map
961 // unlikely-prefixed ones to unlikely output section, and map the rest
962 // (hot-prefixed or prefix-less) to the canonical output section.
963 for (GlobalVariable &GVar : M.globals()) {
964 assert(!GVar.getSectionPrefix().has_value() &&
965 "GVar shouldn't have section prefix yet");
966 auto Kind = llvm::memprof::getAnnotationKind(GVar);
969 continue;
970 }
971
972 StringRef Name = GVar.getName();
973 SymbolHandleRef Handle = SymbolHandleRef(Name);
974 // Skip string literals as their mangled names don't stay stable across
975 // binary releases.
976 if (!shouldAnnotateStringLiteralSectionPrefix(GVar.getContext()))
977 if (Name.starts_with(".str"))
978 continue;
979
980 if (Name.starts_with(".str")) {
981 std::optional<uint64_t> Hash = getStringContentHash(GVar);
982 if (!Hash) {
983 LLVM_DEBUG(dbgs() << "Cannot compute content hash for string literal "
984 << Name << "\n");
985 continue;
986 }
987 Handle = SymbolHandleRef(Hash.value());
988 }
989
990 // DataAccessProfRecord's get* methods will canonicalize the name under the
991 // hood before looking it up, so optimizer doesn't need to do it.
992 std::optional<DataAccessProfRecord> Record =
993 DataAccessProf->getProfileRecord(Handle);
994 // Annotate a global variable as hot if it has non-zero sampled count, and
995 // annotate it as cold if it's seen in the profiled binary
996 // file but doesn't have any access sample.
997 // For logging, optimization remark emitter requires a llvm::Function, but
998 // it's not well defined how to associate a global variable with a function.
999 // So we just print out the static data section prefix in LLVM_DEBUG.
1000 if (Record && Record->AccessCount > 0) {
1001 ++NumOfMemProfHotGlobalVars;
1002 Changed |= GVar.setSectionPrefix("hot");
1003 LLVM_DEBUG(dbgs() << "Global variable " << Name
1004 << " is annotated as hot\n");
1005 } else if (DataAccessProf->isKnownColdSymbol(Handle)) {
1006 ++NumOfMemProfColdGlobalVars;
1007 Changed |= GVar.setSectionPrefix("unlikely");
1008 Changed = true;
1009 LLVM_DEBUG(dbgs() << "Global variable " << Name
1010 << " is annotated as unlikely\n");
1011 } else {
1012 ++NumOfMemProfUnknownGlobalVars;
1013 LLVM_DEBUG(dbgs() << "Global variable " << Name << " is not annotated\n");
1014 }
1015 }
1016
1017 return Changed;
1018}
const TargetLowering & TLI
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")
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:757
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:766
iterator end()
Definition DenseMap.h:686
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:827
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
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:76
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:28
void append(StringRef RHS)
Append from a StringRef.
Definition SmallString.h:70
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.
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:314
std::pair< iterator, bool > insert(const ValueT &V)
Definition DenseSet.h:210
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.
#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:55
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.
LLVM_ABI bool shouldAnnotateStringLiteralSectionPrefix(const LLVMContext &C)
Return -memprof-annotate-string-literal-section-prefix.
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.
const InstrumentationOptions & getInstrumentationOptions(const LLVMContext &C)
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
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