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