LLVM 24.0.0git
MemProfContextDisambiguation.cpp
Go to the documentation of this file.
1//==-- MemProfContextDisambiguation.cpp - Disambiguate contexts -------------=//
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 support for context disambiguation of allocation
10// calls for profile-guided memory optimization (MemPGO). Specifically, it uses
11// MemProf profiles which indicate context specific allocation behavior
12// (currently distinguishing cold vs hot memory allocations). Cloning is
13// performed to expose the cold allocation call contexts, and the allocation
14// calls are subsequently annotated with an attribute for later transformation.
15//
16// The transformations can be performed either directly on IR (regular LTO), or
17// on a ThinLTO index (and later applied to the IR during the ThinLTO backend).
18// Both types of LTO operate on a the same base graph representation, which
19// uses CRTP to support either IR or Index formats.
20//
21//===----------------------------------------------------------------------===//
22
24#include "llvm/ADT/DenseMap.h"
25#include "llvm/ADT/DenseSet.h"
26#include "llvm/ADT/MapVector.h"
29#include "llvm/ADT/SmallSet.h"
31#include "llvm/ADT/Statistic.h"
38#include "llvm/IR/Module.h"
40#include "llvm/Pass.h"
43#include "llvm/Support/SHA1.h"
45#include "llvm/Transforms/IPO.h"
49#include <deque>
50#include <sstream>
51#include <vector>
52using namespace llvm;
53using namespace llvm::memprof;
54
55#define DEBUG_TYPE "memprof-context-disambiguation"
56
57STATISTIC(FunctionClonesAnalysis,
58 "Number of function clones created during whole program analysis");
59STATISTIC(FunctionClonesThinBackend,
60 "Number of function clones created during ThinLTO backend");
61STATISTIC(FunctionsClonedThinBackend,
62 "Number of functions that had clones created during ThinLTO backend");
64 FunctionCloneDuplicatesThinBackend,
65 "Number of function clone duplicates detected during ThinLTO backend");
66STATISTIC(AllocTypeNotCold, "Number of not cold static allocations (possibly "
67 "cloned) during whole program analysis");
68STATISTIC(AllocTypeCold, "Number of cold static allocations (possibly cloned) "
69 "during whole program analysis");
70STATISTIC(AllocTypeAmbiguous,
71 "Number of ambiguous static allocations (possibly cloned) during "
72 "whole program analysis");
73STATISTIC(AllocTypeNotColdThinBackend,
74 "Number of not cold static allocations (possibly cloned) during "
75 "ThinLTO backend");
76STATISTIC(AllocTypeColdThinBackend, "Number of cold static allocations "
77 "(possibly cloned) during ThinLTO backend");
78STATISTIC(AllocTypeAmbiguousThinBackend,
79 "Number of ambiguous static allocations (possibly cloned) during "
80 "ThinLTO backend");
81STATISTIC(OrigAllocsThinBackend,
82 "Number of original (not cloned) allocations with memprof profiles "
83 "during ThinLTO backend");
85 AllocVersionsThinBackend,
86 "Number of allocation versions (including clones) during ThinLTO backend");
87STATISTIC(MaxAllocVersionsThinBackend,
88 "Maximum number of allocation versions created for an original "
89 "allocation during ThinLTO backend");
90STATISTIC(UnclonableAllocsThinBackend,
91 "Number of unclonable ambigous allocations during ThinLTO backend");
92STATISTIC(RemovedEdgesWithMismatchedCallees,
93 "Number of edges removed due to mismatched callees (profiled vs IR)");
94STATISTIC(FoundProfiledCalleeCount,
95 "Number of profiled callees found via tail calls");
96STATISTIC(FoundProfiledCalleeDepth,
97 "Aggregate depth of profiled callees found via tail calls");
98STATISTIC(FoundProfiledCalleeMaxDepth,
99 "Maximum depth of profiled callees found via tail calls");
100STATISTIC(FoundProfiledCalleeNonUniquelyCount,
101 "Number of profiled callees found via multiple tail call chains");
102STATISTIC(FoundProfiledCalleeIndirectTailCallCount,
103 "Number of tail calls in chains to profiled callees that are "
104 "indirect (thin link)");
105STATISTIC(IndirectTailCallsRecordedForICPThinBackend,
106 "Number of indirect tail calls recorded for ICP for cloning during "
107 "ThinLTO backend");
108STATISTIC(DeferredBackedges, "Number of backedges with deferred cloning");
109STATISTIC(NewMergedNodes, "Number of new nodes created during merging");
110STATISTIC(NonNewMergedNodes, "Number of non new nodes used during merging");
111STATISTIC(MissingAllocForContextId,
112 "Number of missing alloc nodes for context ids");
113STATISTIC(SkippedCallsCloning,
114 "Number of calls skipped during cloning due to unexpected operand");
115STATISTIC(MismatchedCloneAssignments,
116 "Number of callsites assigned to call multiple non-matching clones");
117STATISTIC(TotalMergeInvokes, "Number of merge invocations for nodes");
118STATISTIC(TotalMergeIters, "Number of merge iterations for nodes");
119STATISTIC(MaxMergeIters, "Max merge iterations for nodes");
120STATISTIC(NumImportantContextIds, "Number of important context ids");
121STATISTIC(NumFixupEdgeIdsInserted, "Number of fixup edge ids inserted");
122STATISTIC(NumFixupEdgesAdded, "Number of fixup edges added");
123STATISTIC(NumFixedContexts, "Number of contexts with fixed edges");
124STATISTIC(NumImplicitCallersAssigned,
125 "Number of callsite clones without an edge to a callee's clones "
126 "assigned the callee function clone of their original node");
127STATISTIC(NumImplicitCallersSourced,
128 "Number of calls in function clones whose callee was taken from a "
129 "callsite clone an implicit caller requires");
130STATISTIC(NumTrimmedContextIds,
131 "Number of context ids with call stacks trimmed at a callsite");
132STATISTIC(NumImplicitCallersUnresolved,
133 "Number of callsite clones without an edge to a callee's clones "
134 "left in a function clone calling a conflicting callee clone");
135STATISTIC(AliaseesPrevailingInDiffModuleFromAlias,
136 "Number of aliasees prevailing in a different module than its alias");
137STATISTIC(NumClonedCalleeCallsites,
138 "Number of summary callsites assigned to call a cloned callee (thin "
139 "link)");
140STATISTIC(NumClonedCalleeIndirectCallsites,
141 "Number of summary callsites assigned to call a cloned callee with "
142 "an indirect call edge (thin link)");
143STATISTIC(NumClonedCalleeEdgesMarkedRequiresDeclImport,
144 "Number of summary indirect call edges to cloned callees marked as "
145 "requiring a declaration import (thin link)");
146
148 "memprof-dot-file-path-prefix", cl::init(""), cl::Hidden,
149 cl::value_desc("filename"),
150 cl::desc("Specify the path prefix of the MemProf dot files."));
151
152static cl::opt<bool> ExportToDot("memprof-export-to-dot", cl::init(false),
154 cl::desc("Export graph to dot files."));
155
156// TODO: Remove this option once new handling is validated more widely.
158 "memprof-merge-iteration", cl::init(true), cl::Hidden,
159 cl::desc("Iteratively apply merging on a node to catch new callers"));
160
161// How much of the graph to export to dot.
163 All, // The full CCG graph.
164 Alloc, // Only contexts for the specified allocation.
165 Context, // Only the specified context.
166};
167
169 "memprof-dot-scope", cl::desc("Scope of graph to export to dot"),
172 clEnumValN(DotScope::All, "all", "Export full callsite graph"),
174 "Export only nodes with contexts feeding given "
175 "-memprof-dot-alloc-id"),
176 clEnumValN(DotScope::Context, "context",
177 "Export only nodes with given -memprof-dot-context-id")));
178
180 AllocIdForDot("memprof-dot-alloc-id", cl::init(0), cl::Hidden,
181 cl::desc("Id of alloc to export if -memprof-dot-scope=alloc "
182 "or to highlight if -memprof-dot-scope=all"));
183
185 "memprof-dot-context-id", cl::init(0), cl::Hidden,
186 cl::desc("Id of context to export if -memprof-dot-scope=context or to "
187 "highlight otherwise"));
188
189static cl::opt<bool>
190 DumpCCG("memprof-dump-ccg", cl::init(false), cl::Hidden,
191 cl::desc("Dump CallingContextGraph to stdout after each stage."));
192
193static cl::opt<bool>
194 VerifyCCG("memprof-verify-ccg", cl::init(false), cl::Hidden,
195 cl::desc("Perform verification checks on CallingContextGraph."));
196
197static cl::opt<bool>
198 VerifyNodes("memprof-verify-nodes", cl::init(false), cl::Hidden,
199 cl::desc("Perform frequent verification checks on nodes."));
200
202 "memprof-import-summary",
203 cl::desc("Import summary to use for testing the ThinLTO backend via opt"),
204 cl::Hidden);
205
207 TailCallSearchDepth("memprof-tail-call-search-depth", cl::init(5),
209 cl::desc("Max depth to recursively search for missing "
210 "frames through tail calls."));
211
212// Whether the ThinLTO search for frames missing due to tail calls should look
213// through indirect tail calls, via the summary call edges to their profiled
214// targets.
216 "memprof-indirect-tail-call-search", cl::init(true), cl::Hidden,
217 cl::desc("Search for missing frames through indirect tail calls to their "
218 "profiled targets (ThinLTO)."));
219
220// Optionally enable cloning of callsites involved with recursive cycles
222 "memprof-allow-recursive-callsites", cl::init(true), cl::Hidden,
223 cl::desc("Allow cloning of callsites involved in recursive cycles"));
224
226 "memprof-clone-recursive-contexts", cl::init(true), cl::Hidden,
227 cl::desc("Allow cloning of contexts through recursive cycles"));
228
229// Generally this is needed for correct assignment of allocation clones to
230// function clones, however, allow it to be disabled for debugging while the
231// functionality is new and being tested more widely.
232static cl::opt<bool>
233 MergeClones("memprof-merge-clones", cl::init(true), cl::Hidden,
234 cl::desc("Merge clones before assigning functions"));
235
236// When disabled, try to detect and prevent cloning of recursive contexts.
237// This is only necessary until we support cloning through recursive cycles.
238// Leave on by default for now, as disabling requires a little bit of compile
239// time overhead and doesn't affect correctness, it will just inflate the cold
240// hinted bytes reporting a bit when -memprof-report-hinted-sizes is enabled.
242 "memprof-allow-recursive-contexts", cl::init(true), cl::Hidden,
243 cl::desc("Allow cloning of contexts having recursive cycles"));
244
245// Set the minimum absolute count threshold for allowing inlining of indirect
246// calls promoted during cloning.
248 "memprof-icp-noinline-threshold", cl::init(0), cl::Hidden,
249 cl::desc("Minimum absolute count for promoted target to be inlinable"));
250
251namespace llvm {
253 "enable-memprof-context-disambiguation", cl::Hidden,
254 cl::desc("Enable MemProf context disambiguation"));
255
256// Indicate we are linking with an allocator that supports hot/cold operator
257// new interfaces.
259 "supports-hot-cold-new", cl::init(false), cl::Hidden,
260 cl::desc("Linking with hot/cold operator new interfaces"));
261
263 "memprof-require-definition-for-promotion", cl::init(false), cl::Hidden,
264 cl::desc(
265 "Require target function definition when promoting indirect calls"));
266
267// Applying the thin link cloning decisions to indirect calls requires the
268// ThinLTO backend to perform ICP to the profiled target, which requires that
269// the target be available in the caller's module (or in any module the caller
270// is imported into). When the target is defined in a different module it must
271// be imported, but the profiled targets are often synthesized from the MemProf
272// profile with a small count, so their summary edges are not hot and large
273// targets are often not imported. Since the thin link cloning runs before the
274// function importing analysis, we can mark the indirect call edges to callees
275// of callsites that were assigned to call a cloned callee as requiring a
276// declaration import, in which case the function importer imports at least a
277// declaration of the callee into any module containing the caller that
278// doesn't define the callee. Direct calls don't require importing the callee,
279// since the ThinLTO backend can simply call a declaration of the callee clone,
280// so we only do this for edges marked as being from indirect calls in the
281// summary. Note that unlike regular ICP, which by default requires the
282// target's definition (see -icp-allow-decls), MemProf ICP can promote to a
283// declaration of the target (see -memprof-require-definition-for-promotion),
284// since the purpose is to call the assigned clone rather than to inline. This
285// is therefore not done under -memprof-require-definition-for-promotion.
287 "memprof-import-cloned-indirect-targets", cl::init(true), cl::Hidden,
288 cl::desc("Import at least a declaration of the indirect call targets of "
289 "callsites assigned to call a cloned callee (needed for MemProf "
290 "ICP in the ThinLTO backend)"));
291
295
296// Appends a per-context diagnostic suffix to each -memprof-report-hinted-sizes
297// line: the allocation function clone, how far the context matched, and the
298// post-cloning call paths from the outermost matched caller to the reached
299// allocation clone(s) and their final hints. Requires
300// -memprof-report-hinted-sizes, and adds some memory and time overhead.
302 "memprof-report-hinted-sizes-detail", cl::init(false), cl::Hidden,
303 cl::desc("Append post-cloning call path and matching details to each "
304 "-memprof-report-hinted-sizes line"));
305
306// Post-cloning call paths in the detail suffix longer than this (in functions)
307// have runs of uncloned (or cloned) functions in their middle elided to
308// "...", keeping the ends and every cloned/uncloned transition.
310 "memprof-report-hinted-sizes-detail-max-path-len", cl::init(7), cl::Hidden,
311 cl::desc("Maximum number of functions printed in full for a post-cloning "
312 "call path in the -memprof-report-hinted-sizes-detail suffix; "
313 "longer paths are elided in the middle"));
314
316 "memprof-top-n-important", cl::init(10), cl::Hidden,
317 cl::desc("Number of largest cold contexts to consider important"));
318
320 "memprof-fixup-important", cl::init(true), cl::Hidden,
321 cl::desc("Enables edge fixup for important contexts"));
322
323} // namespace llvm
324
325namespace {
326
327/// CRTP base for graphs built from either IR or ThinLTO summary index.
328///
329/// The graph represents the call contexts in all memprof metadata on allocation
330/// calls, with nodes for the allocations themselves, as well as for the calls
331/// in each context. The graph is initially built from the allocation memprof
332/// metadata (or summary) MIBs. It is then updated to match calls with callsite
333/// metadata onto the nodes, updating it to reflect any inlining performed on
334/// those calls.
335///
336/// Each MIB (representing an allocation's call context with allocation
337/// behavior) is assigned a unique context id during the graph build. The edges
338/// and nodes in the graph are decorated with the context ids they carry. This
339/// is used to correctly update the graph when cloning is performed so that we
340/// can uniquify the context for a single (possibly cloned) allocation.
341template <typename DerivedCCG, typename FuncTy, typename CallTy>
342class CallsiteContextGraph {
343public:
344 CallsiteContextGraph() = default;
345 CallsiteContextGraph(const CallsiteContextGraph &) = default;
346 CallsiteContextGraph(CallsiteContextGraph &&) = default;
347
348 /// Main entry point to perform analysis and transformations on graph.
349 bool process(function_ref<void(StringRef, StringRef, const Twine &)>
350 EmitRemark = nullptr,
351 bool AllowExtraAnalysis = false);
352
353 /// Perform cloning on the graph necessary to uniquely identify the allocation
354 /// behavior of an allocation based on its context.
355 void identifyClones();
356
357 /// Assign callsite clones to functions, cloning functions as needed to
358 /// accommodate the combinations of their callsite clones reached by callers.
359 /// For regular LTO this clones functions and callsites in the IR, but for
360 /// ThinLTO the cloning decisions are noted in the summaries and later applied
361 /// in applyImport.
362 bool assignFunctions();
363
364 void dump() const;
365 void print(raw_ostream &OS) const;
366 void printTotalSizes(raw_ostream &OS,
367 function_ref<void(StringRef, StringRef, const Twine &)>
368 EmitRemark = nullptr) const;
369
371 const CallsiteContextGraph &CCG) {
372 CCG.print(OS);
373 return OS;
374 }
375
376 friend struct GraphTraits<
377 const CallsiteContextGraph<DerivedCCG, FuncTy, CallTy> *>;
378 friend struct DOTGraphTraits<
379 const CallsiteContextGraph<DerivedCCG, FuncTy, CallTy> *>;
380
381 void exportToDot(std::string Label) const;
382
383 /// Represents a function clone via FuncTy pointer and clone number pair.
384 struct FuncInfo final
385 : public std::pair<FuncTy *, unsigned /*Clone number*/> {
386 using Base = std::pair<FuncTy *, unsigned>;
387 FuncInfo(const Base &B) : Base(B) {}
388 FuncInfo(FuncTy *F = nullptr, unsigned CloneNo = 0) : Base(F, CloneNo) {}
389 explicit operator bool() const { return this->first != nullptr; }
390 FuncTy *func() const { return this->first; }
391 unsigned cloneNo() const { return this->second; }
392 };
393
394 /// Represents a callsite clone via CallTy and clone number pair.
395 struct CallInfo final : public std::pair<CallTy, unsigned /*Clone number*/> {
396 using Base = std::pair<CallTy, unsigned>;
397 CallInfo(const Base &B) : Base(B) {}
398 CallInfo(CallTy Call = nullptr, unsigned CloneNo = 0)
399 : Base(Call, CloneNo) {}
400 explicit operator bool() const { return (bool)this->first; }
401 CallTy call() const { return this->first; }
402 unsigned cloneNo() const { return this->second; }
403 void setCloneNo(unsigned N) { this->second = N; }
404 void print(raw_ostream &OS) const {
405 if (!operator bool()) {
406 assert(!cloneNo());
407 OS << "null Call";
408 return;
409 }
410 call()->print(OS);
411 OS << "\t(clone " << cloneNo() << ")";
412 }
413 void dump() const {
414 print(dbgs());
415 dbgs() << "\n";
416 }
417 friend raw_ostream &operator<<(raw_ostream &OS, const CallInfo &Call) {
418 Call.print(OS);
419 return OS;
420 }
421 };
422
423 struct ContextEdge;
424
425 /// Node in the Callsite Context Graph
426 struct ContextNode {
427 // Assigned to nodes as they are created, useful for debugging.
428 unsigned NodeId = 0;
429
430 // Keep this for now since in the IR case where we have an Instruction* it
431 // is not as immediately discoverable. Used for printing richer information
432 // when dumping graph.
433 bool IsAllocation;
434
435 // Keeps track of when the Call was reset to null because there was
436 // recursion.
437 bool Recursive = false;
438
439 // This will be formed by ORing together the AllocationType enum values
440 // for contexts including this node.
441 uint8_t AllocTypes = 0;
442
443 // The corresponding allocation or interior call. This is the primary call
444 // for which we have created this node.
445 CallInfo Call;
446
447 // List of other calls that can be treated the same as the primary call
448 // through cloning. I.e. located in the same function and have the same
449 // (possibly trimmed) stack ids. They will be updated the same way as the
450 // primary call when assigning to function clones.
451 SmallVector<CallInfo, 0> MatchingCalls;
452
453 // For alloc nodes this is a unique id assigned when constructed, and for
454 // callsite stack nodes it is the original stack id when the node is
455 // constructed from the memprof MIB metadata on the alloc nodes. Note that
456 // this is only used when matching callsite metadata onto the stack nodes
457 // created when processing the allocation memprof MIBs, and for labeling
458 // nodes in the dot graph. Therefore we don't bother to assign a value for
459 // clones.
460 uint64_t OrigStackOrAllocId = 0;
461
462 // Edges to all callees in the profiled call stacks.
463 // TODO: Should this be a map (from Callee node) for more efficient lookup?
464 std::vector<std::shared_ptr<ContextEdge>> CalleeEdges;
465
466 // Edges to all callers in the profiled call stacks.
467 // TODO: Should this be a map (from Caller node) for more efficient lookup?
468 std::vector<std::shared_ptr<ContextEdge>> CallerEdges;
469
470 // Returns true if we need to look at the callee edges for determining the
471 // node context ids and allocation type.
472 bool useCallerEdgesForContextInfo() const {
473 // Typically if the callee edges are empty either the caller edges are
474 // also empty, or this is an allocation (leaf node). However, if we are
475 // allowing recursive callsites and contexts this will be violated for
476 // incompletely cloned recursive cycles.
477 assert(!CalleeEdges.empty() || CallerEdges.empty() || IsAllocation ||
479 // When cloning for a recursive context, during cloning we might be in the
480 // midst of cloning for a recurrence and have moved context ids off of a
481 // caller edge onto the clone but not yet off of the incoming caller
482 // (back) edge. If we don't look at those we miss the fact that this node
483 // still has context ids of interest.
484 return IsAllocation || CloneRecursiveContexts;
485 }
486
487 // Compute the context ids for this node from the union of its edge context
488 // ids.
489 DenseSet<uint32_t> getContextIds() const {
490 unsigned Count = 0;
491 // Compute the number of ids for reserve below. In general we only need to
492 // look at one set of edges, typically the callee edges, since other than
493 // allocations and in some cases during recursion cloning, all the context
494 // ids on the callers should also flow out via callee edges.
495 for (auto &Edge : CalleeEdges.empty() ? CallerEdges : CalleeEdges)
496 Count += Edge->getContextIds().size();
497 DenseSet<uint32_t> ContextIds;
498 ContextIds.reserve(Count);
500 CalleeEdges, useCallerEdgesForContextInfo()
501 ? CallerEdges
502 : std::vector<std::shared_ptr<ContextEdge>>());
503 for (const auto &Edge : Edges)
504 ContextIds.insert_range(Edge->getContextIds());
505 return ContextIds;
506 }
507
508 // Compute the allocation type for this node from the OR of its edge
509 // allocation types.
510 uint8_t computeAllocType() const {
511 uint8_t BothTypes =
512 (uint8_t)AllocationType::Cold | (uint8_t)AllocationType::NotCold;
513 uint8_t AllocType = (uint8_t)AllocationType::None;
515 CalleeEdges, useCallerEdgesForContextInfo()
516 ? CallerEdges
517 : std::vector<std::shared_ptr<ContextEdge>>());
518 for (const auto &Edge : Edges) {
519 AllocType |= Edge->AllocTypes;
520 // Bail early if alloc type reached both, no further refinement.
521 if (AllocType == BothTypes)
522 return AllocType;
523 }
524 return AllocType;
525 }
526
527 // The context ids set for this node is empty if its edge context ids are
528 // also all empty.
529 bool emptyContextIds() const {
531 CalleeEdges, useCallerEdgesForContextInfo()
532 ? CallerEdges
533 : std::vector<std::shared_ptr<ContextEdge>>());
534 for (const auto &Edge : Edges) {
535 if (!Edge->getContextIds().empty())
536 return false;
537 }
538 return true;
539 }
540
541 // Whether the given context id is among this node's context ids.
542 bool hasContextId(uint32_t Id) const {
544 CalleeEdges, useCallerEdgesForContextInfo()
545 ? CallerEdges
546 : std::vector<std::shared_ptr<ContextEdge>>());
547 for (const auto &Edge : Edges) {
548 if (Edge->getContextIds().contains(Id))
549 return true;
550 }
551 return false;
552 }
553
554 // List of clones of this ContextNode, initially empty.
555 std::vector<ContextNode *> Clones;
556
557 // If a clone, points to the original uncloned node.
558 ContextNode *CloneOf = nullptr;
559
560 ContextNode(bool IsAllocation) : IsAllocation(IsAllocation), Call() {}
561
562 ContextNode(bool IsAllocation, CallInfo C)
563 : IsAllocation(IsAllocation), Call(C) {}
564
565 void addClone(ContextNode *Clone) {
566 if (CloneOf) {
567 CloneOf->Clones.push_back(Clone);
568 Clone->CloneOf = CloneOf;
569 } else {
570 Clones.push_back(Clone);
571 assert(!Clone->CloneOf);
572 Clone->CloneOf = this;
573 }
574 }
575
576 ContextNode *getOrigNode() {
577 if (!CloneOf)
578 return this;
579 return CloneOf;
580 }
581
582 const ContextNode *getOrigNode() const {
583 if (!CloneOf)
584 return this;
585 return CloneOf;
586 }
587
588 void addOrUpdateCallerEdge(ContextNode *Caller, AllocationType AllocType,
589 unsigned int ContextId);
590
591 ContextEdge *findEdgeFromCallee(const ContextNode *Callee);
592 ContextEdge *findEdgeFromCaller(const ContextNode *Caller);
593 void eraseCalleeEdge(const ContextEdge *Edge);
594 void eraseCallerEdge(const ContextEdge *Edge);
595
596 void setCall(CallInfo C) { Call = std::move(C); }
597
598 bool hasCall() const { return (bool)Call.call(); }
599
600 void printCall(raw_ostream &OS) const { Call.print(OS); }
601
602 // True if this node was effectively removed from the graph, in which case
603 // it should have an allocation type of None and empty context ids.
604 bool isRemoved() const {
605 // Typically if the callee edges are empty either the caller edges are
606 // also empty, or this is an allocation (leaf node). However, if we are
607 // allowing recursive callsites and contexts this will be violated for
608 // incompletely cloned recursive cycles.
610 (AllocTypes == (uint8_t)AllocationType::None) ==
611 emptyContextIds());
612 return AllocTypes == (uint8_t)AllocationType::None;
613 }
614
615 void dump() const;
616 void print(raw_ostream &OS) const;
617
618 friend raw_ostream &operator<<(raw_ostream &OS, const ContextNode &Node) {
619 Node.print(OS);
620 return OS;
621 }
622 };
623
624 /// Edge in the Callsite Context Graph from a ContextNode N to a caller or
625 /// callee.
626 struct ContextEdge {
627 ContextNode *Callee;
628 ContextNode *Caller;
629
630 // This will be formed by ORing together the AllocationType enum values
631 // for contexts including this edge.
632 uint8_t AllocTypes = 0;
633
634 // Set just before initiating cloning when cloning of recursive contexts is
635 // enabled. Used to defer cloning of backedges until we have done cloning of
636 // the callee node for non-backedge caller edges. This exposes cloning
637 // opportunities through the backedge of the cycle.
638 // TODO: Note that this is not updated during cloning, and it is unclear
639 // whether that would be needed.
640 bool IsBackedge = false;
641
642 // The set of IDs for contexts including this edge.
643 DenseSet<uint32_t> ContextIds;
644
645 ContextEdge(ContextNode *Callee, ContextNode *Caller, uint8_t AllocType,
646 DenseSet<uint32_t> ContextIds)
647 : Callee(Callee), Caller(Caller), AllocTypes(AllocType),
648 ContextIds(std::move(ContextIds)) {}
649
650 DenseSet<uint32_t> &getContextIds() { return ContextIds; }
651
652 // Helper to clear the fields of this edge when we are removing it from the
653 // graph.
654 inline void clear() {
655 ContextIds.clear();
656 AllocTypes = (uint8_t)AllocationType::None;
657 Caller = nullptr;
658 Callee = nullptr;
659 }
660
661 // Check if edge was removed from the graph. This is useful while iterating
662 // over a copy of edge lists when performing operations that mutate the
663 // graph in ways that might remove one of the edges.
664 inline bool isRemoved() const {
665 if (Callee || Caller)
666 return false;
667 // Any edges that have been removed from the graph but are still in a
668 // shared_ptr somewhere should have all fields null'ed out by clear()
669 // above.
670 assert(AllocTypes == (uint8_t)AllocationType::None);
671 assert(ContextIds.empty());
672 return true;
673 }
674
675 void dump() const;
676 void print(raw_ostream &OS) const;
677
678 friend raw_ostream &operator<<(raw_ostream &OS, const ContextEdge &Edge) {
679 Edge.print(OS);
680 return OS;
681 }
682 };
683
684 /// Helpers to remove edges that have allocation type None (due to not
685 /// carrying any context ids) after transformations.
686 void removeNoneTypeCalleeEdges(ContextNode *Node);
687 void removeNoneTypeCallerEdges(ContextNode *Node);
688 void
689 recursivelyRemoveNoneTypeCalleeEdges(ContextNode *Node,
690 DenseSet<const ContextNode *> &Visited);
691
692protected:
693 /// Get the list of context nodes for the stack ids in the given callsite
694 /// context, stopping at the first stack id that does not have a node.
695 template <class NodeT, class IteratorT>
696 std::vector<ContextNode *>
697 getStackNodesForCallsite(CallStack<NodeT, IteratorT> &CallsiteContext);
698
699 /// Adds nodes for the given allocation and any stack ids on its memprof MIB
700 /// metadata (or summary).
701 ContextNode *addAllocNode(CallInfo Call, const FuncTy *F);
702
703 /// Adds nodes for the given MIB stack ids.
704 template <class NodeT, class IteratorT>
705 void addStackNodesForMIB(
706 ContextNode *AllocNode, CallStack<NodeT, IteratorT> &StackContext,
707 CallStack<NodeT, IteratorT> &CallsiteContext, AllocationType AllocType,
708 ArrayRef<ContextTotalSize> ContextSizeInfo,
709 std::map<uint64_t, uint32_t> &TotalSizeToContextIdTopNCold);
710
711 /// Matches all callsite metadata (or summary) to the nodes created for
712 /// allocation memprof MIB metadata, synthesizing new nodes to reflect any
713 /// inlining performed on those callsite instructions.
714 void updateStackNodes();
715
716 /// Optionally fixup edges for the N largest cold contexts to better enable
717 /// cloning. This is particularly helpful if the context includes recursion
718 /// as well as inlining, resulting in a single stack node for multiple stack
719 /// ids in the context. With recursion it is particularly difficult to get the
720 /// edge updates correct as in the general case we have lost the original
721 /// stack id ordering for the context. Do more expensive fixup for the largest
722 /// contexts, controlled by MemProfTopNImportant and MemProfFixupImportant.
723 void fixupImportantContexts();
724
725 /// Update graph to conservatively handle any callsite stack nodes that target
726 /// multiple different callee target functions.
727 void handleCallsitesWithMultipleTargets();
728
729 /// Mark backedges via the standard DFS based backedge algorithm.
730 void markBackedges();
731
732 /// Merge clones generated during cloning for different allocations but that
733 /// are called by the same caller node, to ensure proper function assignment.
734 void mergeClones();
735
736 // Try to partition calls on the given node (already placed into the AllCalls
737 // array) by callee function, creating new copies of Node as needed to hold
738 // calls with different callees, and moving the callee edges appropriately.
739 // Returns true if partitioning was successful.
740 bool partitionCallsByCallee(
741 ContextNode *Node, ArrayRef<CallInfo> AllCalls,
742 std::vector<std::pair<CallInfo, ContextNode *>> &NewCallToNode);
743
744 /// Save lists of calls with MemProf metadata in each function, for faster
745 /// iteration.
746 MapVector<FuncTy *, std::vector<CallInfo>> FuncToCallsWithMetadata;
747
748 /// Map from callsite node to the enclosing caller function.
749 std::map<const ContextNode *, const FuncTy *> NodeToCallingFunc;
750
751 const FuncTy *getCallingFunc(const ContextNode *N) const {
752 auto It = NodeToCallingFunc.find(N);
753 return It != NodeToCallingFunc.end() ? It->second : nullptr;
754 }
755
756 /// Functions that are referenced (called directly, or address-taken) in the
757 /// module or summary index. Only populated, at the start of reporting, when
758 /// MemProfReportHintedSizesDetail is enabled; used to distinguish allocation
759 /// functions with no references at all from those whose callers simply did
760 /// not match the profile.
761 DenseSet<const FuncTy *> FunctionsWithCallers;
762
763 // When exporting to dot, and an allocation id is specified, contains the
764 // context ids on that allocation.
765 DenseSet<uint32_t> DotAllocContextIds;
766
767private:
768 using EdgeIter = typename std::vector<std::shared_ptr<ContextEdge>>::iterator;
769
770 // Structure to keep track of information for each call as we are matching
771 // non-allocation callsites onto context nodes created from the allocation
772 // call metadata / summary contexts.
773 struct CallContextInfo {
774 // The callsite we're trying to match.
775 CallTy Call;
776 // The context nodes for the callsite's stack ids that have one, saved to
777 // avoid repeatedly looking them up. The stack ids are available via the
778 // nodes' OrigStackOrAllocId. Since each stack id has its own node, and the
779 // stack id to node map is not modified while matching calls, two calls
780 // have the same stack ids iff they have the same nodes.
781 std::vector<ContextNode *> StackNodes;
782 // The function containing this callsite.
783 const FuncTy *Func;
784 // Initially empty, if needed this will be updated to contain the context
785 // ids for use in a new context node created for this callsite.
786 DenseSet<uint32_t> ContextIds;
787 };
788
789 /// Helper to remove edge from graph, updating edge iterator if it is provided
790 /// (in which case CalleeIter indicates which edge list is being iterated).
791 /// This will also perform the necessary clearing of the ContextEdge members
792 /// to enable later checking if the edge has been removed (since we may have
793 /// other copies of the shared_ptr in existence, and in fact rely on this to
794 /// enable removal while iterating over a copy of a node's edge list).
795 void removeEdgeFromGraph(ContextEdge *Edge, EdgeIter *EI = nullptr,
796 bool CalleeIter = true);
797
798 /// Assigns the given Node to calls at or inlined into the location with
799 /// the Node's stack id, after post order traversing and processing its
800 /// caller nodes. Uses the call information recorded in the given
801 /// StackIdToMatchingCalls map, and creates new nodes for inlined sequences
802 /// as needed. Called by updateStackNodes which sets up the given
803 /// StackIdToMatchingCalls map.
804 void assignStackNodesPostOrder(
805 ContextNode *Node, DenseSet<const ContextNode *> &Visited,
806 DenseMap<uint64_t, std::vector<CallContextInfo>> &StackIdToMatchingCalls,
807 DenseMap<CallInfo, CallInfo> &CallToMatchingCall,
808 const DenseSet<uint32_t> &ImportantContextIds);
809
810 /// Duplicates the given set of context ids, updating the provided
811 /// map from each original id with the newly generated context ids,
812 /// and returning the new duplicated id set.
813 DenseSet<uint32_t> duplicateContextIds(
814 const DenseSet<uint32_t> &StackSequenceContextIds,
815 DenseMap<uint32_t, DenseSet<uint32_t>> &OldToNewContextIds);
816
817 /// Propagates all duplicated context ids across the graph.
818 void propagateDuplicateContextIds(
819 const DenseMap<uint32_t, DenseSet<uint32_t>> &OldToNewContextIds);
820
821 /// Connect the NewNode to OrigNode's callees if TowardsCallee is true,
822 /// else to its callers. Also updates OrigNode's edges to remove any context
823 /// ids moved to the newly created edge.
824 void connectNewNode(ContextNode *NewNode, ContextNode *OrigNode,
825 bool TowardsCallee, const DenseSet<uint32_t> &ContextIds);
826
827 /// Get the stack id corresponding to the given Id or Index (for IR this will
828 /// return itself, for a summary index this will return the id recorded in the
829 /// index for that stack id index value).
830 uint64_t getStackId(uint64_t IdOrIndex) const {
831 return static_cast<const DerivedCCG *>(this)->getStackId(IdOrIndex);
832 }
833
834 /// Returns true if the given call targets the callee of the given edge, or if
835 /// we were able to identify the call chain through intermediate tail calls.
836 /// In the latter case new context nodes are added to the graph for the
837 /// identified tail calls, and their synthesized nodes are added to
838 /// TailCallToContextNodeMap. The EdgeIter is updated in the latter case for
839 /// the updated edges and to prepare it for an increment in the caller.
840 bool
841 calleesMatch(CallTy Call, EdgeIter &EI,
842 MapVector<CallInfo, ContextNode *> &TailCallToContextNodeMap);
843
844 // Return the callee function of the given call, or nullptr if it can't be
845 // determined
846 const FuncTy *getCalleeFunc(CallTy Call) {
847 return static_cast<DerivedCCG *>(this)->getCalleeFunc(Call);
848 }
849
850 /// Returns true if the given call targets the given function, or if we were
851 /// able to identify the call chain through intermediate tail calls (in which
852 /// case FoundCalleeChain will be populated).
853 bool calleeMatchesFunc(
854 CallTy Call, const FuncTy *Func, const FuncTy *CallerFunc,
855 std::vector<std::pair<CallTy, FuncTy *>> &FoundCalleeChain) {
856 return static_cast<DerivedCCG *>(this)->calleeMatchesFunc(
857 Call, Func, CallerFunc, FoundCalleeChain);
858 }
859
860 /// Returns true if both call instructions have the same callee.
861 bool sameCallee(CallTy Call1, CallTy Call2) {
862 return static_cast<DerivedCCG *>(this)->sameCallee(Call1, Call2);
863 }
864
865 /// Get the list of context nodes for the stack ids in the given callsite's
866 /// context, stopping at the first stack id that does not have a node.
867 std::vector<ContextNode *> getStackNodesForCall(CallTy Call) {
868 return static_cast<DerivedCCG *>(this)->getStackNodesForCall(Call);
869 }
870
871 /// Get the last stack id in the context for callsite.
872 uint64_t getLastStackId(CallTy Call) {
873 return static_cast<DerivedCCG *>(this)->getLastStackId(Call);
874 }
875
876 /// Update the allocation call to record type of allocated memory.
877 void updateAllocationCall(CallInfo &Call, AllocationType AllocType) {
878 if (AllocType == AllocationType::Cold)
879 AllocTypeCold++;
880 else if (isAmbiguousAllocType((uint8_t)AllocType))
881 AllocTypeAmbiguous++;
882 else
883 AllocTypeNotCold++;
884 static_cast<DerivedCCG *>(this)->updateAllocationCall(Call, AllocType);
885 }
886
887 /// Get the AllocationType assigned to the given allocation instruction clone.
888 AllocationType getAllocationCallType(const CallInfo &Call) const {
889 return static_cast<const DerivedCCG *>(this)->getAllocationCallType(Call);
890 }
891
892 /// Update non-allocation call to invoke (possibly cloned) function
893 /// CalleeFunc.
894 void updateCall(CallInfo &CallerCall, FuncInfo CalleeFunc) {
895 static_cast<DerivedCCG *>(this)->updateCall(CallerCall, CalleeFunc);
896 }
897
898 /// Clone the given function for the given callsite, recording mapping of all
899 /// of the functions tracked calls to their new versions in the CallMap.
900 /// Assigns new clones to clone number CloneNo.
901 FuncInfo cloneFunctionForCallsite(
902 FuncInfo &Func, CallInfo &Call, DenseMap<CallInfo, CallInfo> &CallMap,
903 std::vector<CallInfo> &CallsWithMetadataInFunc, unsigned CloneNo) {
904 return static_cast<DerivedCCG *>(this)->cloneFunctionForCallsite(
905 Func, Call, CallMap, CallsWithMetadataInFunc, CloneNo);
906 }
907
908 /// Gets a label to use in the dot graph for the given call clone in the given
909 /// function.
910 std::string getLabel(const FuncTy *Func, const CallTy Call,
911 unsigned CloneNo) const {
912 return static_cast<const DerivedCCG *>(this)->getLabel(Func, Call, CloneNo);
913 }
914
915 /// Gets the function name (with optional clone suffix) for reporting.
916 std::string getFuncName(const FuncTy *Func, unsigned CloneNo = 0) const {
917 return static_cast<const DerivedCCG *>(this)->getFuncName(Func, CloneNo);
918 }
919
920 /// Returns true if the given function was marked dead by ThinLTO dead symbol
921 /// analysis.
922 bool isFuncDead(const FuncTy *Func) const {
923 return static_cast<const DerivedCCG *>(this)->isFuncDead(Func);
924 }
925
926 /// Populates FunctionsWithCallers (MemProfReportHintedSizesDetail only).
927 void populateFunctionsWithCallers() {
928 static_cast<DerivedCCG *>(this)->populateFunctionsWithCallers();
929 }
930
931 /// Records, before identifyClones(), the chain of (uncloned) nodes of every
932 /// context and how far it matched (MemProfReportHintedSizesDetail only).
933 void capturePreCloningContextInfo();
934
935 /// Formats the detail suffix for the report line of context Id, whose
936 /// (possibly cloned) allocation node is Node (MemProfReportHintedSizesDetail
937 /// only). See the option description for the format.
938 std::string formatContextReportSuffix(const ContextNode *Node,
939 uint32_t Id) const;
940
941 // Create and return a new ContextNode.
942 ContextNode *createNewNode(bool IsAllocation, const FuncTy *F = nullptr,
943 CallInfo C = CallInfo()) {
944 NodeOwner.push_back(std::make_unique<ContextNode>(IsAllocation, C));
945 auto *NewNode = NodeOwner.back().get();
946 if (F)
947 NodeToCallingFunc[NewNode] = F;
948 NewNode->NodeId = NodeOwner.size();
949 return NewNode;
950 }
951
952 /// Helpers to find the node corresponding to the given call or stackid.
953 ContextNode *getNodeForInst(const CallInfo &C);
954 ContextNode *getNodeForAlloc(const CallInfo &C);
955 ContextNode *getNodeForStackId(uint64_t StackId);
956
957 /// Computes the alloc type corresponding to the given context ids, by
958 /// unioning their recorded alloc types.
959 uint8_t computeAllocType(DenseSet<uint32_t> &ContextIds) const;
960
961 /// Returns the allocation type of the intersection of the contexts of two
962 /// nodes (based on their provided context id sets), optimized for the case
963 /// when Node1Ids is smaller than Node2Ids.
964 uint8_t intersectAllocTypesImpl(const DenseSet<uint32_t> &Node1Ids,
965 const DenseSet<uint32_t> &Node2Ids) const;
966
967 /// Returns the allocation type of the intersection of the contexts of two
968 /// nodes (based on their provided context id sets).
969 uint8_t intersectAllocTypes(const DenseSet<uint32_t> &Node1Ids,
970 const DenseSet<uint32_t> &Node2Ids) const;
971
972 /// Create a clone of Edge's callee and move Edge to that new callee node,
973 /// performing the necessary context id and allocation type updates.
974 /// If ContextIdsToMove is non-empty, only that subset of Edge's ids are
975 /// moved to an edge to the new callee.
976 ContextNode *
977 moveEdgeToNewCalleeClone(const std::shared_ptr<ContextEdge> &Edge,
978 DenseSet<uint32_t> ContextIdsToMove = {});
979
980 /// Change the callee of Edge to existing callee clone NewCallee, performing
981 /// the necessary context id and allocation type updates.
982 /// If ContextIdsToMove is non-empty, only that subset of Edge's ids are
983 /// moved to an edge to the new callee.
984 void moveEdgeToExistingCalleeClone(const std::shared_ptr<ContextEdge> &Edge,
985 ContextNode *NewCallee,
986 bool NewClone = false,
987 DenseSet<uint32_t> ContextIdsToMove = {});
988
989 /// Change the caller of the edge at the given callee edge iterator to be
990 /// NewCaller, performing the necessary context id and allocation type
991 /// updates. This is similar to the above moveEdgeToExistingCalleeClone, but
992 /// a simplified version of it as we always move the given edge and all of its
993 /// context ids.
994 void moveCalleeEdgeToNewCaller(const std::shared_ptr<ContextEdge> &Edge,
995 ContextNode *NewCaller);
996
997 /// Recursive helper for marking backedges via DFS.
998 void markBackedges(ContextNode *Node, DenseSet<const ContextNode *> &Visited,
999 DenseSet<const ContextNode *> &CurrentStack);
1000
1001 /// Recursive helper for merging clones.
1002 void
1003 mergeClones(ContextNode *Node, DenseSet<const ContextNode *> &Visited,
1004 DenseMap<uint32_t, ContextNode *> &ContextIdToAllocationNode);
1005 /// Main worker for merging callee clones for a given node.
1006 void mergeNodeCalleeClones(
1007 ContextNode *Node, DenseSet<const ContextNode *> &Visited,
1008 DenseMap<uint32_t, ContextNode *> &ContextIdToAllocationNode);
1009 /// Helper to find other callers of the given set of callee edges that can
1010 /// share the same callee merge node.
1011 void findOtherCallersToShareMerge(
1012 ContextNode *Node, std::vector<std::shared_ptr<ContextEdge>> &CalleeEdges,
1013 DenseMap<uint32_t, ContextNode *> &ContextIdToAllocationNode,
1014 DenseSet<ContextNode *> &OtherCallersToShareMerge);
1015
1016 /// Recursively perform cloning on the graph for the given Node and its
1017 /// callers, in order to uniquely identify the allocation behavior of an
1018 /// allocation given its context. The context ids of the allocation being
1019 /// processed are given in AllocContextIds.
1020 void identifyClones(ContextNode *Node, DenseSet<const ContextNode *> &Visited,
1021 const DenseSet<uint32_t> &AllocContextIds);
1022
1023 /// Records which clone of a callsite node an implicit caller requires (see
1024 /// assignImplicitCallers). The call to that callsite in a given function
1025 /// clone (the map key below) must call the same callee version as Source.
1026 struct ImplicitSource {
1027 /// The required clone of the callsite node.
1028 const ContextNode *Source;
1029 /// One of the trimmed context ids that made Source required. If Source is
1030 /// later emptied by further cloning, this id is used to find the clone
1031 /// that now carries the trimmed contexts (see resolveImplicitSource).
1032 uint32_t ContextId;
1033 };
1034 /// Map from (original callsite node, function clone number) to the clone of
1035 /// that callsite node that the call in that function clone must follow.
1036 using ImplicitSourceMap =
1037 DenseMap<std::pair<const ContextNode *, unsigned>, ImplicitSource>;
1038
1039 /// Assign the implicit callers of the clones of Node (callsite clones without
1040 /// an edge to any clone of Node which contexts trimmed at Node's frame would
1041 /// have reached) the function clone called by the caller carrying those
1042 /// contexts, and record the clone of Node their calls must follow. See
1043 /// assignFunctions for the maps.
1044 void assignImplicitCallers(
1045 ContextNode *Node, const DenseSet<uint32_t> &TrimmedContextIds,
1046 DenseMap<ContextNode *, FuncInfo> &CallsiteToCalleeFuncCloneMap,
1047 const std::map<FuncInfo, ContextNode *> &FuncCloneToCurNodeCloneMap,
1048 ImplicitSourceMap &ImplicitSources);
1049
1050 /// Returns the clone of Node (the original callsite node) that the implicit
1051 /// source Src refers to: Src.Source unless it has since been emptied, in
1052 /// which case the clone that now carries Src.ContextId (null if none does,
1053 /// which is not expected).
1054 static const ContextNode *resolveImplicitSource(const ContextNode *Node,
1055 const ImplicitSource &Src);
1056
1057 /// Map from each context ID to the AllocationType assigned to that context.
1058 DenseMap<uint32_t, AllocationType> ContextIdToAllocationType;
1059
1060 /// Map from each contextID to the profiled full contexts and their total
1061 /// sizes (there may be more than one due to context trimming),
1062 /// optionally populated when requested (via MemProfReportHintedSizes or
1063 /// MinClonedColdBytePercent).
1064 DenseMap<uint32_t, std::vector<ContextTotalSize>> ContextIdToContextSizeInfos;
1065
1066 /// Identifies the context node created for a stack id when adding the MIB
1067 /// contexts to the graph. This is used to locate the context nodes when
1068 /// trying to assign the corresponding callsites with those stack ids to these
1069 /// nodes.
1070 DenseMap<uint64_t, ContextNode *> StackEntryIdToContextNodeMap;
1071
1072 /// Saves information for the contexts identified as important (the largest
1073 /// cold contexts up to MemProfTopNImportant).
1074 struct ImportantContextInfo {
1075 // The original list of leaf first stack ids corresponding to this context.
1076 std::vector<uint64_t> StackIds;
1077 // Max length of stack ids corresponding to a single stack ContextNode for
1078 // this context (i.e. the max length of a key in StackIdsToNode below).
1079 unsigned MaxLength = 0;
1080 // Mapping of slices of the stack ids to the corresponding ContextNode
1081 // (there can be multiple stack ids due to inlining). Populated when
1082 // updating stack nodes while matching them to the IR or summary.
1083 std::map<std::vector<uint64_t>, ContextNode *> StackIdsToNode;
1084 };
1085
1086 // Map of important full context ids to information about each.
1087 DenseMap<uint32_t, ImportantContextInfo> ImportantContextIdInfo;
1088
1089 // For each important context id found in Node (if any), records the list of
1090 // stack ids (those of the given StackNodes) that corresponded to the given
1091 // callsite Node. There can be more than one in the case of inlining.
1092 void recordStackNode(ArrayRef<ContextNode *> StackNodes, ContextNode *Node,
1093 // We pass in the Node's context ids to avoid the
1094 // overhead of computing them as the caller already has
1095 // them in some cases.
1096 const DenseSet<uint32_t> &NodeContextIds,
1097 const DenseSet<uint32_t> &ImportantContextIds) {
1098 if (!MemProfTopNImportant) {
1099 assert(ImportantContextIds.empty());
1100 return;
1101 }
1102 DenseSet<uint32_t> Ids =
1103 set_intersection(NodeContextIds, ImportantContextIds);
1104 if (Ids.empty())
1105 return;
1106 std::vector<uint64_t> StackIds;
1107 StackIds.reserve(StackNodes.size());
1108 for (const ContextNode *N : StackNodes)
1109 StackIds.push_back(N->OrigStackOrAllocId);
1110 auto Size = StackIds.size();
1111 for (auto Id : Ids) {
1112 auto &Entry = ImportantContextIdInfo[Id];
1113 Entry.StackIdsToNode[StackIds] = Node;
1114 // Keep track of the max to simplify later analysis.
1115 if (Size > Entry.MaxLength)
1116 Entry.MaxLength = Size;
1117 }
1118 }
1119
1120 /// Maps to track the calls to their corresponding nodes in the graph.
1121 MapVector<CallInfo, ContextNode *> AllocationCallToContextNodeMap;
1122 MapVector<CallInfo, ContextNode *> NonAllocationCallToContextNodeMap;
1123
1124 /// Owner of all ContextNode unique_ptrs.
1125 std::vector<std::unique_ptr<ContextNode>> NodeOwner;
1126
1127 /// Perform sanity checks on graph when requested.
1128 void check() const;
1129
1130 /// Keeps track of the last unique context id assigned.
1131 unsigned int LastContextId = 0;
1132
1133 /// Per-context information captured before identifyClones() when
1134 /// MemProfReportHintedSizesDetail is enabled, so that the report can relate
1135 /// the final (cloned) state back to the original context. "Frames" below are
1136 /// CCG nodes, not profile stack frames: a node matched to a call covers all
1137 /// of that call's inlined stack frames, so a chain can be shorter than the
1138 /// profiled stack.
1139 struct PreCloningContextInfo {
1140 // Ordered chain of uncloned ContextNodes for this context ID from the leaf
1141 // allocation node (Chain[0]) up to the outermost node in the CCG for this
1142 // context.
1143 std::vector<const ContextNode *> Chain;
1144 // Index in Chain of the outermost matched callsite node, i.e. the
1145 // outermost node such that it and all nodes below it
1146 // (Chain[1..MaxMatchedFrame]) were matched to a call in the IR/summary
1147 // (hasCall() == true). If the whole context matched, this is the
1148 // context's outermost node (possibly where the context was trimmed);
1149 // otherwise it is the last matched node below the first unmatched one. The
1150 // function containing it (the "outermost matched caller") is where the
1151 // reported post-cloning paths start. 0 if no caller of the allocation
1152 // matched.
1153 unsigned MaxMatchedFrame = 0;
1154 // True if the outermost matched node had caller edges for other contexts,
1155 // i.e. the context was trimmed below callers that other contexts reach.
1156 bool OutermostMatchedNodeHasOtherCallers = false;
1157 // If MaxMatchedFrame + 1 < Chain.size(), why did Chain[MaxMatchedFrame + 1]
1158 // not have a call: it was a recursive cycle node, or its calling function
1159 // was found but the call there did not match the callee (mismatched
1160 // callee); otherwise the caller had no !callsite for this stack id.
1161 bool StoppedAtRecursive = false;
1162 bool StoppedAtMismatchedCallee = false;
1163 // Stack id and (when known) calling function of the first unmatched node.
1164 uint64_t UnmatchedStackId = 0;
1165 const FuncTy *UnmatchedCallingFunc = nullptr;
1166 };
1167 /// Map from context id to its pre-cloning information.
1168 DenseMap<uint32_t, PreCloningContextInfo> PreCloningContextInfoMap;
1169 /// Allocation nodes (uncloned) that had at least one matched caller before
1170 /// cloning.
1171 DenseSet<const ContextNode *> PreCloningAllocHasMatchedCaller;
1172 /// Map from function to the number of function clones assigned to it
1173 /// (including the original), recorded during assignFunctions().
1174 DenseMap<const FuncTy *, unsigned> FuncToNumClones;
1175 /// Map from (original callsite node, clone number of the function clone
1176 /// containing the call) to the clone number of the callee function the call
1177 /// was updated to in assignFunctions(). Used to follow the post-cloning call
1178 /// path from a caller clone down to the allocation clone it reaches.
1179 DenseMap<std::pair<const ContextNode *, unsigned>, unsigned>
1180 OrigNodeAndCloneToCalleeClone;
1181 /// Map from (original allocation node, clone number of the function clone
1182 /// containing the allocation) to the allocation node in that clone, whose
1183 /// call carries the final hint.
1184 DenseMap<std::pair<const ContextNode *, unsigned>, const ContextNode *>
1185 OrigAllocAndCloneToNode;
1186};
1187
1188template <typename DerivedCCG, typename FuncTy, typename CallTy>
1189using ContextNode =
1190 typename CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextNode;
1191template <typename DerivedCCG, typename FuncTy, typename CallTy>
1192using ContextEdge =
1193 typename CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextEdge;
1194template <typename DerivedCCG, typename FuncTy, typename CallTy>
1195using FuncInfo =
1196 typename CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::FuncInfo;
1197template <typename DerivedCCG, typename FuncTy, typename CallTy>
1198using CallInfo =
1199 typename CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::CallInfo;
1200
1201/// CRTP derived class for graphs built from IR (regular LTO).
1202class ModuleCallsiteContextGraph
1203 : public CallsiteContextGraph<ModuleCallsiteContextGraph, Function,
1204 Instruction *> {
1205public:
1206 ModuleCallsiteContextGraph(
1207 Module &M,
1208 llvm::function_ref<OptimizationRemarkEmitter &(Function *)> OREGetter);
1209
1210private:
1211 friend CallsiteContextGraph<ModuleCallsiteContextGraph, Function,
1212 Instruction *>;
1213
1214 uint64_t getStackId(uint64_t IdOrIndex) const;
1215 const Function *getCalleeFunc(Instruction *Call);
1216 bool calleeMatchesFunc(
1217 Instruction *Call, const Function *Func, const Function *CallerFunc,
1218 std::vector<std::pair<Instruction *, Function *>> &FoundCalleeChain);
1219 bool sameCallee(Instruction *Call1, Instruction *Call2);
1220 bool findProfiledCalleeThroughTailCalls(
1221 const Function *ProfiledCallee, Value *CurCallee, unsigned Depth,
1222 std::vector<std::pair<Instruction *, Function *>> &FoundCalleeChain,
1223 bool &FoundMultipleCalleeChains);
1224 uint64_t getLastStackId(Instruction *Call);
1225 std::vector<ContextNode *> getStackNodesForCall(Instruction *Call);
1226 void updateAllocationCall(CallInfo &Call, AllocationType AllocType);
1227 AllocationType getAllocationCallType(const CallInfo &Call) const;
1228 void updateCall(CallInfo &CallerCall, FuncInfo CalleeFunc);
1229 CallsiteContextGraph<ModuleCallsiteContextGraph, Function,
1230 Instruction *>::FuncInfo
1231 cloneFunctionForCallsite(FuncInfo &Func, CallInfo &Call,
1232 DenseMap<CallInfo, CallInfo> &CallMap,
1233 std::vector<CallInfo> &CallsWithMetadataInFunc,
1234 unsigned CloneNo);
1235 std::string getLabel(const Function *Func, const Instruction *Call,
1236 unsigned CloneNo) const;
1237 std::string getFuncName(const Function *Func, unsigned CloneNo = 0) const;
1238 bool isFuncDead(const Function *Func) const { return false; }
1239 void populateFunctionsWithCallers();
1240
1241 const Module &Mod;
1242 llvm::function_ref<OptimizationRemarkEmitter &(Function *)> OREGetter;
1243};
1244
1245/// Represents a call in the summary index graph, which can either be an
1246/// allocation or an interior callsite node in an allocation's context.
1247/// Holds a pointer to the corresponding data structure in the index.
1248struct IndexCall : public PointerUnion<CallsiteInfo *, AllocInfo *> {
1249 IndexCall() : PointerUnion() {}
1250 IndexCall(std::nullptr_t) : IndexCall() {}
1251 IndexCall(CallsiteInfo *StackNode) : PointerUnion(StackNode) {}
1252 IndexCall(AllocInfo *AllocNode) : PointerUnion(AllocNode) {}
1253 IndexCall(PointerUnion PT) : PointerUnion(PT) {}
1254
1255 IndexCall *operator->() { return this; }
1256
1257 void print(raw_ostream &OS) const {
1258 PointerUnion<CallsiteInfo *, AllocInfo *> Base = *this;
1260 OS << *AI;
1261 } else {
1263 assert(CI);
1264 OS << *CI;
1265 }
1266 }
1267};
1268} // namespace
1269
1270namespace llvm {
1271template <> struct simplify_type<IndexCall> {
1273 static SimpleType getSimplifiedValue(IndexCall &Val) { return Val; }
1274};
1275template <> struct simplify_type<const IndexCall> {
1277 static SimpleType getSimplifiedValue(const IndexCall &Val) { return Val; }
1278};
1279} // namespace llvm
1280
1281namespace {
1282/// CRTP derived class for graphs built from summary index (ThinLTO).
1283class IndexCallsiteContextGraph
1284 : public CallsiteContextGraph<IndexCallsiteContextGraph, FunctionSummary,
1285 IndexCall> {
1286public:
1287 IndexCallsiteContextGraph(
1288 ModuleSummaryIndex &Index,
1289 llvm::function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
1290 isPrevailing);
1291
1292 ~IndexCallsiteContextGraph() {
1293 // Now that we are done with the graph it is safe to add the new
1294 // CallsiteInfo structs to the function summary vectors. The graph nodes
1295 // point into locations within these vectors, so we don't want to add them
1296 // any earlier.
1297 for (auto &I : FunctionCalleesToSynthesizedCallsiteInfos) {
1298 auto *FS = I.first;
1299 for (auto &Callsite : I.second)
1300 FS->addCallsite(std::move(*Callsite.second));
1301 }
1302 }
1303
1304private:
1305 friend CallsiteContextGraph<IndexCallsiteContextGraph, FunctionSummary,
1306 IndexCall>;
1307
1308 uint64_t getStackId(uint64_t IdOrIndex) const;
1309 const FunctionSummary *getCalleeFunc(IndexCall &Call);
1310 bool calleeMatchesFunc(
1311 IndexCall &Call, const FunctionSummary *Func,
1312 const FunctionSummary *CallerFunc,
1313 std::vector<std::pair<IndexCall, FunctionSummary *>> &FoundCalleeChain);
1314 bool sameCallee(IndexCall &Call1, IndexCall &Call2);
1315 bool findProfiledCalleeThroughTailCalls(
1316 ValueInfo ProfiledCallee, ValueInfo CurCallee, unsigned Depth,
1317 std::vector<std::pair<ValueInfo, FunctionSummary *>> &FoundCalleeChain,
1318 bool &FoundMultipleCalleeChains);
1319 uint64_t getLastStackId(IndexCall &Call);
1320 std::vector<ContextNode *> getStackNodesForCall(IndexCall &Call);
1321 void updateAllocationCall(CallInfo &Call, AllocationType AllocType);
1322 AllocationType getAllocationCallType(const CallInfo &Call) const;
1323 void updateCall(CallInfo &CallerCall, FuncInfo CalleeFunc);
1324 CallsiteContextGraph<IndexCallsiteContextGraph, FunctionSummary,
1325 IndexCall>::FuncInfo
1326 cloneFunctionForCallsite(FuncInfo &Func, CallInfo &Call,
1327 DenseMap<CallInfo, CallInfo> &CallMap,
1328 std::vector<CallInfo> &CallsWithMetadataInFunc,
1329 unsigned CloneNo);
1330 std::string getLabel(const FunctionSummary *Func, const IndexCall &Call,
1331 unsigned CloneNo) const;
1332 std::string getFuncName(const FunctionSummary *Func,
1333 unsigned CloneNo = 0) const;
1334 bool isFuncDead(const FunctionSummary *Func) const;
1335 void populateFunctionsWithCallers();
1336 DenseSet<GlobalValue::GUID> findAliaseeGUIDsPrevailingInDifferentModule();
1337
1338 // Saves mapping from function summaries containing memprof records back to
1339 // its VI, for use in checking and debugging.
1340 std::map<const FunctionSummary *, ValueInfo> FSToVIMap;
1341
1342 const ModuleSummaryIndex &Index;
1343 llvm::function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
1344 isPrevailing;
1345
1346 // Saves/owns the callsite info structures synthesized for missing tail call
1347 // frames that we discover while building the graph.
1348 // It maps from the summary of the function making the tail call, to a map
1349 // of callee ValueInfo to corresponding synthesized callsite info.
1350 DenseMap<FunctionSummary *,
1351 std::map<ValueInfo, std::unique_ptr<CallsiteInfo>>>
1352 FunctionCalleesToSynthesizedCallsiteInfos;
1353};
1354} // namespace
1355
1356template <>
1357struct llvm::DenseMapInfo<CallsiteContextGraph<
1358 ModuleCallsiteContextGraph, Function, Instruction *>::CallInfo>
1360template <>
1361struct llvm::DenseMapInfo<CallsiteContextGraph<
1362 IndexCallsiteContextGraph, FunctionSummary, IndexCall>::CallInfo>
1363 : public DenseMapInfo<std::pair<IndexCall, unsigned>> {};
1364template <>
1365struct llvm::DenseMapInfo<IndexCall>
1366 : public DenseMapInfo<PointerUnion<CallsiteInfo *, AllocInfo *>> {};
1367
1368namespace {
1369
1370// Map the uint8_t alloc types (which may contain NotCold|Cold) to the alloc
1371// type we should actually use on the corresponding allocation.
1372// If we can't clone a node that has NotCold+Cold alloc type, we will fall
1373// back to using NotCold. So don't bother cloning to distinguish NotCold+Cold
1374// from NotCold.
1375AllocationType allocTypeToUse(uint8_t AllocTypes) {
1376 assert(AllocTypes != (uint8_t)AllocationType::None);
1377 if (AllocTypes ==
1380 else
1381 return (AllocationType)AllocTypes;
1382}
1383
1384// Helper to check if the alloc types for all edges recorded in the
1385// InAllocTypes vector match the alloc types for all edges in the Edges
1386// vector.
1387template <typename DerivedCCG, typename FuncTy, typename CallTy>
1388bool allocTypesMatch(
1389 const std::vector<uint8_t> &InAllocTypes,
1390 const std::vector<std::shared_ptr<ContextEdge<DerivedCCG, FuncTy, CallTy>>>
1391 &Edges) {
1392 // This should be called only when the InAllocTypes vector was computed for
1393 // this set of Edges. Make sure the sizes are the same.
1394 assert(InAllocTypes.size() == Edges.size());
1395 return std::equal(
1396 InAllocTypes.begin(), InAllocTypes.end(), Edges.begin(), Edges.end(),
1397 [](const uint8_t &l,
1398 const std::shared_ptr<ContextEdge<DerivedCCG, FuncTy, CallTy>> &r) {
1399 // Can share if one of the edges is None type - don't
1400 // care about the type along that edge as it doesn't
1401 // exist for those context ids.
1402 if (l == (uint8_t)AllocationType::None ||
1403 r->AllocTypes == (uint8_t)AllocationType::None)
1404 return true;
1405 return allocTypeToUse(l) == allocTypeToUse(r->AllocTypes);
1406 });
1407}
1408
1409// Helper to check if the alloc types for all edges recorded in the
1410// InAllocTypes vector match the alloc types for callee edges in the given
1411// clone. Because the InAllocTypes were computed from the original node's callee
1412// edges, and other cloning could have happened after this clone was created, we
1413// need to find the matching clone callee edge, which may or may not exist.
1414template <typename DerivedCCG, typename FuncTy, typename CallTy>
1415bool allocTypesMatchClone(
1416 const std::vector<uint8_t> &InAllocTypes,
1417 const ContextNode<DerivedCCG, FuncTy, CallTy> *Clone) {
1418 const ContextNode<DerivedCCG, FuncTy, CallTy> *Node = Clone->CloneOf;
1419 assert(Node);
1420 // InAllocTypes should have been computed for the original node's callee
1421 // edges.
1422 assert(InAllocTypes.size() == Node->CalleeEdges.size());
1423 // First create a map of the clone callee edge callees to the edge alloc type.
1425 EdgeCalleeMap;
1426 for (const auto &E : Clone->CalleeEdges) {
1427 assert(!EdgeCalleeMap.contains(E->Callee));
1428 EdgeCalleeMap[E->Callee] = E->AllocTypes;
1429 }
1430 // Next, walk the original node's callees, and look for the corresponding
1431 // clone edge to that callee.
1432 for (unsigned I = 0; I < Node->CalleeEdges.size(); I++) {
1433 auto Iter = EdgeCalleeMap.find(Node->CalleeEdges[I]->Callee);
1434 // Not found is ok, we will simply add an edge if we use this clone.
1435 if (Iter == EdgeCalleeMap.end())
1436 continue;
1437 // Can share if one of the edges is None type - don't
1438 // care about the type along that edge as it doesn't
1439 // exist for those context ids.
1440 if (InAllocTypes[I] == (uint8_t)AllocationType::None ||
1441 Iter->second == (uint8_t)AllocationType::None)
1442 continue;
1443 if (allocTypeToUse(Iter->second) != allocTypeToUse(InAllocTypes[I]))
1444 return false;
1445 }
1446 return true;
1447}
1448
1449} // end anonymous namespace
1450
1451template <typename DerivedCCG, typename FuncTy, typename CallTy>
1452typename CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextNode *
1453CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::getNodeForInst(
1454 const CallInfo &C) {
1455 ContextNode *Node = getNodeForAlloc(C);
1456 if (Node)
1457 return Node;
1458
1459 return NonAllocationCallToContextNodeMap.lookup(C);
1460}
1461
1462template <typename DerivedCCG, typename FuncTy, typename CallTy>
1463typename CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextNode *
1464CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::getNodeForAlloc(
1465 const CallInfo &C) {
1466 return AllocationCallToContextNodeMap.lookup(C);
1467}
1468
1469template <typename DerivedCCG, typename FuncTy, typename CallTy>
1470typename CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextNode *
1471CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::getNodeForStackId(
1472 uint64_t StackId) {
1473 auto StackEntryNode = StackEntryIdToContextNodeMap.find(StackId);
1474 if (StackEntryNode != StackEntryIdToContextNodeMap.end())
1475 return StackEntryNode->second;
1476 return nullptr;
1477}
1478
1479template <typename DerivedCCG, typename FuncTy, typename CallTy>
1480void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextNode::
1481 addOrUpdateCallerEdge(ContextNode *Caller, AllocationType AllocType,
1482 unsigned int ContextId) {
1483 for (auto &Edge : CallerEdges) {
1484 if (Edge->Caller == Caller) {
1485 Edge->AllocTypes |= (uint8_t)AllocType;
1486 Edge->getContextIds().insert(ContextId);
1487 return;
1488 }
1489 }
1490 std::shared_ptr<ContextEdge> Edge = std::make_shared<ContextEdge>(
1491 this, Caller, (uint8_t)AllocType, DenseSet<uint32_t>({ContextId}));
1492 CallerEdges.push_back(Edge);
1493 Caller->CalleeEdges.push_back(Edge);
1494}
1495
1496template <typename DerivedCCG, typename FuncTy, typename CallTy>
1497void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::removeEdgeFromGraph(
1498 ContextEdge *Edge, EdgeIter *EI, bool CalleeIter) {
1499 assert(!EI || (*EI)->get() == Edge);
1500 assert(!Edge->isRemoved());
1501 // Save the Caller and Callee pointers so we can erase Edge from their edge
1502 // lists after clearing Edge below. We do the clearing first in case it is
1503 // destructed after removing from the edge lists (if those were the last
1504 // shared_ptr references to Edge).
1505 auto *Callee = Edge->Callee;
1506 auto *Caller = Edge->Caller;
1507
1508 // Make sure the edge fields are cleared out so we can properly detect
1509 // removed edges if Edge is not destructed because there is still a shared_ptr
1510 // reference.
1511 Edge->clear();
1512
1513#ifndef NDEBUG
1514 auto CalleeCallerCount = Callee->CallerEdges.size();
1515 auto CallerCalleeCount = Caller->CalleeEdges.size();
1516#endif
1517 if (!EI) {
1518 Callee->eraseCallerEdge(Edge);
1519 Caller->eraseCalleeEdge(Edge);
1520 } else if (CalleeIter) {
1521 Callee->eraseCallerEdge(Edge);
1522 *EI = Caller->CalleeEdges.erase(*EI);
1523 } else {
1524 Caller->eraseCalleeEdge(Edge);
1525 *EI = Callee->CallerEdges.erase(*EI);
1526 }
1527 assert(Callee->CallerEdges.size() < CalleeCallerCount);
1528 assert(Caller->CalleeEdges.size() < CallerCalleeCount);
1529}
1530
1531template <typename DerivedCCG, typename FuncTy, typename CallTy>
1532void CallsiteContextGraph<
1533 DerivedCCG, FuncTy, CallTy>::removeNoneTypeCalleeEdges(ContextNode *Node) {
1534 for (auto EI = Node->CalleeEdges.begin(); EI != Node->CalleeEdges.end();) {
1535 auto Edge = *EI;
1536 if (Edge->AllocTypes == (uint8_t)AllocationType::None) {
1537 assert(Edge->ContextIds.empty());
1538 removeEdgeFromGraph(Edge.get(), &EI, /*CalleeIter=*/true);
1539 } else
1540 ++EI;
1541 }
1542}
1543
1544template <typename DerivedCCG, typename FuncTy, typename CallTy>
1545void CallsiteContextGraph<
1546 DerivedCCG, FuncTy, CallTy>::removeNoneTypeCallerEdges(ContextNode *Node) {
1547 for (auto EI = Node->CallerEdges.begin(); EI != Node->CallerEdges.end();) {
1548 auto Edge = *EI;
1549 if (Edge->AllocTypes == (uint8_t)AllocationType::None) {
1550 assert(Edge->ContextIds.empty());
1551 Edge->Caller->eraseCalleeEdge(Edge.get());
1552 EI = Node->CallerEdges.erase(EI);
1553 } else
1554 ++EI;
1555 }
1556}
1557
1558template <typename DerivedCCG, typename FuncTy, typename CallTy>
1559typename CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextEdge *
1560CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextNode::
1561 findEdgeFromCallee(const ContextNode *Callee) {
1562 for (const auto &Edge : CalleeEdges)
1563 if (Edge->Callee == Callee)
1564 return Edge.get();
1565 return nullptr;
1566}
1567
1568template <typename DerivedCCG, typename FuncTy, typename CallTy>
1569typename CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextEdge *
1570CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextNode::
1571 findEdgeFromCaller(const ContextNode *Caller) {
1572 for (const auto &Edge : CallerEdges)
1573 if (Edge->Caller == Caller)
1574 return Edge.get();
1575 return nullptr;
1576}
1577
1578template <typename DerivedCCG, typename FuncTy, typename CallTy>
1579void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextNode::
1580 eraseCalleeEdge(const ContextEdge *Edge) {
1581 auto EI = llvm::find_if(
1582 CalleeEdges, [Edge](const std::shared_ptr<ContextEdge> &CalleeEdge) {
1583 return CalleeEdge.get() == Edge;
1584 });
1585 assert(EI != CalleeEdges.end());
1586 CalleeEdges.erase(EI);
1587}
1588
1589template <typename DerivedCCG, typename FuncTy, typename CallTy>
1590void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextNode::
1591 eraseCallerEdge(const ContextEdge *Edge) {
1592 auto EI = llvm::find_if(
1593 CallerEdges, [Edge](const std::shared_ptr<ContextEdge> &CallerEdge) {
1594 return CallerEdge.get() == Edge;
1595 });
1596 assert(EI != CallerEdges.end());
1597 CallerEdges.erase(EI);
1598}
1599
1600template <typename DerivedCCG, typename FuncTy, typename CallTy>
1601uint8_t CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::computeAllocType(
1602 DenseSet<uint32_t> &ContextIds) const {
1603 uint8_t BothTypes =
1604 (uint8_t)AllocationType::Cold | (uint8_t)AllocationType::NotCold;
1605 uint8_t AllocType = (uint8_t)AllocationType::None;
1606 for (auto Id : ContextIds) {
1607 AllocType |= (uint8_t)ContextIdToAllocationType.at(Id);
1608 // Bail early if alloc type reached both, no further refinement.
1609 if (AllocType == BothTypes)
1610 return AllocType;
1611 }
1612 return AllocType;
1613}
1614
1615template <typename DerivedCCG, typename FuncTy, typename CallTy>
1616uint8_t
1617CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::intersectAllocTypesImpl(
1618 const DenseSet<uint32_t> &Node1Ids,
1619 const DenseSet<uint32_t> &Node2Ids) const {
1620 uint8_t BothTypes =
1621 (uint8_t)AllocationType::Cold | (uint8_t)AllocationType::NotCold;
1622 uint8_t AllocType = (uint8_t)AllocationType::None;
1623 for (auto Id : Node1Ids) {
1624 if (!Node2Ids.count(Id))
1625 continue;
1626 AllocType |= (uint8_t)ContextIdToAllocationType.at(Id);
1627 // Bail early if alloc type reached both, no further refinement.
1628 if (AllocType == BothTypes)
1629 return AllocType;
1630 }
1631 return AllocType;
1632}
1633
1634template <typename DerivedCCG, typename FuncTy, typename CallTy>
1635uint8_t CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::intersectAllocTypes(
1636 const DenseSet<uint32_t> &Node1Ids,
1637 const DenseSet<uint32_t> &Node2Ids) const {
1638 if (Node1Ids.size() < Node2Ids.size())
1639 return intersectAllocTypesImpl(Node1Ids, Node2Ids);
1640 else
1641 return intersectAllocTypesImpl(Node2Ids, Node1Ids);
1642}
1643
1644template <typename DerivedCCG, typename FuncTy, typename CallTy>
1645typename CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextNode *
1646CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::addAllocNode(
1647 CallInfo Call, const FuncTy *F) {
1648 assert(!getNodeForAlloc(Call));
1649 ContextNode *AllocNode = createNewNode(/*IsAllocation=*/true, F, Call);
1650 AllocationCallToContextNodeMap[Call] = AllocNode;
1651 // Use LastContextId as a uniq id for MIB allocation nodes.
1652 AllocNode->OrigStackOrAllocId = LastContextId;
1653 // Alloc type should be updated as we add in the MIBs. We should assert
1654 // afterwards that it is not still None.
1655 AllocNode->AllocTypes = (uint8_t)AllocationType::None;
1656
1657 return AllocNode;
1658}
1659
1660static std::string getAllocTypeString(uint8_t AllocTypes) {
1661 if (!AllocTypes)
1662 return "None";
1663 std::string Str;
1664 if (AllocTypes & (uint8_t)AllocationType::NotCold)
1665 Str += "NotCold";
1666 if (AllocTypes & (uint8_t)AllocationType::Cold)
1667 Str += "Cold";
1668 return Str;
1669}
1670
1671template <typename DerivedCCG, typename FuncTy, typename CallTy>
1672template <class NodeT, class IteratorT>
1673void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::addStackNodesForMIB(
1674 ContextNode *AllocNode, CallStack<NodeT, IteratorT> &StackContext,
1675 CallStack<NodeT, IteratorT> &CallsiteContext, AllocationType AllocType,
1676 ArrayRef<ContextTotalSize> ContextSizeInfo,
1677 std::map<uint64_t, uint32_t> &TotalSizeToContextIdTopNCold) {
1678 // Treating the hot alloc type as NotCold before the disambiguation for "hot"
1679 // is done.
1680 if (AllocType == AllocationType::Hot)
1681 AllocType = AllocationType::NotCold;
1682
1683 ContextIdToAllocationType[++LastContextId] = AllocType;
1684
1685 bool IsImportant = false;
1686 if (!ContextSizeInfo.empty()) {
1687 auto &Entry = ContextIdToContextSizeInfos[LastContextId];
1688 // If this is a cold allocation, and we are collecting non-zero largest
1689 // contexts, see if this is a candidate.
1690 if (AllocType == AllocationType::Cold && MemProfTopNImportant > 0) {
1691 uint64_t TotalCold = 0;
1692 for (auto &CSI : ContextSizeInfo)
1693 TotalCold += CSI.TotalSize;
1694 // Record this context if either we haven't found the first top-n largest
1695 // yet, or if it is larger than the smallest already recorded.
1696 if (TotalSizeToContextIdTopNCold.size() < MemProfTopNImportant ||
1697 // Since TotalSizeToContextIdTopNCold is a std::map, it is implicitly
1698 // sorted in ascending size of its key which is the size.
1699 TotalCold > TotalSizeToContextIdTopNCold.begin()->first) {
1700 if (TotalSizeToContextIdTopNCold.size() == MemProfTopNImportant) {
1701 // Remove old one and its associated entries.
1702 auto IdToRemove = TotalSizeToContextIdTopNCold.begin()->second;
1703 TotalSizeToContextIdTopNCold.erase(
1704 TotalSizeToContextIdTopNCold.begin());
1705 assert(ImportantContextIdInfo.count(IdToRemove));
1706 ImportantContextIdInfo.erase(IdToRemove);
1707 }
1708 TotalSizeToContextIdTopNCold[TotalCold] = LastContextId;
1709 IsImportant = true;
1710 }
1711 }
1712 Entry.insert(Entry.begin(), ContextSizeInfo.begin(), ContextSizeInfo.end());
1713 }
1714
1715 // Update alloc type and context ids for this MIB.
1716 AllocNode->AllocTypes |= (uint8_t)AllocType;
1717
1718 // Now add or update nodes for each stack id in alloc's context.
1719 // Later when processing the stack ids on non-alloc callsites we will adjust
1720 // for any inlining in the context.
1721 ContextNode *PrevNode = AllocNode;
1722 // Look for recursion (direct recursion should have been collapsed by
1723 // module summary analysis, here we should just be detecting mutual
1724 // recursion). Mark these nodes so we don't try to clone.
1725 SmallSet<uint64_t, 8> StackIdSet;
1726 // Skip any on the allocation call (inlining).
1727 for (auto ContextIter = StackContext.beginAfterSharedPrefix(CallsiteContext);
1728 ContextIter != StackContext.end(); ++ContextIter) {
1729 auto StackId = getStackId(*ContextIter);
1730 if (IsImportant)
1731 ImportantContextIdInfo[LastContextId].StackIds.push_back(StackId);
1732 ContextNode *StackNode = getNodeForStackId(StackId);
1733 if (!StackNode) {
1734 StackNode = createNewNode(/*IsAllocation=*/false);
1735 StackEntryIdToContextNodeMap[StackId] = StackNode;
1736 StackNode->OrigStackOrAllocId = StackId;
1737 }
1738 // Marking a node recursive will prevent its cloning completely, even for
1739 // non-recursive contexts flowing through it.
1741 auto Ins = StackIdSet.insert(StackId);
1742 if (!Ins.second)
1743 StackNode->Recursive = true;
1744 }
1745 StackNode->AllocTypes |= (uint8_t)AllocType;
1746 PrevNode->addOrUpdateCallerEdge(StackNode, AllocType, LastContextId);
1747 PrevNode = StackNode;
1748 }
1749}
1750
1751template <typename DerivedCCG, typename FuncTy, typename CallTy>
1752DenseSet<uint32_t>
1753CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::duplicateContextIds(
1754 const DenseSet<uint32_t> &StackSequenceContextIds,
1755 DenseMap<uint32_t, DenseSet<uint32_t>> &OldToNewContextIds) {
1756 DenseSet<uint32_t> NewContextIds;
1757 for (auto OldId : StackSequenceContextIds) {
1758 NewContextIds.insert(++LastContextId);
1759 OldToNewContextIds[OldId].insert(LastContextId);
1760 assert(ContextIdToAllocationType.count(OldId));
1761 // The new context has the same allocation type and size info as original.
1762 ContextIdToAllocationType[LastContextId] = ContextIdToAllocationType[OldId];
1763 auto CSI = ContextIdToContextSizeInfos.find(OldId);
1764 if (CSI != ContextIdToContextSizeInfos.end())
1765 ContextIdToContextSizeInfos[LastContextId] = CSI->second;
1766 if (DotAllocContextIds.contains(OldId))
1767 DotAllocContextIds.insert(LastContextId);
1768 }
1769 return NewContextIds;
1770}
1771
1772template <typename DerivedCCG, typename FuncTy, typename CallTy>
1773void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::
1774 propagateDuplicateContextIds(
1775 const DenseMap<uint32_t, DenseSet<uint32_t>> &OldToNewContextIds) {
1776 // Build a set of duplicated context ids corresponding to the input id set.
1777 auto GetNewIds = [&OldToNewContextIds](const DenseSet<uint32_t> &ContextIds) {
1778 DenseSet<uint32_t> NewIds;
1779 for (auto Id : ContextIds)
1780 if (auto NewId = OldToNewContextIds.find(Id);
1781 NewId != OldToNewContextIds.end())
1782 NewIds.insert_range(NewId->second);
1783 return NewIds;
1784 };
1785
1786 // Recursively update context ids sets along caller edges.
1787 auto UpdateCallers = [&](ContextNode *Node,
1788 DenseSet<const ContextEdge *> &Visited,
1789 auto &&UpdateCallers) -> void {
1790 for (const auto &Edge : Node->CallerEdges) {
1791 auto Inserted = Visited.insert(Edge.get());
1792 if (!Inserted.second)
1793 continue;
1794 ContextNode *NextNode = Edge->Caller;
1795 DenseSet<uint32_t> NewIdsToAdd = GetNewIds(Edge->getContextIds());
1796 // Only need to recursively iterate to NextNode via this caller edge if
1797 // it resulted in any added ids to NextNode.
1798 if (!NewIdsToAdd.empty()) {
1799 Edge->getContextIds().insert_range(NewIdsToAdd);
1800 UpdateCallers(NextNode, Visited, UpdateCallers);
1801 }
1802 }
1803 };
1804
1805 DenseSet<const ContextEdge *> Visited;
1806 for (auto &Entry : AllocationCallToContextNodeMap) {
1807 auto *Node = Entry.second;
1808 UpdateCallers(Node, Visited, UpdateCallers);
1809 }
1810}
1811
1812template <typename DerivedCCG, typename FuncTy, typename CallTy>
1813void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::connectNewNode(
1814 ContextNode *NewNode, ContextNode *OrigNode, bool TowardsCallee,
1815 const DenseSet<uint32_t> &ContextIds) {
1816 auto &OrigEdges =
1817 TowardsCallee ? OrigNode->CalleeEdges : OrigNode->CallerEdges;
1818 // Increment iterator in loop so that we can remove edges as needed.
1819 for (auto EI = OrigEdges.begin(); EI != OrigEdges.end();) {
1820 auto Edge = *EI;
1821 DenseSet<uint32_t> NewEdgeContextIds;
1822 // Remove any matching context ids from Edge, return set that were found and
1823 // removed, these are the new edge's context ids.
1824 set_subtract(Edge->getContextIds(), ContextIds, NewEdgeContextIds);
1825 // If no matching context ids for this edge, skip it.
1826 if (NewEdgeContextIds.empty()) {
1827 ++EI;
1828 continue;
1829 }
1830 if (TowardsCallee) {
1831 uint8_t NewAllocType = computeAllocType(NewEdgeContextIds);
1832 auto NewEdge = std::make_shared<ContextEdge>(
1833 Edge->Callee, NewNode, NewAllocType, std::move(NewEdgeContextIds));
1834 NewNode->CalleeEdges.push_back(NewEdge);
1835 NewEdge->Callee->CallerEdges.push_back(NewEdge);
1836 } else {
1837 uint8_t NewAllocType = computeAllocType(NewEdgeContextIds);
1838 auto NewEdge = std::make_shared<ContextEdge>(
1839 NewNode, Edge->Caller, NewAllocType, std::move(NewEdgeContextIds));
1840 NewNode->CallerEdges.push_back(NewEdge);
1841 NewEdge->Caller->CalleeEdges.push_back(NewEdge);
1842 }
1843 // Remove old edge if context ids empty, otherwise update its alloc type to
1844 // reflect the removed context ids.
1845 if (Edge->getContextIds().empty()) {
1846 removeEdgeFromGraph(Edge.get(), &EI, TowardsCallee);
1847 continue;
1848 }
1849 Edge->AllocTypes = computeAllocType(Edge->getContextIds());
1850 ++EI;
1851 }
1852}
1853
1854template <typename DerivedCCG, typename FuncTy, typename CallTy>
1855static void checkEdge(
1856 const std::shared_ptr<ContextEdge<DerivedCCG, FuncTy, CallTy>> &Edge) {
1857 // Confirm that alloc type is not None and that we have at least one context
1858 // id.
1859 assert(Edge->AllocTypes != (uint8_t)AllocationType::None);
1860 assert(!Edge->ContextIds.empty());
1861}
1862
1863template <typename DerivedCCG, typename FuncTy, typename CallTy>
1864static void checkNode(const ContextNode<DerivedCCG, FuncTy, CallTy> *Node,
1865 bool CheckEdges = true) {
1866 if (Node->isRemoved())
1867 return;
1868#ifndef NDEBUG
1869 // Compute node's context ids once for use in asserts.
1870 auto NodeContextIds = Node->getContextIds();
1871#endif
1872 // Node's context ids should be the union of both its callee and caller edge
1873 // context ids.
1874 if (Node->CallerEdges.size()) {
1875 DenseSet<uint32_t> CallerEdgeContextIds(
1876 Node->CallerEdges.front()->ContextIds);
1877 for (const auto &Edge : llvm::drop_begin(Node->CallerEdges)) {
1878 if (CheckEdges)
1880 set_union(CallerEdgeContextIds, Edge->ContextIds);
1881 }
1882 // Node can have more context ids than callers if some contexts terminate at
1883 // node and some are longer. If we are allowing recursive callsites and
1884 // contexts this will be violated for incompletely cloned recursive cycles,
1885 // so skip the checking in that case.
1887 NodeContextIds == CallerEdgeContextIds ||
1888 set_is_subset(CallerEdgeContextIds, NodeContextIds));
1889 }
1890 if (Node->CalleeEdges.size()) {
1891 DenseSet<uint32_t> CalleeEdgeContextIds(
1892 Node->CalleeEdges.front()->ContextIds);
1893 for (const auto &Edge : llvm::drop_begin(Node->CalleeEdges)) {
1894 if (CheckEdges)
1896 set_union(CalleeEdgeContextIds, Edge->getContextIds());
1897 }
1898 // If we are allowing recursive callsites and contexts this will be violated
1899 // for incompletely cloned recursive cycles, so skip the checking in that
1900 // case.
1902 NodeContextIds == CalleeEdgeContextIds);
1903 }
1904 // FIXME: Since this checking is only invoked under an option, we should
1905 // change the error checking from using assert to something that will trigger
1906 // an error on a release build.
1907#ifndef NDEBUG
1908 // Make sure we don't end up with duplicate edges between the same caller and
1909 // callee.
1911 for (const auto &E : Node->CalleeEdges)
1912 NodeSet.insert(E->Callee);
1913 assert(NodeSet.size() == Node->CalleeEdges.size());
1914#endif
1915}
1916
1917template <typename DerivedCCG, typename FuncTy, typename CallTy>
1918void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::
1919 assignStackNodesPostOrder(ContextNode *Node,
1920 DenseSet<const ContextNode *> &Visited,
1921 DenseMap<uint64_t, std::vector<CallContextInfo>>
1922 &StackIdToMatchingCalls,
1923 DenseMap<CallInfo, CallInfo> &CallToMatchingCall,
1924 const DenseSet<uint32_t> &ImportantContextIds) {
1925 auto Inserted = Visited.insert(Node);
1926 if (!Inserted.second)
1927 return;
1928 // Post order traversal. Iterate over a copy since we may add nodes and
1929 // therefore new callers during the recursive call, invalidating any
1930 // iterator over the original edge vector. We don't need to process these
1931 // new nodes as they were already processed on creation.
1932 auto CallerEdges = Node->CallerEdges;
1933 for (auto &Edge : CallerEdges) {
1934 // Skip any that have been removed during the recursion.
1935 if (Edge->isRemoved()) {
1936 assert(!is_contained(Node->CallerEdges, Edge));
1937 continue;
1938 }
1939 assignStackNodesPostOrder(Edge->Caller, Visited, StackIdToMatchingCalls,
1940 CallToMatchingCall, ImportantContextIds);
1941 }
1942
1943 // If this node's stack id is in the map, update the graph to contain new
1944 // nodes representing any inlining at interior callsites. Note we move the
1945 // associated context ids over to the new nodes.
1946
1947 // Ignore this node if it is for an allocation or we didn't record any
1948 // stack id lists ending at it.
1949 if (Node->IsAllocation ||
1950 !StackIdToMatchingCalls.count(Node->OrigStackOrAllocId))
1951 return;
1952
1953 auto &Calls = StackIdToMatchingCalls[Node->OrigStackOrAllocId];
1954 // Handle the simple case first. A single call with a single stack id.
1955 // In this case there is no need to create any new context nodes, simply
1956 // assign the context node for stack id to this Call.
1957 if (Calls.size() == 1) {
1958 auto &[Call, StackNodes, Func, SavedContextIds] = Calls[0];
1959 if (StackNodes.size() == 1) {
1960 assert(SavedContextIds.empty());
1961 // It should be this Node
1962 assert(Node == StackNodes[0]);
1963 if (Node->Recursive)
1964 return;
1965 Node->setCall(Call);
1966 NonAllocationCallToContextNodeMap[Call] = Node;
1967 NodeToCallingFunc[Node] = Func;
1968 recordStackNode(StackNodes, Node, Node->getContextIds(),
1969 ImportantContextIds);
1970 return;
1971 }
1972 }
1973
1974#ifndef NDEBUG
1975 // Find the node for the last stack id, which should be the same
1976 // across all calls recorded for this id, and is this node's id.
1977 uint64_t LastId = Node->OrigStackOrAllocId;
1978 ContextNode *LastNode = getNodeForStackId(LastId);
1979 // We should only have kept stack ids that had nodes.
1980 assert(LastNode);
1981 assert(LastNode == Node);
1982#else
1983 ContextNode *LastNode = Node;
1984#endif
1985
1986 // Compute the last node's context ids once, as it is shared by all calls in
1987 // this entry.
1988 DenseSet<uint32_t> LastNodeContextIds = LastNode->getContextIds();
1989
1990 [[maybe_unused]] bool PrevIterCreatedNode = false;
1991 bool CreatedNode = false;
1992 for (unsigned I = 0; I < Calls.size();
1993 I++, PrevIterCreatedNode = CreatedNode) {
1994 CreatedNode = false;
1995 auto &[Call, StackNodes, Func, SavedContextIds] = Calls[I];
1996 // Skip any for which we didn't assign any ids, these don't get a node in
1997 // the graph.
1998 if (SavedContextIds.empty()) {
1999 // If this call has a matching call (located in the same function and
2000 // having the same stack ids), simply add it to the context node created
2001 // for its matching call earlier. These can be treated the same through
2002 // cloning and get updated at the same time.
2003 if (!CallToMatchingCall.contains(Call))
2004 continue;
2005 auto MatchingCall = CallToMatchingCall[Call];
2006 if (!NonAllocationCallToContextNodeMap.contains(MatchingCall)) {
2007 // This should only happen if we had a prior iteration, and it didn't
2008 // create a node because of the below recomputation of context ids
2009 // finding none remaining and continuing early.
2010 assert(I > 0 && !PrevIterCreatedNode);
2011 continue;
2012 }
2013 NonAllocationCallToContextNodeMap[MatchingCall]->MatchingCalls.push_back(
2014 Call);
2015 continue;
2016 }
2017
2018 assert(LastNode == StackNodes.back());
2019
2020 // Recompute the context ids for this stack id sequence (the
2021 // intersection of the context ids of the corresponding nodes).
2022 // Start with the ids we saved in the map for this call, which could be
2023 // duplicated context ids. We have to recompute as we might have overlap
2024 // overlap between the saved context ids for different last nodes, and
2025 // removed them already during the post order traversal.
2026 set_intersect(SavedContextIds, LastNodeContextIds);
2027 ContextNode *PrevNode = LastNode;
2028 bool Skip = false;
2029 // Iterate backwards through the stack nodes, starting after the last one
2030 // in the list, which was handled once outside for all Calls.
2031 for (auto NodeIter = StackNodes.rbegin() + 1; NodeIter != StackNodes.rend();
2032 NodeIter++) {
2033 ContextNode *CurNode = *NodeIter;
2034 // We should only have kept stack ids that had nodes and weren't
2035 // recursive.
2036 assert(CurNode);
2037 assert(!CurNode->Recursive);
2038
2039 auto *Edge = CurNode->findEdgeFromCaller(PrevNode);
2040 if (!Edge) {
2041 Skip = true;
2042 break;
2043 }
2044 PrevNode = CurNode;
2045
2046 // Update the context ids, which is the intersection of the ids along
2047 // all edges in the sequence.
2048 set_intersect(SavedContextIds, Edge->getContextIds());
2049
2050 // If we now have no context ids for clone, skip this call.
2051 if (SavedContextIds.empty()) {
2052 Skip = true;
2053 break;
2054 }
2055 }
2056 if (Skip)
2057 continue;
2058
2059 // Create new context node.
2060 ContextNode *NewNode = createNewNode(/*IsAllocation=*/false, Func, Call);
2061 NonAllocationCallToContextNodeMap[Call] = NewNode;
2062 CreatedNode = true;
2063 NewNode->AllocTypes = computeAllocType(SavedContextIds);
2064
2065 ContextNode *FirstNode = StackNodes[0];
2066 assert(FirstNode);
2067
2068 // Connect to callees of innermost stack frame in inlined call chain.
2069 // This updates context ids for FirstNode's callee's to reflect those
2070 // moved to NewNode.
2071 connectNewNode(NewNode, FirstNode, /*TowardsCallee=*/true, SavedContextIds);
2072
2073 // Connect to callers of outermost stack frame in inlined call chain.
2074 // This updates context ids for FirstNode's caller's to reflect those
2075 // moved to NewNode.
2076 connectNewNode(NewNode, LastNode, /*TowardsCallee=*/false, SavedContextIds);
2077
2078 // Now we need to remove context ids from edges/nodes between First and
2079 // Last Node.
2080 PrevNode = nullptr;
2081 for (ContextNode *CurNode : StackNodes) {
2082 // We should only have kept stack ids that had nodes.
2083 assert(CurNode);
2084
2085 // Remove the context ids moved to NewNode from CurNode, and the
2086 // edge from the prior node.
2087 if (PrevNode) {
2088 auto *PrevEdge = CurNode->findEdgeFromCallee(PrevNode);
2089 // If the sequence contained recursion, we might have already removed
2090 // some edges during the connectNewNode calls above.
2091 if (!PrevEdge) {
2092 PrevNode = CurNode;
2093 continue;
2094 }
2095 set_subtract(PrevEdge->getContextIds(), SavedContextIds);
2096 if (PrevEdge->getContextIds().empty())
2097 removeEdgeFromGraph(PrevEdge);
2098 else
2099 PrevEdge->AllocTypes = computeAllocType(PrevEdge->getContextIds());
2100 }
2101 // Since we update the edges from leaf to tail, only look at the callee
2102 // edges. This isn't an alloc node, so if there are no callee edges, the
2103 // alloc type is None.
2104 CurNode->AllocTypes = CurNode->CalleeEdges.empty()
2105 ? (uint8_t)AllocationType::None
2106 : CurNode->computeAllocType();
2107 PrevNode = CurNode;
2108 }
2109
2110 recordStackNode(StackNodes, NewNode, SavedContextIds, ImportantContextIds);
2111
2112 if (VerifyNodes) {
2113 checkNode<DerivedCCG, FuncTy, CallTy>(NewNode, /*CheckEdges=*/true);
2114 for (ContextNode *CurNode : StackNodes) {
2115 // We should only have kept stack ids that had nodes.
2116 assert(CurNode);
2117 checkNode<DerivedCCG, FuncTy, CallTy>(CurNode, /*CheckEdges=*/true);
2118 }
2119 }
2120 }
2121}
2122
2123template <typename DerivedCCG, typename FuncTy, typename CallTy>
2124void CallsiteContextGraph<DerivedCCG, FuncTy,
2125 CallTy>::fixupImportantContexts() {
2126 if (ImportantContextIdInfo.empty())
2127 return;
2128
2129 // Update statistics as we are done building this map at this point.
2130 NumImportantContextIds = ImportantContextIdInfo.size();
2131
2133 return;
2134
2135 if (ExportToDot)
2136 exportToDot("beforestackfixup");
2137
2138 // For each context we identified as important, walk through the saved context
2139 // stack ids in order from leaf upwards, and make sure all edges are correct.
2140 // These can be difficult to get right when updating the graph while mapping
2141 // nodes onto summary or IR, especially when there is recursion. In
2142 // particular, when we have created new nodes to reflect inlining, it is
2143 // sometimes impossible to know exactly how to update the edges in the face of
2144 // recursion, as we have lost the original ordering of the stack ids in the
2145 // contexts.
2146 // TODO: Consider only doing this if we detect the context has recursive
2147 // cycles.
2148 //
2149 // I.e. assume we have a context with stack ids like: {A B A C A D E}
2150 // and let's say A was inlined into B, C, and D. The original graph will have
2151 // multiple recursive cycles through A. When we match the original context
2152 // nodes onto the IR or summary, we will merge {A B} into one context node,
2153 // {A C} onto another, and {A D} onto another. Looking at the stack sequence
2154 // above, we should end up with a non-cyclic set of edges like:
2155 // {AB} <- {AC} <- {AD} <- E. However, because we normally have lost the
2156 // original ordering, we won't get the edges correct initially (it's
2157 // impossible without the original ordering). Here we do the fixup (add and
2158 // removing edges where necessary) for this context. In the
2159 // ImportantContextInfo struct in this case we should have a MaxLength = 2,
2160 // and map entries for {A B}, {A C}, {A D}, and {E}.
2161 for (auto &[CurContextId, Info] : ImportantContextIdInfo) {
2162 if (Info.StackIdsToNode.empty())
2163 continue;
2164 bool Changed = false;
2165 ContextNode *PrevNode = nullptr;
2166 ContextNode *CurNode = nullptr;
2167 DenseSet<const ContextEdge *> VisitedEdges;
2168 ArrayRef<uint64_t> AllStackIds(Info.StackIds);
2169 // Try to identify what callsite ContextNode maps to which slice of the
2170 // context's ordered stack ids.
2171 for (unsigned I = 0; I < AllStackIds.size(); I++, PrevNode = CurNode) {
2172 // We will do this greedily, trying up to MaxLength stack ids in a row, to
2173 // see if we recorded a context node for that sequence.
2174 auto Len = Info.MaxLength;
2175 auto LenToEnd = AllStackIds.size() - I;
2176 if (Len > LenToEnd)
2177 Len = LenToEnd;
2178 CurNode = nullptr;
2179 // Try to find a recorded context node starting with the longest length
2180 // recorded, and on down until we check for just a single stack node.
2181 for (; Len > 0; Len--) {
2182 // Get the slice of the original stack id sequence to check.
2183 auto CheckStackIds = AllStackIds.slice(I, Len);
2184 auto EntryIt = Info.StackIdsToNode.find(CheckStackIds);
2185 if (EntryIt == Info.StackIdsToNode.end())
2186 continue;
2187 CurNode = EntryIt->second;
2188 // Skip forward so we don't try to look for the ones we just matched.
2189 // We increment by Len - 1, because the outer for loop will increment I.
2190 I += Len - 1;
2191 break;
2192 }
2193 // Give up if we couldn't find a node. Since we need to clone from the
2194 // leaf allocation upwards, no sense in doing anymore fixup further up
2195 // the context if we couldn't match part of the original stack context
2196 // onto a callsite node.
2197 if (!CurNode)
2198 break;
2199 // No edges to fix up until we have a pair of nodes that should be
2200 // adjacent in the graph.
2201 if (!PrevNode)
2202 continue;
2203 // See if we already have a call edge from CurNode to PrevNode.
2204 auto *CurEdge = PrevNode->findEdgeFromCaller(CurNode);
2205 if (CurEdge) {
2206 // We already have an edge. Make sure it contains this context id.
2207 if (CurEdge->getContextIds().insert(CurContextId).second) {
2208 NumFixupEdgeIdsInserted++;
2209 Changed = true;
2210 }
2211 } else {
2212 // No edge exists - add one.
2213 NumFixupEdgesAdded++;
2214 DenseSet<uint32_t> ContextIds({CurContextId});
2215 auto AllocType = computeAllocType(ContextIds);
2216 auto NewEdge = std::make_shared<ContextEdge>(
2217 PrevNode, CurNode, AllocType, std::move(ContextIds));
2218 PrevNode->CallerEdges.push_back(NewEdge);
2219 CurNode->CalleeEdges.push_back(NewEdge);
2220 // Save the new edge for the below handling.
2221 CurEdge = NewEdge.get();
2222 Changed = true;
2223 }
2224 VisitedEdges.insert(CurEdge);
2225 // Now remove this context id from any other caller edges calling
2226 // PrevNode.
2227 for (auto &Edge : PrevNode->CallerEdges) {
2228 // Skip the edge updating/created above and edges we have already
2229 // visited (due to recursion).
2230 if (Edge.get() != CurEdge && !VisitedEdges.contains(Edge.get()))
2231 Edge->getContextIds().erase(CurContextId);
2232 }
2233 }
2234 if (Changed)
2235 NumFixedContexts++;
2236 }
2237}
2238
2239template <typename DerivedCCG, typename FuncTy, typename CallTy>
2240void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::updateStackNodes() {
2241 // Map of stack id to all calls with that as the last (outermost caller)
2242 // callsite id that has a context node (some might not due to trimming
2243 // performed during matching of the allocation profile contexts).
2244 // The CallContextInfo contains the Call and a list of the context nodes for
2245 // its stack ids, the function containing Call, and the set of context ids
2246 // the analysis will eventually identify for use in any new node created
2247 // for that callsite.
2248 DenseMap<uint64_t, std::vector<CallContextInfo>> StackIdToMatchingCalls;
2249 for (auto &[Func, CallsWithMetadata] : FuncToCallsWithMetadata) {
2250 for (auto &Call : CallsWithMetadata) {
2251 // Ignore allocations, already handled.
2252 if (AllocationCallToContextNodeMap.count(Call))
2253 continue;
2254 std::vector<ContextNode *> StackNodes = getStackNodesForCall(Call.call());
2255 // If there were no nodes created for MIBs on allocs (maybe this was in
2256 // the unambiguous part of the MIB stack that was trimmed), ignore.
2257 if (StackNodes.empty())
2258 continue;
2259 // Otherwise, record this Call along with the list of nodes for the last
2260 // (outermost caller) stack id with a node.
2261 uint64_t LastId = StackNodes.back()->OrigStackOrAllocId;
2262 StackIdToMatchingCalls[LastId].push_back(
2263 {Call.call(), std::move(StackNodes), Func, {}});
2264 }
2265 }
2266
2267 // First make a pass through all stack ids that correspond to a call,
2268 // as identified in the above loop. Compute the context ids corresponding to
2269 // each of these calls when they correspond to multiple stack ids due to
2270 // due to inlining. Perform any duplication of context ids required when
2271 // there is more than one call with the same stack ids. Their (possibly newly
2272 // duplicated) context ids are saved in the StackIdToMatchingCalls map.
2273 DenseMap<uint32_t, DenseSet<uint32_t>> OldToNewContextIds;
2274 // Save a map from each call to any that are found to match it. I.e. located
2275 // in the same function and have the same (possibly trimmed) stack ids. We use
2276 // this to avoid creating extra graph nodes as they can be treated the same.
2277 DenseMap<CallInfo, CallInfo> CallToMatchingCall;
2278 for (auto &It : StackIdToMatchingCalls) {
2279 auto &Calls = It.getSecond();
2280 // Skip single calls with a single stack id. These don't need a new node.
2281 if (Calls.size() == 1) {
2282 auto &StackNodes = Calls[0].StackNodes;
2283 if (StackNodes.size() == 1)
2284 continue;
2285 }
2286 // In order to do the best and maximal matching of inlined calls to context
2287 // node sequences we will sort the vectors of stack nodes in descending
2288 // order of length, and within each length, lexicographically by stack id.
2289 // The latter is so that we can specially handle calls that have identical
2290 // stack id sequences (either due to cloning or artificially because of the
2291 // MIB context trimming). Those with the same stack ids are then sorted by
2292 // function to facilitate efficiently mapping them to the same context node.
2293 // Because the functions are pointers, to ensure a stable sort first assign
2294 // each function pointer to its first index in the Calls array, and then use
2295 // that to sort by.
2296 DenseMap<const FuncTy *, unsigned> FuncToIndex;
2297 for (const auto &[Idx, CallCtxInfo] : enumerate(Calls))
2298 FuncToIndex.insert({CallCtxInfo.Func, Idx});
2299 auto StackIdsLess = [](ArrayRef<ContextNode *> A,
2301 return std::lexicographical_compare(
2302 A.begin(), A.end(), B.begin(), B.end(),
2303 [](const ContextNode *X, const ContextNode *Y) {
2304 return X->OrigStackOrAllocId < Y->OrigStackOrAllocId;
2305 });
2306 };
2307 auto CallLess = [&FuncToIndex, &StackIdsLess](const CallContextInfo &A,
2308 const CallContextInfo &B) {
2309 return A.StackNodes.size() > B.StackNodes.size() ||
2310 (A.StackNodes.size() == B.StackNodes.size() &&
2311 (StackIdsLess(A.StackNodes, B.StackNodes) ||
2312 (A.StackNodes == B.StackNodes &&
2313 FuncToIndex[A.Func] < FuncToIndex[B.Func])));
2314 };
2315 llvm::stable_sort(Calls, CallLess);
2316
2317 // Find the node for the last stack id, which should be the same
2318 // across all calls recorded for this id, and is the id for this
2319 // entry in the StackIdToMatchingCalls map.
2320 uint64_t LastId = It.getFirst();
2321 // All calls in this entry share the same last node.
2322 ContextNode *LastNode = Calls[0].StackNodes.back();
2323 // We should only have kept stack ids that had nodes.
2324 assert(LastNode);
2325 assert(LastNode == getNodeForStackId(LastId));
2326
2327 if (LastNode->Recursive)
2328 continue;
2329
2330 // Initialize the context ids with the last node's. We will subsequently
2331 // refine the context ids by computing the intersection along all edges.
2332 DenseSet<uint32_t> LastNodeContextIds = LastNode->getContextIds();
2333 assert(!LastNodeContextIds.empty());
2334
2335#ifndef NDEBUG
2336 // Save the set of functions seen for a particular set of the same stack
2337 // ids. This is used to ensure that they have been correctly sorted to be
2338 // adjacent in the Calls list, since we rely on that to efficiently place
2339 // all such matching calls onto the same context node.
2340 DenseSet<const FuncTy *> MatchingIdsFuncSet;
2341#endif
2342
2343 for (unsigned I = 0; I < Calls.size(); I++) {
2344 auto &[Call, StackNodes, Func, SavedContextIds] = Calls[I];
2345 assert(SavedContextIds.empty());
2346 assert(LastNode == StackNodes.back());
2347
2348#ifndef NDEBUG
2349 // If this call has a different set of ids than the last one, clear the
2350 // set used to ensure they are sorted properly.
2351 if (I > 0 && StackNodes != Calls[I - 1].StackNodes)
2352 MatchingIdsFuncSet.clear();
2353#endif
2354
2355 // First compute the context ids for this stack id sequence (the
2356 // intersection of the context ids of the corresponding nodes).
2357 // Start with the remaining saved ids for the last node.
2358 assert(!LastNodeContextIds.empty());
2359 DenseSet<uint32_t> StackSequenceContextIds = LastNodeContextIds;
2360
2361 ContextNode *PrevNode = LastNode;
2362 ContextNode *CurNode = LastNode;
2363 bool Skip = false;
2364
2365 // Iterate backwards through the stack nodes, starting after the last
2366 // one in the list, which was handled once outside for all Calls.
2367 for (auto NodeIter = StackNodes.rbegin() + 1;
2368 NodeIter != StackNodes.rend(); NodeIter++) {
2369 CurNode = *NodeIter;
2370 // We should only have kept stack ids that had nodes.
2371 assert(CurNode);
2372
2373 if (CurNode->Recursive) {
2374 Skip = true;
2375 break;
2376 }
2377
2378 auto *Edge = CurNode->findEdgeFromCaller(PrevNode);
2379 // If there is no edge then the nodes belong to different MIB contexts,
2380 // and we should skip this inlined context sequence. For example, this
2381 // particular inlined context may include stack ids A->B, and we may
2382 // indeed have nodes for both A and B, but it is possible that they were
2383 // never profiled in sequence in a single MIB for any allocation (i.e.
2384 // we might have profiled an allocation that involves the callsite A,
2385 // but through a different one of its callee callsites, and we might
2386 // have profiled an allocation that involves callsite B, but reached
2387 // from a different caller callsite).
2388 if (!Edge) {
2389 Skip = true;
2390 break;
2391 }
2392 PrevNode = CurNode;
2393
2394 // Update the context ids, which is the intersection of the ids along
2395 // all edges in the sequence.
2396 set_intersect(StackSequenceContextIds, Edge->getContextIds());
2397
2398 // If we now have no context ids for clone, skip this call.
2399 if (StackSequenceContextIds.empty()) {
2400 Skip = true;
2401 break;
2402 }
2403 }
2404 if (Skip)
2405 continue;
2406
2407 // If some of this call's stack ids did not have corresponding nodes (due
2408 // to trimming), don't include any context ids for contexts that extend
2409 // beyond these nodes. Otherwise we would be matching part of unrelated /
2410 // not fully matching stack contexts. To do this, subtract any context ids
2411 // found in caller nodes of the last node found above.
2412 if (LastId != getLastStackId(Call)) {
2413 for (const auto &PE : LastNode->CallerEdges) {
2414 set_subtract(StackSequenceContextIds, PE->getContextIds());
2415 if (StackSequenceContextIds.empty())
2416 break;
2417 }
2418 // If we now have no context ids for clone, skip this call.
2419 if (StackSequenceContextIds.empty())
2420 continue;
2421 }
2422
2423#ifndef NDEBUG
2424 // If the prior call had the same stack ids this set would not be empty.
2425 // Check if we already have a call that "matches" because it is located
2426 // in the same function. If the Calls list was sorted properly we should
2427 // not encounter this situation as all such entries should be adjacent
2428 // and processed in bulk further below.
2429 assert(!MatchingIdsFuncSet.contains(Func));
2430
2431 MatchingIdsFuncSet.insert(Func);
2432#endif
2433
2434 // Check if the next set of stack ids is the same (since the Calls vector
2435 // of tuples is sorted by the stack ids we can just look at the next one).
2436 // If so, save them in the CallToMatchingCall map so that they get
2437 // assigned to the same context node, and skip them. Comparing the stack
2438 // nodes is equivalent to comparing the stack ids, as each stack id has
2439 // its own node and the stack id to node map is not modified here.
2440 bool DuplicateContextIds = false;
2441 for (unsigned J = I + 1; J < Calls.size(); J++) {
2442 auto &CallCtxInfo = Calls[J];
2443 if (CallCtxInfo.StackNodes != StackNodes)
2444 break;
2445 auto *NextFunc = CallCtxInfo.Func;
2446 if (NextFunc != Func) {
2447 // We have another Call with the same ids but that cannot share this
2448 // node, must duplicate ids for it.
2449 DuplicateContextIds = true;
2450 break;
2451 }
2452 auto &NextCall = CallCtxInfo.Call;
2453 CallToMatchingCall[NextCall] = Call;
2454 // Update I so that it gets incremented correctly to skip this call.
2455 I = J;
2456 }
2457
2458 // If we don't have duplicate context ids, then we can assign all the
2459 // context ids computed for the original node sequence to this call.
2460 // If there are duplicate calls with the same stack ids then we synthesize
2461 // new context ids that are duplicates of the originals. These are
2462 // assigned to SavedContextIds, which is a reference into the map entry
2463 // for this call, allowing us to access these ids later on.
2464 OldToNewContextIds.reserve(OldToNewContextIds.size() +
2465 StackSequenceContextIds.size());
2466 SavedContextIds =
2467 DuplicateContextIds
2468 ? duplicateContextIds(StackSequenceContextIds, OldToNewContextIds)
2469 : StackSequenceContextIds;
2470 assert(!SavedContextIds.empty());
2471
2472 if (!DuplicateContextIds) {
2473 // Update saved last node's context ids to remove those that are
2474 // assigned to other calls, so that it is ready for the next call at
2475 // this stack id.
2476 set_subtract(LastNodeContextIds, StackSequenceContextIds);
2477 if (LastNodeContextIds.empty())
2478 break;
2479 }
2480 }
2481 }
2482
2483 // Propagate the duplicate context ids over the graph.
2484 propagateDuplicateContextIds(OldToNewContextIds);
2485
2486 if (VerifyCCG)
2487 check();
2488
2489 // Now perform a post-order traversal over the graph, starting with the
2490 // allocation nodes, essentially processing nodes from callers to callees.
2491 // For any that contains an id in the map, update the graph to contain new
2492 // nodes representing any inlining at interior callsites. Note we move the
2493 // associated context ids over to the new nodes.
2494 DenseSet<const ContextNode *> Visited;
2495 DenseSet<uint32_t> ImportantContextIds(llvm::from_range,
2496 ImportantContextIdInfo.keys());
2497 for (auto &Entry : AllocationCallToContextNodeMap)
2498 assignStackNodesPostOrder(Entry.second, Visited, StackIdToMatchingCalls,
2499 CallToMatchingCall, ImportantContextIds);
2500
2501 fixupImportantContexts();
2502
2503 if (VerifyCCG)
2504 check();
2505}
2506
2507uint64_t ModuleCallsiteContextGraph::getLastStackId(Instruction *Call) {
2508 CallStack<MDNode, MDNode::op_iterator> CallsiteContext(
2509 Call->getMetadata(LLVMContext::MD_callsite));
2510 return CallsiteContext.back();
2511}
2512
2513uint64_t IndexCallsiteContextGraph::getLastStackId(IndexCall &Call) {
2515 CallStack<CallsiteInfo, SmallVector<unsigned>::const_iterator>
2516 CallsiteContext(dyn_cast_if_present<CallsiteInfo *>(Call));
2517 // Need to convert index into stack id.
2518 return Index.getStackIdAtIndex(CallsiteContext.back());
2519}
2520
2521static std::string getMemProfFuncName(Twine Base, unsigned CloneNo) {
2522 // We use CloneNo == 0 to refer to the original version, which doesn't get
2523 // renamed with a suffix.
2524 if (!CloneNo)
2525 return Base.str();
2526 return (Base + MemProfCloneSuffix + Twine(CloneNo)).str();
2527}
2528
2529// Return the clone number of the given function by extracting it from the
2530// memprof suffix. Assumes the caller has already confirmed it is a memprof
2531// clone.
2532static unsigned getMemProfCloneNum(const Function &F) {
2534 auto Pos = F.getName().find_last_of('.');
2535 assert(Pos > 0);
2536 unsigned CloneNo;
2537 bool Err = F.getName().drop_front(Pos + 1).getAsInteger(10, CloneNo);
2538 assert(!Err);
2539 (void)Err;
2540 return CloneNo;
2541}
2542
2543std::string ModuleCallsiteContextGraph::getLabel(const Function *Func,
2544 const Instruction *Call,
2545 unsigned CloneNo) const {
2546 return (Twine(Call->getFunction()->getName()) + " -> " +
2547 cast<CallBase>(Call)->getCalledFunction()->getName())
2548 .str();
2549}
2550
2551std::string IndexCallsiteContextGraph::getLabel(const FunctionSummary *Func,
2552 const IndexCall &Call,
2553 unsigned CloneNo) const {
2554 auto VI = FSToVIMap.find(Func);
2555 assert(VI != FSToVIMap.end());
2556 std::string CallerName = getMemProfFuncName(VI->second.name(), CloneNo);
2558 return CallerName + " -> alloc";
2559 else {
2560 auto *Callsite = dyn_cast_if_present<CallsiteInfo *>(Call);
2561 return CallerName + " -> " +
2562 getMemProfFuncName(Callsite->Callee.name(),
2563 Callsite->Clones[CloneNo]);
2564 }
2565}
2566
2567std::string ModuleCallsiteContextGraph::getFuncName(const Function *Func,
2568 unsigned CloneNo) const {
2569 if (!Func)
2570 return "<unknown>";
2571 return getMemProfFuncName(Func->getName(), CloneNo);
2572}
2573
2574void ModuleCallsiteContextGraph::populateFunctionsWithCallers() {
2575 // Any use (direct call, address taken, alias, etc.) means the function is
2576 // referenced and may be reached by callers above the profiled context.
2577 for (const auto &F : Mod)
2578 if (!F.use_empty())
2579 FunctionsWithCallers.insert(&F);
2580}
2581
2582std::string IndexCallsiteContextGraph::getFuncName(const FunctionSummary *Func,
2583 unsigned CloneNo) const {
2584 if (!Func)
2585 return "<unknown>";
2586 auto VI = FSToVIMap.find(Func);
2587 if (VI != FSToVIMap.end()) {
2588 if (!VI->second.name().empty())
2589 return getMemProfFuncName(VI->second.name(), CloneNo);
2590 return getMemProfFuncName("GUID:" + std::to_string(VI->second.getGUID()),
2591 CloneNo);
2592 }
2593 return getMemProfFuncName("<unknown>", CloneNo);
2594}
2595
2596bool IndexCallsiteContextGraph::isFuncDead(const FunctionSummary *Func) const {
2597 return Index.withGlobalValueDeadStripping() && Func && !Func->isLive();
2598}
2599
2600void IndexCallsiteContextGraph::populateFunctionsWithCallers() {
2601 for (const auto &I : Index) {
2602 auto VI = Index.getValueInfo(I);
2603 for (const auto &S : VI.getSummaryList()) {
2604 if (!GlobalValue::isLocalLinkage(S->linkage()) &&
2605 !isPrevailing(VI.getGUID(), S.get()))
2606 continue;
2607 if (Index.withGlobalValueDeadStripping() && !S->isLive())
2608 continue;
2609 auto AddReferenced = [&](ValueInfo RefVI) {
2610 for (const auto &RefS : RefVI.getSummaryList()) {
2611 const GlobalValueSummary *Base = RefS->getBaseObject();
2612 if (const auto *RefFS = dyn_cast<FunctionSummary>(Base))
2613 FunctionsWithCallers.insert(RefFS);
2614 }
2615 };
2616 // Address-taken references (e.g. from vtables or function pointers).
2617 for (const auto &RefVI : S->refs())
2618 AddReferenced(RefVI);
2619 // Direct calls.
2620 if (const auto *FS = dyn_cast<FunctionSummary>(S.get()))
2621 for (const auto &CallEdge : FS->calls())
2622 AddReferenced(CallEdge.first);
2623 }
2624 }
2625}
2626
2627std::vector<ModuleCallsiteContextGraph::ContextNode *>
2628ModuleCallsiteContextGraph::getStackNodesForCall(Instruction *Call) {
2629 CallStack<MDNode, MDNode::op_iterator> CallsiteContext(
2630 Call->getMetadata(LLVMContext::MD_callsite));
2631 return getStackNodesForCallsite<MDNode, MDNode::op_iterator>(CallsiteContext);
2632}
2633
2634std::vector<IndexCallsiteContextGraph::ContextNode *>
2635IndexCallsiteContextGraph::getStackNodesForCall(IndexCall &Call) {
2637 CallStack<CallsiteInfo, SmallVector<unsigned>::const_iterator>
2638 CallsiteContext(dyn_cast_if_present<CallsiteInfo *>(Call));
2639 return getStackNodesForCallsite<CallsiteInfo,
2640 SmallVector<unsigned>::const_iterator>(
2641 CallsiteContext);
2642}
2643
2644template <typename DerivedCCG, typename FuncTy, typename CallTy>
2645template <class NodeT, class IteratorT>
2646std::vector<
2647 typename CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextNode *>
2648CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::getStackNodesForCallsite(
2649 CallStack<NodeT, IteratorT> &CallsiteContext) {
2650 std::vector<ContextNode *> StackNodes;
2651 for (auto IdOrIndex : CallsiteContext) {
2652 auto StackId = getStackId(IdOrIndex);
2653 ContextNode *Node = getNodeForStackId(StackId);
2654 if (!Node)
2655 break;
2656 StackNodes.push_back(Node);
2657 }
2658 return StackNodes;
2659}
2660
2661ModuleCallsiteContextGraph::ModuleCallsiteContextGraph(
2662 Module &M,
2663 llvm::function_ref<OptimizationRemarkEmitter &(Function *)> OREGetter)
2664 : Mod(M), OREGetter(OREGetter) {
2665 // Map for keeping track of the largest cold contexts up to the number given
2666 // by MemProfTopNImportant. Must be a std::map (not DenseMap) because keys
2667 // must be sorted.
2668 std::map<uint64_t, uint32_t> TotalSizeToContextIdTopNCold;
2669 for (auto &F : M) {
2670 std::vector<CallInfo> CallsWithMetadata;
2671 for (auto &BB : F) {
2672 for (auto &I : BB) {
2673 if (!isa<CallBase>(I))
2674 continue;
2675 if (auto *MemProfMD = I.getMetadata(LLVMContext::MD_memprof)) {
2676 CallsWithMetadata.push_back(&I);
2677 auto *AllocNode = addAllocNode(&I, &F);
2678 auto *CallsiteMD = I.getMetadata(LLVMContext::MD_callsite);
2679 assert(CallsiteMD);
2680 CallStack<MDNode, MDNode::op_iterator> CallsiteContext(CallsiteMD);
2681 // Add all of the MIBs and their stack nodes.
2682 for (auto &MDOp : MemProfMD->operands()) {
2683 auto *MIBMD = cast<const MDNode>(MDOp);
2684 std::vector<ContextTotalSize> ContextSizeInfo;
2685 // Collect the context size information if it exists.
2686 if (MIBMD->getNumOperands() > 2) {
2687 for (unsigned I = 2; I < MIBMD->getNumOperands(); I++) {
2688 MDNode *ContextSizePair =
2689 dyn_cast<MDNode>(MIBMD->getOperand(I));
2690 assert(ContextSizePair->getNumOperands() == 2);
2692 ContextSizePair->getOperand(0))
2693 ->getZExtValue();
2695 ContextSizePair->getOperand(1))
2696 ->getZExtValue();
2697 ContextSizeInfo.push_back({FullStackId, TotalSize});
2698 }
2699 }
2703 addStackNodesForMIB<MDNode, MDNode::op_iterator>(
2704 AllocNode, StackContext, CallsiteContext,
2705 getMIBAllocType(MIBMD), ContextSizeInfo,
2706 TotalSizeToContextIdTopNCold);
2707 }
2708 // If exporting the graph to dot and an allocation id of interest was
2709 // specified, record all the context ids for this allocation node.
2710 if (ExportToDot && AllocNode->OrigStackOrAllocId == AllocIdForDot)
2711 DotAllocContextIds = AllocNode->getContextIds();
2712 assert(AllocNode->AllocTypes != (uint8_t)AllocationType::None);
2713 // Memprof and callsite metadata on memory allocations no longer
2714 // needed.
2715 I.setMetadata(LLVMContext::MD_memprof, nullptr);
2716 I.setMetadata(LLVMContext::MD_callsite, nullptr);
2717 }
2718 // For callsite metadata, add to list for this function for later use.
2719 else if (I.getMetadata(LLVMContext::MD_callsite)) {
2720 CallsWithMetadata.push_back(&I);
2721 }
2722 }
2723 }
2724 if (!CallsWithMetadata.empty())
2725 FuncToCallsWithMetadata[&F] = CallsWithMetadata;
2726 }
2727
2728 if (DumpCCG) {
2729 dbgs() << "CCG before updating call stack chains:\n";
2730 dbgs() << *this;
2731 }
2732
2733 if (ExportToDot)
2734 exportToDot("prestackupdate");
2735
2736 updateStackNodes();
2737
2738 if (ExportToDot)
2739 exportToDot("poststackupdate");
2740
2741 handleCallsitesWithMultipleTargets();
2742
2743 markBackedges();
2744
2745 // Strip off remaining callsite metadata, no longer needed.
2746 for (auto &FuncEntry : FuncToCallsWithMetadata)
2747 for (auto &Call : FuncEntry.second)
2748 Call.call()->setMetadata(LLVMContext::MD_callsite, nullptr);
2749}
2750
2751// Finds the set of GUIDs for weak aliasees that are prevailing in different
2752// modules than any of their aliases. We need to handle these specially.
2754IndexCallsiteContextGraph::findAliaseeGUIDsPrevailingInDifferentModule() {
2755 DenseSet<GlobalValue::GUID> AliaseeGUIDs;
2756 for (auto &I : Index) {
2757 auto VI = Index.getValueInfo(I);
2758 for (auto &S : VI.getSummaryList()) {
2759 // We only care about aliases to functions.
2760 auto *AS = dyn_cast<AliasSummary>(S.get());
2761 if (!AS)
2762 continue;
2763 auto *AliaseeSummary = &AS->getAliasee();
2764 auto *AliaseeFS = dyn_cast<FunctionSummary>(AliaseeSummary);
2765 if (!AliaseeFS)
2766 continue;
2767 // Skip this summary if it is not for the prevailing symbol for this GUID.
2768 // The linker doesn't resolve local linkage values so don't check whether
2769 // those are prevailing.
2770 if (!GlobalValue::isLocalLinkage(S->linkage()) &&
2771 !isPrevailing(VI.getGUID(), S.get()))
2772 continue;
2773 // Prevailing aliasee could be in a different module only if it is weak.
2774 if (!GlobalValue::isWeakForLinker(AliaseeSummary->linkage()))
2775 continue;
2776 auto AliaseeGUID = AS->getAliaseeGUID();
2777 // If the aliasee copy in this module is not prevailing, record it.
2778 if (!isPrevailing(AliaseeGUID, AliaseeSummary))
2779 AliaseeGUIDs.insert(AliaseeGUID);
2780 }
2781 }
2782 AliaseesPrevailingInDiffModuleFromAlias += AliaseeGUIDs.size();
2783 return AliaseeGUIDs;
2784}
2785
2786IndexCallsiteContextGraph::IndexCallsiteContextGraph(
2787 ModuleSummaryIndex &Index,
2788 llvm::function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
2789 isPrevailing)
2790 : Index(Index), isPrevailing(isPrevailing) {
2791 // Since we use the aliasee summary info to create the necessary clones for
2792 // its aliases, conservatively skip recording the aliasee function's callsites
2793 // in the CCG for any that are prevailing in a different module than one of
2794 // its aliases. We could record the necessary information to do this in the
2795 // summary, but this case should not be common.
2796 DenseSet<GlobalValue::GUID> GUIDsToSkip =
2797 findAliaseeGUIDsPrevailingInDifferentModule();
2798 // Map for keeping track of the largest cold contexts up to the number given
2799 // by MemProfTopNImportant. Must be a std::map (not DenseMap) because keys
2800 // must be sorted.
2801 std::map<uint64_t, uint32_t> TotalSizeToContextIdTopNCold;
2802 // Sort by GUID for deterministic graph construction order.
2803 // TODO: This sort has a measurable cost on the thin link when memprof is
2804 // enabled. Investigate gating it behind an option that is only enabled for
2805 // tests that check internal state.
2806 for (const auto &I : Index.sortedGlobalValueSummariesRange()) {
2807 auto VI = Index.getValueInfo(I);
2808 if (GUIDsToSkip.contains(VI.getGUID()))
2809 continue;
2810 for (auto &S : VI.getSummaryList()) {
2811 // We should only add the prevailing nodes. Otherwise we may try to clone
2812 // in a weak copy that won't be linked (and may be different than the
2813 // prevailing version).
2814 // We only keep the memprof summary on the prevailing copy now when
2815 // building the combined index, as a space optimization, however don't
2816 // rely on this optimization. The linker doesn't resolve local linkage
2817 // values so don't check whether those are prevailing.
2818 if (!GlobalValue::isLocalLinkage(S->linkage()) &&
2819 !isPrevailing(VI.getGUID(), S.get()))
2820 continue;
2821 auto *FS = dyn_cast<FunctionSummary>(S.get());
2822 if (!FS)
2823 continue;
2824 std::vector<CallInfo> CallsWithMetadata;
2825 if (!FS->allocs().empty()) {
2826 for (auto &AN : FS->mutableAllocs()) {
2827 // This can happen because of recursion elimination handling that
2828 // currently exists in ModuleSummaryAnalysis. Skip these for now.
2829 // We still added them to the summary because we need to be able to
2830 // correlate properly in applyImport in the backends.
2831 if (AN.MIBs.empty())
2832 continue;
2833 IndexCall AllocCall(&AN);
2834 CallsWithMetadata.push_back(AllocCall);
2835 auto *AllocNode = addAllocNode(AllocCall, FS);
2836 // Pass an empty CallStack to the CallsiteContext (second)
2837 // parameter, since for ThinLTO we already collapsed out the inlined
2838 // stack ids on the allocation call during ModuleSummaryAnalysis.
2840 EmptyContext;
2841 unsigned I = 0;
2843 AN.ContextSizeInfos.size() == AN.MIBs.size());
2844 // Now add all of the MIBs and their stack nodes.
2845 for (auto &MIB : AN.MIBs) {
2847 StackContext(&MIB);
2848 std::vector<ContextTotalSize> ContextSizeInfo;
2849 if (!AN.ContextSizeInfos.empty()) {
2850 for (auto [FullStackId, TotalSize] : AN.ContextSizeInfos[I])
2851 ContextSizeInfo.push_back({FullStackId, TotalSize});
2852 }
2853 addStackNodesForMIB<MIBInfo, SmallVector<unsigned>::const_iterator>(
2854 AllocNode, StackContext, EmptyContext, MIB.AllocType,
2855 ContextSizeInfo, TotalSizeToContextIdTopNCold);
2856 I++;
2857 }
2858 // If exporting the graph to dot and an allocation id of interest was
2859 // specified, record all the context ids for this allocation node.
2860 if (ExportToDot && AllocNode->OrigStackOrAllocId == AllocIdForDot)
2861 DotAllocContextIds = AllocNode->getContextIds();
2862 assert(AllocNode->AllocTypes != (uint8_t)AllocationType::None);
2863 // Initialize version 0 on the summary alloc node to the current alloc
2864 // type, unless it has both types in which case make it default, so
2865 // that in the case where we aren't able to clone the original version
2866 // always ends up with the default allocation behavior.
2867 AN.Versions[0] = (uint8_t)allocTypeToUse(AllocNode->AllocTypes);
2868 }
2869 }
2870 // For callsite metadata, add to list for this function for later use.
2871 if (!FS->callsites().empty())
2872 for (auto &SN : FS->mutableCallsites()) {
2873 IndexCall StackNodeCall(&SN);
2874 CallsWithMetadata.push_back(StackNodeCall);
2875 }
2876
2877 if (!CallsWithMetadata.empty())
2878 FuncToCallsWithMetadata[FS] = CallsWithMetadata;
2879
2880 if (!FS->allocs().empty() || !FS->callsites().empty())
2881 FSToVIMap[FS] = VI;
2882 }
2883 }
2884
2885 if (DumpCCG) {
2886 dbgs() << "CCG before updating call stack chains:\n";
2887 dbgs() << *this;
2888 }
2889
2890 if (ExportToDot)
2891 exportToDot("prestackupdate");
2892
2893 updateStackNodes();
2894
2895 if (ExportToDot)
2896 exportToDot("poststackupdate");
2897
2898 handleCallsitesWithMultipleTargets();
2899
2900 markBackedges();
2901}
2902
2903template <typename DerivedCCG, typename FuncTy, typename CallTy>
2904void CallsiteContextGraph<DerivedCCG, FuncTy,
2905 CallTy>::handleCallsitesWithMultipleTargets() {
2906 // Look for and workaround callsites that call multiple functions.
2907 // This can happen for indirect calls, which needs better handling, and in
2908 // more rare cases (e.g. macro expansion).
2909 // TODO: To fix this for indirect calls we will want to perform speculative
2910 // devirtualization using either the normal PGO info with ICP, or using the
2911 // information in the profiled MemProf contexts. We can do this prior to
2912 // this transformation for regular LTO, and for ThinLTO we can simulate that
2913 // effect in the summary and perform the actual speculative devirtualization
2914 // while cloning in the ThinLTO backend.
2915
2916 // Keep track of the new nodes synthesized for discovered tail calls missing
2917 // from the profiled contexts.
2918 MapVector<CallInfo, ContextNode *> TailCallToContextNodeMap;
2919
2920 std::vector<std::pair<CallInfo, ContextNode *>> NewCallToNode;
2921 for (auto &Entry : NonAllocationCallToContextNodeMap) {
2922 auto *Node = Entry.second;
2923 assert(Node->Clones.empty());
2924 // Check all node callees and see if in the same function.
2925 // We need to check all of the calls recorded in this Node, because in some
2926 // cases we may have had multiple calls with the same debug info calling
2927 // different callees. This can happen, for example, when an object is
2928 // constructed in the paramter list - the destructor call of the object has
2929 // the same debug info (line/col) as the call the object was passed to.
2930 // Here we will prune any that don't match all callee nodes.
2931 std::vector<CallInfo> AllCalls;
2932 AllCalls.reserve(Node->MatchingCalls.size() + 1);
2933 AllCalls.push_back(Node->Call);
2934 llvm::append_range(AllCalls, Node->MatchingCalls);
2935
2936 // First see if we can partition the calls by callee function, creating new
2937 // nodes to host each set of calls calling the same callees. This is
2938 // necessary for support indirect calls with ThinLTO, for which we
2939 // synthesized CallsiteInfo records for each target. They will all have the
2940 // same callsite stack ids and would be sharing a context node at this
2941 // point. We need to perform separate cloning for each, which will be
2942 // applied along with speculative devirtualization in the ThinLTO backends
2943 // as needed. Note this does not currently support looking through tail
2944 // calls, it is unclear if we need that for indirect call targets.
2945 // First partition calls by callee func. Map indexed by func, value is
2946 // struct with list of matching calls, assigned node.
2947 if (partitionCallsByCallee(Node, AllCalls, NewCallToNode))
2948 continue;
2949
2950 auto It = AllCalls.begin();
2951 // Iterate through the calls until we find the first that matches.
2952 for (; It != AllCalls.end(); ++It) {
2953 auto ThisCall = *It;
2954 bool Match = true;
2955 for (auto EI = Node->CalleeEdges.begin(); EI != Node->CalleeEdges.end();
2956 ++EI) {
2957 auto Edge = *EI;
2958 if (!Edge->Callee->hasCall())
2959 continue;
2960 assert(NodeToCallingFunc.count(Edge->Callee));
2961 // Check if the called function matches that of the callee node.
2962 if (!calleesMatch(ThisCall.call(), EI, TailCallToContextNodeMap)) {
2963 Match = false;
2964 break;
2965 }
2966 }
2967 // Found a call that matches the callee nodes, we can quit now.
2968 if (Match) {
2969 // If the first match is not the primary call on the Node, update it
2970 // now. We will update the list of matching calls further below.
2971 if (Node->Call != ThisCall) {
2972 Node->setCall(ThisCall);
2973 // We need to update the NonAllocationCallToContextNodeMap, but don't
2974 // want to do this during iteration over that map, so save the calls
2975 // that need updated entries.
2976 NewCallToNode.push_back({ThisCall, Node});
2977 }
2978 break;
2979 }
2980 }
2981 // We will update this list below (or leave it cleared if there was no
2982 // match found above).
2983 Node->MatchingCalls.clear();
2984 // If we hit the end of the AllCalls vector, no call matching the callee
2985 // nodes was found, clear the call information in the node.
2986 if (It == AllCalls.end()) {
2987 RemovedEdgesWithMismatchedCallees++;
2988 // Work around by setting Node to have a null call, so it gets
2989 // skipped during cloning. Otherwise assignFunctions will assert
2990 // because its data structures are not designed to handle this case.
2991 Node->setCall(CallInfo());
2992 continue;
2993 }
2994 // Now add back any matching calls that call the same function as the
2995 // matching primary call on Node.
2996 for (++It; It != AllCalls.end(); ++It) {
2997 auto ThisCall = *It;
2998 if (!sameCallee(Node->Call.call(), ThisCall.call()))
2999 continue;
3000 Node->MatchingCalls.push_back(ThisCall);
3001 }
3002 }
3003
3004 // Remove all mismatched nodes identified in the above loop from the node map
3005 // (checking whether they have a null call which is set above). For a
3006 // MapVector like NonAllocationCallToContextNodeMap it is much more efficient
3007 // to do the removal via remove_if than by individually erasing entries above.
3008 // Also remove any entries if we updated the node's primary call above.
3009 NonAllocationCallToContextNodeMap.remove_if([](const auto &it) {
3010 return !it.second->hasCall() || it.second->Call != it.first;
3011 });
3012
3013 // Add entries for any new primary calls recorded above.
3014 for (auto &[Call, Node] : NewCallToNode)
3015 NonAllocationCallToContextNodeMap[Call] = Node;
3016
3017 // Add the new nodes after the above loop so that the iteration is not
3018 // invalidated.
3019 for (auto &[Call, Node] : TailCallToContextNodeMap)
3020 NonAllocationCallToContextNodeMap[Call] = Node;
3021}
3022
3023template <typename DerivedCCG, typename FuncTy, typename CallTy>
3024bool CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::partitionCallsByCallee(
3025 ContextNode *Node, ArrayRef<CallInfo> AllCalls,
3026 std::vector<std::pair<CallInfo, ContextNode *>> &NewCallToNode) {
3027 // Struct to keep track of all the calls having the same callee function,
3028 // and the node we eventually assign to them. Eventually we will record the
3029 // context node assigned to this group of calls.
3030 struct CallsWithSameCallee {
3031 std::vector<CallInfo> Calls;
3032 ContextNode *Node = nullptr;
3033 };
3034
3035 // First partition calls by callee function. Build map from each function
3036 // to the list of matching calls.
3038 for (auto ThisCall : AllCalls) {
3039 auto *F = getCalleeFunc(ThisCall.call());
3040 if (F)
3041 CalleeFuncToCallInfo[F].Calls.push_back(ThisCall);
3042 }
3043
3044 // Next, walk through all callee edges. For each callee node, get its
3045 // containing function and see if it was recorded in the above map (meaning we
3046 // have at least one matching call). Build another map from each callee node
3047 // with a matching call to the structure instance created above containing all
3048 // the calls.
3050 for (const auto &Edge : Node->CalleeEdges) {
3051 if (!Edge->Callee->hasCall())
3052 continue;
3053 const FuncTy *ProfiledCalleeFunc = NodeToCallingFunc[Edge->Callee];
3054 if (CalleeFuncToCallInfo.contains(ProfiledCalleeFunc))
3055 CalleeNodeToCallInfo[Edge->Callee] =
3056 &CalleeFuncToCallInfo[ProfiledCalleeFunc];
3057 }
3058
3059 // If there are entries in the second map, then there were no matching
3060 // calls/callees, nothing to do here. Return so we can go to the handling that
3061 // looks through tail calls.
3062 if (CalleeNodeToCallInfo.empty())
3063 return false;
3064
3065 // Walk through all callee edges again. Any and all callee edges that didn't
3066 // match any calls (callee not in the CalleeNodeToCallInfo map) are moved to a
3067 // new caller node (UnmatchedCalleesNode) which gets a null call so that it is
3068 // ignored during cloning. If it is in the map, then we use the node recorded
3069 // in that entry (creating it if needed), and move the callee edge to it.
3070 // The first callee will use the original node instead of creating a new one.
3071 // Note that any of the original calls on this node (in AllCalls) that didn't
3072 // have a callee function automatically get dropped from the node as part of
3073 // this process.
3074 ContextNode *UnmatchedCalleesNode = nullptr;
3075 // Track whether we already assigned original node to a callee.
3076 bool UsedOrigNode = false;
3077 assert(NodeToCallingFunc[Node]);
3078 // Iterate over a copy of Node's callee edges, since we may need to remove
3079 // edges in moveCalleeEdgeToNewCaller, and this simplifies the handling and
3080 // makes it less error-prone.
3081 auto CalleeEdges = Node->CalleeEdges;
3082 for (auto &Edge : CalleeEdges) {
3083 if (!Edge->Callee->hasCall())
3084 continue;
3085
3086 // Will be updated below to point to whatever (caller) node this callee edge
3087 // should be moved to.
3088 ContextNode *CallerNodeToUse = nullptr;
3089
3090 // Handle the case where there were no matching calls first. Move this
3091 // callee edge to the UnmatchedCalleesNode, creating it if needed.
3092 if (!CalleeNodeToCallInfo.contains(Edge->Callee)) {
3093 if (!UnmatchedCalleesNode)
3094 UnmatchedCalleesNode =
3095 createNewNode(/*IsAllocation=*/false, NodeToCallingFunc[Node]);
3096 CallerNodeToUse = UnmatchedCalleesNode;
3097 } else {
3098 // Look up the information recorded for this callee node, and use the
3099 // recorded caller node (creating it if needed).
3100 auto *Info = CalleeNodeToCallInfo[Edge->Callee];
3101 if (!Info->Node) {
3102 // If we haven't assigned any callees to the original node use it.
3103 if (!UsedOrigNode) {
3104 Info->Node = Node;
3105 // Clear the set of matching calls which will be updated below.
3106 Node->MatchingCalls.clear();
3107 UsedOrigNode = true;
3108 } else
3109 Info->Node =
3110 createNewNode(/*IsAllocation=*/false, NodeToCallingFunc[Node]);
3111 assert(!Info->Calls.empty());
3112 // The first call becomes the primary call for this caller node, and the
3113 // rest go in the matching calls list.
3114 Info->Node->setCall(Info->Calls.front());
3115 llvm::append_range(Info->Node->MatchingCalls,
3116 llvm::drop_begin(Info->Calls));
3117 // Save the primary call to node correspondence so that we can update
3118 // the NonAllocationCallToContextNodeMap, which is being iterated in the
3119 // caller of this function.
3120 NewCallToNode.push_back({Info->Node->Call, Info->Node});
3121 }
3122 CallerNodeToUse = Info->Node;
3123 }
3124
3125 // Don't need to move edge if we are using the original node;
3126 if (CallerNodeToUse == Node)
3127 continue;
3128
3129 moveCalleeEdgeToNewCaller(Edge, CallerNodeToUse);
3130 }
3131 // Now that we are done moving edges, clean up any caller edges that ended
3132 // up with no type or context ids. During moveCalleeEdgeToNewCaller all
3133 // caller edges from Node are replicated onto the new callers, and it
3134 // simplifies the handling to leave them until we have moved all
3135 // edges/context ids.
3136 for (auto &I : CalleeNodeToCallInfo)
3137 removeNoneTypeCallerEdges(I.second->Node);
3138 if (UnmatchedCalleesNode)
3139 removeNoneTypeCallerEdges(UnmatchedCalleesNode);
3140 removeNoneTypeCallerEdges(Node);
3141
3142 return true;
3143}
3144
3145uint64_t ModuleCallsiteContextGraph::getStackId(uint64_t IdOrIndex) const {
3146 // In the Module (IR) case this is already the Id.
3147 return IdOrIndex;
3148}
3149
3150uint64_t IndexCallsiteContextGraph::getStackId(uint64_t IdOrIndex) const {
3151 // In the Index case this is an index into the stack id list in the summary
3152 // index, convert it to an Id.
3153 return Index.getStackIdAtIndex(IdOrIndex);
3154}
3155
3156template <typename DerivedCCG, typename FuncTy, typename CallTy>
3157bool CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::calleesMatch(
3158 CallTy Call, EdgeIter &EI,
3159 MapVector<CallInfo, ContextNode *> &TailCallToContextNodeMap) {
3160 auto Edge = *EI;
3161 const FuncTy *ProfiledCalleeFunc = NodeToCallingFunc[Edge->Callee];
3162 const FuncTy *CallerFunc = NodeToCallingFunc[Edge->Caller];
3163 // Will be populated in order of callee to caller if we find a chain of tail
3164 // calls between the profiled caller and callee.
3165 std::vector<std::pair<CallTy, FuncTy *>> FoundCalleeChain;
3166 if (!calleeMatchesFunc(Call, ProfiledCalleeFunc, CallerFunc,
3167 FoundCalleeChain))
3168 return false;
3169
3170 // The usual case where the profiled callee matches that of the IR/summary.
3171 if (FoundCalleeChain.empty())
3172 return true;
3173
3174 auto AddEdge = [Edge, &EI](ContextNode *Caller, ContextNode *Callee) {
3175 auto *CurEdge = Callee->findEdgeFromCaller(Caller);
3176 // If there is already an edge between these nodes, simply update it and
3177 // return.
3178 if (CurEdge) {
3179 CurEdge->ContextIds.insert_range(Edge->ContextIds);
3180 CurEdge->AllocTypes |= Edge->AllocTypes;
3181 return;
3182 }
3183 // Otherwise, create a new edge and insert it into the caller and callee
3184 // lists.
3185 auto NewEdge = std::make_shared<ContextEdge>(
3186 Callee, Caller, Edge->AllocTypes, Edge->ContextIds);
3187 Callee->CallerEdges.push_back(NewEdge);
3188 if (Caller == Edge->Caller) {
3189 // If we are inserting the new edge into the current edge's caller, insert
3190 // the new edge before the current iterator position, and then increment
3191 // back to the current edge.
3192 EI = Caller->CalleeEdges.insert(EI, NewEdge);
3193 ++EI;
3194 assert(*EI == Edge &&
3195 "Iterator position not restored after insert and increment");
3196 } else
3197 Caller->CalleeEdges.push_back(NewEdge);
3198 };
3199
3200 // Create new nodes for each found callee and connect in between the profiled
3201 // caller and callee.
3202 auto *CurCalleeNode = Edge->Callee;
3203 for (auto &[NewCall, Func] : FoundCalleeChain) {
3204 ContextNode *NewNode = nullptr;
3205 // First check if we have already synthesized a node for this tail call.
3206 if (TailCallToContextNodeMap.count(NewCall)) {
3207 NewNode = TailCallToContextNodeMap[NewCall];
3208 NewNode->AllocTypes |= Edge->AllocTypes;
3209 } else {
3210 FuncToCallsWithMetadata[Func].push_back({NewCall});
3211 // Create Node and record node info.
3212 NewNode = createNewNode(/*IsAllocation=*/false, Func, NewCall);
3213 TailCallToContextNodeMap[NewCall] = NewNode;
3214 NewNode->AllocTypes = Edge->AllocTypes;
3215 }
3216
3217 // Hook up node to its callee node
3218 AddEdge(NewNode, CurCalleeNode);
3219
3220 CurCalleeNode = NewNode;
3221 }
3222
3223 // Hook up edge's original caller to new callee node.
3224 AddEdge(Edge->Caller, CurCalleeNode);
3225
3226#ifndef NDEBUG
3227 // Save this because Edge's fields get cleared below when removed.
3228 auto *Caller = Edge->Caller;
3229#endif
3230
3231 // Remove old edge
3232 removeEdgeFromGraph(Edge.get(), &EI, /*CalleeIter=*/true);
3233
3234 // To simplify the increment of EI in the caller, subtract one from EI.
3235 // In the final AddEdge call we would have either added a new callee edge,
3236 // to Edge->Caller, or found an existing one. Either way we are guaranteed
3237 // that there is at least one callee edge.
3238 assert(!Caller->CalleeEdges.empty());
3239 --EI;
3240
3241 return true;
3242}
3243
3244bool ModuleCallsiteContextGraph::findProfiledCalleeThroughTailCalls(
3245 const Function *ProfiledCallee, Value *CurCallee, unsigned Depth,
3246 std::vector<std::pair<Instruction *, Function *>> &FoundCalleeChain,
3247 bool &FoundMultipleCalleeChains) {
3248 // Stop recursive search if we have already explored the maximum specified
3249 // depth.
3251 return false;
3252
3253 auto SaveCallsiteInfo = [&](Instruction *Callsite, Function *F) {
3254 FoundCalleeChain.push_back({Callsite, F});
3255 };
3256
3257 auto *CalleeFunc = dyn_cast<Function>(CurCallee);
3258 if (!CalleeFunc) {
3259 auto *Alias = dyn_cast<GlobalAlias>(CurCallee);
3260 assert(Alias);
3261 CalleeFunc = dyn_cast<Function>(Alias->getAliasee());
3262 assert(CalleeFunc);
3263 }
3264
3265 // Look for tail calls in this function, and check if they either call the
3266 // profiled callee directly, or indirectly (via a recursive search).
3267 // Only succeed if there is a single unique tail call chain found between the
3268 // profiled caller and callee, otherwise we could perform incorrect cloning.
3269 bool FoundSingleCalleeChain = false;
3270 for (auto &BB : *CalleeFunc) {
3271 for (auto &I : BB) {
3272 auto *CB = dyn_cast<CallBase>(&I);
3273 if (!CB || !CB->isTailCall())
3274 continue;
3275 auto *CalledValue = CB->getCalledOperand();
3276 auto *CalledFunction = CB->getCalledFunction();
3277 if (CalledValue && !CalledFunction) {
3278 CalledValue = CalledValue->stripPointerCasts();
3279 // Stripping pointer casts can reveal a called function.
3280 CalledFunction = dyn_cast<Function>(CalledValue);
3281 }
3282 // Check if this is an alias to a function. If so, get the
3283 // called aliasee for the checks below.
3284 if (auto *GA = dyn_cast<GlobalAlias>(CalledValue)) {
3285 assert(!CalledFunction &&
3286 "Expected null called function in callsite for alias");
3287 CalledFunction = dyn_cast<Function>(GA->getAliaseeObject());
3288 }
3289 if (!CalledFunction)
3290 continue;
3291 if (CalledFunction == ProfiledCallee) {
3292 if (FoundSingleCalleeChain) {
3293 FoundMultipleCalleeChains = true;
3294 return false;
3295 }
3296 FoundSingleCalleeChain = true;
3297 FoundProfiledCalleeCount++;
3298 FoundProfiledCalleeDepth += Depth;
3299 if (Depth > FoundProfiledCalleeMaxDepth)
3300 FoundProfiledCalleeMaxDepth = Depth;
3301 SaveCallsiteInfo(&I, CalleeFunc);
3302 } else if (findProfiledCalleeThroughTailCalls(
3303 ProfiledCallee, CalledFunction, Depth + 1,
3304 FoundCalleeChain, FoundMultipleCalleeChains)) {
3305 // findProfiledCalleeThroughTailCalls should not have returned
3306 // true if FoundMultipleCalleeChains.
3307 assert(!FoundMultipleCalleeChains);
3308 if (FoundSingleCalleeChain) {
3309 FoundMultipleCalleeChains = true;
3310 return false;
3311 }
3312 FoundSingleCalleeChain = true;
3313 SaveCallsiteInfo(&I, CalleeFunc);
3314 } else if (FoundMultipleCalleeChains)
3315 return false;
3316 }
3317 }
3318
3319 return FoundSingleCalleeChain;
3320}
3321
3322const Function *ModuleCallsiteContextGraph::getCalleeFunc(Instruction *Call) {
3323 auto *CB = dyn_cast<CallBase>(Call);
3324 if (!CB->getCalledOperand() || CB->isIndirectCall())
3325 return nullptr;
3326 auto *CalleeVal = CB->getCalledOperand()->stripPointerCasts();
3327 auto *Alias = dyn_cast<GlobalAlias>(CalleeVal);
3328 if (Alias)
3329 return dyn_cast<Function>(Alias->getAliasee());
3330 return dyn_cast<Function>(CalleeVal);
3331}
3332
3333bool ModuleCallsiteContextGraph::calleeMatchesFunc(
3334 Instruction *Call, const Function *Func, const Function *CallerFunc,
3335 std::vector<std::pair<Instruction *, Function *>> &FoundCalleeChain) {
3336 auto *CB = dyn_cast<CallBase>(Call);
3337 if (!CB->getCalledOperand() || CB->isIndirectCall())
3338 return false;
3339 auto *CalleeVal = CB->getCalledOperand()->stripPointerCasts();
3340 auto *CalleeFunc = dyn_cast<Function>(CalleeVal);
3341 if (CalleeFunc == Func)
3342 return true;
3343 auto *Alias = dyn_cast<GlobalAlias>(CalleeVal);
3344 if (Alias && Alias->getAliasee() == Func)
3345 return true;
3346
3347 // Recursively search for the profiled callee through tail calls starting with
3348 // the actual Callee. The discovered tail call chain is saved in
3349 // FoundCalleeChain, and we will fixup the graph to include these callsites
3350 // after returning.
3351 // FIXME: We will currently redo the same recursive walk if we find the same
3352 // mismatched callee from another callsite. We can improve this with more
3353 // bookkeeping of the created chain of new nodes for each mismatch.
3354 unsigned Depth = 1;
3355 bool FoundMultipleCalleeChains = false;
3356 if (!findProfiledCalleeThroughTailCalls(Func, CalleeVal, Depth,
3357 FoundCalleeChain,
3358 FoundMultipleCalleeChains)) {
3359 LLVM_DEBUG(dbgs() << "Not found through unique tail call chain: "
3360 << Func->getName() << " from " << CallerFunc->getName()
3361 << " that actually called " << CalleeVal->getName()
3362 << (FoundMultipleCalleeChains
3363 ? " (found multiple possible chains)"
3364 : "")
3365 << "\n");
3366 if (FoundMultipleCalleeChains)
3367 FoundProfiledCalleeNonUniquelyCount++;
3368 return false;
3369 }
3370
3371 return true;
3372}
3373
3374bool ModuleCallsiteContextGraph::sameCallee(Instruction *Call1,
3375 Instruction *Call2) {
3376 auto *CB1 = cast<CallBase>(Call1);
3377 if (!CB1->getCalledOperand() || CB1->isIndirectCall())
3378 return false;
3379 auto *CalleeVal1 = CB1->getCalledOperand()->stripPointerCasts();
3380 auto *CalleeFunc1 = dyn_cast<Function>(CalleeVal1);
3381 auto *CB2 = cast<CallBase>(Call2);
3382 if (!CB2->getCalledOperand() || CB2->isIndirectCall())
3383 return false;
3384 auto *CalleeVal2 = CB2->getCalledOperand()->stripPointerCasts();
3385 auto *CalleeFunc2 = dyn_cast<Function>(CalleeVal2);
3386 return CalleeFunc1 == CalleeFunc2;
3387}
3388
3389bool IndexCallsiteContextGraph::findProfiledCalleeThroughTailCalls(
3390 ValueInfo ProfiledCallee, ValueInfo CurCallee, unsigned Depth,
3391 std::vector<std::pair<ValueInfo, FunctionSummary *>> &FoundCalleeChain,
3392 bool &FoundMultipleCalleeChains) {
3393 // Stop recursive search if we have already explored the maximum specified
3394 // depth.
3396 return false;
3397
3398 // Record each discovered tail call (callee and calling function) in the
3399 // chain. The CallsiteInfo records are only synthesized by the caller once
3400 // the search succeeds, since the chain is discarded if the profiled callee
3401 // is found through multiple chains.
3402 auto SaveTailCall = [&](ValueInfo Callee, FunctionSummary *FS) {
3403 FoundCalleeChain.push_back({Callee, FS});
3404 };
3405
3406 // Look for tail calls in this function, and check if they either call the
3407 // profiled callee directly, or indirectly (via a recursive search).
3408 // Only succeed if there is a single unique tail call chain found between the
3409 // profiled caller and callee, otherwise we could perform incorrect cloning.
3410 bool FoundSingleCalleeChain = false;
3411 for (auto &S : CurCallee.getSummaryList()) {
3412 if (!GlobalValue::isLocalLinkage(S->linkage()) &&
3413 !isPrevailing(CurCallee.getGUID(), S.get()))
3414 continue;
3415 auto *FS = dyn_cast<FunctionSummary>(S->getBaseObject());
3416 if (!FS)
3417 continue;
3418 auto FSVI = CurCallee;
3419 auto *AS = dyn_cast<AliasSummary>(S.get());
3420 if (AS)
3421 FSVI = AS->getAliaseeVI();
3422 for (auto &CallEdge : FS->calls()) {
3423 if (!CallEdge.second.hasTailCall())
3424 continue;
3425 // Edges marked indirect are the profiled targets of indirect calls.
3426 // If the tail call is indirect, the ThinLTO backend will perform
3427 // ICP to the target in order to call a clone of it.
3428 if (CallEdge.second.hasIndirectCall() && !IndirectTailCallSearch)
3429 continue;
3430 if (CallEdge.first == ProfiledCallee) {
3431 if (FoundSingleCalleeChain) {
3432 FoundMultipleCalleeChains = true;
3433 return false;
3434 }
3435 FoundSingleCalleeChain = true;
3436 FoundProfiledCalleeCount++;
3437 FoundProfiledCalleeDepth += Depth;
3438 if (Depth > FoundProfiledCalleeMaxDepth)
3439 FoundProfiledCalleeMaxDepth = Depth;
3440 if (CallEdge.second.hasIndirectCall())
3441 FoundProfiledCalleeIndirectTailCallCount++;
3442 SaveTailCall(CallEdge.first, FS);
3443 // Add FS to FSToVIMap in case it isn't already there.
3444 assert(!FSToVIMap.count(FS) || FSToVIMap[FS] == FSVI);
3445 FSToVIMap[FS] = FSVI;
3446 } else if (findProfiledCalleeThroughTailCalls(
3447 ProfiledCallee, CallEdge.first, Depth + 1,
3448 FoundCalleeChain, FoundMultipleCalleeChains)) {
3449 // findProfiledCalleeThroughTailCalls should not have returned
3450 // true if FoundMultipleCalleeChains.
3451 assert(!FoundMultipleCalleeChains);
3452 if (FoundSingleCalleeChain) {
3453 FoundMultipleCalleeChains = true;
3454 return false;
3455 }
3456 FoundSingleCalleeChain = true;
3457 if (CallEdge.second.hasIndirectCall())
3458 FoundProfiledCalleeIndirectTailCallCount++;
3459 SaveTailCall(CallEdge.first, FS);
3460 // Add FS to FSToVIMap in case it isn't already there.
3461 assert(!FSToVIMap.count(FS) || FSToVIMap[FS] == FSVI);
3462 FSToVIMap[FS] = FSVI;
3463 } else if (FoundMultipleCalleeChains)
3464 return false;
3465 }
3466 }
3467
3468 return FoundSingleCalleeChain;
3469}
3470
3471const FunctionSummary *
3472IndexCallsiteContextGraph::getCalleeFunc(IndexCall &Call) {
3473 ValueInfo Callee = dyn_cast_if_present<CallsiteInfo *>(Call)->Callee;
3474 if (Callee.getSummaryList().empty())
3475 return nullptr;
3476 return dyn_cast<FunctionSummary>(Callee.getSummaryList()[0]->getBaseObject());
3477}
3478
3479bool IndexCallsiteContextGraph::calleeMatchesFunc(
3480 IndexCall &Call, const FunctionSummary *Func,
3481 const FunctionSummary *CallerFunc,
3482 std::vector<std::pair<IndexCall, FunctionSummary *>> &FoundCalleeChain) {
3483 ValueInfo Callee = dyn_cast_if_present<CallsiteInfo *>(Call)->Callee;
3484 // If there is no summary list then this is a call to an externally defined
3485 // symbol.
3486 AliasSummary *Alias =
3487 Callee.getSummaryList().empty()
3488 ? nullptr
3489 : dyn_cast<AliasSummary>(Callee.getSummaryList()[0].get());
3490 assert(FSToVIMap.count(Func));
3491 auto FuncVI = FSToVIMap[Func];
3492 if (Callee == FuncVI ||
3493 // If callee is an alias, check the aliasee, since only function
3494 // summary base objects will contain the stack node summaries and thus
3495 // get a context node.
3496 (Alias && Alias->getAliaseeVI() == FuncVI))
3497 return true;
3498
3499 // Recursively search for the profiled callee through tail calls starting with
3500 // the actual Callee. The discovered tail call chain is saved in
3501 // FoundCalleeChain, and we will fixup the graph to include these callsites
3502 // after returning.
3503 // FIXME: We will currently redo the same recursive walk if we find the same
3504 // mismatched callee from another callsite. We can improve this with more
3505 // bookkeeping of the created chain of new nodes for each mismatch.
3506 unsigned Depth = 1;
3507 bool FoundMultipleCalleeChains = false;
3508 std::vector<std::pair<ValueInfo, FunctionSummary *>> FoundCalleeVIChain;
3509 if (!findProfiledCalleeThroughTailCalls(FuncVI, Callee, Depth,
3510 FoundCalleeVIChain,
3511 FoundMultipleCalleeChains)) {
3512 LLVM_DEBUG(dbgs() << "Not found through unique tail call chain: " << FuncVI
3513 << " from " << FSToVIMap[CallerFunc]
3514 << " that actually called " << Callee
3515 << (FoundMultipleCalleeChains
3516 ? " (found multiple possible chains)"
3517 : "")
3518 << "\n");
3519 if (FoundMultipleCalleeChains)
3520 FoundProfiledCalleeNonUniquelyCount++;
3521 return false;
3522 }
3523
3524 // Now that we know the chain is unique, synthesize a CallsiteInfo for each
3525 // tail call in it, if one hasn't already been synthesized (e.g. for a chain
3526 // to a different profiled callee through the same tail call). These are only
3527 // added to the function summaries once the graph is destroyed (see
3528 // ~IndexCallsiteContextGraph).
3529 for (auto &[CalleeVI, FS] : FoundCalleeVIChain) {
3530 auto &CallsiteInfoPtr =
3531 FunctionCalleesToSynthesizedCallsiteInfos[FS][CalleeVI];
3532 if (!CallsiteInfoPtr)
3533 // StackIds is empty (we don't have debug info available in the index for
3534 // these callsites)
3535 CallsiteInfoPtr =
3536 std::make_unique<CallsiteInfo>(CalleeVI, SmallVector<unsigned>());
3537 FoundCalleeChain.push_back({CallsiteInfoPtr.get(), FS});
3538 }
3539
3540 return true;
3541}
3542
3543bool IndexCallsiteContextGraph::sameCallee(IndexCall &Call1, IndexCall &Call2) {
3544 ValueInfo Callee1 = dyn_cast_if_present<CallsiteInfo *>(Call1)->Callee;
3545 ValueInfo Callee2 = dyn_cast_if_present<CallsiteInfo *>(Call2)->Callee;
3546 return Callee1 == Callee2;
3547}
3548
3549template <typename DerivedCCG, typename FuncTy, typename CallTy>
3550void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextNode::dump()
3551 const {
3552 print(dbgs());
3553 dbgs() << "\n";
3554}
3555
3556template <typename DerivedCCG, typename FuncTy, typename CallTy>
3557void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextNode::print(
3558 raw_ostream &OS) const {
3559 OS << "Node " << this << "\n";
3560 OS << "\t";
3561 printCall(OS);
3562 if (Recursive)
3563 OS << " (recursive)";
3564 OS << "\n";
3565 if (!MatchingCalls.empty()) {
3566 OS << "\tMatchingCalls:\n";
3567 for (auto &MatchingCall : MatchingCalls) {
3568 OS << "\t";
3569 MatchingCall.print(OS);
3570 OS << "\n";
3571 }
3572 }
3573 OS << "\tNodeId: " << NodeId << "\n";
3574 OS << "\tAllocTypes: " << getAllocTypeString(AllocTypes) << "\n";
3575 OS << "\tContextIds:";
3576 // Make a copy of the computed context ids that we can sort for stability.
3577 auto ContextIds = getContextIds();
3578 std::vector<uint32_t> SortedIds(ContextIds.begin(), ContextIds.end());
3579 std::sort(SortedIds.begin(), SortedIds.end());
3580 for (auto Id : SortedIds)
3581 OS << " " << Id;
3582 OS << "\n";
3583 OS << "\tCalleeEdges:\n";
3584 for (auto &Edge : CalleeEdges)
3585 OS << "\t\t" << *Edge << " (Callee NodeId: " << Edge->Callee->NodeId
3586 << ")\n";
3587 OS << "\tCallerEdges:\n";
3588 for (auto &Edge : CallerEdges)
3589 OS << "\t\t" << *Edge << " (Caller NodeId: " << Edge->Caller->NodeId
3590 << ")\n";
3591 if (!Clones.empty()) {
3592 OS << "\tClones: ";
3593 ListSeparator LS;
3594 for (auto *C : Clones)
3595 OS << LS << C << " NodeId: " << C->NodeId;
3596 OS << "\n";
3597 } else if (CloneOf) {
3598 OS << "\tClone of " << CloneOf << " NodeId: " << CloneOf->NodeId << "\n";
3599 }
3600}
3601
3602template <typename DerivedCCG, typename FuncTy, typename CallTy>
3603void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextEdge::dump()
3604 const {
3605 print(dbgs());
3606 dbgs() << "\n";
3607}
3608
3609template <typename DerivedCCG, typename FuncTy, typename CallTy>
3610void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextEdge::print(
3611 raw_ostream &OS) const {
3612 OS << "Edge from Callee " << Callee << " to Caller: " << Caller
3613 << (IsBackedge ? " (BE)" : "")
3614 << " AllocTypes: " << getAllocTypeString(AllocTypes);
3615 OS << " ContextIds:";
3616 std::vector<uint32_t> SortedIds(ContextIds.begin(), ContextIds.end());
3617 std::sort(SortedIds.begin(), SortedIds.end());
3618 for (auto Id : SortedIds)
3619 OS << " " << Id;
3620}
3621
3622template <typename DerivedCCG, typename FuncTy, typename CallTy>
3623void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::dump() const {
3624 print(dbgs());
3625}
3626
3627template <typename DerivedCCG, typename FuncTy, typename CallTy>
3628void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::print(
3629 raw_ostream &OS) const {
3630 OS << "Callsite Context Graph:\n";
3631 using GraphType = const CallsiteContextGraph<DerivedCCG, FuncTy, CallTy> *;
3632 for (const auto Node : nodes<GraphType>(this)) {
3633 if (Node->isRemoved())
3634 continue;
3635 Node->print(OS);
3636 OS << "\n";
3637 }
3638}
3639
3640template <typename DerivedCCG, typename FuncTy, typename CallTy>
3641void CallsiteContextGraph<DerivedCCG, FuncTy,
3642 CallTy>::capturePreCloningContextInfo() {
3643 for (const auto &Entry : AllocationCallToContextNodeMap) {
3644 const ContextNode *AllocNode = Entry.second;
3645 // Remember whether any caller of this allocation matched a call, so that
3646 // the report can distinguish "no matched callers" from an allocation whose
3647 // callers are simply not part of this context.
3648 for (const auto &Edge : AllocNode->CallerEdges) {
3649 if (!Edge->isRemoved() && Edge->Caller->hasCall()) {
3650 PreCloningAllocHasMatchedCaller.insert(AllocNode);
3651 break;
3652 }
3653 }
3654 DenseSet<uint32_t> ContextIds = AllocNode->getContextIds();
3655 for (uint32_t Id : ContextIds) {
3656 PreCloningContextInfo Info;
3657 // Walk the caller edges carrying this context id from the allocation
3658 // node outwards to build the chain of nodes for this context. Each node
3659 // is visited once; backedges (recursive cycles) are only followed when
3660 // no other caller edge carries the id, so that the chain reflects the
3661 // context's stack order rather than looping.
3662 Info.Chain.push_back(AllocNode);
3663 SmallPtrSet<const ContextNode *, 16> Visited;
3664 Visited.insert(AllocNode);
3665 const ContextNode *Cur = AllocNode;
3666 while (true) {
3667 const ContextNode *Next = nullptr;
3668 for (const auto &Edge : Cur->CallerEdges) {
3669 if (Edge->isRemoved() || Edge->IsBackedge)
3670 continue;
3671 if (Edge->getContextIds().contains(Id) &&
3672 !Visited.contains(Edge->Caller)) {
3673 Next = Edge->Caller;
3674 break;
3675 }
3676 }
3677 if (!Next) {
3678 for (const auto &Edge : Cur->CallerEdges) {
3679 if (Edge->isRemoved())
3680 continue;
3681 if (Edge->getContextIds().contains(Id) &&
3682 !Visited.contains(Edge->Caller)) {
3683 Next = Edge->Caller;
3684 break;
3685 }
3686 }
3687 }
3688 if (!Next)
3689 break;
3690 Visited.insert(Next);
3691 Info.Chain.push_back(Next);
3692 Cur = Next;
3693 }
3694
3695 // Find the outermost node (walking from the allocation) such that it
3696 // and all nodes below it matched a call, and record why the first
3697 // unmatched node (if any) did not match.
3698 Info.MaxMatchedFrame = 0;
3699 for (unsigned I = 1; I < Info.Chain.size(); ++I) {
3700 if (Info.Chain[I]->hasCall()) {
3701 Info.MaxMatchedFrame = I;
3702 } else {
3703 const ContextNode *Unmatched = Info.Chain[I];
3704 Info.UnmatchedStackId = Unmatched->OrigStackOrAllocId;
3705 Info.StoppedAtRecursive = Unmatched->Recursive;
3706 // A calling function is known for the unmatched node only when a
3707 // call in that function was considered and rejected because its
3708 // callee did not match the node's callee.
3709 if (auto It = NodeToCallingFunc.find(Unmatched);
3710 It != NodeToCallingFunc.end()) {
3711 Info.StoppedAtMismatchedCallee = true;
3712 Info.UnmatchedCallingFunc = It->second;
3713 }
3714 break;
3715 }
3716 }
3717
3718 // If the whole context matched, check whether its outermost node has
3719 // matched callers reached by other contexts: then this context was
3720 // trimmed below them, and clones of those callers can change which
3721 // allocation clone it reaches.
3722 if (Info.MaxMatchedFrame > 0 &&
3723 Info.MaxMatchedFrame + 1 == Info.Chain.size()) {
3724 const ContextNode *OutermostMatchedNode =
3725 Info.Chain[Info.MaxMatchedFrame];
3726 for (const auto &Edge : OutermostMatchedNode->CallerEdges) {
3727 if (!Edge->isRemoved() && Edge->Caller->hasCall()) {
3728 Info.OutermostMatchedNodeHasOtherCallers = true;
3729 break;
3730 }
3731 }
3732 }
3733
3734 PreCloningContextInfoMap[Id] = std::move(Info);
3735 }
3736 }
3737}
3738
3739template <typename DerivedCCG, typename FuncTy, typename CallTy>
3740std::string
3741CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::formatContextReportSuffix(
3742 const ContextNode *Node, uint32_t Id) const {
3743 auto InfoIt = PreCloningContextInfoMap.find(Id);
3744 if (InfoIt == PreCloningContextInfoMap.end())
3745 return "";
3746 const PreCloningContextInfo &Info = InfoIt->second;
3747
3748 // 1. The allocation function (clone) the context's allocation node ended up
3749 // in, with a qualifier when it is dead, or when the context has callers in
3750 // the profile but none of the allocation's callers matched (either because
3751 // nothing references the function at all, or because the references did not
3752 // match the profiled callsites).
3753 const ContextNode *OrigAlloc = Node->getOrigNode();
3754 const FuncTy *AllocFunc = getCallingFunc(OrigAlloc);
3755 unsigned AllocCloneNo = Node->Call.cloneNo();
3756 std::string AllocFuncStr = getFuncName(AllocFunc, AllocCloneNo);
3757 if (isFuncDead(AllocFunc)) {
3758 AllocFuncStr += " (dead)";
3759 } else if (!PreCloningAllocHasMatchedCaller.contains(OrigAlloc) &&
3760 Info.Chain.size() > 1) {
3761 // Distinguish a function with no references in the IR/summary (it may
3762 // still be referenced from native objects) from one whose references did
3763 // not match.
3764 AllocFuncStr += AllocFunc && !FunctionsWithCallers.contains(AllocFunc)
3765 ? " (no references in IR/summary)"
3766 : " (no matched callers)";
3767 }
3768
3769 // 2. How far the context matched: all of it ("matched N frames to F", or
3770 // "trimmed at frame N in F" when F has callers above that the context does
3771 // not cover), or up to an unmatched node (with the reason and stack id).
3772 unsigned TotalFrames = Info.Chain.size() > 0 ? Info.Chain.size() - 1 : 0;
3773 unsigned Matched = Info.MaxMatchedFrame;
3774 std::string StatusStr;
3775 if (TotalFrames == 0) {
3776 StatusStr = "inlined into leaf";
3777 } else if (Matched < TotalFrames) {
3778 // Where and why matching stopped: the first unmatched node was either a
3779 // recursive callsite (not matched when recursive callsites are disabled),
3780 // a callsite whose IR callee did not match the profiled callee, or a
3781 // callsite with no matching call at all.
3782 if (Info.StoppedAtRecursive)
3783 StatusStr = "unmatched recursive callsite";
3784 else if (Info.StoppedAtMismatchedCallee)
3785 StatusStr = "unmatched callsite (mismatched callee in " +
3786 getFuncName(Info.UnmatchedCallingFunc, 0) + ")";
3787 else
3788 StatusStr = "unmatched callsite";
3789 StatusStr += " at frame " + std::to_string(Matched + 1) + "/" +
3790 std::to_string(TotalFrames) + " (stack id " +
3791 std::to_string(Info.UnmatchedStackId) + ")";
3792 } else {
3793 const ContextNode *OutermostMatchedNode = Info.Chain[Matched];
3794 const FuncTy *OutermostMatchedFunc = getCallingFunc(OutermostMatchedNode);
3795 unsigned NumOutermostMatchedFuncClones =
3796 std::max<unsigned>(1, FuncToNumClones.lookup(OutermostMatchedFunc));
3797 bool HasCallersAbove =
3798 NumOutermostMatchedFuncClones > 1 ||
3799 Info.OutermostMatchedNodeHasOtherCallers ||
3800 (OutermostMatchedFunc &&
3801 FunctionsWithCallers.contains(OutermostMatchedFunc));
3802 if (HasCallersAbove) {
3803 StatusStr = "trimmed at frame " + std::to_string(Matched) + " in " +
3804 getFuncName(OutermostMatchedFunc, 0);
3805 } else {
3806 StatusStr = "matched " + std::to_string(Matched) + " frames to " +
3807 getFuncName(OutermostMatchedFunc, 0);
3808 }
3809 }
3810
3811 // 3. The post-cloning call paths: starting from each function clone of the
3812 // outermost matched caller, follow the callee clones assigned to the
3813 // context's callsites down to the allocation clone reached, and report the
3814 // hint that clone ended up with. Paths reaching the same allocation clone
3815 // are reported once.
3816 std::string ReachesStr;
3817 if (Matched >= 1) {
3818 const ContextNode *OutermostMatchedNode = Info.Chain[Matched];
3819 const FuncTy *OutermostMatchedFunc = getCallingFunc(OutermostMatchedNode);
3820 unsigned NumOutermostMatchedFuncClones =
3821 std::max<unsigned>(1, FuncToNumClones.lookup(OutermostMatchedFunc));
3822 ReachesStr = "; reaches ";
3823 // Allocation clones (by clone number) already reported for this context.
3824 // Different function clones of the outermost matched caller often lead to
3825 // the same allocation clone; such paths are reported only once, for the
3826 // first caller clone reaching that allocation clone.
3827 SmallSet<unsigned, 4> ReportedAllocClones;
3828 bool FirstPath = true;
3829 for (unsigned OutermostMatchedFuncClone = 0;
3830 OutermostMatchedFuncClone < NumOutermostMatchedFuncClones;
3831 ++OutermostMatchedFuncClone) {
3832 // PathFuncs/PathClones[S] is the function and clone number at step S of
3833 // the path, from the outermost matched caller (S = 0) down to the
3834 // allocation function (S = Matched).
3835 std::vector<const FuncTy *> PathFuncs(Matched + 1);
3836 std::vector<unsigned> PathClones(Matched + 1);
3837 PathFuncs[0] = OutermostMatchedFunc;
3838 PathClones[0] = OutermostMatchedFuncClone;
3839 unsigned CurClone = OutermostMatchedFuncClone;
3840 for (unsigned Step = 0; Step < Matched; ++Step) {
3841 unsigned FrameIdx = Matched - Step;
3842 const ContextNode *CallNode = Info.Chain[FrameIdx];
3843 unsigned NextClone =
3844 OrigNodeAndCloneToCalleeClone.lookup({CallNode, CurClone});
3845 const FuncTy *CalleeFunc = getCallingFunc(Info.Chain[FrameIdx - 1]);
3846 PathFuncs[Step + 1] = CalleeFunc;
3847 PathClones[Step + 1] = NextClone;
3848 CurClone = NextClone;
3849 }
3850
3851 if (!ReportedAllocClones.insert(CurClone).second)
3852 continue;
3853 if (!FirstPath)
3854 ReachesStr += ", ";
3855 FirstPath = false;
3856
3857 const ContextNode *ReachedAlloc =
3858 OrigAllocAndCloneToNode.lookup({OrigAlloc, CurClone});
3859 // Report the hint actually applied to the reached allocation clone
3860 // (which accounts for allocTypeToUse and MinClonedColdBytePercent),
3861 // rather than the graph node's (possibly ambiguous) AllocTypes.
3862 std::string ReachedTypeStr;
3863 if (ReachedAlloc)
3864 ReachedTypeStr = getAllocTypeString(
3865 (uint8_t)getAllocationCallType(ReachedAlloc->Call));
3866 else if (CurClone == 0)
3867 ReachedTypeStr =
3868 getAllocTypeString((uint8_t)getAllocationCallType(OrigAlloc->Call));
3869 else
3870 ReachedTypeStr = "None";
3871
3872 // Print the path, eliding runs of uncloned (or cloned) functions in the
3873 // middle of paths longer than MemProfReportHintedSizesDetailMaxPathLen;
3874 // the ends and every transition between cloned and uncloned functions
3875 // are kept.
3876 std::string PathStr;
3877 bool SkippedPrev = false;
3878 bool PrintFullPath =
3880 for (unsigned S = 0; S <= Matched; ++S) {
3881 bool IsCloned = PathClones[S] > 0;
3882 bool PrevCloned = S > 0 ? (PathClones[S - 1] > 0) : IsCloned;
3883 bool NextCloned = S + 1 <= Matched ? (PathClones[S + 1] > 0) : IsCloned;
3884 bool Include = PrintFullPath || (S <= 1) || (S + 1 >= Matched) ||
3885 (IsCloned != PrevCloned) || (IsCloned != NextCloned);
3886 if (!Include) {
3887 if (!SkippedPrev) {
3888 PathStr += " -> ...";
3889 SkippedPrev = true;
3890 }
3891 continue;
3892 }
3893 SkippedPrev = false;
3894 if (!PathStr.empty())
3895 PathStr += " -> ";
3896 PathStr += getFuncName(PathFuncs[S], PathClones[S]);
3897 }
3898 ReachesStr += ReachedTypeStr + " via " + PathStr;
3899 }
3900 }
3901
3902 return " [alloc in " + AllocFuncStr + "; " + StatusStr + ReachesStr + "]";
3903}
3904
3905template <typename DerivedCCG, typename FuncTy, typename CallTy>
3906void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::printTotalSizes(
3907 raw_ostream &OS,
3908 function_ref<void(StringRef, StringRef, const Twine &)> EmitRemark) const {
3909 using GraphType = const CallsiteContextGraph<DerivedCCG, FuncTy, CallTy> *;
3910 for (const auto Node : nodes<GraphType>(this)) {
3911 if (Node->isRemoved())
3912 continue;
3913 if (!Node->IsAllocation)
3914 continue;
3915 DenseSet<uint32_t> ContextIds = Node->getContextIds();
3916 auto AllocTypeFromCall = getAllocationCallType(Node->Call);
3917 std::vector<uint32_t> SortedIds(ContextIds.begin(), ContextIds.end());
3918 std::sort(SortedIds.begin(), SortedIds.end());
3919 for (auto Id : SortedIds) {
3920 auto TypeI = ContextIdToAllocationType.find(Id);
3921 assert(TypeI != ContextIdToAllocationType.end());
3922 std::string Suffix;
3923 bool ComputedSuffix = false;
3924 auto GetSuffix = [&]() -> const std::string & {
3925 if (!ComputedSuffix) {
3927 ? formatContextReportSuffix(Node, Id)
3928 : "";
3929 ComputedSuffix = true;
3930 }
3931 return Suffix;
3932 };
3933 auto CSI = ContextIdToContextSizeInfos.find(Id);
3934 if (CSI != ContextIdToContextSizeInfos.end()) {
3935 for (auto &Info : CSI->second) {
3936 std::string Msg =
3937 "MemProf hinting: " + getAllocTypeString((uint8_t)TypeI->second) +
3938 " full allocation context " + std::to_string(Info.FullStackId) +
3939 " with total size " + std::to_string(Info.TotalSize) + " is " +
3940 getAllocTypeString(Node->AllocTypes) + " after cloning";
3941 if (allocTypeToUse(Node->AllocTypes) !=
3942 allocTypeToUse((uint8_t)AllocTypeFromCall))
3943 Msg += " marked " + getAllocTypeString((uint8_t)AllocTypeFromCall) +
3944 " due to cold byte percent";
3945 // Print the internal context id to aid debugging and visualization.
3946 Msg += " (internal context id " + std::to_string(Id) + ")";
3948 OS << Msg << GetSuffix() << "\n";
3949 if (EmitRemark)
3950 EmitRemark(DEBUG_TYPE, "MemProfReport", Msg);
3951 }
3952 } else {
3953 // This is only emitted if the context size info is not present.
3954 std::string Msg =
3955 "MemProf hinting: " + getAllocTypeString((uint8_t)TypeI->second) +
3956 " context is " + getAllocTypeString(Node->AllocTypes) +
3957 " after cloning";
3958 if (allocTypeToUse(Node->AllocTypes) !=
3959 allocTypeToUse((uint8_t)AllocTypeFromCall))
3960 Msg += " marked " + getAllocTypeString((uint8_t)AllocTypeFromCall) +
3961 " due to cold byte percent";
3962 // Print the internal context id to aid debugging and visualization.
3963 Msg += " (internal context id " + std::to_string(Id) + ")";
3965 OS << Msg << GetSuffix() << "\n";
3966 if (EmitRemark)
3967 EmitRemark(DEBUG_TYPE, "MemProfReport", Msg);
3968 }
3969 }
3970 }
3971}
3972
3973template <typename DerivedCCG, typename FuncTy, typename CallTy>
3974void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::check() const {
3975 using GraphType = const CallsiteContextGraph<DerivedCCG, FuncTy, CallTy> *;
3976 for (const auto Node : nodes<GraphType>(this)) {
3977 checkNode<DerivedCCG, FuncTy, CallTy>(Node, /*CheckEdges=*/false);
3978 for (auto &Edge : Node->CallerEdges)
3980 }
3981}
3982
3983template <typename DerivedCCG, typename FuncTy, typename CallTy>
3984struct GraphTraits<const CallsiteContextGraph<DerivedCCG, FuncTy, CallTy> *> {
3985 using GraphType = const CallsiteContextGraph<DerivedCCG, FuncTy, CallTy> *;
3986 using NodeRef = const ContextNode<DerivedCCG, FuncTy, CallTy> *;
3987
3988 using NodePtrTy = std::unique_ptr<ContextNode<DerivedCCG, FuncTy, CallTy>>;
3989 static NodeRef getNode(const NodePtrTy &P) { return P.get(); }
3990
3993 decltype(&getNode)>;
3994
3996 return nodes_iterator(G->NodeOwner.begin(), &getNode);
3997 }
3998
4000 return nodes_iterator(G->NodeOwner.end(), &getNode);
4001 }
4002
4004 return G->NodeOwner.begin()->get();
4005 }
4006
4007 using EdgePtrTy = std::shared_ptr<ContextEdge<DerivedCCG, FuncTy, CallTy>>;
4008 static const ContextNode<DerivedCCG, FuncTy, CallTy> *
4010 return P->Callee;
4011 }
4012
4014 mapped_iterator<typename std::vector<std::shared_ptr<ContextEdge<
4015 DerivedCCG, FuncTy, CallTy>>>::const_iterator,
4016 decltype(&GetCallee)>;
4017
4019 return ChildIteratorType(N->CalleeEdges.begin(), &GetCallee);
4020 }
4021
4023 return ChildIteratorType(N->CalleeEdges.end(), &GetCallee);
4024 }
4025};
4026
4027template <typename DerivedCCG, typename FuncTy, typename CallTy>
4028struct DOTGraphTraits<const CallsiteContextGraph<DerivedCCG, FuncTy, CallTy> *>
4029 : public DefaultDOTGraphTraits {
4030 DOTGraphTraits(bool IsSimple = false) : DefaultDOTGraphTraits(IsSimple) {
4031 // If the user requested the full graph to be exported, but provided an
4032 // allocation id, or if the user gave a context id and requested more than
4033 // just a specific context to be exported, note that highlighting is
4034 // enabled.
4035 DoHighlight =
4036 (AllocIdForDot.getNumOccurrences() && DotGraphScope == DotScope::All) ||
4037 (ContextIdForDot.getNumOccurrences() &&
4039 }
4040
4041 using GraphType = const CallsiteContextGraph<DerivedCCG, FuncTy, CallTy> *;
4043 using NodeRef = typename GTraits::NodeRef;
4044 using ChildIteratorType = typename GTraits::ChildIteratorType;
4045
4046 static std::string getNodeLabel(NodeRef Node, GraphType G) {
4047 std::string LabelString =
4048 (Twine("OrigId: ") + (Node->IsAllocation ? "Alloc" : "") +
4049 Twine(Node->OrigStackOrAllocId) + " NodeId: " + Twine(Node->NodeId))
4050 .str();
4051 LabelString += "\n";
4052 if (Node->hasCall()) {
4053 auto Func = G->NodeToCallingFunc.find(Node);
4054 assert(Func != G->NodeToCallingFunc.end());
4055 LabelString +=
4056 G->getLabel(Func->second, Node->Call.call(), Node->Call.cloneNo());
4057 for (auto &MatchingCall : Node->MatchingCalls) {
4058 LabelString += "\n";
4059 LabelString += G->getLabel(Func->second, MatchingCall.call(),
4060 MatchingCall.cloneNo());
4061 }
4062 } else {
4063 LabelString += "null call";
4064 if (Node->Recursive)
4065 LabelString += " (recursive)";
4066 else
4067 LabelString += " (external)";
4068 }
4069 return LabelString;
4070 }
4071
4073 auto ContextIds = Node->getContextIds();
4074 // If highlighting enabled, see if this node contains any of the context ids
4075 // of interest. If so, it will use a different color and a larger fontsize
4076 // (which makes the node larger as well).
4077 bool Highlight = false;
4078 if (DoHighlight) {
4079 assert(ContextIdForDot.getNumOccurrences() ||
4080 AllocIdForDot.getNumOccurrences());
4081 if (ContextIdForDot.getNumOccurrences())
4082 Highlight = ContextIds.contains(ContextIdForDot);
4083 else
4084 Highlight = set_intersects(ContextIds, G->DotAllocContextIds);
4085 }
4086 std::string AttributeString = (Twine("tooltip=\"") + getNodeId(Node) + " " +
4087 getContextIds(ContextIds) + "\"")
4088 .str();
4089 // Default fontsize is 14
4090 if (Highlight)
4091 AttributeString += ",fontsize=\"30\"";
4092 AttributeString +=
4093 (Twine(",fillcolor=\"") + getColor(Node->AllocTypes, Highlight) + "\"")
4094 .str();
4095 if (Node->CloneOf) {
4096 AttributeString += ",color=\"blue\"";
4097 AttributeString += ",style=\"filled,bold,dashed\"";
4098 } else
4099 AttributeString += ",style=\"filled\"";
4100 return AttributeString;
4101 }
4102
4103 static std::string getEdgeAttributes(NodeRef, ChildIteratorType ChildIter,
4104 GraphType G) {
4105 auto &Edge = *(ChildIter.getCurrent());
4106 // If highlighting enabled, see if this edge contains any of the context ids
4107 // of interest. If so, it will use a different color and a heavier arrow
4108 // size and weight (the larger weight makes the highlighted path
4109 // straighter).
4110 bool Highlight = false;
4111 if (DoHighlight) {
4112 assert(ContextIdForDot.getNumOccurrences() ||
4113 AllocIdForDot.getNumOccurrences());
4114 if (ContextIdForDot.getNumOccurrences())
4115 Highlight = Edge->ContextIds.contains(ContextIdForDot);
4116 else
4117 Highlight = set_intersects(Edge->ContextIds, G->DotAllocContextIds);
4118 }
4119 auto Color = getColor(Edge->AllocTypes, Highlight);
4120 std::string AttributeString =
4121 (Twine("tooltip=\"") + getContextIds(Edge->ContextIds) + "\"" +
4122 // fillcolor is the arrow head and color is the line
4123 Twine(",fillcolor=\"") + Color + "\"" + Twine(",color=\"") + Color +
4124 "\"")
4125 .str();
4126 if (Edge->IsBackedge)
4127 AttributeString += ",style=\"dotted\"";
4128 // Default penwidth and weight are both 1.
4129 if (Highlight)
4130 AttributeString += ",penwidth=\"2.0\",weight=\"2\"";
4131 return AttributeString;
4132 }
4133
4134 // Since the NodeOwners list includes nodes that are no longer connected to
4135 // the graph, skip them here.
4137 if (Node->isRemoved())
4138 return true;
4139 // If a scope smaller than the full graph was requested, see if this node
4140 // contains any of the context ids of interest.
4142 return !set_intersects(Node->getContextIds(), G->DotAllocContextIds);
4144 return !Node->getContextIds().contains(ContextIdForDot);
4145 return false;
4146 }
4147
4148private:
4149 static std::string getContextIds(const DenseSet<uint32_t> &ContextIds) {
4150 std::string IdString = "ContextIds:";
4151 if (ContextIds.size() < 100) {
4152 std::vector<uint32_t> SortedIds(ContextIds.begin(), ContextIds.end());
4153 std::sort(SortedIds.begin(), SortedIds.end());
4154 for (auto Id : SortedIds)
4155 IdString += (" " + Twine(Id)).str();
4156 } else {
4157 IdString += (" (" + Twine(ContextIds.size()) + " ids)").str();
4158 }
4159 return IdString;
4160 }
4161
4162 static std::string getColor(uint8_t AllocTypes, bool Highlight) {
4163 // If DoHighlight is not enabled, we want to use the highlight colors for
4164 // NotCold and Cold, and the non-highlight color for NotCold+Cold. This is
4165 // both compatible with the color scheme before highlighting was supported,
4166 // and for the NotCold+Cold color the non-highlight color is a bit more
4167 // readable.
4168 if (AllocTypes == (uint8_t)AllocationType::NotCold)
4169 // Color "brown1" actually looks like a lighter red.
4170 return !DoHighlight || Highlight ? "brown1" : "lightpink";
4171 if (AllocTypes == (uint8_t)AllocationType::Cold)
4172 return !DoHighlight || Highlight ? "cyan" : "lightskyblue";
4173 if (AllocTypes ==
4174 ((uint8_t)AllocationType::NotCold | (uint8_t)AllocationType::Cold))
4175 return Highlight ? "magenta" : "mediumorchid1";
4176 return "gray";
4177 }
4178
4179 static std::string getNodeId(NodeRef Node) {
4180 std::stringstream SStream;
4181 SStream << std::hex << "N0x" << (unsigned long long)Node;
4182 std::string Result = SStream.str();
4183 return Result;
4184 }
4185
4186 // True if we should highlight a specific context or allocation's contexts in
4187 // the emitted graph.
4188 static bool DoHighlight;
4189};
4190
4191template <typename DerivedCCG, typename FuncTy, typename CallTy>
4192bool DOTGraphTraits<
4193 const CallsiteContextGraph<DerivedCCG, FuncTy, CallTy> *>::DoHighlight =
4194 false;
4195
4196template <typename DerivedCCG, typename FuncTy, typename CallTy>
4197void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::exportToDot(
4198 std::string Label) const {
4199 WriteGraph(this, "", false, Label,
4200 DotFilePathPrefix + "ccg." + Label + ".dot");
4201}
4202
4203template <typename DerivedCCG, typename FuncTy, typename CallTy>
4204typename CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextNode *
4205CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::moveEdgeToNewCalleeClone(
4206 const std::shared_ptr<ContextEdge> &Edge,
4207 DenseSet<uint32_t> ContextIdsToMove) {
4208 ContextNode *Node = Edge->Callee;
4209 assert(NodeToCallingFunc.count(Node));
4210 ContextNode *Clone =
4211 createNewNode(Node->IsAllocation, NodeToCallingFunc[Node], Node->Call);
4212 Node->addClone(Clone);
4213 Clone->MatchingCalls = Node->MatchingCalls;
4214 moveEdgeToExistingCalleeClone(Edge, Clone, /*NewClone=*/true,
4215 ContextIdsToMove);
4216 return Clone;
4217}
4218
4219template <typename DerivedCCG, typename FuncTy, typename CallTy>
4220void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::
4221 moveEdgeToExistingCalleeClone(const std::shared_ptr<ContextEdge> &Edge,
4222 ContextNode *NewCallee, bool NewClone,
4223 DenseSet<uint32_t> ContextIdsToMove) {
4224 // NewCallee and Edge's current callee must be clones of the same original
4225 // node (Edge's current callee may be the original node too).
4226 assert(NewCallee->getOrigNode() == Edge->Callee->getOrigNode());
4227
4228 bool EdgeIsRecursive = Edge->Callee == Edge->Caller;
4229
4230 ContextNode *OldCallee = Edge->Callee;
4231
4232 // We might already have an edge to the new callee from earlier cloning for a
4233 // different allocation. If one exists we will reuse it.
4234 auto ExistingEdgeToNewCallee = NewCallee->findEdgeFromCaller(Edge->Caller);
4235
4236 // Callers will pass an empty ContextIdsToMove set when they want to move the
4237 // edge. Copy in Edge's ids for simplicity.
4238 if (ContextIdsToMove.empty())
4239 ContextIdsToMove = Edge->getContextIds();
4240
4241 // If we are moving all of Edge's ids, then just move the whole Edge.
4242 // Otherwise only move the specified subset, to a new edge if needed.
4243 if (Edge->getContextIds().size() == ContextIdsToMove.size()) {
4244 // First, update the alloc types on New Callee from Edge.
4245 // Do this before we potentially clear Edge's fields below!
4246 NewCallee->AllocTypes |= Edge->AllocTypes;
4247 // Moving the whole Edge.
4248 if (ExistingEdgeToNewCallee) {
4249 // Since we already have an edge to NewCallee, simply move the ids
4250 // onto it, and remove the existing Edge.
4251 ExistingEdgeToNewCallee->getContextIds().insert_range(ContextIdsToMove);
4252 ExistingEdgeToNewCallee->AllocTypes |= Edge->AllocTypes;
4253 assert(Edge->ContextIds == ContextIdsToMove);
4254 removeEdgeFromGraph(Edge.get());
4255 } else {
4256 // Otherwise just reconnect Edge to NewCallee.
4257 Edge->Callee = NewCallee;
4258 NewCallee->CallerEdges.push_back(Edge);
4259 // Remove it from callee where it was previously connected.
4260 OldCallee->eraseCallerEdge(Edge.get());
4261 // Don't need to update Edge's context ids since we are simply
4262 // reconnecting it.
4263 }
4264 } else {
4265 // Only moving a subset of Edge's ids.
4266 // Compute the alloc type of the subset of ids being moved.
4267 auto CallerEdgeAllocType = computeAllocType(ContextIdsToMove);
4268 if (ExistingEdgeToNewCallee) {
4269 // Since we already have an edge to NewCallee, simply move the ids
4270 // onto it.
4271 ExistingEdgeToNewCallee->getContextIds().insert_range(ContextIdsToMove);
4272 ExistingEdgeToNewCallee->AllocTypes |= CallerEdgeAllocType;
4273 } else {
4274 // Otherwise, create a new edge to NewCallee for the ids being moved.
4275 auto NewEdge = std::make_shared<ContextEdge>(
4276 NewCallee, Edge->Caller, CallerEdgeAllocType, ContextIdsToMove);
4277 Edge->Caller->CalleeEdges.push_back(NewEdge);
4278 NewCallee->CallerEdges.push_back(NewEdge);
4279 }
4280 // In either case, need to update the alloc types on NewCallee, and remove
4281 // those ids and update the alloc type on the original Edge.
4282 NewCallee->AllocTypes |= CallerEdgeAllocType;
4283 set_subtract(Edge->ContextIds, ContextIdsToMove);
4284 Edge->AllocTypes = computeAllocType(Edge->ContextIds);
4285 }
4286 // Now walk the old callee node's callee edges and move Edge's context ids
4287 // over to the corresponding edge into the clone (which is created here if
4288 // this is a newly created clone).
4289 for (auto &OldCalleeEdge : OldCallee->CalleeEdges) {
4290 ContextNode *CalleeToUse = OldCalleeEdge->Callee;
4291 // If this is a direct recursion edge, use NewCallee (the clone) as the
4292 // callee as well, so that any edge updated/created here is also direct
4293 // recursive.
4294 if (CalleeToUse == OldCallee) {
4295 // If this is a recursive edge, see if we already moved a recursive edge
4296 // (which would have to have been this one) - if we were only moving a
4297 // subset of context ids it would still be on OldCallee.
4298 if (EdgeIsRecursive) {
4299 assert(OldCalleeEdge == Edge);
4300 continue;
4301 }
4302 CalleeToUse = NewCallee;
4303 }
4304 // The context ids moving to the new callee are the subset of this edge's
4305 // context ids and the context ids on the caller edge being moved.
4306 DenseSet<uint32_t> EdgeContextIdsToMove =
4307 set_intersection(OldCalleeEdge->getContextIds(), ContextIdsToMove);
4308 set_subtract(OldCalleeEdge->getContextIds(), EdgeContextIdsToMove);
4309 OldCalleeEdge->AllocTypes =
4310 computeAllocType(OldCalleeEdge->getContextIds());
4311 if (!NewClone) {
4312 // Update context ids / alloc type on corresponding edge to NewCallee.
4313 // There is a chance this may not exist if we are reusing an existing
4314 // clone, specifically during function assignment, where we would have
4315 // removed none type edges after creating the clone. If we can't find
4316 // a corresponding edge there, fall through to the cloning below.
4317 if (auto *NewCalleeEdge = NewCallee->findEdgeFromCallee(CalleeToUse)) {
4318 NewCalleeEdge->getContextIds().insert_range(EdgeContextIdsToMove);
4319 NewCalleeEdge->AllocTypes |= computeAllocType(EdgeContextIdsToMove);
4320 continue;
4321 }
4322 }
4323 auto NewEdge = std::make_shared<ContextEdge>(
4324 CalleeToUse, NewCallee, computeAllocType(EdgeContextIdsToMove),
4325 EdgeContextIdsToMove);
4326 NewCallee->CalleeEdges.push_back(NewEdge);
4327 NewEdge->Callee->CallerEdges.push_back(NewEdge);
4328 }
4329 // Recompute the node alloc type now that its callee edges have been
4330 // updated (since we will compute from those edges).
4331 OldCallee->AllocTypes = OldCallee->computeAllocType();
4332 // OldCallee alloc type should be None iff its context id set is now empty.
4333 assert((OldCallee->AllocTypes == (uint8_t)AllocationType::None) ==
4334 OldCallee->emptyContextIds());
4335 if (VerifyCCG) {
4336 checkNode<DerivedCCG, FuncTy, CallTy>(OldCallee, /*CheckEdges=*/false);
4337 checkNode<DerivedCCG, FuncTy, CallTy>(NewCallee, /*CheckEdges=*/false);
4338 for (const auto &OldCalleeEdge : OldCallee->CalleeEdges)
4339 checkNode<DerivedCCG, FuncTy, CallTy>(OldCalleeEdge->Callee,
4340 /*CheckEdges=*/false);
4341 for (const auto &NewCalleeEdge : NewCallee->CalleeEdges)
4342 checkNode<DerivedCCG, FuncTy, CallTy>(NewCalleeEdge->Callee,
4343 /*CheckEdges=*/false);
4344 }
4345}
4346
4347template <typename DerivedCCG, typename FuncTy, typename CallTy>
4348void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::
4349 moveCalleeEdgeToNewCaller(const std::shared_ptr<ContextEdge> &Edge,
4350 ContextNode *NewCaller) {
4351 auto *OldCallee = Edge->Callee;
4352 auto *NewCallee = OldCallee;
4353 // If this edge was direct recursive, make any new/updated edge also direct
4354 // recursive to NewCaller.
4355 bool Recursive = Edge->Caller == Edge->Callee;
4356 if (Recursive)
4357 NewCallee = NewCaller;
4358
4359 ContextNode *OldCaller = Edge->Caller;
4360 OldCaller->eraseCalleeEdge(Edge.get());
4361
4362 // We might already have an edge to the new caller. If one exists we will
4363 // reuse it.
4364 auto ExistingEdgeToNewCaller = NewCaller->findEdgeFromCallee(NewCallee);
4365
4366 if (ExistingEdgeToNewCaller) {
4367 // Since we already have an edge to NewCaller, simply move the ids
4368 // onto it, and remove the existing Edge.
4369 ExistingEdgeToNewCaller->getContextIds().insert_range(
4370 Edge->getContextIds());
4371 ExistingEdgeToNewCaller->AllocTypes |= Edge->AllocTypes;
4372 Edge->ContextIds.clear();
4373 Edge->AllocTypes = (uint8_t)AllocationType::None;
4374 OldCallee->eraseCallerEdge(Edge.get());
4375 } else {
4376 // Otherwise just reconnect Edge to NewCaller.
4377 Edge->Caller = NewCaller;
4378 NewCaller->CalleeEdges.push_back(Edge);
4379 if (Recursive) {
4380 assert(NewCallee == NewCaller);
4381 // In the case of (direct) recursive edges, we update the callee as well
4382 // so that it becomes recursive on the new caller.
4383 Edge->Callee = NewCallee;
4384 NewCallee->CallerEdges.push_back(Edge);
4385 OldCallee->eraseCallerEdge(Edge.get());
4386 }
4387 // Don't need to update Edge's context ids since we are simply
4388 // reconnecting it.
4389 }
4390 // In either case, need to update the alloc types on New Caller.
4391 NewCaller->AllocTypes |= Edge->AllocTypes;
4392
4393 // Now walk the old caller node's caller edges and move Edge's context ids
4394 // over to the corresponding edge into the node (which is created here if
4395 // this is a newly created node). We can tell whether this is a newly created
4396 // node by seeing if it has any caller edges yet.
4397#ifndef NDEBUG
4398 bool IsNewNode = NewCaller->CallerEdges.empty();
4399#endif
4400 // If we just moved a direct recursive edge, presumably its context ids should
4401 // also flow out of OldCaller via some other non-recursive callee edge. We
4402 // don't want to remove the recursive context ids from other caller edges yet,
4403 // otherwise the context ids get into an inconsistent state on OldCaller.
4404 // We will update these context ids on the non-recursive caller edge when and
4405 // if they are updated on the non-recursive callee.
4406 if (!Recursive) {
4407 for (auto &OldCallerEdge : OldCaller->CallerEdges) {
4408 auto OldCallerCaller = OldCallerEdge->Caller;
4409 // The context ids moving to the new caller are the subset of this edge's
4410 // context ids and the context ids on the callee edge being moved.
4411 DenseSet<uint32_t> EdgeContextIdsToMove = set_intersection(
4412 OldCallerEdge->getContextIds(), Edge->getContextIds());
4413 if (OldCaller == OldCallerCaller) {
4414 OldCallerCaller = NewCaller;
4415 // Don't actually move this one. The caller will move it directly via a
4416 // call to this function with this as the Edge if it is appropriate to
4417 // move to a diff node that has a matching callee (itself).
4418 continue;
4419 }
4420 set_subtract(OldCallerEdge->getContextIds(), EdgeContextIdsToMove);
4421 OldCallerEdge->AllocTypes =
4422 computeAllocType(OldCallerEdge->getContextIds());
4423 // In this function we expect that any pre-existing node already has edges
4424 // from the same callers as the old node. That should be true in the
4425 // current use case, where we will remove None-type edges after copying
4426 // over all caller edges from the callee.
4427 auto *ExistingCallerEdge = NewCaller->findEdgeFromCaller(OldCallerCaller);
4428 // Since we would have skipped caller edges when moving a direct recursive
4429 // edge, this may not hold true when recursive handling enabled.
4430 assert(IsNewNode || ExistingCallerEdge || AllowRecursiveCallsites);
4431 if (ExistingCallerEdge) {
4432 ExistingCallerEdge->getContextIds().insert_range(EdgeContextIdsToMove);
4433 ExistingCallerEdge->AllocTypes |=
4434 computeAllocType(EdgeContextIdsToMove);
4435 continue;
4436 }
4437 auto NewEdge = std::make_shared<ContextEdge>(
4438 NewCaller, OldCallerCaller, computeAllocType(EdgeContextIdsToMove),
4439 EdgeContextIdsToMove);
4440 NewCaller->CallerEdges.push_back(NewEdge);
4441 NewEdge->Caller->CalleeEdges.push_back(NewEdge);
4442 }
4443 }
4444 // Recompute the node alloc type now that its caller edges have been
4445 // updated (since we will compute from those edges).
4446 OldCaller->AllocTypes = OldCaller->computeAllocType();
4447 // OldCaller alloc type should be None iff its context id set is now empty.
4448 assert((OldCaller->AllocTypes == (uint8_t)AllocationType::None) ==
4449 OldCaller->emptyContextIds());
4450 if (VerifyCCG) {
4451 checkNode<DerivedCCG, FuncTy, CallTy>(OldCaller, /*CheckEdges=*/false);
4452 checkNode<DerivedCCG, FuncTy, CallTy>(NewCaller, /*CheckEdges=*/false);
4453 for (const auto &OldCallerEdge : OldCaller->CallerEdges)
4454 checkNode<DerivedCCG, FuncTy, CallTy>(OldCallerEdge->Caller,
4455 /*CheckEdges=*/false);
4456 for (const auto &NewCallerEdge : NewCaller->CallerEdges)
4457 checkNode<DerivedCCG, FuncTy, CallTy>(NewCallerEdge->Caller,
4458 /*CheckEdges=*/false);
4459 }
4460}
4461
4462template <typename DerivedCCG, typename FuncTy, typename CallTy>
4463void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::
4464 recursivelyRemoveNoneTypeCalleeEdges(
4465 ContextNode *Node, DenseSet<const ContextNode *> &Visited) {
4466 auto Inserted = Visited.insert(Node);
4467 if (!Inserted.second)
4468 return;
4469
4470 removeNoneTypeCalleeEdges(Node);
4471
4472 for (auto *Clone : Node->Clones)
4473 recursivelyRemoveNoneTypeCalleeEdges(Clone, Visited);
4474
4475 // The recursive call may remove some of this Node's caller edges.
4476 // Iterate over a copy and skip any that were removed.
4477 auto CallerEdges = Node->CallerEdges;
4478 for (auto &Edge : CallerEdges) {
4479 // Skip any that have been removed by an earlier recursive call.
4480 if (Edge->isRemoved()) {
4481 assert(!is_contained(Node->CallerEdges, Edge));
4482 continue;
4483 }
4484 recursivelyRemoveNoneTypeCalleeEdges(Edge->Caller, Visited);
4485 }
4486}
4487
4488// This is the standard DFS based backedge discovery algorithm.
4489template <typename DerivedCCG, typename FuncTy, typename CallTy>
4490void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::markBackedges() {
4491 // If we are cloning recursive contexts, find and mark backedges from all root
4492 // callers, using the typical DFS based backedge analysis.
4494 return;
4495 DenseSet<const ContextNode *> Visited;
4496 DenseSet<const ContextNode *> CurrentStack;
4497 for (auto &Entry : NonAllocationCallToContextNodeMap) {
4498 auto *Node = Entry.second;
4499 if (Node->isRemoved())
4500 continue;
4501 // It is a root if it doesn't have callers.
4502 if (!Node->CallerEdges.empty())
4503 continue;
4504 markBackedges(Node, Visited, CurrentStack);
4505 assert(CurrentStack.empty());
4506 }
4507}
4508
4509// Recursive helper for above markBackedges method.
4510template <typename DerivedCCG, typename FuncTy, typename CallTy>
4511void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::markBackedges(
4512 ContextNode *Node, DenseSet<const ContextNode *> &Visited,
4513 DenseSet<const ContextNode *> &CurrentStack) {
4514 auto I = Visited.insert(Node);
4515 // We should only call this for unvisited nodes.
4516 assert(I.second);
4517 (void)I;
4518 for (auto &CalleeEdge : Node->CalleeEdges) {
4519 auto *Callee = CalleeEdge->Callee;
4520 if (Visited.count(Callee)) {
4521 // Since this was already visited we need to check if it is currently on
4522 // the recursive stack in which case it is a backedge.
4523 if (CurrentStack.count(Callee))
4524 CalleeEdge->IsBackedge = true;
4525 continue;
4526 }
4527 CurrentStack.insert(Callee);
4528 markBackedges(Callee, Visited, CurrentStack);
4529 CurrentStack.erase(Callee);
4530 }
4531}
4532
4533template <typename DerivedCCG, typename FuncTy, typename CallTy>
4534void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::identifyClones() {
4535 DenseSet<const ContextNode *> Visited;
4536 for (auto &Entry : AllocationCallToContextNodeMap) {
4537 Visited.clear();
4538 identifyClones(Entry.second, Visited, Entry.second->getContextIds());
4539 }
4540 Visited.clear();
4541 for (auto &Entry : AllocationCallToContextNodeMap)
4542 recursivelyRemoveNoneTypeCalleeEdges(Entry.second, Visited);
4543 if (VerifyCCG)
4544 check();
4545}
4546
4547// helper function to check an AllocType is cold or notcold or both.
4554
4555template <typename DerivedCCG, typename FuncTy, typename CallTy>
4556void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::identifyClones(
4557 ContextNode *Node, DenseSet<const ContextNode *> &Visited,
4558 const DenseSet<uint32_t> &AllocContextIds) {
4559 if (VerifyNodes)
4560 checkNode<DerivedCCG, FuncTy, CallTy>(Node, /*CheckEdges=*/false);
4561 assert(!Node->CloneOf);
4562
4563 // If Node as a null call, then either it wasn't found in the module (regular
4564 // LTO) or summary index (ThinLTO), or there were other conditions blocking
4565 // cloning (e.g. recursion, calls multiple targets, etc).
4566 // Do this here so that we don't try to recursively clone callers below, which
4567 // isn't useful at least for this node.
4568 if (!Node->hasCall())
4569 return;
4570
4571 // No need to look at any callers if allocation type already unambiguous.
4572 if (hasSingleAllocType(Node->AllocTypes))
4573 return;
4574
4575#ifndef NDEBUG
4576 auto Insert =
4577#endif
4578 Visited.insert(Node);
4579 // We should not have visited this node yet.
4580 assert(Insert.second);
4581 // The recursive call to identifyClones may delete the current edge from the
4582 // CallerEdges vector. Make a copy and iterate on that, simpler than passing
4583 // in an iterator and having recursive call erase from it. Other edges may
4584 // also get removed during the recursion, which will have null Callee and
4585 // Caller pointers (and are deleted later), so we skip those below.
4586 {
4587 auto CallerEdges = Node->CallerEdges;
4588 for (auto &Edge : CallerEdges) {
4589 // Skip any that have been removed by an earlier recursive call.
4590 if (Edge->isRemoved()) {
4591 assert(!is_contained(Node->CallerEdges, Edge));
4592 continue;
4593 }
4594 // Defer backedges. See comments further below where these edges are
4595 // handled during the cloning of this Node.
4596 if (Edge->IsBackedge) {
4597 // We should only mark these if cloning recursive contexts, where we
4598 // need to do this deferral.
4600 continue;
4601 }
4602 // Ignore any caller we previously visited via another edge.
4603 if (!Visited.count(Edge->Caller) && !Edge->Caller->CloneOf) {
4604 identifyClones(Edge->Caller, Visited, AllocContextIds);
4605 }
4606 }
4607 }
4608
4609 // Check if we reached an unambiguous call or have have only a single caller.
4610 if (hasSingleAllocType(Node->AllocTypes) || Node->CallerEdges.size() <= 1)
4611 return;
4612
4613 // We need to clone.
4614
4615 // Try to keep the original version as alloc type NotCold. This will make
4616 // cases with indirect calls or any other situation with an unknown call to
4617 // the original function get the default behavior. We do this by sorting the
4618 // CallerEdges of the Node we will clone by alloc type.
4619 //
4620 // Give NotCold edge the lowest sort priority so those edges are at the end of
4621 // the caller edges vector, and stay on the original version (since the below
4622 // code clones greedily until it finds all remaining edges have the same type
4623 // and leaves the remaining ones on the original Node).
4624 //
4625 // We shouldn't actually have any None type edges, so the sorting priority for
4626 // that is arbitrary, and we assert in that case below.
4627 const unsigned AllocTypeCloningPriority[] = {/*None*/ 3, /*NotCold*/ 4,
4628 /*Cold*/ 1,
4629 /*NotColdCold*/ 2};
4630 llvm::stable_sort(Node->CallerEdges,
4631 [&](const std::shared_ptr<ContextEdge> &A,
4632 const std::shared_ptr<ContextEdge> &B) {
4633 // Nodes with non-empty context ids should be sorted
4634 // before those with empty context ids.
4635 if (A->ContextIds.empty())
4636 // Either B ContextIds are non-empty (in which case we
4637 // should return false because B < A), or B ContextIds
4638 // are empty, in which case they are equal, and we
4639 // should maintain the original relative ordering.
4640 return false;
4641 if (B->ContextIds.empty())
4642 return true;
4643
4644 if (A->AllocTypes == B->AllocTypes)
4645 // Use the caller node id as a deterministic
4646 // tie-breaker.
4647 return A->Caller->NodeId < B->Caller->NodeId;
4648 return AllocTypeCloningPriority[A->AllocTypes] <
4649 AllocTypeCloningPriority[B->AllocTypes];
4650 });
4651
4652 assert(Node->AllocTypes != (uint8_t)AllocationType::None);
4653
4654 DenseSet<uint32_t> RecursiveContextIds;
4656 // If we are allowing recursive callsites, but have also disabled recursive
4657 // contexts, look for context ids that show up in multiple caller edges.
4659 DenseSet<uint32_t> AllCallerContextIds;
4660 for (auto &CE : Node->CallerEdges) {
4661 // Resize to the largest set of caller context ids, since we know the
4662 // final set will be at least that large.
4663 AllCallerContextIds.reserve(CE->getContextIds().size());
4664 for (auto Id : CE->getContextIds())
4665 if (!AllCallerContextIds.insert(Id).second)
4666 RecursiveContextIds.insert(Id);
4667 }
4668 }
4669
4670 // Iterate until we find no more opportunities for disambiguating the alloc
4671 // types via cloning. In most cases this loop will terminate once the Node
4672 // has a single allocation type, in which case no more cloning is needed.
4673 // Iterate over a copy of Node's caller edges, since we may need to remove
4674 // edges in the moveEdgeTo* methods, and this simplifies the handling and
4675 // makes it less error-prone.
4676 auto CallerEdges = Node->CallerEdges;
4677 for (auto &CallerEdge : CallerEdges) {
4678 // Skip any that have been removed by an earlier recursive call.
4679 if (CallerEdge->isRemoved()) {
4680 assert(!is_contained(Node->CallerEdges, CallerEdge));
4681 continue;
4682 }
4683 assert(CallerEdge->Callee == Node);
4684
4685 // See if cloning the prior caller edge left this node with a single alloc
4686 // type or a single caller. In that case no more cloning of Node is needed.
4687 if (hasSingleAllocType(Node->AllocTypes) || Node->CallerEdges.size() <= 1)
4688 break;
4689
4690 // If the caller was not successfully matched to a call in the IR/summary,
4691 // there is no point in trying to clone for it as we can't update that call.
4692 if (!CallerEdge->Caller->hasCall())
4693 continue;
4694
4695 // Only need to process the ids along this edge pertaining to the given
4696 // allocation.
4697 auto CallerEdgeContextsForAlloc =
4698 set_intersection(CallerEdge->getContextIds(), AllocContextIds);
4699 if (!RecursiveContextIds.empty())
4700 CallerEdgeContextsForAlloc =
4701 set_difference(CallerEdgeContextsForAlloc, RecursiveContextIds);
4702 if (CallerEdgeContextsForAlloc.empty())
4703 continue;
4704
4705 auto CallerAllocTypeForAlloc = computeAllocType(CallerEdgeContextsForAlloc);
4706
4707 // Compute the node callee edge alloc types corresponding to the context ids
4708 // for this caller edge.
4709 std::vector<uint8_t> CalleeEdgeAllocTypesForCallerEdge;
4710 CalleeEdgeAllocTypesForCallerEdge.reserve(Node->CalleeEdges.size());
4711 for (auto &CalleeEdge : Node->CalleeEdges)
4712 CalleeEdgeAllocTypesForCallerEdge.push_back(intersectAllocTypes(
4713 CalleeEdge->getContextIds(), CallerEdgeContextsForAlloc));
4714
4715 // Don't clone if doing so will not disambiguate any alloc types amongst
4716 // caller edges (including the callee edges that would be cloned).
4717 // Otherwise we will simply move all edges to the clone.
4718 //
4719 // First check if by cloning we will disambiguate the caller allocation
4720 // type from node's allocation type. Query allocTypeToUse so that we don't
4721 // bother cloning to distinguish NotCold+Cold from NotCold. Note that
4722 // neither of these should be None type.
4723 //
4724 // Then check if by cloning node at least one of the callee edges will be
4725 // disambiguated by splitting out different context ids.
4726 //
4727 // However, always do the cloning if this is a backedge, in which case we
4728 // have not yet cloned along this caller edge.
4729 assert(CallerEdge->AllocTypes != (uint8_t)AllocationType::None);
4730 assert(Node->AllocTypes != (uint8_t)AllocationType::None);
4731 if (!CallerEdge->IsBackedge &&
4732 allocTypeToUse(CallerAllocTypeForAlloc) ==
4733 allocTypeToUse(Node->AllocTypes) &&
4734 allocTypesMatch<DerivedCCG, FuncTy, CallTy>(
4735 CalleeEdgeAllocTypesForCallerEdge, Node->CalleeEdges)) {
4736 continue;
4737 }
4738
4739 if (CallerEdge->IsBackedge) {
4740 // We should only mark these if cloning recursive contexts, where we
4741 // need to do this deferral.
4743 DeferredBackedges++;
4744 }
4745
4746 // If this is a backedge, we now do recursive cloning starting from its
4747 // caller since we may have moved unambiguous caller contexts to a clone
4748 // of this Node in a previous iteration of the current loop, giving more
4749 // opportunity for cloning through the backedge. Because we sorted the
4750 // caller edges earlier so that cold caller edges are first, we would have
4751 // visited and cloned this node for any unamibiguously cold non-recursive
4752 // callers before any ambiguous backedge callers. Note that we don't do this
4753 // if the caller is already cloned or visited during cloning (e.g. via a
4754 // different context path from the allocation).
4755 // TODO: Can we do better in the case where the caller was already visited?
4756 if (CallerEdge->IsBackedge && !CallerEdge->Caller->CloneOf &&
4757 !Visited.count(CallerEdge->Caller)) {
4758 const auto OrigIdCount = CallerEdge->getContextIds().size();
4759 // Now do the recursive cloning of this backedge's caller, which was
4760 // deferred earlier.
4761 identifyClones(CallerEdge->Caller, Visited, CallerEdgeContextsForAlloc);
4762 removeNoneTypeCalleeEdges(CallerEdge->Caller);
4763 // See if the recursive call to identifyClones moved the context ids to a
4764 // new edge from this node to a clone of caller, and switch to looking at
4765 // that new edge so that we clone Node for the new caller clone.
4766 bool UpdatedEdge = false;
4767 if (OrigIdCount > CallerEdge->getContextIds().size()) {
4768 for (auto E : Node->CallerEdges) {
4769 // Only interested in clones of the current edges caller.
4770 if (E->Caller->CloneOf != CallerEdge->Caller)
4771 continue;
4772 // See if this edge contains any of the context ids originally on the
4773 // current caller edge.
4774 auto CallerEdgeContextsForAllocNew =
4775 set_intersection(CallerEdgeContextsForAlloc, E->getContextIds());
4776 if (CallerEdgeContextsForAllocNew.empty())
4777 continue;
4778 // Make sure we don't pick a previously existing caller edge of this
4779 // Node, which would be processed on a different iteration of the
4780 // outer loop over the saved CallerEdges.
4781 if (llvm::is_contained(CallerEdges, E))
4782 continue;
4783 // The CallerAllocTypeForAlloc and CalleeEdgeAllocTypesForCallerEdge
4784 // are updated further below for all cases where we just invoked
4785 // identifyClones recursively.
4786 CallerEdgeContextsForAlloc.swap(CallerEdgeContextsForAllocNew);
4787 CallerEdge = E;
4788 UpdatedEdge = true;
4789 break;
4790 }
4791 }
4792 // If cloning removed this edge (and we didn't update it to a new edge
4793 // above), we're done with this edge. It's possible we moved all of the
4794 // context ids to an existing clone, in which case there's no need to do
4795 // further processing for them.
4796 if (CallerEdge->isRemoved())
4797 continue;
4798
4799 // Now we need to update the information used for the cloning decisions
4800 // further below, as we may have modified edges and their context ids.
4801
4802 // Note if we changed the CallerEdge above we would have already updated
4803 // the context ids.
4804 if (!UpdatedEdge) {
4805 CallerEdgeContextsForAlloc = set_intersection(
4806 CallerEdgeContextsForAlloc, CallerEdge->getContextIds());
4807 if (CallerEdgeContextsForAlloc.empty())
4808 continue;
4809 }
4810 // Update the other information that depends on the edges and on the now
4811 // updated CallerEdgeContextsForAlloc.
4812 CallerAllocTypeForAlloc = computeAllocType(CallerEdgeContextsForAlloc);
4813 CalleeEdgeAllocTypesForCallerEdge.clear();
4814 for (auto &CalleeEdge : Node->CalleeEdges) {
4815 CalleeEdgeAllocTypesForCallerEdge.push_back(intersectAllocTypes(
4816 CalleeEdge->getContextIds(), CallerEdgeContextsForAlloc));
4817 }
4818 }
4819
4820 // First see if we can use an existing clone. Check each clone and its
4821 // callee edges for matching alloc types.
4822 ContextNode *Clone = nullptr;
4823 for (auto *CurClone : Node->Clones) {
4824 if (allocTypeToUse(CurClone->AllocTypes) !=
4825 allocTypeToUse(CallerAllocTypeForAlloc))
4826 continue;
4827
4828 bool BothSingleAlloc = hasSingleAllocType(CurClone->AllocTypes) &&
4829 hasSingleAllocType(CallerAllocTypeForAlloc);
4830 // The above check should mean that if both have single alloc types that
4831 // they should be equal.
4832 assert(!BothSingleAlloc ||
4833 CurClone->AllocTypes == CallerAllocTypeForAlloc);
4834
4835 // If either both have a single alloc type (which are the same), or if the
4836 // clone's callee edges have the same alloc types as those for the current
4837 // allocation on Node's callee edges (CalleeEdgeAllocTypesForCallerEdge),
4838 // then we can reuse this clone.
4839 if (BothSingleAlloc || allocTypesMatchClone<DerivedCCG, FuncTy, CallTy>(
4840 CalleeEdgeAllocTypesForCallerEdge, CurClone)) {
4841 Clone = CurClone;
4842 break;
4843 }
4844 }
4845
4846 // The edge iterator is adjusted when we move the CallerEdge to the clone.
4847 if (Clone)
4848 moveEdgeToExistingCalleeClone(CallerEdge, Clone, /*NewClone=*/false,
4849 CallerEdgeContextsForAlloc);
4850 else
4851 Clone = moveEdgeToNewCalleeClone(CallerEdge, CallerEdgeContextsForAlloc);
4852
4853 // Sanity check that no alloc types on clone or its edges are None.
4854 assert(Clone->AllocTypes != (uint8_t)AllocationType::None);
4855 }
4856
4857 // We should still have some context ids on the original Node.
4858 assert(!Node->emptyContextIds());
4859
4860 // Sanity check that no alloc types on node or edges are None.
4861 assert(Node->AllocTypes != (uint8_t)AllocationType::None);
4862
4863 if (VerifyNodes)
4864 checkNode<DerivedCCG, FuncTy, CallTy>(Node, /*CheckEdges=*/false);
4865}
4866
4867void ModuleCallsiteContextGraph::updateAllocationCall(
4868 CallInfo &Call, AllocationType AllocType) {
4869 std::string AllocTypeString = getAllocTypeAttributeString(AllocType);
4870 auto *CB = cast<CallBase>(Call.call());
4871 if (isAmbiguousAllocType((uint8_t)AllocType)) {
4872 // The contexts reaching this allocation could not be disambiguated, so it
4873 // keeps (or gets) the ambiguous attribute added during matching rather than
4874 // the default not cold attribute.
4876 } else {
4878 auto A = llvm::Attribute::get(CB->getFunction()->getContext(), "memprof",
4879 AllocTypeString);
4880 CB->addFnAttr(A);
4881 }
4882 OREGetter(Call.call()->getFunction())
4883 .emit(OptimizationRemark(DEBUG_TYPE, "MemprofAttribute", Call.call())
4884 << ore::NV("AllocationCall", Call.call()) << " in clone "
4885 << ore::NV("Caller", Call.call()->getFunction())
4886 << " marked with memprof allocation attribute "
4887 << ore::NV("Attribute", AllocTypeString));
4888}
4889
4890void IndexCallsiteContextGraph::updateAllocationCall(CallInfo &Call,
4892 auto *AI = cast<AllocInfo *>(Call.call());
4893 assert(AI);
4894 assert(AI->Versions.size() > Call.cloneNo());
4895 AI->Versions[Call.cloneNo()] = (uint8_t)AllocType;
4896}
4897
4899ModuleCallsiteContextGraph::getAllocationCallType(const CallInfo &Call) const {
4900 const auto *CB = cast<CallBase>(Call.call());
4901 if (!CB->getAttributes().hasFnAttr("memprof"))
4902 return AllocationType::None;
4903 StringRef AllocTypeString =
4904 CB->getAttributes().getFnAttr("memprof").getValueAsString();
4905 if (AllocTypeString == "cold")
4906 return AllocationType::Cold;
4907 if (AllocTypeString == "ambiguous")
4908 return (AllocationType)((uint8_t)AllocationType::NotCold |
4909 (uint8_t)AllocationType::Cold);
4910 return AllocationType::NotCold;
4911}
4912
4914IndexCallsiteContextGraph::getAllocationCallType(const CallInfo &Call) const {
4915 const auto *AI = cast<AllocInfo *>(Call.call());
4916 assert(AI->Versions.size() > Call.cloneNo());
4917 return (AllocationType)AI->Versions[Call.cloneNo()];
4918}
4919
4920void ModuleCallsiteContextGraph::updateCall(CallInfo &CallerCall,
4921 FuncInfo CalleeFunc) {
4922 auto *CurF = getCalleeFunc(CallerCall.call());
4923 auto NewCalleeCloneNo = CalleeFunc.cloneNo();
4924 if (isMemProfClone(*CurF)) {
4925 // If we already assigned this callsite to call a specific non-default
4926 // clone (i.e. not the original function which is clone 0), ensure that we
4927 // aren't trying to now update it to call a different clone, which is
4928 // indicative of a bug in the graph or function assignment.
4929 auto CurCalleeCloneNo = getMemProfCloneNum(*CurF);
4930 if (CurCalleeCloneNo != NewCalleeCloneNo) {
4931 LLVM_DEBUG(dbgs() << "Mismatch in call clone assignment: was "
4932 << CurCalleeCloneNo << " now " << NewCalleeCloneNo
4933 << "\n");
4934 MismatchedCloneAssignments++;
4935 }
4936 }
4937 if (NewCalleeCloneNo > 0)
4938 cast<CallBase>(CallerCall.call())->setCalledFunction(CalleeFunc.func());
4939 OREGetter(CallerCall.call()->getFunction())
4940 .emit(OptimizationRemark(DEBUG_TYPE, "MemprofCall", CallerCall.call())
4941 << ore::NV("Call", CallerCall.call()) << " in clone "
4942 << ore::NV("Caller", CallerCall.call()->getFunction())
4943 << " assigned to call function clone "
4944 << ore::NV("Callee", CalleeFunc.func()));
4945}
4946
4947void IndexCallsiteContextGraph::updateCall(CallInfo &CallerCall,
4948 FuncInfo CalleeFunc) {
4949 auto *CI = cast<CallsiteInfo *>(CallerCall.call());
4950 assert(CI &&
4951 "Caller cannot be an allocation which should not have profiled calls");
4952 assert(CI->Clones.size() > CallerCall.cloneNo());
4953 auto NewCalleeCloneNo = CalleeFunc.cloneNo();
4954 auto &CurCalleeCloneNo = CI->Clones[CallerCall.cloneNo()];
4955 // If we already assigned this callsite to call a specific non-default
4956 // clone (i.e. not the original function which is clone 0), ensure that we
4957 // aren't trying to now update it to call a different clone, which is
4958 // indicative of a bug in the graph or function assignment.
4959 if (CurCalleeCloneNo != 0 && CurCalleeCloneNo != NewCalleeCloneNo) {
4960 LLVM_DEBUG(dbgs() << "Mismatch in call clone assignment: was "
4961 << CurCalleeCloneNo << " now " << NewCalleeCloneNo
4962 << "\n");
4963 MismatchedCloneAssignments++;
4964 }
4965 CurCalleeCloneNo = NewCalleeCloneNo;
4966}
4967
4968// Update the debug information attached to NewFunc to use the clone Name. Note
4969// this needs to be done for both any existing DISubprogram for the definition,
4970// as well as any separate declaration DISubprogram.
4972 assert(Name == NewFunc->getName());
4973 auto *SP = NewFunc->getSubprogram();
4974 if (!SP)
4975 return;
4976 auto *MDName = MDString::get(NewFunc->getParent()->getContext(), Name);
4977 SP->replaceLinkageName(MDName);
4978 DISubprogram *Decl = SP->getDeclaration();
4979 if (!Decl)
4980 return;
4981 TempDISubprogram NewDecl = Decl->clone();
4982 NewDecl->replaceLinkageName(MDName);
4983 SP->replaceDeclaration(MDNode::replaceWithUniqued(std::move(NewDecl)));
4984}
4985
4986CallsiteContextGraph<ModuleCallsiteContextGraph, Function,
4987 Instruction *>::FuncInfo
4988ModuleCallsiteContextGraph::cloneFunctionForCallsite(
4989 FuncInfo &Func, CallInfo &Call, DenseMap<CallInfo, CallInfo> &CallMap,
4990 std::vector<CallInfo> &CallsWithMetadataInFunc, unsigned CloneNo) {
4991 // Use existing LLVM facilities for cloning and obtaining Call in clone
4992 ValueToValueMapTy VMap;
4993 auto *NewFunc = CloneFunction(Func.func(), VMap);
4994 std::string Name = getMemProfFuncName(Func.func()->getName(), CloneNo);
4995 assert(!Func.func()->getParent()->getFunction(Name));
4996 NewFunc->setName(Name);
4997 updateSubprogramLinkageName(NewFunc, Name);
4998 for (auto &Inst : CallsWithMetadataInFunc) {
4999 // This map always has the initial version in it.
5000 assert(Inst.cloneNo() == 0);
5001 CallMap[Inst] = {cast<Instruction>(VMap[Inst.call()]), CloneNo};
5002 }
5003 OREGetter(Func.func())
5004 .emit(OptimizationRemark(DEBUG_TYPE, "MemprofClone", Func.func())
5005 << "created clone " << ore::NV("NewFunction", NewFunc));
5006 return {NewFunc, CloneNo};
5007}
5008
5009CallsiteContextGraph<IndexCallsiteContextGraph, FunctionSummary,
5010 IndexCall>::FuncInfo
5011IndexCallsiteContextGraph::cloneFunctionForCallsite(
5012 FuncInfo &Func, CallInfo &Call, DenseMap<CallInfo, CallInfo> &CallMap,
5013 std::vector<CallInfo> &CallsWithMetadataInFunc, unsigned CloneNo) {
5014 // Check how many clones we have of Call (and therefore function).
5015 // The next clone number is the current size of versions array.
5016 // Confirm this matches the CloneNo provided by the caller, which is based on
5017 // the number of function clones we have.
5018 assert(CloneNo == (isa<AllocInfo *>(Call.call())
5019 ? cast<AllocInfo *>(Call.call())->Versions.size()
5020 : cast<CallsiteInfo *>(Call.call())->Clones.size()));
5021 // Walk all the instructions in this function. Create a new version for
5022 // each (by adding an entry to the Versions/Clones summary array), and copy
5023 // over the version being called for the function clone being cloned here.
5024 // Additionally, add an entry to the CallMap for the new function clone,
5025 // mapping the original call (clone 0, what is in CallsWithMetadataInFunc)
5026 // to the new call clone.
5027 for (auto &Inst : CallsWithMetadataInFunc) {
5028 // This map always has the initial version in it.
5029 assert(Inst.cloneNo() == 0);
5030 if (auto *AI = dyn_cast<AllocInfo *>(Inst.call())) {
5031 assert(AI->Versions.size() == CloneNo);
5032 // We assign the allocation type later (in updateAllocationCall), just add
5033 // an entry for it here.
5034 AI->Versions.push_back(0);
5035 } else {
5036 auto *CI = cast<CallsiteInfo *>(Inst.call());
5037 assert(CI && CI->Clones.size() == CloneNo);
5038 // We assign the clone number later (in updateCall), just add an entry for
5039 // it here.
5040 CI->Clones.push_back(0);
5041 }
5042 CallMap[Inst] = {Inst.call(), CloneNo};
5043 }
5044 return {Func.func(), CloneNo};
5045}
5046
5047// We perform cloning for each allocation node separately. However, this
5048// sometimes results in a situation where the same node calls multiple
5049// clones of the same callee, created for different allocations. This
5050// causes issues when assigning functions to these clones, as each node can
5051// in reality only call a single callee clone.
5052//
5053// To address this, before assigning functions, merge callee clone nodes as
5054// needed using a post order traversal from the allocations. We attempt to
5055// use existing clones as the merge node when legal, and to share them
5056// among callers with the same properties (callers calling the same set of
5057// callee clone nodes for the same allocations).
5058//
5059// Without this fix, in some cases incorrect function assignment will lead
5060// to calling the wrong allocation clone.
5061template <typename DerivedCCG, typename FuncTy, typename CallTy>
5062void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::mergeClones() {
5063 if (!MergeClones)
5064 return;
5065
5066 // Generate a map from context id to the associated allocation node for use
5067 // when merging clones.
5068 DenseMap<uint32_t, ContextNode *> ContextIdToAllocationNode;
5069 for (auto &Entry : AllocationCallToContextNodeMap) {
5070 auto *Node = Entry.second;
5071 for (auto Id : Node->getContextIds())
5072 ContextIdToAllocationNode[Id] = Node->getOrigNode();
5073 for (auto *Clone : Node->Clones) {
5074 for (auto Id : Clone->getContextIds())
5075 ContextIdToAllocationNode[Id] = Clone->getOrigNode();
5076 }
5077 }
5078
5079 // Post order traversal starting from allocations to ensure each callsite
5080 // calls a single clone of its callee. Callee nodes that are clones of each
5081 // other are merged (via new merge nodes if needed) to achieve this.
5082 DenseSet<const ContextNode *> Visited;
5083 for (auto &Entry : AllocationCallToContextNodeMap) {
5084 auto *Node = Entry.second;
5085
5086 mergeClones(Node, Visited, ContextIdToAllocationNode);
5087
5088 // Make a copy so the recursive post order traversal that may create new
5089 // clones doesn't mess up iteration. Note that the recursive traversal
5090 // itself does not call mergeClones on any of these nodes, which are all
5091 // (clones of) allocations.
5092 auto Clones = Node->Clones;
5093 for (auto *Clone : Clones)
5094 mergeClones(Clone, Visited, ContextIdToAllocationNode);
5095 }
5096
5097 if (DumpCCG) {
5098 dbgs() << "CCG after merging:\n";
5099 dbgs() << *this;
5100 }
5101 if (ExportToDot)
5102 exportToDot("aftermerge");
5103
5104 if (VerifyCCG) {
5105 check();
5106 }
5107}
5108
5109// Recursive helper for above mergeClones method.
5110template <typename DerivedCCG, typename FuncTy, typename CallTy>
5111void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::mergeClones(
5112 ContextNode *Node, DenseSet<const ContextNode *> &Visited,
5113 DenseMap<uint32_t, ContextNode *> &ContextIdToAllocationNode) {
5114 auto Inserted = Visited.insert(Node);
5115 if (!Inserted.second)
5116 return;
5117
5118 // Iteratively perform merging on this node to handle new caller nodes created
5119 // during the recursive traversal. We could do something more elegant such as
5120 // maintain a worklist, but this is a simple approach that doesn't cause a
5121 // measureable compile time effect, as most nodes don't have many caller
5122 // edges to check.
5123 bool FoundUnvisited = true;
5124 unsigned Iters = 0;
5125 while (FoundUnvisited) {
5126 Iters++;
5127 FoundUnvisited = false;
5128 // Make a copy since the recursive call may move a caller edge to a new
5129 // callee, messing up the iterator.
5130 auto CallerEdges = Node->CallerEdges;
5131 for (auto CallerEdge : CallerEdges) {
5132 // Skip any caller edge moved onto a different callee during recursion.
5133 if (CallerEdge->Callee != Node)
5134 continue;
5135 // If we found an unvisited caller, note that we should check the caller
5136 // edges again as mergeClones may add or change caller nodes.
5137 if (DoMergeIteration && !Visited.contains(CallerEdge->Caller))
5138 FoundUnvisited = true;
5139 mergeClones(CallerEdge->Caller, Visited, ContextIdToAllocationNode);
5140 }
5141 }
5142
5143 TotalMergeInvokes++;
5144 TotalMergeIters += Iters;
5145 if (Iters > MaxMergeIters)
5146 MaxMergeIters = Iters;
5147
5148 // Merge for this node after we handle its callers.
5149 mergeNodeCalleeClones(Node, Visited, ContextIdToAllocationNode);
5150}
5151
5152template <typename DerivedCCG, typename FuncTy, typename CallTy>
5153void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::mergeNodeCalleeClones(
5154 ContextNode *Node, DenseSet<const ContextNode *> &Visited,
5155 DenseMap<uint32_t, ContextNode *> &ContextIdToAllocationNode) {
5156 // Ignore Node if we moved all of its contexts to clones.
5157 if (Node->emptyContextIds())
5158 return;
5159
5160 // First identify groups of clones among Node's callee edges, by building
5161 // a map from each callee base node to the associated callee edges from Node.
5162 MapVector<ContextNode *, std::vector<std::shared_ptr<ContextEdge>>>
5163 OrigNodeToCloneEdges;
5164 for (const auto &E : Node->CalleeEdges) {
5165 auto *Callee = E->Callee;
5166 if (!Callee->CloneOf && Callee->Clones.empty())
5167 continue;
5168 ContextNode *Base = Callee->getOrigNode();
5169 OrigNodeToCloneEdges[Base].push_back(E);
5170 }
5171
5172 // Helper for callee edge sorting below. Return true if A's callee has fewer
5173 // caller edges than B, or if A is a clone and B is not, or if A's callee
5174 // node id is smaller than B's.
5175 auto CalleeCallerEdgeLessThan = [](const std::shared_ptr<ContextEdge> &A,
5176 const std::shared_ptr<ContextEdge> &B) {
5177 if (A->Callee->CallerEdges.size() != B->Callee->CallerEdges.size())
5178 return A->Callee->CallerEdges.size() < B->Callee->CallerEdges.size();
5179 if (A->Callee->CloneOf && !B->Callee->CloneOf)
5180 return true;
5181 else if (!A->Callee->CloneOf && B->Callee->CloneOf)
5182 return false;
5183 // Use the callee node id as a deterministic tie-breaker.
5184 return A->Callee->NodeId < B->Callee->NodeId;
5185 };
5186
5187 // Process each set of callee clones called by Node, performing the needed
5188 // merging.
5189 for (auto Entry : OrigNodeToCloneEdges) {
5190 // CalleeEdges is the set of edges from Node reaching callees that are
5191 // mutual clones of each other.
5192 auto &CalleeEdges = Entry.second;
5193 auto NumCalleeClones = CalleeEdges.size();
5194 // A single edge means there is no merging needed.
5195 if (NumCalleeClones == 1)
5196 continue;
5197 // Sort the CalleeEdges calling this group of clones in ascending order of
5198 // their caller edge counts, putting the original non-clone node first in
5199 // cases of a tie. This simplifies finding an existing node to use as the
5200 // merge node.
5201 llvm::stable_sort(CalleeEdges, CalleeCallerEdgeLessThan);
5202
5203 /// Find other callers of the given set of callee edges that can
5204 /// share the same callee merge node. See the comments at this method
5205 /// definition for details.
5206 DenseSet<ContextNode *> OtherCallersToShareMerge;
5207 findOtherCallersToShareMerge(Node, CalleeEdges, ContextIdToAllocationNode,
5208 OtherCallersToShareMerge);
5209
5210 // Now do the actual merging. Identify existing or create a new MergeNode
5211 // during the first iteration. Move each callee over, along with edges from
5212 // other callers we've determined above can share the same merge node.
5213 ContextNode *MergeNode = nullptr;
5214 DenseMap<ContextNode *, unsigned> CallerToMoveCount;
5215 for (auto CalleeEdge : CalleeEdges) {
5216 auto *OrigCallee = CalleeEdge->Callee;
5217 // If we don't have a MergeNode yet (only happens on the first iteration,
5218 // as a new one will be created when we go to move the first callee edge
5219 // over as needed), see if we can use this callee.
5220 if (!MergeNode) {
5221 // If there are no other callers, simply use this callee.
5222 if (CalleeEdge->Callee->CallerEdges.size() == 1) {
5223 MergeNode = OrigCallee;
5224 NonNewMergedNodes++;
5225 continue;
5226 }
5227 // Otherwise, if we have identified other caller nodes that can share
5228 // the merge node with Node, see if all of OrigCallee's callers are
5229 // going to share the same merge node. In that case we can use callee
5230 // (since all of its callers would move to the new merge node).
5231 if (!OtherCallersToShareMerge.empty()) {
5232 bool MoveAllCallerEdges = true;
5233 for (auto CalleeCallerE : OrigCallee->CallerEdges) {
5234 if (CalleeCallerE == CalleeEdge)
5235 continue;
5236 if (!OtherCallersToShareMerge.contains(CalleeCallerE->Caller)) {
5237 MoveAllCallerEdges = false;
5238 break;
5239 }
5240 }
5241 // If we are going to move all callers over, we can use this callee as
5242 // the MergeNode.
5243 if (MoveAllCallerEdges) {
5244 MergeNode = OrigCallee;
5245 NonNewMergedNodes++;
5246 continue;
5247 }
5248 }
5249 }
5250 // Move this callee edge, creating a new merge node if necessary.
5251 if (MergeNode) {
5252 assert(MergeNode != OrigCallee);
5253 moveEdgeToExistingCalleeClone(CalleeEdge, MergeNode,
5254 /*NewClone*/ false);
5255 } else {
5256 MergeNode = moveEdgeToNewCalleeClone(CalleeEdge);
5257 NewMergedNodes++;
5258 }
5259 // Now move all identified edges from other callers over to the merge node
5260 // as well.
5261 if (!OtherCallersToShareMerge.empty()) {
5262 // Make and iterate over a copy of OrigCallee's caller edges because
5263 // some of these will be moved off of the OrigCallee and that would mess
5264 // up the iteration from OrigCallee.
5265 auto OrigCalleeCallerEdges = OrigCallee->CallerEdges;
5266 for (auto &CalleeCallerE : OrigCalleeCallerEdges) {
5267 if (CalleeCallerE == CalleeEdge)
5268 continue;
5269 if (!OtherCallersToShareMerge.contains(CalleeCallerE->Caller))
5270 continue;
5271 CallerToMoveCount[CalleeCallerE->Caller]++;
5272 moveEdgeToExistingCalleeClone(CalleeCallerE, MergeNode,
5273 /*NewClone*/ false);
5274 }
5275 }
5276 removeNoneTypeCalleeEdges(OrigCallee);
5277 removeNoneTypeCalleeEdges(MergeNode);
5278 }
5279 }
5280}
5281
5282// Look for other nodes that have edges to the same set of callee
5283// clones as the current Node. Those can share the eventual merge node
5284// (reducing cloning and binary size overhead) iff:
5285// - they have edges to the same set of callee clones
5286// - each callee edge reaches a subset of the same allocations as Node's
5287// corresponding edge to the same callee clone.
5288// The second requirement is to ensure that we don't undo any of the
5289// necessary cloning to distinguish contexts with different allocation
5290// behavior.
5291// FIXME: This is somewhat conservative, as we really just need to ensure
5292// that they don't reach the same allocations as contexts on edges from Node
5293// going to any of the *other* callee clones being merged. However, that
5294// requires more tracking and checking to get right.
5295template <typename DerivedCCG, typename FuncTy, typename CallTy>
5296void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::
5297 findOtherCallersToShareMerge(
5298 ContextNode *Node,
5299 std::vector<std::shared_ptr<ContextEdge>> &CalleeEdges,
5300 DenseMap<uint32_t, ContextNode *> &ContextIdToAllocationNode,
5301 DenseSet<ContextNode *> &OtherCallersToShareMerge) {
5302 auto NumCalleeClones = CalleeEdges.size();
5303 // This map counts how many edges to the same callee clone exist for other
5304 // caller nodes of each callee clone.
5305 DenseMap<ContextNode *, unsigned> OtherCallersToSharedCalleeEdgeCount;
5306 // Counts the number of other caller nodes that have edges to all callee
5307 // clones that don't violate the allocation context checking.
5308 unsigned PossibleOtherCallerNodes = 0;
5309
5310 // We only need to look at other Caller nodes if the first callee edge has
5311 // multiple callers (recall they are sorted in ascending order above).
5312 if (CalleeEdges[0]->Callee->CallerEdges.size() < 2)
5313 return;
5314
5315 // For each callee edge:
5316 // - Collect the count of other caller nodes calling the same callees.
5317 // - Collect the alloc nodes reached by contexts on each callee edge.
5318 DenseMap<ContextEdge *, DenseSet<ContextNode *>> CalleeEdgeToAllocNodes;
5319 for (auto CalleeEdge : CalleeEdges) {
5320 assert(CalleeEdge->Callee->CallerEdges.size() > 1);
5321 // For each other caller of the same callee, increment the count of
5322 // edges reaching the same callee clone.
5323 for (auto CalleeCallerEdges : CalleeEdge->Callee->CallerEdges) {
5324 if (CalleeCallerEdges->Caller == Node) {
5325 assert(CalleeCallerEdges == CalleeEdge);
5326 continue;
5327 }
5328 OtherCallersToSharedCalleeEdgeCount[CalleeCallerEdges->Caller]++;
5329 // If this caller edge now reaches all of the same callee clones,
5330 // increment the count of candidate other caller nodes.
5331 if (OtherCallersToSharedCalleeEdgeCount[CalleeCallerEdges->Caller] ==
5332 NumCalleeClones)
5333 PossibleOtherCallerNodes++;
5334 }
5335 // Collect the alloc nodes reached by contexts on each callee edge, for
5336 // later analysis.
5337 for (auto Id : CalleeEdge->getContextIds()) {
5338 auto *Alloc = ContextIdToAllocationNode.lookup(Id);
5339 if (!Alloc) {
5340 // FIXME: unclear why this happens occasionally, presumably
5341 // imperfect graph updates possibly with recursion.
5342 MissingAllocForContextId++;
5343 continue;
5344 }
5345 CalleeEdgeToAllocNodes[CalleeEdge.get()].insert(Alloc);
5346 }
5347 }
5348
5349 // Now walk the callee edges again, and make sure that for each candidate
5350 // caller node all of its edges to the callees reach the same allocs (or
5351 // a subset) as those along the corresponding callee edge from Node.
5352 for (auto CalleeEdge : CalleeEdges) {
5353 assert(CalleeEdge->Callee->CallerEdges.size() > 1);
5354 // Stop if we do not have any (more) candidate other caller nodes.
5355 if (!PossibleOtherCallerNodes)
5356 break;
5357 auto &CurCalleeAllocNodes = CalleeEdgeToAllocNodes[CalleeEdge.get()];
5358 // Check each other caller of this callee clone.
5359 for (auto &CalleeCallerE : CalleeEdge->Callee->CallerEdges) {
5360 // Not interested in the callee edge from Node itself.
5361 if (CalleeCallerE == CalleeEdge)
5362 continue;
5363 // Skip any callers that didn't have callee edges to all the same
5364 // callee clones.
5365 if (OtherCallersToSharedCalleeEdgeCount[CalleeCallerE->Caller] !=
5366 NumCalleeClones)
5367 continue;
5368 // Make sure that each context along edge from candidate caller node
5369 // reaches an allocation also reached by this callee edge from Node.
5370 for (auto Id : CalleeCallerE->getContextIds()) {
5371 auto *Alloc = ContextIdToAllocationNode.lookup(Id);
5372 if (!Alloc)
5373 continue;
5374 // If not, simply reset the map entry to 0 so caller is ignored, and
5375 // reduce the count of candidate other caller nodes.
5376 if (!CurCalleeAllocNodes.contains(Alloc)) {
5377 OtherCallersToSharedCalleeEdgeCount[CalleeCallerE->Caller] = 0;
5378 PossibleOtherCallerNodes--;
5379 break;
5380 }
5381 }
5382 }
5383 }
5384
5385 if (!PossibleOtherCallerNodes)
5386 return;
5387
5388 // Build the set of other caller nodes that can use the same callee merge
5389 // node.
5390 for (auto &[OtherCaller, Count] : OtherCallersToSharedCalleeEdgeCount) {
5391 if (Count != NumCalleeClones)
5392 continue;
5393 OtherCallersToShareMerge.insert(OtherCaller);
5394 }
5395}
5396
5397template <typename DerivedCCG, typename FuncTy, typename CallTy>
5398const typename CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::ContextNode *
5399CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::resolveImplicitSource(
5400 const ContextNode *Node, const ImplicitSource &Src) {
5401 if (!Src.Source->emptyContextIds())
5402 return Src.Source;
5403 // Src.Source lost its contexts to another clone (e.g. its last caller was
5404 // moved to a new clone when specializing a function clone further). The
5405 // trimmed contexts stay together, so the clone carrying one of them is the
5406 // version the implicit caller requires.
5407 if (Node->hasContextId(Src.ContextId))
5408 return Node;
5409 for (const ContextNode *C : Node->Clones)
5410 if (C->hasContextId(Src.ContextId))
5411 return C;
5412 // Context ids only move between the clones of a node during function
5413 // assignment, so the id should still be on one of them. Return null, which
5414 // makes the call follow the original node, rather than an emptied clone.
5415 assert(false && "trimmed context id on no clone of its callsite node");
5416 return nullptr;
5417}
5418
5419// Contexts whose call stacks were trimmed at a callsite node's frame are on
5420// its callee edges but on none of its caller edges. When that node, or one
5421// below it on the path of such a context, is cloned for the contexts of
5422// another allocation reaching it through a caller edge, the trimmed contexts
5423// stay with the node that was cloned, and the clone gets no edge to the callee
5424// nodes the trimmed contexts flow through. The clone is therefore not a caller
5425// of any clone of such a callee node, and would otherwise be assigned a
5426// function clone of the callee without regard to it, possibly one calling the
5427// wrong version of the callee for the trimmed contexts, which are agnostic to
5428// the callers of the node they were trimmed at and apply to the clone equally.
5429//
5430// This is called once the clones of callsite Node have been assigned to
5431// function clones. For each caller Y of a clone of Node whose edge carries
5432// trimmed contexts, each clone K of Y's original node that has no edge to any
5433// clone of Node, and which some of those trimmed contexts would reach (see
5434// ImpliesContextIds), is an implicit caller of Node. For example, with a
5435// context t trimmed at the frame of Y's callsite:
5436//
5437// (callers of Y) (callers of K)
5438// | |
5439// Y K clones of the same callsite node
5440// | \
5441// t | \ K has no edge to any clone of Node
5442// v v
5443// Required (other callsites in Node's function)
5444// (clone of Node called
5445// by Y, assigned to
5446// Y's function clone)
5447//
5448// Had t not been trimmed, it would also be on an edge from K, so K should get
5449// the same version of Node's function as Y:
5450// - If K was not yet assigned a function clone, assign it Y's, so that the
5451// assignment of the callsites it does have edges to takes it into account
5452// (creating further function clones derived from it if needed).
5453// - If K was already assigned to a function clone without a clone of Node,
5454// record that the Node call in that function clone should follow Required.
5455// - Otherwise K's function clone calls a conflicting clone of Node, which is
5456// left as is (and counted).
5457template <typename DerivedCCG, typename FuncTy, typename CallTy>
5458void CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::assignImplicitCallers(
5459 ContextNode *Node, const DenseSet<uint32_t> &TrimmedContextIds,
5460 DenseMap<ContextNode *, FuncInfo> &CallsiteToCalleeFuncCloneMap,
5461 const std::map<FuncInfo, ContextNode *> &FuncCloneToCurNodeCloneMap,
5462 ImplicitSourceMap &ImplicitSources) {
5463 auto HasEdgeToNodeFamily = [&](const ContextNode *N) {
5464 return llvm::any_of(N->CalleeEdges,
5465 [&](const std::shared_ptr<ContextEdge> &E) {
5466 return E->Callee->getOrigNode() == Node;
5467 });
5468 };
5469 // Returns true if any of the trimmed context ids Ids, which are on (the
5470 // clone) Y but not on K, a clone of the same callsite node, would reach K had
5471 // they not been trimmed:
5472 // - An id terminating at Y applies to all clones of Y's original node (see
5473 // the example above assignImplicitCallers).
5474 // - An id reaching Y from a caller Z applies to K only if it would equally
5475 // apply to some caller C of K that is a clone of Z's original node, i.e.
5476 // it is not on C (if it were, C explicitly directs it to a callee other
5477 // than K) and, recursively, it applies to C the way it applies to Z (e.g.
5478 // because it terminates at Z, so it applies to all clones of Z's original
5479 // node). The id would then flow from C to K just as it flows from Z to Y,
5480 // had it not been trimmed:
5481 //
5482 // ... ... t terminates at Z or one of its callers
5483 // |
5484 // Z C clones of the same callsite node
5485 // | :
5486 // t | : (t) t is not on C or K; it applies to them
5487 // v v because it was trimmed above
5488 // Y K clones of the same callsite node
5489 // |
5490 // t v
5491 // Required
5492 //
5493 // This is checked recursively on (C, Z) with the ids not on C. If C == Z,
5494 // Z explicitly directs the ids to Y rather than K, so they don't apply to
5495 // K.
5496 //
5497 // Visited records the ids already examined for each (K, Y) pair, which
5498 // guards against cycles from recursion while still examining ids first seen
5499 // for the pair on a reconverging caller chain.
5500 auto ImpliesContextIds =
5501 [&](ContextNode *K, ContextNode *Y, const DenseSet<uint32_t> &Ids,
5502 DenseMap<std::pair<ContextNode *, ContextNode *>, DenseSet<uint32_t>>
5503 &Visited,
5504 auto &&ImpliesContextIds) -> bool {
5505 assert(K->getOrigNode() == Y->getOrigNode());
5506 DenseSet<uint32_t> &VisitedIds = Visited[{K, Y}];
5507 DenseSet<uint32_t> NewIds;
5508 for (auto Id : Ids)
5509 if (VisitedIds.insert(Id).second)
5510 NewIds.insert(Id);
5511 if (NewIds.empty())
5512 return false;
5513 // The ids found on each caller edge of Y, with that edge's caller Z, and
5514 // their union (a set rather than a count, as a recursive context can put
5515 // the same id on several caller edges).
5517 DenseSet<uint32_t> IdsOnCallerEdges;
5518 for (auto &YEdge : Y->CallerEdges) {
5519 DenseSet<uint32_t> IdsFromZ =
5520 set_intersection(NewIds, YEdge->getContextIds());
5521 if (IdsFromZ.empty())
5522 continue;
5523 set_union(IdsOnCallerEdges, IdsFromZ);
5524 IdsFromCallers.push_back({YEdge->Caller, std::move(IdsFromZ)});
5525 }
5526 // Any ids on none of Y's caller edges terminate at Y, and so apply to all
5527 // clones of Y's original node, including K.
5528 if (IdsOnCallerEdges.size() < NewIds.size())
5529 return true;
5530 // Otherwise check whether the ids reaching Y from a caller Z also apply to
5531 // K through a caller C of K that is a clone of Z's original node.
5532 for (auto &[Z, IdsFromZ] : IdsFromCallers) {
5533 for (auto &KEdge : K->CallerEdges) {
5534 ContextNode *C = KEdge->Caller;
5535 if (C == Z || C->getOrigNode() != Z->getOrigNode())
5536 continue;
5537 // Only the ids not on C can apply to C implicitly (C directs the ones
5538 // it has elsewhere); recursively check whether they do.
5539 DenseSet<uint32_t> IdsNotOnC;
5540 for (auto Id : IdsFromZ)
5541 if (!C->hasContextId(Id))
5542 IdsNotOnC.insert(Id);
5543 if (!IdsNotOnC.empty() &&
5544 ImpliesContextIds(C, Z, IdsNotOnC, Visited, ImpliesContextIds))
5545 return true;
5546 }
5547 }
5548 return false;
5549 };
5550 // Returns true if the given clones of Node are interchangeable for an
5551 // implicit caller: the same clone, allocations with the same hint, or
5552 // callsites already assigned to call the same function clone.
5553 auto SameVersion = [&](const ContextNode *A, const ContextNode *B) {
5554 if (A == B)
5555 return true;
5556 if (Node->IsAllocation)
5557 return allocTypeToUse(A->AllocTypes) == allocTypeToUse(B->AllocTypes);
5558 auto AIt = CallsiteToCalleeFuncCloneMap.find(A);
5559 auto BIt = CallsiteToCalleeFuncCloneMap.find(B);
5560 return AIt != CallsiteToCalleeFuncCloneMap.end() &&
5561 BIt != CallsiteToCalleeFuncCloneMap.end() &&
5562 AIt->second == BIt->second;
5563 };
5564 // The clones already identified as implicit callers of Node, so that each is
5565 // handled once (for the first caller edge whose trimmed contexts reach it).
5566 DenseSet<const ContextNode *> ImplicitCallers;
5567 // Handles the caller edge Edge of a clone of Node (or of Node itself): finds
5568 // the implicit callers among the clones of its caller Y's original node, and
5569 // assigns them, or records the clone of Node their calls must follow, as
5570 // described above.
5571 auto ProcessCaller = [&](const std::shared_ptr<ContextEdge> &Edge) {
5572 ContextNode *Y = Edge->Caller;
5573 ContextNode *Orig = Y->getOrigNode();
5574 if (!Y->hasCall() || Orig->Clones.empty())
5575 return;
5576 DenseSet<uint32_t> TrimmedIds =
5577 set_intersection(Edge->getContextIds(), TrimmedContextIds);
5578 if (TrimmedIds.empty())
5579 return;
5580 auto YIt = CallsiteToCalleeFuncCloneMap.find(Y);
5581 if (YIt == CallsiteToCalleeFuncCloneMap.end())
5582 return;
5583 // Copy, as recording assignments below may grow the map.
5584 const FuncInfo YFuncClone = YIt->second;
5585 // The clone of Node called by Y, which must be assigned to the same
5586 // function clone.
5587 auto RequiredIt = FuncCloneToCurNodeCloneMap.find(YFuncClone);
5588 assert(RequiredIt != FuncCloneToCurNodeCloneMap.end());
5589 const ContextNode *Required = RequiredIt->second;
5590 // Record in ImplicitSources that the Node call in function clone F must
5591 // follow the callsite clone Src. This is consulted when the calls in
5592 // function clones without their own clone of Node are collected (see
5593 // UnassignedCallClones in assignFunctions), and makes the requirement
5594 // survive if Src is later moved to another function clone derived from F
5595 // (when one of its callers conflicts at another callsite), after which the
5596 // call in F would otherwise follow the function clone F was derived from.
5597 auto RecordImplicitSource = [&](const FuncInfo &F, const ContextNode *Src) {
5598 // The calls in the original function (clone 0) are not collected there,
5599 // so nothing can be recorded for it.
5600 if (F.cloneNo() != 0)
5601 ImplicitSources.try_emplace({Node, F.cloneNo()},
5602 ImplicitSource{Src, *TrimmedIds.begin()});
5603 };
5604 // Check each clone of Y's original node (and the original itself) without
5605 // an edge to any clone of Node.
5606 for (ContextNode *K : llvm::concat<ContextNode *const>(
5607 Orig->Clones, ArrayRef<ContextNode *>(Orig))) {
5608 if (K == Y || !K->hasCall() || K->emptyContextIds() ||
5609 HasEdgeToNodeFamily(K) || ImplicitCallers.contains(K))
5610 continue;
5611 DenseMap<std::pair<ContextNode *, ContextNode *>, DenseSet<uint32_t>>
5612 Visited;
5613 if (!ImpliesContextIds(K, Y, TrimmedIds, Visited, ImpliesContextIds))
5614 continue;
5615 // K is an implicit caller of Node.
5616 ImplicitCallers.insert(K);
5617 auto KIt = CallsiteToCalleeFuncCloneMap.find(K);
5618 if (KIt == CallsiteToCalleeFuncCloneMap.end()) {
5619 // Not yet assigned: give it Y's function clone, in which the Node call
5620 // then follows Required.
5621 CallsiteToCalleeFuncCloneMap[K] = YFuncClone;
5622 RecordImplicitSource(YFuncClone, Required);
5623 NumImplicitCallersAssigned++;
5624 continue;
5625 }
5626 const FuncInfo KFuncClone = KIt->second;
5627 if (KFuncClone == YFuncClone) {
5628 // Already in Y's function clone.
5629 RecordImplicitSource(YFuncClone, Required);
5630 continue;
5631 }
5632 unsigned KCloneNo = KFuncClone.cloneNo();
5633 auto KNodeCloneIt = FuncCloneToCurNodeCloneMap.find(KFuncClone);
5634 if (KNodeCloneIt == FuncCloneToCurNodeCloneMap.end()) {
5635 // K's function clone has no clone of Node.
5636 if (KCloneNo == 0) {
5637 // The call in the original function keeps calling the original
5638 // callee function, or stays unhinted for an allocation. That
5639 // satisfies the requirement only if Required is that version.
5640 if (Node->IsAllocation) {
5641 if (allocTypeToUse(Required->AllocTypes) == AllocationType::NotCold)
5642 continue;
5643 } else if (auto It = CallsiteToCalleeFuncCloneMap.find(Required);
5644 It != CallsiteToCalleeFuncCloneMap.end() &&
5645 It->second.cloneNo() == 0)
5646 continue;
5647 } else {
5648 // Record that the Node call in K's function clone must follow
5649 // Required, unless an earlier implicit caller already recorded a
5650 // conflicting clone.
5651 auto [It, Inserted] = ImplicitSources.try_emplace(
5652 {Node, KCloneNo}, ImplicitSource{Required, *TrimmedIds.begin()});
5653 if (Inserted)
5654 NumImplicitCallersSourced++;
5655 if (SameVersion(It->second.Source, Required))
5656 continue;
5657 }
5658 } else if (SameVersion(KNodeCloneIt->second, Required)) {
5659 // K's function clone has a clone of Node interchangeable with
5660 // Required.
5661 RecordImplicitSource(KFuncClone, KNodeCloneIt->second);
5662 continue;
5663 }
5664 // K's function clone calls a conflicting clone of Node.
5665 NumImplicitCallersUnresolved++;
5666 }
5667 };
5668 // Process the caller edges of Node itself and of each of its clones: any of
5669 // them may carry trimmed contexts (a trimmed context stays with the clone
5670 // that was cloned, which may be Node or a clone made earlier).
5671 for (auto &Edge : Node->CallerEdges)
5672 ProcessCaller(Edge);
5673 for (auto *Clone : Node->Clones)
5674 for (auto &Edge : Clone->CallerEdges)
5675 ProcessCaller(Edge);
5676}
5677
5678// This method assigns cloned callsites to functions, cloning the functions as
5679// needed. The assignment is greedy and proceeds roughly as follows:
5680//
5681// For each function Func:
5682// For each call with graph Node having clones:
5683// Initialize ClonesWorklist to Node and its clones
5684// Initialize NodeCloneCount to 0
5685// While ClonesWorklist is not empty:
5686// Clone = pop front ClonesWorklist
5687// NodeCloneCount++
5688// If Func has been cloned less than NodeCloneCount times:
5689// If NodeCloneCount is 1:
5690// Assign Clone to original Func
5691// Continue
5692// Create a new function clone
5693// If other callers not assigned to call a function clone yet:
5694// Assign them to call new function clone
5695// Continue
5696// Assign any other caller calling the cloned version to new clone
5697//
5698// For each caller of Clone:
5699// If caller is assigned to call a specific function clone:
5700// If we cannot assign Clone to that function clone:
5701// Create new callsite Clone NewClone
5702// Add NewClone to ClonesWorklist
5703// Continue
5704// Assign Clone to existing caller's called function clone
5705// Else:
5706// If Clone not already assigned to a function clone:
5707// Assign to first function clone without assignment
5708// Assign caller to selected function clone
5709// For each call with graph Node having clones:
5710// If number func clones > number call's callsite Node clones:
5711// Record func CallInfo clones without Node clone in UnassignedCallClones
5712// For callsite Nodes in DFS order from allocations:
5713// If IsAllocation:
5714// Update allocation with alloc type
5715// Else:
5716// For Call, all MatchingCalls, and associated UnnassignedCallClones:
5717// Update call to call recorded callee clone
5718//
5719template <typename DerivedCCG, typename FuncTy, typename CallTy>
5720bool CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::assignFunctions() {
5721 bool Changed = false;
5722
5723 mergeClones();
5724
5725 // Context ids terminating at a non-allocation node which has or had callers
5726 // (i.e. is not a root), meaning their call stacks were trimmed there. Used
5727 // to identify implicit callers (see assignImplicitCallers).
5728 DenseSet<uint32_t> TrimmedContextIds;
5729 for (auto &NodePtr : NodeOwner) {
5730 ContextNode *N = NodePtr.get();
5731 if (N->IsAllocation || N->CalleeEdges.empty() ||
5732 (N->CallerEdges.empty() && N->Clones.empty() && !N->CloneOf))
5733 continue;
5734 // A context id trimmed at N is on a callee edge but on no caller edge.
5735 // Compare distinct ids rather than edge sizes: a recursive context can put
5736 // the same id on several callee and caller edges of N.
5737 DenseSet<uint32_t> CallerIds;
5738 for (auto &E : N->CallerEdges)
5739 set_union(CallerIds, E->getContextIds());
5740 for (auto &CalleeEdge : N->CalleeEdges)
5741 for (auto Id : CalleeEdge->getContextIds())
5742 if (!CallerIds.contains(Id))
5743 TrimmedContextIds.insert(Id);
5744 }
5745 NumTrimmedContextIds += TrimmedContextIds.size();
5746
5747 // Keep track of the assignment of nodes (callsites) to function clones they
5748 // call.
5749 DenseMap<ContextNode *, FuncInfo> CallsiteToCalleeFuncCloneMap;
5750
5751 // Update caller node to call function version CalleeFunc, by recording the
5752 // assignment in CallsiteToCalleeFuncCloneMap.
5753 auto RecordCalleeFuncOfCallsite = [&](ContextNode *Caller,
5754 const FuncInfo &CalleeFunc) {
5755 assert(Caller->hasCall());
5756 CallsiteToCalleeFuncCloneMap[Caller] = CalleeFunc;
5757 };
5758
5759 // Information for a single clone of this Func.
5760 struct FuncCloneInfo {
5761 // The function clone.
5762 FuncInfo FuncClone;
5763 // Remappings of each call of interest (from original uncloned call to the
5764 // corresponding cloned call in this function clone).
5765 DenseMap<CallInfo, CallInfo> CallMap;
5766 };
5767
5768 // Map to keep track of information needed to update calls in function clones
5769 // when their corresponding callsite node was not itself cloned for that
5770 // function clone. Because of call context trimming (i.e. we only keep as much
5771 // caller information as needed to distinguish hot vs cold), we may not have
5772 // caller edges coming to each callsite node from all possible function
5773 // callers. A function clone may get created for other callsites in the
5774 // function for which there are caller edges that were not trimmed. Any other
5775 // callsites in that function clone, which were not themselved cloned for
5776 // that function clone, should get updated the same way as the corresponding
5777 // callsite in the original function (which may call a clone of its callee).
5778 //
5779 // We build this map after completing function cloning for each function, so
5780 // that we can record the information from its call maps before they are
5781 // destructed. The map will be used as we update calls to update any still
5782 // unassigned call clones. Note that we may create new node clones as we clone
5783 // other functions, so later on we check which node clones were still not
5784 // created. To this end, the inner map is a map from function clone number to
5785 // the list of calls cloned for that function (can be more than one due to the
5786 // Node's MatchingCalls array).
5787 //
5788 // The alternative is creating new callsite clone nodes below as we clone the
5789 // function, but that is tricker to get right and likely more overhead.
5790 //
5791 // Each entry also records the callsite node whose callee assignment the
5792 // calls should follow (Source). By default that is the callsite clone (if
5793 // any) in the function clone the function clone was derived from, following
5794 // the chain of derivations to the original function, since a function clone
5795 // created to specialize another one should otherwise behave like it. It can
5796 // also be the callsite clone required by an implicit caller (see
5797 // assignImplicitCallers). A null Source means the original node.
5798 //
5799 // Inner map is a std::map so sorted by key (clone number), in order to get
5800 // ordered remarks in the full LTO case.
5801 struct UnassignedCallCloneInfo {
5803 const ContextNode *Source = nullptr;
5804 };
5805 DenseMap<const ContextNode *, std::map<unsigned, UnassignedCallCloneInfo>>
5806 UnassignedCallClones;
5807
5808 // Walk all functions for which we saw calls with memprof metadata, and handle
5809 // cloning for each of its calls.
5810 for (auto &[Func, CallsWithMetadata] : FuncToCallsWithMetadata) {
5811 FuncInfo OrigFunc(Func);
5812 // Map from each clone number of OrigFunc to information about that function
5813 // clone (the function clone FuncInfo and call remappings). The index into
5814 // the vector is the clone number, as function clones are created and
5815 // numbered sequentially.
5816 std::vector<FuncCloneInfo> FuncCloneInfos;
5817 // For each function clone number, the clone number of the function clone
5818 // it was derived from (created to further specialize, when a caller
5819 // already assigned to it needed a different clone of some callsite), or 0
5820 // for clones created from the original function. Used to decide which
5821 // callsite clone the calls not themselves cloned for a function clone
5822 // should follow (see UnassignedCallClones).
5823 std::vector<unsigned> FuncCloneParent;
5824 // Callsite clones required for calls in specific function clones by
5825 // implicit callers (see assignImplicitCallers).
5826 ImplicitSourceMap ImplicitSources;
5827 // Map from each original callsite node in this function to its original
5828 // call and matching calls (clone 0). The calls recorded on an original node
5829 // are updated to the calls in a function clone if that node is assigned to
5830 // a function clone, after which they can no longer be used to index the
5831 // function clone CallMaps (which are keyed by the original calls). No node
5832 // in this function has been assigned yet at this point.
5833 struct OrigCallsInfo {
5834 CallInfo Call;
5835 SmallVector<CallInfo, 0> MatchingCalls;
5836 };
5837 DenseMap<const ContextNode *, OrigCallsInfo> OrigNodeToOrigCalls;
5838 for (auto &Call : CallsWithMetadata) {
5839 ContextNode *Node = getNodeForInst(Call);
5840 if (Node && Node->Call == Call)
5841 OrigNodeToOrigCalls[Node] = {Call, Node->MatchingCalls};
5842 }
5843 for (auto &Call : CallsWithMetadata) {
5844 ContextNode *Node = getNodeForInst(Call);
5845 // Skip call if we do not have a node for it (all uses of its stack ids
5846 // were either on inlined chains or trimmed from the MIBs), or if we did
5847 // not create any clones for it.
5848 if (!Node || Node->Clones.empty())
5849 continue;
5850 assert(Node->hasCall() &&
5851 "Not having a call should have prevented cloning");
5852
5853 // Track the assignment of function clones to clones of the current
5854 // callsite Node being handled.
5855 std::map<FuncInfo, ContextNode *> FuncCloneToCurNodeCloneMap;
5856
5857 // Assign callsite version CallsiteClone to function version FuncClone,
5858 // and also assign (possibly cloned) Call to CallsiteClone.
5859 auto AssignCallsiteCloneToFuncClone = [&](const FuncInfo &FuncClone,
5860 CallInfo &Call,
5861 ContextNode *CallsiteClone,
5862 bool IsAlloc) {
5863 // Record the clone of callsite node assigned to this function clone.
5864 FuncCloneToCurNodeCloneMap[FuncClone] = CallsiteClone;
5865
5866 assert(FuncCloneInfos.size() > FuncClone.cloneNo());
5867 DenseMap<CallInfo, CallInfo> &CallMap =
5868 FuncCloneInfos[FuncClone.cloneNo()].CallMap;
5869 CallInfo CallClone(Call);
5870 if (auto It = CallMap.find(Call); It != CallMap.end())
5871 CallClone = It->second;
5872 CallsiteClone->setCall(CallClone);
5873 // Need to do the same for all matching calls. Rebuild the list of
5874 // CallsiteClone from the original matching calls (it may have been
5875 // copied from a node whose calls were already remapped), using the
5876 // same mapping as for Call.
5877 assert(OrigNodeToOrigCalls.count(Node));
5878 CallsiteClone->MatchingCalls.clear();
5879 for (const CallInfo &OrigMatchingCall :
5880 OrigNodeToOrigCalls[Node].MatchingCalls) {
5881 CallInfo CallClone(OrigMatchingCall);
5882 if (auto It = CallMap.find(OrigMatchingCall); It != CallMap.end())
5883 CallClone = It->second;
5884 CallsiteClone->MatchingCalls.push_back(CallClone);
5885 }
5886 };
5887
5888 // Invokes moveEdgeToNewCalleeClone which creates a new clone, and then
5889 // performs the necessary fixups (removing none type edges, and
5890 // importantly, propagating any function call assignment of the original
5891 // node to the new clone).
5892 auto MoveEdgeToNewCalleeCloneAndSetUp =
5893 [&](const std::shared_ptr<ContextEdge> &Edge) {
5894 ContextNode *OrigCallee = Edge->Callee;
5895 ContextNode *NewClone = moveEdgeToNewCalleeClone(Edge);
5896 removeNoneTypeCalleeEdges(NewClone);
5897 assert(NewClone->AllocTypes != (uint8_t)AllocationType::None);
5898 // If the original Callee was already assigned to call a specific
5899 // function version, make sure its new clone is assigned to call
5900 // that same function clone.
5901 if (CallsiteToCalleeFuncCloneMap.count(OrigCallee))
5902 RecordCalleeFuncOfCallsite(
5903 NewClone, CallsiteToCalleeFuncCloneMap[OrigCallee]);
5904 return NewClone;
5905 };
5906
5907 // Keep track of the clones of callsite Node that need to be assigned to
5908 // function clones. This list may be expanded in the loop body below if we
5909 // find additional cloning is required.
5910 std::deque<ContextNode *> ClonesWorklist;
5911 // Ignore original Node if we moved all of its contexts to clones.
5912 if (!Node->emptyContextIds())
5913 ClonesWorklist.push_back(Node);
5914 llvm::append_range(ClonesWorklist, Node->Clones);
5915
5916 // Now walk through all of the clones of this callsite Node that we need,
5917 // and determine the assignment to a corresponding clone of the current
5918 // function (creating new function clones as needed).
5919 unsigned NodeCloneCount = 0;
5920 while (!ClonesWorklist.empty()) {
5921 ContextNode *Clone = ClonesWorklist.front();
5922 ClonesWorklist.pop_front();
5923 NodeCloneCount++;
5924 if (VerifyNodes)
5926
5927 // Need to create a new function clone if we have more callsite clones
5928 // than existing function clones, which would have been assigned to an
5929 // earlier clone in the list (we assign callsite clones to function
5930 // clones greedily).
5931 if (FuncCloneInfos.size() < NodeCloneCount) {
5932 // If this is the first callsite copy, assign to original function.
5933 if (NodeCloneCount == 1) {
5934 // Since FuncCloneInfos is empty in this case, no clones have
5935 // been created for this function yet, and no callers should have
5936 // been assigned a function clone for this callee node yet.
5938 Clone->CallerEdges, [&](const std::shared_ptr<ContextEdge> &E) {
5939 return CallsiteToCalleeFuncCloneMap.count(E->Caller);
5940 }));
5941 // Initialize with empty call map, assign Clone to original function
5942 // and its callers, and skip to the next clone.
5943 FuncCloneInfos.push_back(
5944 {OrigFunc, DenseMap<CallInfo, CallInfo>()});
5945 FuncCloneParent.push_back(0);
5946 AssignCallsiteCloneToFuncClone(
5947 OrigFunc, Call, Clone,
5948 AllocationCallToContextNodeMap.count(Call));
5949 for (auto &CE : Clone->CallerEdges) {
5950 // Ignore any caller that does not have a recorded callsite Call.
5951 if (!CE->Caller->hasCall())
5952 continue;
5953 RecordCalleeFuncOfCallsite(CE->Caller, OrigFunc);
5954 }
5955 continue;
5956 }
5957
5958 // First locate which copy of OrigFunc to clone again. If a caller
5959 // of this callsite clone was already assigned to call a particular
5960 // function clone, we need to redirect all of those callers to the
5961 // new function clone, and update their other callees within this
5962 // function.
5963 FuncInfo PreviousAssignedFuncClone;
5964 auto EI = llvm::find_if(
5965 Clone->CallerEdges, [&](const std::shared_ptr<ContextEdge> &E) {
5966 return CallsiteToCalleeFuncCloneMap.count(E->Caller);
5967 });
5968 bool CallerAssignedToCloneOfFunc = false;
5969 if (EI != Clone->CallerEdges.end()) {
5970 const std::shared_ptr<ContextEdge> &Edge = *EI;
5971 PreviousAssignedFuncClone =
5972 CallsiteToCalleeFuncCloneMap[Edge->Caller];
5973 CallerAssignedToCloneOfFunc = true;
5974 }
5975
5976 // Clone function and save it along with the CallInfo map created
5977 // during cloning in the FuncCloneInfos.
5978 DenseMap<CallInfo, CallInfo> NewCallMap;
5979 unsigned CloneNo = FuncCloneInfos.size();
5980 assert(CloneNo > 0 && "Clone 0 is the original function, which "
5981 "should already exist in the map");
5982 FuncInfo NewFuncClone = cloneFunctionForCallsite(
5983 OrigFunc, Call, NewCallMap, CallsWithMetadata, CloneNo);
5984 FuncCloneInfos.push_back({NewFuncClone, std::move(NewCallMap)});
5985 // Record the function clone it is derived from (if any), whose
5986 // callers it will take over below.
5987 FuncCloneParent.push_back(CallerAssignedToCloneOfFunc
5988 ? PreviousAssignedFuncClone.cloneNo()
5989 : 0);
5990 FunctionClonesAnalysis++;
5991 Changed = true;
5992
5993 // If no caller callsites were already assigned to a clone of this
5994 // function, we can simply assign this clone to the new func clone
5995 // and update all callers to it, then skip to the next clone.
5996 if (!CallerAssignedToCloneOfFunc) {
5997 AssignCallsiteCloneToFuncClone(
5998 NewFuncClone, Call, Clone,
5999 AllocationCallToContextNodeMap.count(Call));
6000 for (auto &CE : Clone->CallerEdges) {
6001 // Ignore any caller that does not have a recorded callsite Call.
6002 if (!CE->Caller->hasCall())
6003 continue;
6004 RecordCalleeFuncOfCallsite(CE->Caller, NewFuncClone);
6005 }
6006 continue;
6007 }
6008
6009 // We may need to do additional node cloning in this case.
6010 // Reset the CallsiteToCalleeFuncCloneMap entry for any callers
6011 // that were previously assigned to call PreviousAssignedFuncClone,
6012 // to record that they now call NewFuncClone.
6013 // The none type edge removal may remove some of this Clone's caller
6014 // edges, if it is reached via another of its caller's callees.
6015 // Iterate over a copy and skip any that were removed.
6016 auto CallerEdges = Clone->CallerEdges;
6017 for (auto CE : CallerEdges) {
6018 // Skip any that have been removed on an earlier iteration.
6019 if (CE->isRemoved()) {
6020 assert(!is_contained(Clone->CallerEdges, CE));
6021 continue;
6022 }
6023 assert(CE);
6024 // Ignore any caller that does not have a recorded callsite Call.
6025 if (!CE->Caller->hasCall())
6026 continue;
6027
6028 if (!CallsiteToCalleeFuncCloneMap.count(CE->Caller) ||
6029 // We subsequently fall through to later handling that
6030 // will perform any additional cloning required for
6031 // callers that were calling other function clones.
6032 CallsiteToCalleeFuncCloneMap[CE->Caller] !=
6033 PreviousAssignedFuncClone)
6034 continue;
6035
6036 RecordCalleeFuncOfCallsite(CE->Caller, NewFuncClone);
6037
6038 // If we are cloning a function that was already assigned to some
6039 // callers, then essentially we are creating new callsite clones
6040 // of the other callsites in that function that are reached by those
6041 // callers. Clone the other callees of the current callsite's caller
6042 // that were already assigned to PreviousAssignedFuncClone
6043 // accordingly. This is important since we subsequently update the
6044 // calls from the nodes in the graph and their assignments to callee
6045 // functions recorded in CallsiteToCalleeFuncCloneMap.
6046 // The none type edge removal may remove some of this caller's
6047 // callee edges, if it is reached via another of its callees.
6048 // Iterate over a copy and skip any that were removed.
6049 auto CalleeEdges = CE->Caller->CalleeEdges;
6050 for (auto CalleeEdge : CalleeEdges) {
6051 // Skip any that have been removed on an earlier iteration when
6052 // cleaning up newly None type callee edges.
6053 if (CalleeEdge->isRemoved()) {
6054 assert(!is_contained(CE->Caller->CalleeEdges, CalleeEdge));
6055 continue;
6056 }
6057 assert(CalleeEdge);
6058 ContextNode *Callee = CalleeEdge->Callee;
6059 // Skip the current callsite, we are looking for other
6060 // callsites Caller calls, as well as any that does not have a
6061 // recorded callsite Call.
6062 if (Callee == Clone || !Callee->hasCall())
6063 continue;
6064 // Skip direct recursive calls. We don't need/want to clone the
6065 // caller node again, and this loop will not behave as expected if
6066 // we tried.
6067 if (Callee == CalleeEdge->Caller)
6068 continue;
6069 ContextNode *NewClone =
6070 MoveEdgeToNewCalleeCloneAndSetUp(CalleeEdge);
6071 // Moving the edge may have resulted in some none type
6072 // callee edges on the original Callee.
6073 removeNoneTypeCalleeEdges(Callee);
6074 // Update NewClone with the new Call clone of this callsite's Call
6075 // created for the new function clone created earlier.
6076 // Recall that we have already ensured when building the graph
6077 // that each caller can only call callsites within the same
6078 // function, so we are guaranteed that Callee Call is in the
6079 // current OrigFunc.
6080 // CallMap is set up as indexed by original calls at clone 0. Note
6081 // that we cannot simply use the calls recorded on Callee's
6082 // original node, as those are updated to the calls in a function
6083 // clone if the original node was itself assigned to a function
6084 // clone.
6085 assert(OrigNodeToOrigCalls.count(Callee->getOrigNode()));
6086 auto &OrigCalls = OrigNodeToOrigCalls[Callee->getOrigNode()];
6087 DenseMap<CallInfo, CallInfo> &CallMap =
6088 FuncCloneInfos[NewFuncClone.cloneNo()].CallMap;
6089 assert(CallMap.count(OrigCalls.Call));
6090 CallInfo NewCall(CallMap[OrigCalls.Call]);
6091 assert(NewCall);
6092 NewClone->setCall(NewCall);
6093 // Need to do the same for all matching calls.
6094 NewClone->MatchingCalls.clear();
6095 for (auto &OrigMatchingCall : OrigCalls.MatchingCalls) {
6096 assert(CallMap.count(OrigMatchingCall));
6097 CallInfo NewCall(CallMap[OrigMatchingCall]);
6098 assert(NewCall);
6099 NewClone->MatchingCalls.push_back(NewCall);
6100 }
6101 }
6102 }
6103 // Fall through to handling below to perform the recording of the
6104 // function for this callsite clone. This enables handling of cases
6105 // where the callers were assigned to different clones of a function.
6106 }
6107
6108 auto FindFirstAvailFuncClone = [&]() {
6109 // Find first function in FuncCloneInfos without an assigned
6110 // clone of this callsite Node. We should always have one
6111 // available at this point due to the earlier cloning when the
6112 // FuncCloneInfos size was smaller than the clone number.
6113 for (auto &CF : FuncCloneInfos) {
6114 if (!FuncCloneToCurNodeCloneMap.count(CF.FuncClone))
6115 return CF.FuncClone;
6116 }
6118 "Expected an available func clone for this callsite clone");
6119 };
6120
6121 // See if we can use existing function clone. Walk through
6122 // all caller edges to see if any have already been assigned to
6123 // a clone of this callsite's function. If we can use it, do so. If not,
6124 // because that function clone is already assigned to a different clone
6125 // of this callsite, then we need to clone again.
6126 // Basically, this checking is needed to handle the case where different
6127 // caller functions/callsites may need versions of this function
6128 // containing different mixes of callsite clones across the different
6129 // callsites within the function. If that happens, we need to create
6130 // additional function clones to handle the various combinations.
6131 //
6132 // Keep track of any new clones of this callsite created by the
6133 // following loop, as well as any existing clone that we decided to
6134 // assign this clone to.
6135 std::map<FuncInfo, ContextNode *> FuncCloneToNewCallsiteCloneMap;
6136 FuncInfo FuncCloneAssignedToCurCallsiteClone;
6137 // Iterate over a copy of Clone's caller edges, since we may need to
6138 // remove edges in the moveEdgeTo* methods, and this simplifies the
6139 // handling and makes it less error-prone.
6140 auto CloneCallerEdges = Clone->CallerEdges;
6141 for (auto &Edge : CloneCallerEdges) {
6142 // Skip removed edges (due to direct recursive edges updated when
6143 // updating callee edges when moving an edge and subsequently
6144 // removed by call to removeNoneTypeCalleeEdges on the Clone).
6145 if (Edge->isRemoved())
6146 continue;
6147 // Ignore any caller that does not have a recorded callsite Call.
6148 if (!Edge->Caller->hasCall())
6149 continue;
6150 // If this caller already assigned to call a version of OrigFunc, need
6151 // to ensure we can assign this callsite clone to that function clone.
6152 if (CallsiteToCalleeFuncCloneMap.count(Edge->Caller)) {
6153 FuncInfo FuncCloneCalledByCaller =
6154 CallsiteToCalleeFuncCloneMap[Edge->Caller];
6155 // First we need to confirm that this function clone is available
6156 // for use by this callsite node clone.
6157 //
6158 // While FuncCloneToCurNodeCloneMap is built only for this Node and
6159 // its callsite clones, one of those callsite clones X could have
6160 // been assigned to the same function clone called by Edge's caller
6161 // - if Edge's caller calls another callsite within Node's original
6162 // function, and that callsite has another caller reaching clone X.
6163 // We need to clone Node again in this case.
6164 if ((FuncCloneToCurNodeCloneMap.count(FuncCloneCalledByCaller) &&
6165 FuncCloneToCurNodeCloneMap[FuncCloneCalledByCaller] !=
6166 Clone) ||
6167 // Detect when we have multiple callers of this callsite that
6168 // have already been assigned to specific, and different, clones
6169 // of OrigFunc (due to other unrelated callsites in Func they
6170 // reach via call contexts). Is this Clone of callsite Node
6171 // assigned to a different clone of OrigFunc? If so, clone Node
6172 // again.
6173 (FuncCloneAssignedToCurCallsiteClone &&
6174 FuncCloneAssignedToCurCallsiteClone !=
6175 FuncCloneCalledByCaller)) {
6176 // We need to use a different newly created callsite clone, in
6177 // order to assign it to another new function clone on a
6178 // subsequent iteration over the Clones array (adjusted below).
6179 // Note we specifically do not reset the
6180 // CallsiteToCalleeFuncCloneMap entry for this caller, so that
6181 // when this new clone is processed later we know which version of
6182 // the function to copy (so that other callsite clones we have
6183 // assigned to that function clone are properly cloned over). See
6184 // comments in the function cloning handling earlier.
6185
6186 // Check if we already have cloned this callsite again while
6187 // walking through caller edges, for a caller calling the same
6188 // function clone. If so, we can move this edge to that new clone
6189 // rather than creating yet another new clone.
6190 if (FuncCloneToNewCallsiteCloneMap.count(
6191 FuncCloneCalledByCaller)) {
6192 ContextNode *NewClone =
6193 FuncCloneToNewCallsiteCloneMap[FuncCloneCalledByCaller];
6194 moveEdgeToExistingCalleeClone(Edge, NewClone);
6195 // Cleanup any none type edges cloned over.
6196 removeNoneTypeCalleeEdges(NewClone);
6197 } else {
6198 // Create a new callsite clone.
6199 ContextNode *NewClone = MoveEdgeToNewCalleeCloneAndSetUp(Edge);
6200 FuncCloneToNewCallsiteCloneMap[FuncCloneCalledByCaller] =
6201 NewClone;
6202 // Add to list of clones and process later.
6203 ClonesWorklist.push_back(NewClone);
6204 }
6205 // Moving the caller edge may have resulted in some none type
6206 // callee edges.
6207 removeNoneTypeCalleeEdges(Clone);
6208 // We will handle the newly created callsite clone in a subsequent
6209 // iteration over this Node's Clones.
6210 continue;
6211 }
6212
6213 // Otherwise, we can use the function clone already assigned to this
6214 // caller.
6215 if (!FuncCloneAssignedToCurCallsiteClone) {
6216 FuncCloneAssignedToCurCallsiteClone = FuncCloneCalledByCaller;
6217 // Assign Clone to FuncCloneCalledByCaller
6218 AssignCallsiteCloneToFuncClone(
6219 FuncCloneCalledByCaller, Call, Clone,
6220 AllocationCallToContextNodeMap.count(Call));
6221 } else
6222 // Don't need to do anything - callsite is already calling this
6223 // function clone.
6224 assert(FuncCloneAssignedToCurCallsiteClone ==
6225 FuncCloneCalledByCaller);
6226
6227 } else {
6228 // We have not already assigned this caller to a version of
6229 // OrigFunc. Do the assignment now.
6230
6231 // First check if we have already assigned this callsite clone to a
6232 // clone of OrigFunc for another caller during this iteration over
6233 // its caller edges.
6234 if (!FuncCloneAssignedToCurCallsiteClone) {
6235 FuncCloneAssignedToCurCallsiteClone = FindFirstAvailFuncClone();
6236 assert(FuncCloneAssignedToCurCallsiteClone);
6237 // Assign Clone to FuncCloneAssignedToCurCallsiteClone
6238 AssignCallsiteCloneToFuncClone(
6239 FuncCloneAssignedToCurCallsiteClone, Call, Clone,
6240 AllocationCallToContextNodeMap.count(Call));
6241 } else
6242 assert(FuncCloneToCurNodeCloneMap
6243 [FuncCloneAssignedToCurCallsiteClone] == Clone);
6244 // Update callers to record function version called.
6245 RecordCalleeFuncOfCallsite(Edge->Caller,
6246 FuncCloneAssignedToCurCallsiteClone);
6247 }
6248 }
6249 // If we didn't assign a function clone to this callsite clone yet, e.g.
6250 // none of its callers has a non-null call, do the assignment here.
6251 // We want to ensure that every callsite clone is assigned to some
6252 // function clone, so that the call updates below work as expected.
6253 // In particular if this is the original callsite, we want to ensure it
6254 // is assigned to the original function, otherwise the original function
6255 // will appear available for assignment to other callsite clones,
6256 // leading to unintended effects. For one, the unknown and not updated
6257 // callers will call into cloned paths leading to the wrong hints,
6258 // because they still call the original function (clone 0). Also,
6259 // because all callsites start out as being clone 0 by default, we can't
6260 // easily distinguish between callsites explicitly assigned to clone 0
6261 // vs those never assigned, which can lead to multiple updates of the
6262 // calls when invoking updateCall below, with mismatched clone values.
6263 // TODO: Add a flag to the callsite nodes or some other mechanism to
6264 // better distinguish and identify callsite clones that are not getting
6265 // assigned to function clones as expected.
6266 if (!FuncCloneAssignedToCurCallsiteClone) {
6267 FuncCloneAssignedToCurCallsiteClone = FindFirstAvailFuncClone();
6268 assert(FuncCloneAssignedToCurCallsiteClone &&
6269 "No available func clone for this callsite clone");
6270 AssignCallsiteCloneToFuncClone(
6271 FuncCloneAssignedToCurCallsiteClone, Call, Clone,
6272 /*IsAlloc=*/AllocationCallToContextNodeMap.contains(Call));
6273 }
6274 }
6275 assignImplicitCallers(Node, TrimmedContextIds,
6276 CallsiteToCalleeFuncCloneMap,
6277 FuncCloneToCurNodeCloneMap, ImplicitSources);
6278 if (VerifyCCG) {
6280 for (const auto &PE : Node->CalleeEdges)
6282 for (const auto &CE : Node->CallerEdges)
6284 for (auto *Clone : Node->Clones) {
6286 for (const auto &PE : Clone->CalleeEdges)
6288 for (const auto &CE : Clone->CallerEdges)
6290 }
6291 }
6292 }
6293
6295 FuncToNumClones[Func] = std::max<unsigned>(1, FuncCloneInfos.size());
6296 if (FuncCloneInfos.size() < 2)
6297 continue;
6298
6299 // In this case there is more than just the original function copy.
6300 // Record call clones of any callsite nodes in the function that did not
6301 // themselves get cloned for all of the function clones.
6302 for (auto &Call : CallsWithMetadata) {
6303 ContextNode *Node = getNodeForInst(Call);
6304 if (!Node || !Node->hasCall() || Node->emptyContextIds())
6305 continue;
6306 // First collect the function clones that have a clone of this callsite
6307 // node (or the node itself). They may not be sequential due to empty
6308 // clones e.g.
6309 DenseMap<unsigned, const ContextNode *> FuncCloneToNodeClone;
6310 FuncCloneToNodeClone[Node->Call.cloneNo()] = Node;
6311 // A clone left without context ids (its callers were all moved to other
6312 // clones while assigning function clones) has no edges and is not
6313 // reached by the call updates below, so the call in its function clone
6314 // keeps the original callee. If an implicit caller recorded the callsite
6315 // clone that call must follow, treat the function clone as having no
6316 // clone of this node, so that the call follows the recorded source like
6317 // any other call not cloned for its function clone.
6318 for (auto *C : Node->Clones)
6319 if (!C->emptyContextIds() ||
6320 !ImplicitSources.contains({Node, C->Call.cloneNo()}))
6321 FuncCloneToNodeClone[C->Call.cloneNo()] = C;
6322 // If Node has enough clones already to cover all function clones, we can
6323 // skip it.
6324 if (FuncCloneToNodeClone.size() >= FuncCloneInfos.size())
6325 continue;
6326 // Now check all the function clones.
6327 for (auto &FC : FuncCloneInfos) {
6328 unsigned I = FC.FuncClone.cloneNo();
6329 // Skip the first clone which got the original call.
6330 // Also skip any other clones created for this Node.
6331 if (I == 0 || FuncCloneToNodeClone.contains(I)) {
6332 continue;
6333 }
6334 // Record the call clones created for this callsite in this function
6335 // clone, and the callsite node whose callee they should follow: the
6336 // one required by an implicit caller, if any, else the clone of this
6337 // callsite node in the nearest function clone in the chain of function
6338 // clones this one was derived from (null for the original node).
6339 auto &Info = UnassignedCallClones[Node][I];
6340 auto &CallVector = Info.Calls;
6341 for (unsigned P = I;; P = FuncCloneParent[P]) {
6342 if (auto It = ImplicitSources.find({Node, P});
6343 It != ImplicitSources.end()) {
6344 Info.Source = resolveImplicitSource(Node, It->second);
6345 break;
6346 }
6347 if (auto It = FuncCloneToNodeClone.find(P);
6348 It != FuncCloneToNodeClone.end()) {
6349 Info.Source = It->second;
6350 break;
6351 }
6352 if (P == 0)
6353 break;
6354 }
6355 DenseMap<CallInfo, CallInfo> &CallMap = FC.CallMap;
6356 if (auto It = CallMap.find(Call); It != CallMap.end()) {
6357 CallInfo CallClone = It->second;
6358 CallVector.push_back(CallClone);
6359 } else {
6360 // All but the original clone (skipped earlier) should have an entry
6361 // for all calls.
6362 assert(false && "Expected to find call in CallMap");
6363 }
6364 // Need to do the same for all matching calls. Use the original
6365 // matching calls, as those on Node may have been remapped to the calls
6366 // of a function clone if Node was assigned to one.
6367 assert(OrigNodeToOrigCalls.count(Node));
6368 for (const CallInfo &OrigMatchingCall :
6369 OrigNodeToOrigCalls[Node].MatchingCalls) {
6370 if (auto It = CallMap.find(OrigMatchingCall); It != CallMap.end()) {
6371 CallInfo CallClone = It->second;
6372 CallVector.push_back(CallClone);
6373 } else {
6374 // All but the original clone (skipped earlier) should have an entry
6375 // for all calls.
6376 assert(false && "Expected to find call in CallMap");
6377 }
6378 }
6379 }
6380 }
6381 }
6382
6383 uint8_t BothTypes =
6384 (uint8_t)AllocationType::Cold | (uint8_t)AllocationType::NotCold;
6385
6386 auto UpdateCalls = [&](ContextNode *Node,
6387 DenseSet<const ContextNode *> &Visited,
6388 auto &&UpdateCalls) {
6389 auto Inserted = Visited.insert(Node);
6390 if (!Inserted.second)
6391 return;
6392
6393 for (auto *Clone : Node->Clones)
6394 UpdateCalls(Clone, Visited, UpdateCalls);
6395
6396 for (auto &Edge : Node->CallerEdges)
6397 UpdateCalls(Edge->Caller, Visited, UpdateCalls);
6398
6399 // Skip if either no call to update, or if we ended up with no context ids
6400 // (we moved all edges onto other clones).
6401 if (!Node->hasCall() || Node->emptyContextIds())
6402 return;
6403
6404 // Returns the recorded call clones in function clones which don't have a
6405 // clone of this callsite node, along with the node whose decision each
6406 // should follow (the Source recorded earlier, falling back to Node).
6407 auto GetUnassignedCallClones = [&](ContextNode *Node) {
6409 Unassigned;
6410 auto UnassignedIt = UnassignedCallClones.find(Node);
6411 if (UnassignedIt == UnassignedCallClones.end())
6412 return Unassigned;
6413 DenseSet<unsigned> NodeCallClones;
6414 for (auto *C : Node->Clones)
6415 if (!C->emptyContextIds())
6416 NodeCallClones.insert(C->Call.cloneNo());
6417 for (auto &[CloneNo, Info] : UnassignedIt->second) {
6418 // Should start at 1 as we never create an entry for original node.
6419 assert(CloneNo > 0);
6420 // If we subsequently created a clone, skip this one.
6421 if (NodeCallClones.contains(CloneNo))
6422 continue;
6423 Unassigned.push_back({Info.Source ? Info.Source : Node, Info.Calls});
6424 }
6425 return Unassigned;
6426 };
6427
6428 if (Node->IsAllocation) {
6429 auto GetAllocTypeToUse = [&](const ContextNode *Node) {
6430 auto AT = allocTypeToUse(Node->AllocTypes);
6431 // If the allocation type is still ambiguous after cloning, record
6432 // that as the allocation type (the attribute stays "ambiguous") rather
6433 // than falling back to the default not cold, unless ambiguous
6434 // attributes are disabled.
6435 if (Node->AllocTypes == BothTypes && MemProfUseAmbiguousAttributes)
6436 AT = (AllocationType)BothTypes;
6437 // If the allocation type is ambiguous, and more aggressive hinting
6438 // has been enabled via the MinClonedColdBytePercent flag, see if this
6439 // allocation should be hinted cold anyway because its fraction cold
6440 // bytes allocated is at least the given threshold.
6441 if (Node->AllocTypes == BothTypes && MinClonedColdBytePercent < 100 &&
6442 !ContextIdToContextSizeInfos.empty()) {
6443 uint64_t TotalCold = 0;
6444 uint64_t Total = 0;
6445 for (auto Id : Node->getContextIds()) {
6446 auto TypeI = ContextIdToAllocationType.find(Id);
6447 assert(TypeI != ContextIdToAllocationType.end());
6448 auto CSI = ContextIdToContextSizeInfos.find(Id);
6449 if (CSI != ContextIdToContextSizeInfos.end()) {
6450 for (auto &Info : CSI->second) {
6451 Total += Info.TotalSize;
6452 if (TypeI->second == AllocationType::Cold)
6453 TotalCold += Info.TotalSize;
6454 }
6455 }
6456 }
6457 if (TotalCold * 100 >= Total * MinClonedColdBytePercent)
6458 AT = AllocationType::Cold;
6459 }
6460 return AT;
6461 };
6462 updateAllocationCall(Node->Call, GetAllocTypeToUse(Node));
6464 OrigAllocAndCloneToNode[{Node->getOrigNode(), Node->Call.cloneNo()}] =
6465 Node;
6466 assert(Node->MatchingCalls.empty());
6467 // Update the allocation calls in function clones without a clone of this
6468 // node the same way as the node they should follow.
6469 for (auto &[Source, Calls] : GetUnassignedCallClones(Node)) {
6470 auto AT = GetAllocTypeToUse(Source);
6471 for (auto &Call : Calls) {
6472 updateAllocationCall(Call, AT);
6473 // For the report, such an allocation clone follows Source's hint.
6475 OrigAllocAndCloneToNode[{Node->getOrigNode(), Call.cloneNo()}] =
6476 Source;
6477 }
6478 }
6479 return;
6480 }
6481
6482 auto CalleeFuncIt = CallsiteToCalleeFuncCloneMap.find(Node);
6483 if (CalleeFuncIt != CallsiteToCalleeFuncCloneMap.end()) {
6484 auto &CalleeFunc = CalleeFuncIt->second;
6485 updateCall(Node->Call, CalleeFunc);
6487 OrigNodeAndCloneToCalleeClone[{
6488 Node->getOrigNode(), Node->Call.cloneNo()}] = CalleeFunc.cloneNo();
6489 // Update all the matching calls as well.
6490 for (auto &Call : Node->MatchingCalls)
6491 updateCall(Call, CalleeFunc);
6492 }
6493
6494 // Now update all calls recorded earlier that are still in function clones
6495 // which don't have a clone of this callsite node, the same way as the
6496 // node they should follow.
6497 for (auto &[Source, Calls] : GetUnassignedCallClones(Node)) {
6498 auto It = CallsiteToCalleeFuncCloneMap.find(Source);
6499 // Fall back to the original Node's callee function.
6500 if (It == CallsiteToCalleeFuncCloneMap.end())
6501 It = CalleeFuncIt;
6502 if (It == CallsiteToCalleeFuncCloneMap.end())
6503 continue;
6504 for (auto &Call : Calls) {
6505 updateCall(Call, It->second);
6507 OrigNodeAndCloneToCalleeClone[{Node->getOrigNode(), Call.cloneNo()}] =
6508 It->second.cloneNo();
6509 }
6510 }
6511 };
6512
6513 // Performs DFS traversal starting from allocation nodes to update calls to
6514 // reflect cloning decisions recorded earlier. For regular LTO this will
6515 // update the actual calls in the IR to call the appropriate function clone
6516 // (and add attributes to allocation calls), whereas for ThinLTO the decisions
6517 // are recorded in the summary entries.
6518 DenseSet<const ContextNode *> Visited;
6519 for (auto &Entry : AllocationCallToContextNodeMap)
6520 UpdateCalls(Entry.second, Visited, UpdateCalls);
6521
6522 return Changed;
6523}
6524
6525// Compute a SHA1 hash of the callsite and alloc version information of clone I
6526// in the summary, to use in detection of duplicate clones.
6528 SHA1 Hasher;
6529 // Add a record for the callsite or alloc at the given index in the summary,
6530 // with the given version. The index must be included, since two clones that
6531 // assign the same versions to different callsites or allocs are not
6532 // duplicates.
6533 auto AddRecord = [&](char Kind, uint32_t Index, uint32_t Version) {
6534 uint8_t Data[1 + 2 * sizeof(uint32_t)];
6535 Data[0] = Kind;
6536 support::endian::write32le(&Data[1], Index);
6537 support::endian::write32le(&Data[1 + sizeof(uint32_t)], Version);
6538 Hasher.update(Data);
6539 };
6540 // Update hash with any callsites that call non-default (non-zero) callee
6541 // versions.
6542 for (auto [Index, SN] : enumerate(FS->callsites())) {
6543 // In theory all callsites and allocs in this function should have the same
6544 // number of clone entries, but handle any discrepancies gracefully below
6545 // for NDEBUG builds.
6546 assert(
6547 SN.Clones.size() > I &&
6548 "Callsite summary has fewer entries than other summaries in function");
6549 if (SN.Clones.size() <= I || !SN.Clones[I])
6550 continue;
6551 AddRecord('c', Index, SN.Clones[I]);
6552 }
6553 // Update hash with any allocs that have non-default (non-None) hints.
6554 for (auto [Index, AN] : enumerate(FS->allocs())) {
6555 // In theory all callsites and allocs in this function should have the same
6556 // number of clone entries, but handle any discrepancies gracefully below
6557 // for NDEBUG builds.
6558 assert(AN.Versions.size() > I &&
6559 "Alloc summary has fewer entries than other summaries in function");
6560 if (AN.Versions.size() <= I ||
6561 (AllocationType)AN.Versions[I] == AllocationType::None)
6562 continue;
6563 AddRecord('a', Index, AN.Versions[I]);
6564 }
6565 return support::endian::read64le(Hasher.result().data());
6566}
6567
6568#ifndef NDEBUG
6569// Check that clones I and J of FS have identical callsite and alloc versions.
6570static bool clonesHaveSameVersions(const FunctionSummary *FS, unsigned I,
6571 unsigned J) {
6572 for (auto &SN : FS->callsites()) {
6573 assert(SN.Clones.size() > I && SN.Clones.size() > J &&
6574 "Callsite summary has fewer entries than other summaries in "
6575 "function");
6576 if (SN.Clones[I] != SN.Clones[J])
6577 return false;
6578 }
6579 for (auto &AN : FS->allocs()) {
6580 assert(AN.Versions.size() > I && AN.Versions.size() > J &&
6581 "Alloc summary has fewer entries than other summaries in function");
6582 if (AN.Versions[I] != AN.Versions[J])
6583 return false;
6584 }
6585 return true;
6586}
6587#endif
6588
6590 Function &F, unsigned NumClones, Module &M, OptimizationRemarkEmitter &ORE,
6592 &FuncToAliasMap,
6593 FunctionSummary *FS) {
6594 auto TakeDeclNameAndReplace = [](GlobalValue *DeclGV, GlobalValue *NewGV) {
6595 // We might have created this when adjusting callsite in another
6596 // function. It should be a declaration.
6597 assert(DeclGV->isDeclaration());
6598 NewGV->takeName(DeclGV);
6599 DeclGV->replaceAllUsesWith(NewGV);
6600 DeclGV->eraseFromParent();
6601 };
6602
6603 // Handle aliases to this function, and create analogous alias clones to the
6604 // provided clone of this function.
6605 auto CloneFuncAliases = [&](Function *NewF, unsigned I) {
6606 if (!FuncToAliasMap.count(&F))
6607 return;
6608 for (auto *A : FuncToAliasMap[&F]) {
6609 std::string AliasName = getMemProfFuncName(A->getName(), I);
6610 auto *PrevA = M.getNamedAlias(AliasName);
6611 auto *NewA = GlobalAlias::create(A->getValueType(),
6612 A->getType()->getPointerAddressSpace(),
6613 A->getLinkage(), AliasName, NewF);
6614 NewA->copyAttributesFrom(A);
6615 if (PrevA)
6616 TakeDeclNameAndReplace(PrevA, NewA);
6617 }
6618 };
6619
6620 // The first "clone" is the original copy, we should only call this if we
6621 // needed to create new clones.
6622 assert(NumClones > 1);
6624 VMaps.reserve(NumClones - 1);
6625 FunctionsClonedThinBackend++;
6626
6627 // Map of hash of callsite/alloc versions to the instantiated function clone
6628 // (possibly the original) implementing those calls and its clone number. Used
6629 // to avoid instantiating duplicate function clones.
6630 // FIXME: Ideally the thin link would not generate such duplicate clones to
6631 // start with, but right now it happens due to phase ordering in the function
6632 // assignment and possible new clones that produces. We simply make each
6633 // duplicate an alias to the matching instantiated clone recorded in the map
6634 // (except for available_externally which are made declarations as they would
6635 // be aliases in the prevailing module, and available_externally aliases are
6636 // not well supported right now).
6638
6639 // Save the hash of the original function version.
6640 HashToFunc[ComputeHash(FS, 0)] = {&F, 0};
6641
6642 for (unsigned I = 1; I < NumClones; I++) {
6643 VMaps.emplace_back(std::make_unique<ValueToValueMapTy>());
6644 std::string Name = getMemProfFuncName(F.getName(), I);
6645 auto Hash = ComputeHash(FS, I);
6646 // If this clone would duplicate a previously seen clone, don't generate the
6647 // duplicate clone body, just make an alias to satisfy any (potentially
6648 // cross-module) references.
6649 if (auto It = HashToFunc.find(Hash); It != HashToFunc.end()) {
6650 FunctionCloneDuplicatesThinBackend++;
6651 auto [Func, OrigI] = It->second;
6652 assert(clonesHaveSameVersions(FS, I, OrigI) &&
6653 "Duplicate clone hash collision");
6654 if (Func->hasAvailableExternallyLinkage()) {
6655 // Skip these as EliminateAvailableExternallyPass does not handle
6656 // available_externally aliases correctly and we end up with an
6657 // available_externally alias to a declaration. Just create a
6658 // declaration for now as we know we will have a definition in another
6659 // module.
6660 auto Decl = M.getOrInsertFunction(Name, Func->getFunctionType());
6661 ORE.emit(OptimizationRemark(DEBUG_TYPE, "MemprofClone", &F)
6662 << "created clone decl " << ore::NV("Decl", Decl.getCallee()));
6663 continue;
6664 }
6665 auto *PrevF = M.getFunction(Name);
6666 auto *Alias = GlobalAlias::create(Name, Func);
6667 if (PrevF)
6668 TakeDeclNameAndReplace(PrevF, Alias);
6669 ORE.emit(OptimizationRemark(DEBUG_TYPE, "MemprofClone", &F)
6670 << "created clone alias " << ore::NV("Alias", Alias));
6671
6672 // Now handle aliases to this function, and clone those as well.
6673 CloneFuncAliases(Func, I);
6674 continue;
6675 }
6676 auto *NewF = CloneFunction(&F, *VMaps.back());
6677 HashToFunc[Hash] = {NewF, I};
6678 FunctionClonesThinBackend++;
6679 // Strip memprof and callsite metadata from clone as they are no longer
6680 // needed.
6681 for (auto &BB : *NewF) {
6682 for (auto &Inst : BB) {
6683 Inst.setMetadata(LLVMContext::MD_memprof, nullptr);
6684 Inst.setMetadata(LLVMContext::MD_callsite, nullptr);
6685 }
6686 }
6687 auto *PrevF = M.getFunction(Name);
6688 if (PrevF)
6689 TakeDeclNameAndReplace(PrevF, NewF);
6690 else
6691 NewF->setName(Name);
6692 updateSubprogramLinkageName(NewF, Name);
6693 ORE.emit(OptimizationRemark(DEBUG_TYPE, "MemprofClone", &F)
6694 << "created clone " << ore::NV("NewFunction", NewF));
6695
6696 // Now handle aliases to this function, and clone those as well.
6697 CloneFuncAliases(NewF, I);
6698 }
6699 return VMaps;
6700}
6701
6702// If F is an imported copy of an alias (materialized as a Function by
6703// replaceAliasWithAliasee during FunctionImport while preserving the aliasee's
6704// !guid metadata for body-level passes), return the original alias GUID
6705// recorded in its thinlto_alias_guid metadata.
6706static std::optional<GlobalValue::GUID>
6708 if (auto *MD = F.getMetadata("thinlto_alias_guid"))
6709 return mdconst::extract<ConstantInt>(MD->getOperand(0))->getZExtValue();
6710 return std::nullopt;
6711}
6712
6713// Locate the summary for GV. This is complicated by the fact that it might
6714// have been internalized, promoted, or imported as a copy of an alias.
6716 const ModuleSummaryIndex *ImportSummary,
6717 const Function *CallingFunc = nullptr) {
6718 if (const auto *F = dyn_cast<Function>(&GV))
6719 if (auto AliasGUID = getImportedAliasGUID(*F)) {
6720 ValueInfo AliasVI = ImportSummary->getValueInfo(*AliasGUID);
6721 assert(AliasVI && "Expected ValueInfo for imported alias GUID");
6722 return AliasVI;
6723 }
6724
6725 // FIXME: Ideally we would retain the original GUID in some fashion on the
6726 // function (e.g. as metadata), but for now do our best to locate the
6727 // summary without that information.
6728 ValueInfo TheFnVI = ImportSummary->getValueInfo(GV.getGUID());
6729 if (!TheFnVI)
6730 // See if GV was internalized, by checking index directly with
6731 // original name (this avoids the name adjustment done by getGUID() for
6732 // internal symbols).
6733 TheFnVI = ImportSummary->getValueInfo(
6735 if (TheFnVI)
6736 return TheFnVI;
6737 // Now query with the original name before any promotion was performed.
6738 StringRef OrigName =
6740 // When this pass is enabled, we always add thinlto_src_file provenance
6741 // metadata to imported function definitions, which allows us to recreate the
6742 // original internal symbol's GUID.
6743 const auto *GO = dyn_cast<GlobalObject>(&GV);
6744 MDNode *SrcFileMD = GO ? GO->getMetadata("thinlto_src_file") : nullptr;
6745 // If this is a call to an imported/promoted local for which we didn't import
6746 // the definition, the metadata will not exist on the declaration. However,
6747 // since we are doing this early, before any inlining in the LTO backend, we
6748 // can simply look at the metadata on the calling function which must have
6749 // been from the same module if GV was an internal symbol originally.
6750 if (!SrcFileMD && GV.isDeclaration()) {
6751 // We would only call this for a declaration for a direct callsite, in which
6752 // case the caller would have provided the calling function pointer.
6753 assert(CallingFunc);
6754 SrcFileMD = CallingFunc->getMetadata("thinlto_src_file");
6755 // If this is a promoted local (OrigName != GV.getName()), since this is a
6756 // declaration, it must be imported from a different module and therefore we
6757 // should always find the metadata on its calling function. Any call to a
6758 // promoted local that came from this module should still be a definition.
6759 assert(SrcFileMD || OrigName == GV.getName());
6760 }
6761 StringRef SrcFile = M.getSourceFileName();
6762 if (SrcFileMD)
6763 SrcFile = dyn_cast<MDString>(SrcFileMD->getOperand(0))->getString();
6764 std::string OrigId = GlobalValue::getGlobalIdentifier(
6765 OrigName, GlobalValue::InternalLinkage, SrcFile);
6766 TheFnVI = ImportSummary->getValueInfo(
6768 // Internal func in original module may have gotten a numbered suffix if we
6769 // imported an external function with the same name. This happens
6770 // automatically during IR linking for naming conflicts. It would have to
6771 // still be internal in that case (otherwise it would have been renamed on
6772 // promotion in which case we wouldn't have a naming conflict).
6773 if (!TheFnVI && OrigName == GV.getName() && GV.hasLocalLinkage() &&
6774 GV.getName().contains('.')) {
6775 OrigName = GV.getName().rsplit('.').first;
6777 OrigName, GlobalValue::InternalLinkage, SrcFile);
6778 TheFnVI = ImportSummary->getValueInfo(
6780 }
6781 // The only way we may not have a VI is if this is a declaration created for
6782 // an imported reference. For distributed ThinLTO we may not have a VI for
6783 // such declarations in the distributed summary.
6784 assert(TheFnVI || GV.isDeclaration());
6785 return TheFnVI;
6786}
6787
6788// Find the CallsiteInfo record synthesized by the thin link for profiled target
6789// CandidateGUID of an indirect tail call, in MapTailCallCalleeVIToCallsite
6790// (which maps each synthesized record's callee to the record). Returns null if
6791// there is none. OrigNameGUIDToTailCallCallsite caches a map from the original
6792// name GUID of each record's callee to the record, and is built on first use
6793// (along with AliasVIToGV, which caches alias ValueInfos in M).
6795 uint64_t CandidateGUID,
6796 const DenseMap<ValueInfo, CallsiteInfo> &MapTailCallCalleeVIToCallsite,
6798 &OrigNameGUIDToTailCallCallsite,
6799 std::optional<DenseMap<ValueInfo, const GlobalAlias *>> &AliasVIToGV,
6800 const Module &M, const ModuleSummaryIndex *ImportSummary,
6801 InstrProfSymtab &Symtab) {
6802 auto End = MapTailCallCalleeVIToCallsite.end();
6803 // The callee of the synthesized record is normally the VP metadata GUID, so
6804 // check that first.
6805 if (ValueInfo VI = ImportSummary->getValueInfo(CandidateGUID)) {
6806 auto It = MapTailCallCalleeVIToCallsite.find(VI);
6807 if (It != End)
6808 return &It->second;
6809 }
6810 // For local targets the VP metadata may contain the GUID of the original
6811 // name without the source file prefix, which the thin link translates to the
6812 // actual GUID of the local function (see updateValueInfoForIndirectCalls).
6813 if (auto LocalGUID = ImportSummary->getGUIDFromOriginalID(CandidateGUID)) {
6814 if (ValueInfo LocalVI = ImportSummary->getValueInfo(LocalGUID)) {
6815 auto It = MapTailCallCalleeVIToCallsite.find(LocalVI);
6816 if (It != End)
6817 return &It->second;
6818 }
6819 }
6820 // The index for a distributed ThinLTO backend does not record the original
6821 // names of local functions, in which case the above lookup via
6822 // getGUIDFromOriginalID fails. Instead, compute the original name GUID of
6823 // each record's callee from its function or alias in this module, using its
6824 // name before any promotion.
6825 if (!OrigNameGUIDToTailCallCallsite) {
6826 // Construct the (initially empty) map so that it is marked as built, even
6827 // if no entries are added below, to avoid rebuilding it on later calls.
6828 OrigNameGUIDToTailCallCallsite.emplace();
6829 for (const auto &[CalleeVI, Callsite] : MapTailCallCalleeVIToCallsite) {
6830 const GlobalValue *Callee = Symtab.getFunction(CalleeVI.getGUID());
6831 if (!Callee) {
6832 // InstrProfSymtab only indexes Functions, not GlobalAliases (imported
6833 // alias copies are materialized as Functions with thinlto_alias_guid
6834 // metadata and are found via Symtab above). Lazily build a module-wide
6835 // map for same-module function GlobalAliases once per module so we can
6836 // recover the alias's pre-promotion name.
6837 if (!AliasVIToGV) {
6838 AliasVIToGV.emplace();
6839 for (const GlobalAlias &A : M.aliases()) {
6840 if (isMemProfClone(A) ||
6841 !isa_and_nonnull<Function>(A.getAliaseeObject()))
6842 continue;
6843 if (ValueInfo VI = findValueInfoForGV(A, M, ImportSummary))
6844 AliasVIToGV->try_emplace(VI, &A);
6845 }
6846 }
6847 Callee = AliasVIToGV->lookup(CalleeVI);
6848 if (!Callee)
6849 continue;
6850 }
6851 StringRef OrigName =
6853 auto [It, Inserted] = OrigNameGUIDToTailCallCallsite->try_emplace(
6854 GlobalValue::getGUIDAssumingExternalLinkage(OrigName), &Callsite);
6855 // If multiple callees have the same original name, we can't tell which
6856 // corresponds to the profiled target.
6857 if (!Inserted && It->second != &Callsite)
6858 It->second = nullptr;
6859 }
6860 }
6861 return OrigNameGUIDToTailCallCallsite->lookup(CandidateGUID);
6862}
6863
6864bool MemProfContextDisambiguation::initializeIndirectCallPromotionInfo(
6865 Module &M) {
6866 ICallAnalysis = std::make_unique<ICallPromotionAnalysis>();
6867 Symtab = std::make_unique<InstrProfSymtab>();
6868 // Don't add canonical names, to avoid multiple functions to the symtab
6869 // when they both have the same root name with "." suffixes stripped.
6870 // If we pick the wrong one then this could lead to incorrect ICP and calling
6871 // a memprof clone that we don't actually create (resulting in linker unsats).
6872 // What this means is that the GUID of the function *must* match that in the
6873 // VP metadata to allow promotion. In practice this should not be a
6874 // limitation, since local functions have a GUID from before they were
6875 // promoted and global function names shouldn't need any special handling
6876 // (they should not get the ".llvm.*" suffix that the canonicalization
6877 // handling is attempting to strip).
6878 // Key imported copies of aliases by the alias's GUID rather than the
6879 // aliasee's GUID retained in their !guid metadata, since we rely on the
6880 // looked up function's name (to compute its original name GUID and the names
6881 // of its clones), and so that they don't shadow the aliasee's own function
6882 // when both are in the module. See AliaseeGUIDToImportedAlias for how
6883 // performICP handles profiled targets that are the aliasee of an imported
6884 // alias copy when the aliasee itself is not in the module.
6885 AliaseeGUIDToImportedAlias.reset();
6886 if (Error E = Symtab->create(M, /*InLTO=*/true, /*AddCanonical=*/false,
6887 /*KeyImportedAliasesByAliasGUID=*/true)) {
6888 std::string SymtabFailure = toString(std::move(E));
6889 M.getContext().emitError("Failed to create symtab: " + SymtabFailure);
6890 return false;
6891 }
6892 return true;
6893}
6894
6895#ifndef NDEBUG
6896// Sanity check that the MIB stack ids match between the summary and
6897// instruction metadata.
6899 const AllocInfo &AllocNode, const MDNode *MemProfMD,
6900 const CallStack<MDNode, MDNode::op_iterator> &CallsiteContext,
6901 const ModuleSummaryIndex *ImportSummary) {
6902 auto MIBIter = AllocNode.MIBs.begin();
6903 for (auto &MDOp : MemProfMD->operands()) {
6904 assert(MIBIter != AllocNode.MIBs.end());
6905 // The combined index may have been written without the MIB contexts (see
6906 // -combined-index-memprof-context, which defaults to false in NDEBUG
6907 // builds), e.g. if the thin link was performed by a release build while
6908 // this backend has assertions enabled. Since the MIB context in the summary
6909 // can never be empty after trimming the allocation's callsite context, an
6910 // empty list means the context was not serialized, and there is nothing to
6911 // check.
6912 if (MIBIter->StackIdIndices.empty()) {
6913 MIBIter++;
6914 continue;
6915 }
6916 auto StackIdIndexIter = MIBIter->StackIdIndices.begin();
6917 auto *MIBMD = cast<const MDNode>(MDOp);
6918 MDNode *StackMDNode = getMIBStackNode(MIBMD);
6919 assert(StackMDNode);
6920 CallStack<MDNode, MDNode::op_iterator> StackContext(StackMDNode);
6921 auto ContextIterBegin =
6922 StackContext.beginAfterSharedPrefix(CallsiteContext);
6923 // Skip the checking on the first iteration.
6924 uint64_t LastStackContextId =
6925 (ContextIterBegin != StackContext.end() && *ContextIterBegin == 0) ? 1
6926 : 0;
6927 for (auto ContextIter = ContextIterBegin; ContextIter != StackContext.end();
6928 ++ContextIter) {
6929 // If this is a direct recursion, simply skip the duplicate
6930 // entries, to be consistent with how the summary ids were
6931 // generated during ModuleSummaryAnalysis.
6932 if (LastStackContextId == *ContextIter)
6933 continue;
6934 LastStackContextId = *ContextIter;
6935 assert(StackIdIndexIter != MIBIter->StackIdIndices.end());
6936 assert(ImportSummary->getStackIdAtIndex(*StackIdIndexIter) ==
6937 *ContextIter);
6938 StackIdIndexIter++;
6939 }
6940 MIBIter++;
6941 }
6942}
6943#endif
6944
6945bool MemProfContextDisambiguation::applyImport(Module &M) {
6946 assert(ImportSummary);
6947 bool Changed = false;
6948
6949 // We also need to clone any aliases that reference cloned functions, because
6950 // the modified callsites may invoke via the alias. Keep track of the aliases
6951 // for each function.
6952 std::map<const Function *, SmallPtrSet<const GlobalAlias *, 1>>
6953 FuncToAliasMap;
6954 for (auto &A : M.aliases()) {
6955 auto *Aliasee = A.getAliaseeObject();
6956 if (auto *F = dyn_cast<Function>(Aliasee))
6957 FuncToAliasMap[F].insert(&A);
6958 }
6959
6960 if (!initializeIndirectCallPromotionInfo(M))
6961 return false;
6962
6963 // Lazily populated map from alias ValueInfo to the corresponding same-module
6964 // GlobalAlias, used by findIndirectTailCallCallsite when a local alias target
6965 // is not in Symtab.
6966 std::optional<DenseMap<ValueInfo, const GlobalAlias *>> AliasVIToGV;
6967
6968 for (auto &F : M) {
6969 if (F.isDeclaration() || isMemProfClone(F))
6970 continue;
6971
6972 OptimizationRemarkEmitter ORE(&F);
6973
6975 bool ClonesCreated = false;
6976 unsigned NumClonesCreated = 0;
6977 auto CloneFuncIfNeeded = [&](unsigned NumClones, FunctionSummary *FS) {
6978 // We should at least have version 0 which is the original copy.
6979 assert(NumClones > 0);
6980 // If only one copy needed use original.
6981 if (NumClones == 1)
6982 return;
6983 // If we already performed cloning of this function, confirm that the
6984 // requested number of clones matches (the thin link should ensure the
6985 // number of clones for each constituent callsite is consistent within
6986 // each function), before returning.
6987 if (ClonesCreated) {
6988 assert(NumClonesCreated == NumClones);
6989 return;
6990 }
6991 VMaps = createFunctionClones(F, NumClones, M, ORE, FuncToAliasMap, FS);
6992 // The first "clone" is the original copy, which doesn't have a VMap.
6993 assert(VMaps.size() == NumClones - 1);
6994 Changed = true;
6995 ClonesCreated = true;
6996 NumClonesCreated = NumClones;
6997 };
6998
6999 auto CloneCallsite = [&](const CallsiteInfo &StackNode, CallBase *CB,
7000 Function *CalledFunction, FunctionSummary *FS) {
7001 // Perform cloning if not yet done.
7002 CloneFuncIfNeeded(/*NumClones=*/StackNode.Clones.size(), FS);
7003
7004 assert(!isMemProfClone(*CalledFunction));
7005
7006 // Because we update the cloned calls by calling setCalledOperand (see
7007 // comment below), out of an abundance of caution make sure the called
7008 // function was actually the called operand (or its aliasee). We also
7009 // strip pointer casts when looking for calls (to match behavior during
7010 // summary generation), however, with opaque pointers in theory this
7011 // should not be an issue. Note we still clone the current function
7012 // (containing this call) above, as that could be needed for its callers.
7013 auto *GA = dyn_cast_or_null<GlobalAlias>(CB->getCalledOperand());
7014 if (CalledFunction != CB->getCalledOperand() &&
7015 (!GA || CalledFunction != GA->getAliaseeObject())) {
7016 SkippedCallsCloning++;
7017 return;
7018 }
7019 // Update the calls per the summary info.
7020 // Save orig name since it gets updated in the first iteration
7021 // below.
7022 auto CalleeOrigName = CalledFunction->getName();
7023 for (unsigned J = 0; J < StackNode.Clones.size(); J++) {
7024 // If the VMap is empty, this clone was a duplicate of another and was
7025 // created as an alias or a declaration.
7026 if (J > 0 && VMaps[J - 1]->empty())
7027 continue;
7028 // Do nothing if this version calls the original version of its
7029 // callee.
7030 if (!StackNode.Clones[J])
7031 continue;
7032 auto NewF = M.getOrInsertFunction(
7033 getMemProfFuncName(CalleeOrigName, StackNode.Clones[J]),
7034 CalledFunction->getFunctionType());
7035 CallBase *CBClone;
7036 // Copy 0 is the original function.
7037 if (!J)
7038 CBClone = CB;
7039 else
7040 CBClone = cast<CallBase>((*VMaps[J - 1])[CB]);
7041 // Set the called operand directly instead of calling setCalledFunction,
7042 // as the latter mutates the function type on the call. In rare cases
7043 // we may have a slightly different type on a callee function
7044 // declaration due to it being imported from a different module with
7045 // incomplete types. We really just want to change the name of the
7046 // function to the clone, and not make any type changes.
7047 CBClone->setCalledOperand(NewF.getCallee());
7048 ORE.emit(OptimizationRemark(DEBUG_TYPE, "MemprofCall", CBClone)
7049 << ore::NV("Call", CBClone) << " in clone "
7050 << ore::NV("Caller", CBClone->getFunction())
7051 << " assigned to call function clone "
7052 << ore::NV("Callee", NewF.getCallee()));
7053 }
7054 };
7055
7056 // Locate the summary for F.
7057 ValueInfo TheFnVI = findValueInfoForGV(F, M, ImportSummary);
7058 // If not found, this could be an imported local (see comment in
7059 // findValueInfoForGV). Skip for now as it will be cloned in its original
7060 // module (where it would have been promoted to global scope so should
7061 // satisfy any reference in this module).
7062 if (!TheFnVI)
7063 continue;
7064
7065 auto *GVSummary =
7066 ImportSummary->findSummaryInModule(TheFnVI, M.getModuleIdentifier());
7067 if (!GVSummary) {
7068 // Must have been imported, use the summary which matches the definition。
7069 // (might be multiple if this was a linkonce_odr).
7070 auto SrcModuleMD = F.getMetadata("thinlto_src_module");
7071 assert(SrcModuleMD &&
7072 "enable-import-metadata is needed to emit thinlto_src_module");
7073 StringRef SrcModule =
7074 dyn_cast<MDString>(SrcModuleMD->getOperand(0))->getString();
7075 for (auto &GVS : TheFnVI.getSummaryList()) {
7076 if (GVS->modulePath() == SrcModule) {
7077 GVSummary = GVS.get();
7078 break;
7079 }
7080 }
7081 assert(GVSummary && GVSummary->modulePath() == SrcModule);
7082 }
7083
7084 // If this was an imported alias skip it as we won't have the function
7085 // summary, and it should be cloned in the original module.
7086 if (isa<AliasSummary>(GVSummary))
7087 continue;
7088
7089 auto *FS = cast<FunctionSummary>(GVSummary->getBaseObject());
7090
7091 if (FS->allocs().empty() && FS->callsites().empty())
7092 continue;
7093
7094 auto SI = FS->callsites().begin();
7095 auto AI = FS->allocs().begin();
7096
7097 // To handle callsite infos synthesized for tail calls which have missing
7098 // frames in the profiled context, map callee VI to the synthesized callsite
7099 // info.
7100 DenseMap<ValueInfo, CallsiteInfo> MapTailCallCalleeVIToCallsite;
7101 // Iterate the callsites for this function in reverse, since we place all
7102 // those synthesized for tail calls at the end.
7103 for (auto CallsiteIt = FS->callsites().rbegin();
7104 CallsiteIt != FS->callsites().rend(); CallsiteIt++) {
7105 auto &Callsite = *CallsiteIt;
7106 // Stop as soon as we see a non-synthesized callsite info (see comment
7107 // above loop). All the entries added for discovered tail calls have empty
7108 // stack ids.
7109 if (!Callsite.StackIdIndices.empty())
7110 break;
7111 MapTailCallCalleeVIToCallsite.insert({Callsite.Callee, Callsite});
7112 }
7113 // Maps the original name GUID of each synthesized callsite info's callee to
7114 // the callsite info, built on first use by findIndirectTailCallCallsite.
7115 std::optional<DenseMap<uint64_t, const CallsiteInfo *>>
7116 OrigNameGUIDToTailCallCallsite;
7117
7118 // Keeps track of needed ICP for the function.
7119 SmallVector<ICallAnalysisData> ICallAnalysisInfo;
7120
7121 // Assume for now that the instructions are in the exact same order
7122 // as when the summary was created, but confirm this is correct by
7123 // matching the stack ids.
7124 for (auto &BB : F) {
7125 for (auto &I : BB) {
7126 auto *CB = dyn_cast<CallBase>(&I);
7127 // Same handling as when creating module summary.
7128 if (!mayHaveMemprofSummary(CB))
7129 continue;
7130
7131 auto *CalledValue = CB->getCalledOperand();
7132 auto *CalledFunction = CB->getCalledFunction();
7133 if (CalledValue && !CalledFunction) {
7134 CalledValue = CalledValue->stripPointerCasts();
7135 // Stripping pointer casts can reveal a called function.
7136 CalledFunction = dyn_cast<Function>(CalledValue);
7137 }
7138 // Check if this is an alias to a function. If so, get the
7139 // called aliasee for the checks below.
7140 if (auto *GA = dyn_cast<GlobalAlias>(CalledValue)) {
7141 assert(!CalledFunction &&
7142 "Expected null called function in callsite for alias");
7143 CalledFunction = dyn_cast<Function>(GA->getAliaseeObject());
7144 }
7145
7146 CallStack<MDNode, MDNode::op_iterator> CallsiteContext(
7147 I.getMetadata(LLVMContext::MD_callsite));
7148 auto *MemProfMD = I.getMetadata(LLVMContext::MD_memprof);
7149
7150 // Include allocs that were already assigned a memprof function
7151 // attribute in the statistics. Only do this for those that do not have
7152 // memprof metadata, since we add an "ambiguous" memprof attribute by
7153 // default.
7154 if (CB->getAttributes().hasFnAttr("memprof") && !MemProfMD) {
7155 CB->getAttributes().getFnAttr("memprof").getValueAsString() == "cold"
7156 ? AllocTypeColdThinBackend++
7157 : AllocTypeNotColdThinBackend++;
7158 OrigAllocsThinBackend++;
7159 AllocVersionsThinBackend++;
7160 if (!MaxAllocVersionsThinBackend)
7161 MaxAllocVersionsThinBackend = 1;
7162 continue;
7163 }
7164
7165 if (MemProfMD) {
7166 // Consult the next alloc node.
7167 assert(AI != FS->allocs().end());
7168 auto &AllocNode = *(AI++);
7169
7170#ifndef NDEBUG
7171 checkAllocContextIds(AllocNode, MemProfMD, CallsiteContext,
7172 ImportSummary);
7173#endif
7174
7175 // Perform cloning if not yet done.
7176 CloneFuncIfNeeded(/*NumClones=*/AllocNode.Versions.size(), FS);
7177
7178 OrigAllocsThinBackend++;
7179 AllocVersionsThinBackend += AllocNode.Versions.size();
7180 if (MaxAllocVersionsThinBackend < AllocNode.Versions.size())
7181 MaxAllocVersionsThinBackend = AllocNode.Versions.size();
7182
7183 // If there is only one version that means we didn't end up
7184 // considering this function for cloning. Count that as unclonable
7185 // unless the single version is cold due to the
7186 // MinClonedColdBytePercent heuristic. The alloc may still be none
7187 // type (not reached during whole program analysis), in which case
7188 // there is nothing to apply; otherwise it got the type the whole
7189 // program analysis resolved it to (not cold, or both types when the
7190 // contexts could not be disambiguated), which is applied below like
7191 // for cloned functions so that the attribute matches the regular
7192 // LTO result.
7193 if (AllocNode.Versions.size() == 1 &&
7194 (AllocationType)AllocNode.Versions[0] != AllocationType::Cold)
7195 UnclonableAllocsThinBackend++;
7196
7197 // Update the allocation types per the summary info.
7198 for (unsigned J = 0; J < AllocNode.Versions.size(); J++) {
7199 // If the VMap is empty, this clone was a duplicate of another and
7200 // was created as an alias or a declaration.
7201 if (J > 0 && VMaps[J - 1]->empty())
7202 continue;
7203 // Ignore any that didn't get an assigned allocation type.
7204 if (AllocNode.Versions[J] == (uint8_t)AllocationType::None)
7205 continue;
7206 AllocationType AllocTy = (AllocationType)AllocNode.Versions[J];
7207 // The whole program analysis only records both types when
7208 // ambiguous attributes are enabled; if the backend runs without
7209 // them, fall back to the not cold default.
7210 if (isAmbiguousAllocType((uint8_t)AllocTy) &&
7212 AllocTy = AllocationType::NotCold;
7213 const bool IsAmbiguous = isAmbiguousAllocType((uint8_t)AllocTy);
7214 if (AllocTy == AllocationType::Cold)
7215 AllocTypeColdThinBackend++;
7216 else if (IsAmbiguous)
7217 AllocTypeAmbiguousThinBackend++;
7218 else
7219 AllocTypeNotColdThinBackend++;
7220 std::string AllocTypeString = getAllocTypeAttributeString(AllocTy);
7221 CallBase *CBClone;
7222 // Copy 0 is the original function.
7223 if (!J)
7224 CBClone = CB;
7225 else
7226 // Since VMaps are only created for new clones, we index with
7227 // clone J-1 (J==0 is the original clone and does not have a VMaps
7228 // entry).
7229 CBClone = cast<CallBase>((*VMaps[J - 1])[CB]);
7230 if (IsAmbiguous) {
7231 // The contexts could not be disambiguated: keep (or add) the
7232 // ambiguous attribute from matching instead of a specific type.
7233 addAmbiguousAttribute(CBClone);
7234 } else {
7236 CBClone->addFnAttr(llvm::Attribute::get(F.getContext(), "memprof",
7237 AllocTypeString));
7238 }
7239 ORE.emit(OptimizationRemark(DEBUG_TYPE, "MemprofAttribute", CBClone)
7240 << ore::NV("AllocationCall", CBClone) << " in clone "
7241 << ore::NV("Caller", CBClone->getFunction())
7242 << " marked with memprof allocation attribute "
7243 << ore::NV("Attribute", AllocTypeString));
7244 }
7245 } else if (!CallsiteContext.empty()) {
7246 if (!CalledFunction) {
7247#ifndef NDEBUG
7248 // We should have skipped inline assembly calls.
7249 auto *CI = dyn_cast<CallInst>(CB);
7250 assert(!CI || !CI->isInlineAsm());
7251#endif
7252 // We should have skipped direct calls via a Constant.
7253 assert(CalledValue && !isa<Constant>(CalledValue));
7254
7255 // This is an indirect call, see if we have profile information and
7256 // whether any clones were recorded for the profiled targets (that
7257 // we synthesized CallsiteInfo summary records for when building the
7258 // index). These records are the next ones in the function's
7259 // callsites, one per profiled target.
7260 auto NumClones = recordICPInfo(
7261 CB,
7262 [&](const InstrProfValueData &Candidate) {
7263 assert(SI != FS->callsites().end());
7264#ifndef NDEBUG
7265 auto CalleeValueInfo =
7266 ImportSummary->getValueInfo(Candidate.Value);
7267 auto LocalGUID =
7268 ImportSummary->getGUIDFromOriginalID(Candidate.Value);
7269#endif
7270 // We might not have a ValueInfo if this is a distributed
7271 // ThinLTO backend and decided not to import that function.
7272 // The thin link may also have updated the callee from the
7273 // original name GUID recorded in the VP metadata to the GUID
7274 // of the local target function (see
7275 // updateValueInfoForIndirectCalls).
7276 assert(!CalleeValueInfo || SI->Callee == CalleeValueInfo ||
7277 (SI->Callee && SI->Callee.getGUID() == LocalGUID));
7278 return &*(SI++);
7279 },
7280 ICallAnalysisInfo);
7281
7282 // Perform cloning if not yet done. This is done here in case
7283 // we don't need to do ICP, but might need to clone this
7284 // function as it is the target of other cloned calls.
7285 if (NumClones)
7286 CloneFuncIfNeeded(NumClones, FS);
7287 }
7288
7289 else {
7290 // Consult the next callsite node.
7291 assert(SI != FS->callsites().end());
7292 auto &StackNode = *(SI++);
7293
7294#ifndef NDEBUG
7295 // Sanity check that the stack ids match between the summary and
7296 // instruction metadata.
7297 auto StackIdIndexIter = StackNode.StackIdIndices.begin();
7298 for (auto StackId : CallsiteContext) {
7299 assert(StackIdIndexIter != StackNode.StackIdIndices.end());
7300 assert(ImportSummary->getStackIdAtIndex(*StackIdIndexIter) ==
7301 StackId);
7302 StackIdIndexIter++;
7303 }
7304#endif
7305
7306 CloneCallsite(StackNode, CB, CalledFunction, FS);
7307 }
7308 } else if (CB->isTailCall() && CalledFunction) {
7309 // Locate the synthesized callsite info for the callee VI, if any was
7310 // created, and use that for cloning.
7311 ValueInfo CalleeVI = findValueInfoForGV(
7312 *cast<GlobalValue>(CalledValue), M, ImportSummary, &F);
7313 if (CalleeVI && MapTailCallCalleeVIToCallsite.count(CalleeVI)) {
7314 auto Callsite = MapTailCallCalleeVIToCallsite.find(CalleeVI);
7315 assert(Callsite != MapTailCallCalleeVIToCallsite.end());
7316 CloneCallsite(Callsite->second, CB, CalledFunction, FS);
7317 }
7318 } else if (CB->isTailCall() && !CalledFunction &&
7319 !MapTailCallCalleeVIToCallsite.empty()) {
7320 // An indirect tail call, which the thin link may have identified as
7321 // being on profiled contexts with a missing frame, via the profiled
7322 // targets in its VP metadata. If so, the callsite infos synthesized
7323 // for those targets are used to perform ICP so that each clone of
7324 // this function calls the assigned clone of the target.
7325 auto PrevNumICallAnalysisInfo = ICallAnalysisInfo.size();
7326 auto NumClones = recordICPInfo(
7327 CB,
7328 [&](const InstrProfValueData &Candidate) {
7330 Candidate.Value, MapTailCallCalleeVIToCallsite,
7331 OrigNameGUIDToTailCallCallsite, AliasVIToGV, M,
7332 ImportSummary, *Symtab);
7333 },
7334 ICallAnalysisInfo);
7335 if (ICallAnalysisInfo.size() > PrevNumICallAnalysisInfo)
7336 IndirectTailCallsRecordedForICPThinBackend++;
7337 if (NumClones)
7338 CloneFuncIfNeeded(NumClones, FS);
7339 }
7340 }
7341 }
7342
7343 // Now do any promotion required for cloning.
7344 performICP(M, VMaps, ICallAnalysisInfo, ORE);
7345 }
7346
7347 // We skip some of the functions and instructions above, so remove all the
7348 // metadata in a single sweep here.
7349 for (auto &F : M) {
7350 // We can skip memprof clones because createFunctionClones already strips
7351 // the metadata from the newly created clones.
7352 if (F.isDeclaration() || isMemProfClone(F))
7353 continue;
7354 for (auto &BB : F) {
7355 for (auto &I : BB) {
7356 if (!isa<CallBase>(I))
7357 continue;
7358 I.setMetadata(LLVMContext::MD_memprof, nullptr);
7359 I.setMetadata(LLVMContext::MD_callsite, nullptr);
7360 }
7361 }
7362 }
7363
7364 return Changed;
7365}
7366
7367unsigned MemProfContextDisambiguation::recordICPInfo(
7368 CallBase *CB,
7369 function_ref<const CallsiteInfo *(const InstrProfValueData &)> GetCallsite,
7370 SmallVector<ICallAnalysisData> &ICallAnalysisInfo) {
7371 // First see if we have profile information for this indirect call.
7372 uint32_t NumCandidates;
7373 uint64_t TotalCount;
7374 auto CandidateProfileData =
7375 ICallAnalysis->getPromotionCandidatesForInstruction(
7376 CB, TotalCount, NumCandidates,
7378 if (CandidateProfileData.empty())
7379 return 0;
7380
7381 // Iterate through all of the candidate profiled targets along with the
7382 // CallsiteInfo summary records synthesized for them, and see if any are
7383 // cloned and/or refer to clones.
7384 bool ICPNeeded = false;
7385 unsigned NumClones = 0;
7387 for (const auto &Candidate : CandidateProfileData) {
7388 const CallsiteInfo *Callsite = GetCallsite(Candidate);
7389 Callsites.push_back(Callsite);
7390 if (!Callsite)
7391 continue;
7392 // See if any of the clones of the indirect callsite for this
7393 // profiled target should call a cloned version of the profiled
7394 // target. We only need to do the ICP here if so.
7395 ICPNeeded |= llvm::any_of(Callsite->Clones,
7396 [](unsigned CloneNo) { return CloneNo != 0; });
7397 // Every callsite in the same function should have been cloned the same
7398 // number of times.
7399 assert(!NumClones || NumClones == Callsite->Clones.size());
7400 NumClones = Callsite->Clones.size();
7401 }
7402 if (!ICPNeeded)
7403 return NumClones;
7404 // Save information for ICP, which is performed later to avoid messing up the
7405 // current function traversal.
7406 ICallAnalysisInfo.push_back({CB, CandidateProfileData.vec(), NumCandidates,
7407 TotalCount, NumClones, std::move(Callsites)});
7408 return NumClones;
7409}
7410
7411void MemProfContextDisambiguation::performICP(
7412 Module &M, ArrayRef<std::unique_ptr<ValueToValueMapTy>> VMaps,
7413 ArrayRef<ICallAnalysisData> ICallAnalysisInfo,
7414 OptimizationRemarkEmitter &ORE) {
7415 // Now do any promotion required for cloning. Specifically, for each
7416 // recorded ICP candidate (which was only recorded because one clone of that
7417 // candidate should call a cloned target), we perform ICP (speculative
7418 // devirtualization) for each clone of the callsite, and update its callee
7419 // to the appropriate clone. Note that the ICP compares against the original
7420 // version of the target, which is what is in the vtable.
7421 for (auto &Info : ICallAnalysisInfo) {
7422 auto *CB = Info.CB;
7423 auto TotalCount = Info.TotalCount;
7424 unsigned NumClones = Info.NumClones;
7425 SmallVector<InstrProfValueData, 8> RemainingCandidates;
7426
7427 assert(Info.CandidateProfileData.size() == Info.Callsites.size());
7428 for (unsigned I = 0; I < Info.CandidateProfileData.size(); I++) {
7429 auto &Candidate = Info.CandidateProfileData[I];
7430 const CallsiteInfo *StackNode = Info.Callsites[I];
7431 // All calls in the same function must have the same number of clones.
7432 assert(!StackNode || NumClones == StackNode->Clones.size());
7433
7434 // See if the target is in the module. If it wasn't imported, it is
7435 // possible that this profile could have been collected on a different
7436 // target (or version of the code), and we need to be conservative
7437 // (similar to what is done in the ICP pass).
7438 Function *TargetFunction = Symtab->getFunction(Candidate.Value);
7439 // If not found, try the GUID of the callee recorded in the summary. For
7440 // local targets the VP metadata may contain the GUID of the original
7441 // name without the source file prefix (e.g. if it was synthesized from
7442 // the MemProf profile's callee GUIDs or from a SamplePGO profile), which
7443 // the thin link translates to the actual GUID of the local function
7444 // (see updateValueInfoForIndirectCalls). The latter is recorded in the
7445 // function's !guid metadata, which is preserved across promotion and
7446 // importing, and is added to the Symtab. If there is no summary record,
7447 // the target was not cloned, so we conservatively only promote it if
7448 // found directly via the VP metadata GUID.
7449 if (!TargetFunction && StackNode && StackNode->Callee &&
7450 StackNode->Callee.getGUID() != Candidate.Value)
7451 TargetFunction = Symtab->getFunction(StackNode->Callee.getGUID());
7452 // The target may be the aliasee of an alias imported as a copy of the
7453 // aliasee, without the aliasee itself being imported (e.g. an IRPGO value
7454 // profile records the aliasee for calls through the alias, as the alias
7455 // has no profile data of its own). The Symtab keys such a copy by the
7456 // alias GUID (see initializeIndirectCallPromotionInfo), so look for one
7457 // with the target's GUID as its aliasee GUID. Promoting to the copy is
7458 // correct as it has the same address, and its clones are aliases of the
7459 // aliasee's clones in the defining module.
7460 if (!TargetFunction) {
7461 if (!AliaseeGUIDToImportedAlias) {
7462 AliaseeGUIDToImportedAlias.emplace();
7463 for (Function &Fn : M) {
7464 if (isMemProfClone(Fn) || !getImportedAliasGUID(Fn))
7465 continue;
7466 if (auto AliaseeGUID = Fn.getGUIDIfAssigned())
7467 AliaseeGUIDToImportedAlias->try_emplace(*AliaseeGUID, &Fn);
7468 }
7469 }
7470 TargetFunction = AliaseeGUIDToImportedAlias->lookup(Candidate.Value);
7471 if (!TargetFunction && StackNode && StackNode->Callee &&
7472 StackNode->Callee.getGUID() != Candidate.Value)
7473 TargetFunction =
7474 AliaseeGUIDToImportedAlias->lookup(StackNode->Callee.getGUID());
7475 }
7476 if (TargetFunction == nullptr ||
7477 // Any ThinLTO global dead symbol removal should have already
7478 // occurred, so it should be safe to promote when the target is a
7479 // declaration.
7480 // TODO: Remove internal option once more fully tested.
7482 TargetFunction->isDeclaration())) {
7483 ORE.emit([&]() {
7484 return OptimizationRemarkMissed(DEBUG_TYPE, "UnableToFindTarget", CB)
7485 << "Memprof cannot promote indirect call: target with md5sum "
7486 << ore::NV("target md5sum", Candidate.Value) << " not found";
7487 });
7488 // FIXME: See if we can use the new declaration importing support to
7489 // at least get the declarations imported for this case. Hot indirect
7490 // targets should have been imported normally, however.
7491 RemainingCandidates.push_back(Candidate);
7492 continue;
7493 }
7494
7495 // Check if legal to promote
7496 const char *Reason = nullptr;
7497 if (!isLegalToPromote(*CB, TargetFunction, &Reason)) {
7498 ORE.emit([&]() {
7499 return OptimizationRemarkMissed(DEBUG_TYPE, "UnableToPromote", CB)
7500 << "Memprof cannot promote indirect call to "
7501 << ore::NV("TargetFunction", TargetFunction)
7502 << " with count of " << ore::NV("TotalCount", TotalCount)
7503 << ": " << Reason;
7504 });
7505 RemainingCandidates.push_back(Candidate);
7506 continue;
7507 }
7508
7509 assert(!isMemProfClone(*TargetFunction));
7510
7511 // Handle each call clone, applying ICP so that each clone directly
7512 // calls the specified callee clone, guarded by the appropriate ICP
7513 // check.
7514 CallBase *CBClone = CB;
7515 for (unsigned J = 0; J < NumClones; J++) {
7516 // If the VMap is empty, this clone was a duplicate of another and was
7517 // created as an alias or a declaration.
7518 if (J > 0 && VMaps[J - 1]->empty())
7519 continue;
7520 // Copy 0 is the original function.
7521 if (J > 0)
7522 CBClone = cast<CallBase>((*VMaps[J - 1])[CB]);
7523 // We do the promotion using the original name, so that the comparison
7524 // is against the name in the vtable. Then just below, change the new
7525 // direct call to call the cloned function.
7526 auto &DirectCall =
7527 pgo::promoteIndirectCall(*CBClone, TargetFunction, Candidate.Count,
7528 TotalCount, isSamplePGO, &ORE);
7529 auto *TargetToUse = TargetFunction;
7530 // Call original if this version calls the original version of its
7531 // callee (always the case if there is no summary record).
7532 if (StackNode && StackNode->Clones[J]) {
7533 TargetToUse =
7534 cast<Function>(M.getOrInsertFunction(
7535 getMemProfFuncName(TargetFunction->getName(),
7536 StackNode->Clones[J]),
7537 TargetFunction->getFunctionType())
7538 .getCallee());
7539 }
7540 DirectCall.setCalledFunction(TargetToUse);
7541 // During matching we generate synthetic VP metadata for indirect calls
7542 // not already having any, from the memprof profile's callee GUIDs. If
7543 // we subsequently promote and inline those callees, we currently lose
7544 // the ability to generate this synthetic VP metadata. Optionally apply
7545 // a noinline attribute to promoted direct calls, where the threshold is
7546 // set to capture synthetic VP metadata targets which get a count of 1.
7548 Candidate.Count < MemProfICPNoInlineThreshold)
7549 DirectCall.setIsNoInline();
7550 ORE.emit(OptimizationRemark(DEBUG_TYPE, "MemprofCall", CBClone)
7551 << ore::NV("Call", CBClone) << " in clone "
7552 << ore::NV("Caller", CBClone->getFunction())
7553 << " promoted and assigned to call function clone "
7554 << ore::NV("Callee", TargetToUse));
7555 }
7556
7557 // Update TotalCount (all clones should get same count above)
7558 TotalCount -= Candidate.Count;
7559 }
7560 // Adjust the MD.prof metadata for all clones, now that we have the new
7561 // TotalCount and the remaining candidates.
7562 CallBase *CBClone = CB;
7563 for (unsigned J = 0; J < NumClones; J++) {
7564 // If the VMap is empty, this clone was a duplicate of another and was
7565 // created as an alias or a declaration.
7566 if (J > 0 && VMaps[J - 1]->empty())
7567 continue;
7568 // Copy 0 is the original function.
7569 if (J > 0)
7570 CBClone = cast<CallBase>((*VMaps[J - 1])[CB]);
7571 // First delete the old one.
7572 CBClone->setMetadata(LLVMContext::MD_prof, nullptr);
7573 // If all promoted, we don't need the MD.prof metadata.
7574 // Otherwise we need update with the un-promoted records back.
7575 if (TotalCount != 0)
7576 annotateValueSite(M, *CBClone, RemainingCandidates, TotalCount,
7577 IPVK_IndirectCallTarget, Info.NumCandidates);
7578 }
7579 }
7580}
7581
7582template <typename DerivedCCG, typename FuncTy, typename CallTy>
7583bool CallsiteContextGraph<DerivedCCG, FuncTy, CallTy>::process(
7584 function_ref<void(StringRef, StringRef, const Twine &)> EmitRemark,
7585 bool AllowExtraAnalysis) {
7586 if (DumpCCG) {
7587 dbgs() << "CCG before cloning:\n";
7588 dbgs() << *this;
7589 }
7590 if (ExportToDot)
7591 exportToDot("postbuild");
7592
7593 if (VerifyCCG) {
7594 check();
7595 }
7596
7597 // The detail suffix needs the pre-cloning state of each context; only
7598 // capture it (extra memory and time) when it will be printed.
7600 capturePreCloningContextInfo();
7601
7602 identifyClones();
7603
7604 if (VerifyCCG) {
7605 check();
7606 }
7607
7608 if (DumpCCG) {
7609 dbgs() << "CCG after cloning:\n";
7610 dbgs() << *this;
7611 }
7612 if (ExportToDot)
7613 exportToDot("cloned");
7614
7615 bool Changed = assignFunctions();
7616
7617 if (DumpCCG) {
7618 dbgs() << "CCG after assigning function clones:\n";
7619 dbgs() << *this;
7620 }
7621 if (ExportToDot)
7622 exportToDot("clonefuncassign");
7623
7624 // AllowExtraAnalysis is set when the hinted size messages were enabled via
7625 // remarks (-pass-remarks=memprof-context-disambiguation).
7626 // TODO: Consider also supporting the detail suffix for the remark output.
7627 if (MemProfReportHintedSizes || AllowExtraAnalysis) {
7628 // The referenced-function set can be large; build it only now, when it is
7629 // used by the detail suffix, rather than keeping it across cloning.
7631 populateFunctionsWithCallers();
7632 printTotalSizes(errs(), EmitRemark);
7633 }
7634
7635 return Changed;
7636}
7637
7638bool MemProfContextDisambiguation::processModule(
7639 Module &M,
7640 llvm::function_ref<OptimizationRemarkEmitter &(Function *)> OREGetter) {
7641
7642 // If we have an import summary, then the cloning decisions were made during
7643 // the thin link on the index. Apply them and return.
7644 if (ImportSummary)
7645 return applyImport(M);
7646
7647 // TODO: If/when other types of memprof cloning are enabled beyond just for
7648 // hot and cold, we will need to change this to individually control the
7649 // AllocationType passed to addStackNodesForMIB during CCG construction.
7650 // Note that we specifically check this after applying imports above, so that
7651 // the option isn't needed to be passed to distributed ThinLTO backend
7652 // clang processes, which won't necessarily have visibility into the linker
7653 // dependences. Instead the information is communicated from the LTO link to
7654 // the backends via the combined summary index.
7655 if (!SupportsHotColdNew)
7656 return false;
7657
7658 ModuleCallsiteContextGraph CCG(M, OREGetter);
7659 // TODO: Set up remarks for regular LTO. We need to decide what function to
7660 // use in the callback.
7661 return CCG.process();
7662}
7663
7665 const ModuleSummaryIndex *Summary, bool isSamplePGO)
7666 : ImportSummary(Summary), isSamplePGO(isSamplePGO) {
7667 // Check the dot graph printing options once here, to make sure we have valid
7668 // and expected combinations.
7669 if (DotGraphScope == DotScope::Alloc && !AllocIdForDot.getNumOccurrences())
7671 "-memprof-dot-scope=alloc requires -memprof-dot-alloc-id");
7673 !ContextIdForDot.getNumOccurrences())
7675 "-memprof-dot-scope=context requires -memprof-dot-context-id");
7676 if (DotGraphScope == DotScope::All && AllocIdForDot.getNumOccurrences() &&
7677 ContextIdForDot.getNumOccurrences())
7679 "-memprof-dot-scope=all can't have both -memprof-dot-alloc-id and "
7680 "-memprof-dot-context-id");
7681 if (ImportSummary) {
7682 // The MemProfImportSummary should only be used for testing ThinLTO
7683 // distributed backend handling via opt, in which case we don't have a
7684 // summary from the pass pipeline.
7686 return;
7687 }
7688 if (MemProfImportSummary.empty())
7689 return;
7690
7691 auto ReadSummaryFile =
7693 if (!ReadSummaryFile) {
7694 logAllUnhandledErrors(ReadSummaryFile.takeError(), errs(),
7695 "Error loading file '" + MemProfImportSummary +
7696 "': ");
7697 return;
7698 }
7699 auto ImportSummaryForTestingOrErr = getModuleSummaryIndex(**ReadSummaryFile);
7700 if (!ImportSummaryForTestingOrErr) {
7701 logAllUnhandledErrors(ImportSummaryForTestingOrErr.takeError(), errs(),
7702 "Error parsing file '" + MemProfImportSummary +
7703 "': ");
7704 return;
7705 }
7706 ImportSummaryForTesting = std::move(*ImportSummaryForTestingOrErr);
7707 ImportSummary = ImportSummaryForTesting.get();
7708}
7709
7712 auto &FAM = AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
7713 auto OREGetter = [&](Function *F) -> OptimizationRemarkEmitter & {
7714 return FAM.getResult<OptimizationRemarkEmitterAnalysis>(*F);
7715 };
7716 if (!processModule(M, OREGetter))
7717 return PreservedAnalyses::all();
7718 return PreservedAnalyses::none();
7719}
7720
7721// After the thin link cloning decisions have been recorded in the summary
7722// callsite records, mark the summary indirect call edges to any callee that a
7723// callsite was assigned to call a (non-original) clone of as requiring a
7724// declaration import.
7725// See the comments for the MemProfImportClonedIndirectTargets option.
7727 ModuleSummaryIndex &Index,
7729 isPrevailing) {
7730 // Map from callee to the corresponding call edge in the current function
7731 // summary, so that we don't need to walk the function's call edges for each
7732 // callsite assigned to call a cloned callee. Note that there is a single call
7733 // edge per callee. The map is built lazily, the first time we encounter such
7734 // a callsite in a given function summary, since most functions have none
7735 // (the map is cleared before processing each function summary). The
7736 // pointers into the call edge vector remain valid since it isn't modified
7737 // while the map is in use.
7739 for (auto &I : Index) {
7740 auto VI = Index.getValueInfo(I);
7741 for (auto &S : VI.getSummaryList()) {
7742 // Only the prevailing copies were added to the CCG (see the
7743 // IndexCallsiteContextGraph constructor).
7744 if (!GlobalValue::isLocalLinkage(S->linkage()) &&
7745 !isPrevailing(VI.getGUID(), S.get()))
7746 continue;
7747 auto *FS = dyn_cast<FunctionSummary>(S.get());
7748 if (!FS || FS->callsites().empty())
7749 continue;
7750 CalleeToEdge.clear();
7751 for (auto &CI : FS->callsites()) {
7752 if (!CI.Callee || llvm::all_of(CI.Clones, [](unsigned CloneNo) {
7753 return CloneNo == 0;
7754 }))
7755 continue;
7756 // Note that we mark the edge even if the callee is defined in the
7757 // same module as the caller, since the caller may be imported into
7758 // other modules. The function importer will skip importing the callee
7759 // into any module that already defines it.
7760 NumClonedCalleeCallsites++;
7761 // Lazily build the map on the first such callsite in this function.
7762 if (CalleeToEdge.empty())
7763 for (auto &[CalleeVI, Edge] : FS->mutableCalls())
7764 CalleeToEdge[CalleeVI] = &Edge;
7765 auto It = CalleeToEdge.find(CI.Callee);
7766 if (It == CalleeToEdge.end())
7767 continue;
7768 CalleeInfo *Edge = It->second;
7769 // Direct calls don't require importing the callee. Note that the
7770 // edge is marked indirect if any call to the callee in this function
7771 // is indirect, in which case we can't distinguish whether this
7772 // callsite is direct and conservatively treat it as indirect.
7773 if (!Edge->hasIndirectCall())
7774 continue;
7775 NumClonedCalleeIndirectCallsites++;
7776 if (!Edge->requiresDeclImport()) {
7777 Edge->setRequiresDeclImport(true);
7778 NumClonedCalleeEdgesMarkedRequiresDeclImport++;
7779 }
7780 }
7781 }
7782 }
7783}
7784
7786 ModuleSummaryIndex &Index,
7788 isPrevailing,
7789 LLVMContext &Ctx,
7790 function_ref<void(StringRef, StringRef, const Twine &)> EmitRemark) {
7791 // TODO: If/when other types of memprof cloning are enabled beyond just for
7792 // hot and cold, we will need to change this to individually control the
7793 // AllocationType passed to addStackNodesForMIB during CCG construction.
7794 // The index was set from the option, so these should be in sync.
7795 assert(Index.withSupportsHotColdNew() == SupportsHotColdNew);
7796 if (!SupportsHotColdNew)
7797 return;
7798
7799 bool AllowExtraAnalysis =
7801
7802 bool Changed = false;
7803 {
7804 IndexCallsiteContextGraph CCG(Index, isPrevailing);
7805 Changed = CCG.process(EmitRemark, AllowExtraAnalysis);
7806 }
7807 // Note this must be done after the CCG is destroyed, which is when the
7808 // callsite records synthesized for missing tail call frames are added to the
7809 // function summaries. Importing declarations is only useful if MemProf ICP
7810 // is allowed to promote to a declaration of the target.
7813 updateClonedCalleeEdgesForImport(Index, isPrevailing);
7814}
7815
7816// Strips MemProf attributes and metadata. Can be invoked by the pass pipeline
7817// when we don't have an index that has recorded that we are linking with
7818// allocation libraries containing the necessary APIs for downstream
7819// transformations.
7821 // The profile matcher applies hotness attributes directly for allocations,
7822 // and those will cause us to generate calls to the hot/cold interfaces
7823 // unconditionally. If supports-hot-cold-new was not enabled in the LTO
7824 // link then assume we don't want these calls (e.g. not linking with
7825 // the appropriate library, or otherwise trying to disable this behavior).
7826 bool Changed = false;
7827 for (auto &F : M) {
7828 for (auto &BB : F) {
7829 for (auto &I : BB) {
7830 auto *CI = dyn_cast<CallBase>(&I);
7831 if (!CI)
7832 continue;
7833 if (CI->hasFnAttr("memprof")) {
7834 CI->removeFnAttr("memprof");
7835 Changed = true;
7836 }
7837 if (!CI->hasMetadata(LLVMContext::MD_callsite)) {
7838 assert(!CI->hasMetadata(LLVMContext::MD_memprof));
7839 continue;
7840 }
7841 // Strip off all memprof metadata as it is no longer needed.
7842 // Importantly, this avoids the addition of new memprof attributes
7843 // after inlining propagation.
7844 CI->setMetadata(LLVMContext::MD_memprof, nullptr);
7845 CI->setMetadata(LLVMContext::MD_callsite, nullptr);
7846 Changed = true;
7847 }
7848 }
7849 }
7850 if (!Changed)
7851 return PreservedAnalyses::all();
7852 return PreservedAnalyses::none();
7853}
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
uint64_t uint64_t
Unify divergent function exit nodes
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
#define X(NUM, ENUM, NAME)
Definition ELF.h:665
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< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
#define clEnumValN(ENUMVAL, FLAGNAME, DESC)
This file defines the DenseMap class.
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
Machine Check Debug Module
This file implements a map that provides insertion order iteration.
static cl::opt< unsigned > TailCallSearchDepth("memprof-tail-call-search-depth", cl::init(5), cl::Hidden, cl::desc("Max depth to recursively search for missing " "frames through tail calls."))
uint64_t ComputeHash(const FunctionSummary *FS, unsigned I)
static cl::opt< DotScope > DotGraphScope("memprof-dot-scope", cl::desc("Scope of graph to export to dot"), cl::Hidden, cl::init(DotScope::All), cl::values(clEnumValN(DotScope::All, "all", "Export full callsite graph"), clEnumValN(DotScope::Alloc, "alloc", "Export only nodes with contexts feeding given " "-memprof-dot-alloc-id"), clEnumValN(DotScope::Context, "context", "Export only nodes with given -memprof-dot-context-id")))
static cl::opt< bool > DoMergeIteration("memprof-merge-iteration", cl::init(true), cl::Hidden, cl::desc("Iteratively apply merging on a node to catch new callers"))
static cl::opt< unsigned > AllocIdForDot("memprof-dot-alloc-id", cl::init(0), cl::Hidden, cl::desc("Id of alloc to export if -memprof-dot-scope=alloc " "or to highlight if -memprof-dot-scope=all"))
static bool clonesHaveSameVersions(const FunctionSummary *FS, unsigned I, unsigned J)
static std::optional< GlobalValue::GUID > getImportedAliasGUID(const Function &F)
static void updateClonedCalleeEdgesForImport(ModuleSummaryIndex &Index, llvm::function_ref< bool(GlobalValue::GUID, const GlobalValueSummary *)> isPrevailing)
static cl::opt< unsigned > ContextIdForDot("memprof-dot-context-id", cl::init(0), cl::Hidden, cl::desc("Id of context to export if -memprof-dot-scope=context or to " "highlight otherwise"))
static cl::opt< bool > ExportToDot("memprof-export-to-dot", cl::init(false), cl::Hidden, cl::desc("Export graph to dot files."))
static ValueInfo findValueInfoForGV(const GlobalValue &GV, const Module &M, const ModuleSummaryIndex *ImportSummary, const Function *CallingFunc=nullptr)
static void checkEdge(const std::shared_ptr< ContextEdge< DerivedCCG, FuncTy, CallTy > > &Edge)
static cl::opt< bool > AllowRecursiveCallsites("memprof-allow-recursive-callsites", cl::init(true), cl::Hidden, cl::desc("Allow cloning of callsites involved in recursive cycles"))
bool checkColdOrNotCold(uint8_t AllocType)
static cl::opt< bool > CloneRecursiveContexts("memprof-clone-recursive-contexts", cl::init(true), cl::Hidden, cl::desc("Allow cloning of contexts through recursive cycles"))
static std::string getAllocTypeString(uint8_t AllocTypes)
static cl::opt< bool > IndirectTailCallSearch("memprof-indirect-tail-call-search", cl::init(true), cl::Hidden, cl::desc("Search for missing frames through indirect tail calls to their " "profiled targets (ThinLTO)."))
bool DOTGraphTraits< constCallsiteContextGraph< DerivedCCG, FuncTy, CallTy > * >::DoHighlight
static unsigned getMemProfCloneNum(const Function &F)
static cl::opt< unsigned > MemProfICPNoInlineThreshold("memprof-icp-noinline-threshold", cl::init(0), cl::Hidden, cl::desc("Minimum absolute count for promoted target to be inlinable"))
static SmallVector< std::unique_ptr< ValueToValueMapTy >, 4 > createFunctionClones(Function &F, unsigned NumClones, Module &M, OptimizationRemarkEmitter &ORE, std::map< const Function *, SmallPtrSet< const GlobalAlias *, 1 > > &FuncToAliasMap, FunctionSummary *FS)
static cl::opt< bool > VerifyCCG("memprof-verify-ccg", cl::init(false), cl::Hidden, cl::desc("Perform verification checks on CallingContextGraph."))
static void checkNode(const ContextNode< DerivedCCG, FuncTy, CallTy > *Node, bool CheckEdges=true)
static cl::opt< bool > MergeClones("memprof-merge-clones", cl::init(true), cl::Hidden, cl::desc("Merge clones before assigning functions"))
static std::string getMemProfFuncName(Twine Base, unsigned CloneNo)
static cl::opt< std::string > MemProfImportSummary("memprof-import-summary", cl::desc("Import summary to use for testing the ThinLTO backend via opt"), cl::Hidden)
static const CallsiteInfo * findIndirectTailCallCallsite(uint64_t CandidateGUID, const DenseMap< ValueInfo, CallsiteInfo > &MapTailCallCalleeVIToCallsite, std::optional< DenseMap< uint64_t, const CallsiteInfo * > > &OrigNameGUIDToTailCallCallsite, std::optional< DenseMap< ValueInfo, const GlobalAlias * > > &AliasVIToGV, const Module &M, const ModuleSummaryIndex *ImportSummary, InstrProfSymtab &Symtab)
static void updateSubprogramLinkageName(Function *NewFunc, StringRef Name)
static cl::opt< bool > AllowRecursiveContexts("memprof-allow-recursive-contexts", cl::init(true), cl::Hidden, cl::desc("Allow cloning of contexts having recursive cycles"))
static cl::opt< std::string > DotFilePathPrefix("memprof-dot-file-path-prefix", cl::init(""), cl::Hidden, cl::value_desc("filename"), cl::desc("Specify the path prefix of the MemProf dot files."))
static cl::opt< bool > VerifyNodes("memprof-verify-nodes", cl::init(false), cl::Hidden, cl::desc("Perform frequent verification checks on nodes."))
static void checkAllocContextIds(const AllocInfo &AllocNode, const MDNode *MemProfMD, const CallStack< MDNode, MDNode::op_iterator > &CallsiteContext, const ModuleSummaryIndex *ImportSummary)
static cl::opt< bool > DumpCCG("memprof-dump-ccg", cl::init(false), cl::Hidden, cl::desc("Dump CallingContextGraph to stdout after each stage."))
AllocType
This is the interface to build a ModuleSummaryIndex for a module.
ModuleSummaryIndex.h This file contains the declarations the classes that hold the module index and s...
#define P(N)
if(auto Err=PB.parsePassPipeline(MPM, Passes)) return wrap(std MPM run * Mod
FunctionAnalysisManager FAM
if(PassOpts->AAPipeline)
const char * Msg
std::pair< BasicBlock *, BasicBlock * > Edge
This file defines generic set operations that may be used on set's of different types,...
This file defines the SmallPtrSet class.
This file defines the SmallSet class.
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
This file contains some functions that are useful when dealing with strings.
#define LLVM_DEBUG(...)
Definition Debug.h:119
static TableGen::Emitter::Opt Y("gen-skeleton-entry", EmitSkeleton, "Generate example skeleton entry")
ValueInfo getAliaseeVI() const
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
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
static LLVM_ABI Attribute get(LLVMContext &Context, AttrKind Kind, uint64_t Val=0)
Return a uniquified Attribute object.
void addFnAttr(Attribute::AttrKind Kind)
Adds the attribute to the function.
void setCalledOperand(Value *V)
Subprogram description. Uses SubclassData1.
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
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
Definition DenseMap.h:762
bool empty() const
Definition DenseMap.h:716
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:766
ValueT & at(const_arg_type_t< KeyT > Val)
Return the entry for the specified key, or abort if no such entry exists.
Definition DenseMap.h:811
void reserve(size_type NumEntries)
Grow the DenseMap so that it can contain at least NumEntries items before resizing again.
Definition DenseMap.h:721
iterator end()
Definition DenseMap.h:686
unsigned size() const
Definition DenseMap.h:717
bool erase(const KeyT &Val)
Definition DenseMap.h:930
ValueT lookup(const_arg_type_t< KeyT > Val) const
Return the entry for the specified key, or a default constructed value if no such entry exists.
Definition DenseMap.h:793
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
Definition DenseMap.h:827
Implements a dense probed hash-table based set.
Definition DenseSet.h:283
Function summary information to aid decisions and implementation of importing.
FunctionType * getFunctionType() const
Returns the FunctionType for me.
Definition Function.h:212
DISubprogram * getSubprogram() const
Get the attached subprogram.
const Function & getFunction() const
Definition Function.h:167
static LLVM_ABI GlobalAlias * create(Type *Ty, unsigned AddressSpace, LinkageTypes Linkage, const Twine &Name, Constant *Aliasee, Module *Parent)
If a parent module is specified, the alias is automatically inserted into the end of the specified mo...
Definition Globals.cpp:692
Function and variable summary information to aid decisions and implementation of importing.
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
static bool isLocalLinkage(LinkageTypes Linkage)
LLVM_ABI bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition Globals.cpp:408
uint64_t GUID
Declare a type to represent a global unique identifier for a global value.
bool hasLocalLinkage() const
Module * getParent()
Get the module that this global value is contained inside of...
LLVM_ABI void eraseFromParent()
This method unlinks 'this' from the containing module and deletes it.
Definition Globals.cpp:158
LLVM_ABI GUID getGUID() const
Return a 64-bit global unique ID for this value.
Definition Globals.cpp:103
static LLVM_ABI std::string getGlobalIdentifier(StringRef Name, GlobalValue::LinkageTypes Linkage, StringRef FileName)
Return the modified name for a global value suitable to be used as the key for a global lookup (e....
Definition Globals.cpp:234
bool isWeakForLinker() const
@ InternalLinkage
Rename collisions when linking (static functions).
Definition GlobalValue.h:60
A symbol table used for function [IR]PGO name look-up with keys (such as pointers,...
Definition InstrProf.h:500
Function * getFunction(uint64_t FuncMD5Hash) const
Return function from the name's md5 hash. Return nullptr if not found.
Definition InstrProf.h:800
LLVM_ABI const Function * getFunction() const
Return the function this instruction belongs to.
MDNode * getMetadata(unsigned KindID) const
Get the metadata of given kind attached to this Instruction.
LLVM_ABI void setMetadata(unsigned KindID, MDNode *Node)
Set the metadata of the specified kind to the specified node.
This is an important class for using LLVM in a threaded context.
Definition LLVMContext.h:76
Metadata node.
Definition Metadata.h:1081
const MDOperand & getOperand(unsigned I) const
Definition Metadata.h:1437
ArrayRef< MDOperand > operands() const
Definition Metadata.h:1435
unsigned getNumOperands() const
Return number of MDNode operands.
Definition Metadata.h:1443
LLVM_ABI TempMDNode clone() const
Create a (temporary) clone of this.
Definition Metadata.cpp:668
static std::enable_if_t< std::is_base_of< MDNode, T >::value, T * > replaceWithUniqued(std::unique_ptr< T, TempMDNodeDeleter > N)
Replace a temporary node with a uniqued one.
Definition Metadata.h:1312
static LLVM_ABI MDString * get(LLVMContext &Context, StringRef Str)
Definition Metadata.cpp:595
This class implements a map that also provides access to all stored values in a deterministic order.
Definition MapVector.h:39
size_type count(const KeyT &Key) const
Definition MapVector.h:153
LLVM_ABI MemProfContextDisambiguation(const ModuleSummaryIndex *Summary=nullptr, bool isSamplePGO=false)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
LLVM_ABI PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM)
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, bool IsText=false, bool RequiresNullTerminator=true, bool IsVolatile=false, std::optional< Align > Alignment=std::nullopt)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful,...
Class to hold module path string table and global value map, and encapsulate methods for operating on...
static StringRef getOriginalNameBeforePromote(StringRef Name)
Helper to obtain the unpromoted name for a global value (or the original name if not promoted).
ValueInfo getValueInfo(const GlobalValueSummaryMapTy::value_type &R) const
Return a ValueInfo for the index value_type (convenient when iterating index).
uint64_t getStackIdAtIndex(unsigned Index) const
GlobalValue::GUID getGUIDFromOriginalID(GlobalValue::GUID OriginalID) const
Return the GUID for OriginalId in the OidGuidMap.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:68
LLVMContext & getContext() const
Get the global data context.
Definition Module.h:332
A NodeSet contains a set of SUnit DAG nodes with additional information that assigns a priority to th...
unsigned size() const
bool insert(SUnit *SU)
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 discriminated union of two or more pointer types, with the discriminator in the low bits of the poi...
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 class that wrap the SHA1 algorithm.
Definition SHA1.h:27
LLVM_ABI void update(ArrayRef< uint8_t > Data)
Digest more data.
Definition SHA1.cpp:208
LLVM_ABI std::array< uint8_t, 20 > result()
Return the current raw 160-bits SHA1 for the digested data since the last call to init().
Definition SHA1.cpp:288
std::pair< iterator, bool > insert(PtrType Ptr)
Inserts Ptr if and only if there is no element in the container equal to Ptr.
bool contains(ConstPtrType Ptr) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
std::pair< const_iterator, bool > insert(const T &V)
insert - Insert an element into the set if it isn't already there.
Definition SmallSet.h:184
reference emplace_back(ArgTypes &&... Args)
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
bool contains(StringRef Other) const
Return true if the given string is a substring of *this, and false otherwise.
Definition StringRef.h:446
std::pair< StringRef, StringRef > rsplit(StringRef Separator) const
Split into two substrings around the last occurrence of a separator string.
Definition StringRef.h:769
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition Twine.h:82
LLVM_ABI void print(raw_ostream &O, bool IsForDebug=false) const
Implement operator<< on Value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Definition Value.cpp:548
LLVMContext & getContext() const
All values hold a context through their type.
Definition Value.h:260
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
bool contains(const_arg_type_t< ValueT > V) const
Check if the set contains the given element.
Definition DenseSet.h:183
bool erase(const ValueT &V)
Definition DenseSet.h:98
void insert_range(Range &&R)
Definition DenseSet.h:236
size_type size() const
Definition DenseSet.h:85
size_type count(const_arg_type_t< ValueT > V) const
Return 1 if the specified key is in the set, 0 otherwise.
Definition DenseSet.h:188
void reserve(size_t Size)
Grow the DenseSet so that it can contain at least NumEntries items before resizing again.
Definition DenseSet.h:94
An efficient, type-erasing, non-owning reference to a callable.
Helper class to iterate through stack ids in both metadata (memprof MIB and callsite) and the corresp...
CallStackIterator beginAfterSharedPrefix(const CallStack &Other)
CallStackIterator end() const
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
CallInst * Call
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ Entry
Definition COFF.h:862
@ CE
Windows NT (Windows on ARM)
Definition MCAsmInfo.h:51
ValuesClass values(OptsTy... Options)
Helper to build a ValuesClass by forwarding a variable number of arguments as an initializer list to ...
initializer< Ty > init(const Ty &Val)
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > dyn_extract(Y &&MD)
Extract a Value from Metadata, if any.
Definition Metadata.h:707
std::enable_if_t< detail::IsValidPointer< X, Y >::value, X * > extract(Y &&MD)
Extract a Value from Metadata.
Definition Metadata.h:679
LLVM_ABI AllocationType getMIBAllocType(const MDNode *MIB)
Returns the allocation type from an MIB metadata node.
LLVM_ABI bool metadataMayIncludeContextSizeInfo()
Whether the alloc memprof metadata may include context size info for some MIBs (but possibly not all)...
LLVM_ABI bool hasSingleAllocType(uint8_t AllocTypes)
True if the AllocTypes bitmask contains just a single type.
LLVM_ABI bool isAmbiguousAllocType(uint8_t AllocTypes)
True if the AllocTypes bitmask contains both NotCold and Cold, i.e.
LLVM_ABI std::string getAllocTypeAttributeString(AllocationType Type)
Returns the string to use in attributes with the given type.
LLVM_ABI MDNode * getMIBStackNode(const MDNode *MIB)
Returns the stack node from an MIB metadata node.
LLVM_ABI void removeAnyExistingAmbiguousAttribute(CallBase *CB)
Removes any existing "ambiguous" memprof attribute.
LLVM_ABI void addAmbiguousAttribute(CallBase *CB)
Adds an "ambiguous" memprof attribute to call with a matched allocation profile but that we haven't y...
DiagnosticInfoOptimizationBase::Argument NV
LLVM_ABI CallBase & promoteIndirectCall(CallBase &CB, Function *F, uint64_t Count, uint64_t TotalCount, bool AttachProfToDirectCall, OptimizationRemarkEmitter *ORE)
uint32_t NodeId
Definition RDFGraph.h:262
NodeAddr< NodeBase * > Node
Definition RDFGraph.h:381
NodeAddr< FuncNode * > Func
Definition RDFGraph.h:393
bool empty() const
Definition BasicBlock.h:101
friend class Instruction
Iterator for Instructions in a `BasicBlock.
Definition BasicBlock.h:73
uint64_t read64le(const void *P)
Definition Endian.h:415
void write32le(void *P, uint32_t V)
Definition Endian.h:455
This is an optimization pass for GlobalISel generic memory operations.
cl::opt< unsigned > MinClonedColdBytePercent("memprof-cloning-cold-threshold", cl::init(100), cl::Hidden, cl::desc("Min percent of cold bytes to hint alloc cold during cloning"))
auto drop_begin(T &&RangeOrContainer, size_t N=1)
Return a range covering RangeOrContainer with the first N elements excluded.
Definition STLExtras.h:316
void dump(const SparseBitVector< ElementSize > &LHS, raw_ostream &out)
LLVM_ABI void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner={})
Log all errors (if any) in E to OS.
Definition Error.cpp:61
void stable_sort(R &&Range)
Definition STLExtras.h:2132
cl::opt< bool > MemProfReportHintedSizes("memprof-report-hinted-sizes", cl::init(false), cl::Hidden, cl::desc("Report total allocation sizes of hinted allocations"))
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1755
LLVM_ABI bool isLegalToPromote(const CallBase &CB, Function *Callee, const char **FailureReason=nullptr)
Return true if the given indirect call site can be made to call Callee.
Printable print(const GCNRegPressure &RP, const GCNSubtarget *ST=nullptr, unsigned DynamicVGPRBlockSize=0)
cl::opt< bool > MemProfUseAmbiguousAttributes
auto enumerate(FirstRange &&First, RestRanges &&...Rest)
Given two or more input ranges, returns a new range whose values are tuples (A, B,...
Definition STLExtras.h:2570
void set_intersect(S1Ty &S1, const S2Ty &S2)
set_intersect(A, B) - Compute A := A ^ B Identical to set_intersection, except that it works on set<>...
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
LLVM_ABI bool mayHaveMemprofSummary(const CallBase *CB)
Returns true if the instruction could have memprof metadata, used to ensure consistency between summa...
constexpr from_range_t from_range
static cl::opt< bool > MemProfRequireDefinitionForPromotion("memprof-require-definition-for-promotion", cl::init(false), cl::Hidden, cl::desc("Require target function definition when promoting indirect calls"))
auto dyn_cast_if_present(const Y &Val)
dyn_cast_if_present<X> - Functionally identical to dyn_cast, except that a null (or none in the case ...
Definition Casting.h:732
cl::opt< unsigned > MemProfTopNImportant("memprof-top-n-important", cl::init(10), cl::Hidden, cl::desc("Number of largest cold contexts to consider important"))
bool set_is_subset(const S1Ty &S1, const S2Ty &S2)
set_is_subset(A, B) - Return true iff A in B
void append_range(Container &C, Range &&R)
Wrapper function to append range R to container C.
Definition STLExtras.h:2224
static cl::opt< bool > MemProfImportClonedIndirectTargets("memprof-import-cloned-indirect-targets", cl::init(true), cl::Hidden, cl::desc("Import at least a declaration of the indirect call targets of " "callsites assigned to call a cloned callee (needed for MemProf " "ICP in the ThinLTO backend)"))
void set_subtract(S1Ty &S1, const S2Ty &S2)
set_subtract(A, B) - Compute A := A - B
InnerAnalysisManagerProxy< FunctionAnalysisManager, Module > FunctionAnalysisManagerModuleProxy
Provide the FunctionAnalysisManager to Module proxy.
raw_ostream & WriteGraph(raw_ostream &O, const GraphType &G, bool ShortNames=false, const Twine &Title="")
bool isa_and_nonnull(const Y &Val)
Definition Casting.h:676
bool set_intersects(const S1Ty &S1, const S2Ty &S2)
set_intersects(A, B) - Return true iff A ^ B is non empty
detail::concat_range< ValueT, RangeTs... > concat(RangeTs &&...Ranges)
Returns a concatenated range across two or more ranges.
Definition STLExtras.h:1167
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
LLVM_ABI Expected< std::unique_ptr< ModuleSummaryIndex > > getModuleSummaryIndex(MemoryBufferRef Buffer)
Parse the specified bitcode buffer, returning the module summary index.
auto dyn_cast_or_null(const Y &Val)
Definition Casting.h:753
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1762
LLVM_ABI 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...
static cl::opt< bool > MemProfReportHintedSizesDetail("memprof-report-hinted-sizes-detail", cl::init(false), cl::Hidden, cl::desc("Append post-cloning call path and matching details to each " "-memprof-report-hinted-sizes line"))
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition Debug.cpp:209
bool none_of(R &&Range, UnaryPredicate P)
Provide wrappers to std::none_of which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1769
LLVM_ABI void report_fatal_error(Error Err, bool gen_crash_diag=true)
Definition Error.cpp:163
bool set_union(S1Ty &S1, const S2Ty &S2)
set_union(A, B) - Compute A := A u B, return whether A changed.
cl::opt< bool > SupportsHotColdNew
Indicate we are linking with an allocator that supports hot/cold operator new interfaces.
static cl::opt< unsigned > MemProfReportHintedSizesDetailMaxPathLen("memprof-report-hinted-sizes-detail-max-path-len", cl::init(7), cl::Hidden, cl::desc("Maximum number of functions printed in full for a post-cloning " "call path in the -memprof-report-hinted-sizes-detail suffix; " "longer paths are elided in the middle"))
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
Definition Casting.h:547
S1Ty set_intersection(const S1Ty &S1, const S2Ty &S2)
set_intersection(A, B) - Return A ^ B
LLVM_ABI raw_fd_ostream & errs()
This returns a reference to a raw_ostream for standard error.
LLVM_ABI unsigned getMaxSummaryIndirectEdges(const LLVMContext &C)
Return -module-summary-max-indirect-edges.
cl::opt< bool > EnableMemProfContextDisambiguation
Enable MemProf context disambiguation for thin link.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
S1Ty set_difference(const S1Ty &S1, const S2Ty &S2)
set_difference(A, B) - Return A - B
bool isMemProfClone(const GlobalValue &GV)
Returns true if GV is a MemProf context-disambiguated clone.
raw_ostream & operator<<(raw_ostream &OS, const APFixedPoint &FX)
Expected< T > errorOrToExpected(ErrorOr< T > &&EO)
Convert an ErrorOr<T> to an Expected<T>.
Definition Error.h:1261
ArrayRef(const T &OneElt) -> ArrayRef< T >
std::string toString(const APInt &I, unsigned Radix, bool Signed, bool formatAsCLiteral=false, bool UpperCase=true, bool InsertSeparators=false)
ValueMap< const Value *, WeakTrackingVH > ValueToValueMapTy
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1933
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559
auto find_if(R &&Range, UnaryPredicate P)
Provide wrappers to std::find_if which take ranges instead of having to pass begin/end explicitly.
Definition STLExtras.h:1788
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1963
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Next
Definition InstrProf.h:147
constexpr StringLiteral MemProfCloneSuffix
@ End
Run the machine verifier once, at the end of the pipeline.
Definition CodeGen.h:320
LLVM_ABI Function * CloneFunction(Function *F, ValueToValueMapTy &VMap, ClonedCodeInfo *CodeInfo=nullptr)
Return a copy of the specified function and add it to that function's module.
AnalysisManager< Module > ModuleAnalysisManager
Convenience typedef for the Module analysis manager.
Definition MIRParser.h:39
cl::opt< bool > MemProfFixupImportant("memprof-fixup-important", cl::init(true), cl::Hidden, cl::desc("Enables edge fixup for important contexts"))
#define N
static std::string getEdgeAttributes(NodeRef, ChildIteratorType ChildIter, GraphType G)
static const ContextNode< DerivedCCG, FuncTy, CallTy > * GetCallee(const EdgePtrTy &P)
std::unique_ptr< ContextNode< DerivedCCG, FuncTy, CallTy > > NodePtrTy
mapped_iterator< typename std::vector< std::shared_ptr< ContextEdge< DerivedCCG, FuncTy, CallTy > > >::const_iterator, decltype(&GetCallee)> ChildIteratorType
mapped_iterator< typename std::vector< NodePtrTy >::const_iterator, decltype(&getNode)> nodes_iterator
std::shared_ptr< ContextEdge< DerivedCCG, FuncTy, CallTy > > EdgePtrTy
Summary of memprof metadata on allocations.
std::vector< MIBInfo > MIBs
Class to accumulate and hold information about a callee.
Summary of memprof callsite metadata.
SmallVector< unsigned > StackIdIndices
SmallVector< unsigned > Clones
DefaultDOTGraphTraits(bool simple=false)
An information struct used to provide DenseMap with the various necessary components for a given valu...
typename GraphType::UnknownGraphTypeError NodeRef
Definition GraphTraits.h:94
Struct that holds a reference to a particular GUID in a global value summary.
ArrayRef< std::unique_ptr< GlobalValueSummary > > getSummaryList() const
GlobalValue::GUID getGUID() const
PointerUnion< CallsiteInfo *, AllocInfo * > SimpleType
static SimpleType getSimplifiedValue(IndexCall &Val)
const PointerUnion< CallsiteInfo *, AllocInfo * > SimpleType
static SimpleType getSimplifiedValue(const IndexCall &Val)
Define a template that can be specialized by smart pointers to reflect the fact that they are automat...
Definition Casting.h:34