LLVM 17.0.0git
MemoryProfileInfo.h
Go to the documentation of this file.
1//===- llvm/Analysis/MemoryProfileInfo.h - memory profile info ---*- C++ -*-==//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains utilities to analyze memory profile information.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_ANALYSIS_MEMORYPROFILEINFO_H
14#define LLVM_ANALYSIS_MEMORYPROFILEINFO_H
15
16#include "llvm/IR/Constants.h"
17#include "llvm/IR/InstrTypes.h"
18#include "llvm/IR/Metadata.h"
19#include "llvm/IR/Module.h"
21#include <map>
22
23namespace llvm {
24namespace memprof {
25
26/// Return the allocation type for a given set of memory profile values.
27AllocationType getAllocType(uint64_t MaxAccessCount, uint64_t MinSize,
28 uint64_t MinLifetime);
29
30/// Build callstack metadata from the provided list of call stack ids. Returns
31/// the resulting metadata node.
33
34/// Returns the stack node from an MIB metadata node.
35MDNode *getMIBStackNode(const MDNode *MIB);
36
37/// Returns the allocation type from an MIB metadata node.
39
40/// Class to build a trie of call stack contexts for a particular profiled
41/// allocation call, along with their associated allocation types.
42/// The allocation will be at the root of the trie, which is then used to
43/// compute the minimum lists of context ids needed to associate a call context
44/// with a single allocation type.
46private:
47 struct CallStackTrieNode {
48 // Allocation types for call context sharing the context prefix at this
49 // node.
50 uint8_t AllocTypes;
51 // Map of caller stack id to the corresponding child Trie node.
52 std::map<uint64_t, CallStackTrieNode *> Callers;
53 CallStackTrieNode(AllocationType Type)
54 : AllocTypes(static_cast<uint8_t>(Type)) {}
55 };
56
57 // The node for the allocation at the root.
58 CallStackTrieNode *Alloc;
59 // The allocation's leaf stack id.
60 uint64_t AllocStackId;
61
62 void deleteTrieNode(CallStackTrieNode *Node) {
63 if (!Node)
64 return;
65 for (auto C : Node->Callers)
66 deleteTrieNode(C.second);
67 delete Node;
68 }
69
70 // Recursive helper to trim contexts and create metadata nodes.
71 bool buildMIBNodes(CallStackTrieNode *Node, LLVMContext &Ctx,
72 std::vector<uint64_t> &MIBCallStack,
73 std::vector<Metadata *> &MIBNodes,
74 bool CalleeHasAmbiguousCallerContext);
75
76public:
77 CallStackTrie() : Alloc(nullptr), AllocStackId(0) {}
78 ~CallStackTrie() { deleteTrieNode(Alloc); }
79
80 bool empty() const { return Alloc == nullptr; }
81
82 /// Add a call stack context with the given allocation type to the Trie.
83 /// The context is represented by the list of stack ids (computed during
84 /// matching via a debug location hash), expected to be in order from the
85 /// allocation call down to the bottom of the call stack (i.e. callee to
86 /// caller order).
88
89 /// Add the call stack context along with its allocation type from the MIB
90 /// metadata to the Trie.
91 void addCallStack(MDNode *MIB);
92
93 /// Build and attach the minimal necessary MIB metadata. If the alloc has a
94 /// single allocation type, add a function attribute instead. The reason for
95 /// adding an attribute in this case is that it matches how the behavior for
96 /// allocation calls will be communicated to lib call simplification after
97 /// cloning or another optimization to distinguish the allocation types,
98 /// which is lower overhead and more direct than maintaining this metadata.
99 /// Returns true if memprof metadata attached, false if not (attribute added).
101};
102
103/// Helper class to iterate through stack ids in both metadata (memprof MIB and
104/// callsite) and the corresponding ThinLTO summary data structures
105/// (CallsiteInfo and MIBInfo). This simplifies implementation of client code
106/// which doesn't need to worry about whether we are operating with IR (Regular
107/// LTO), or summary (ThinLTO).
108template <class NodeT, class IteratorT> class CallStack {
109public:
110 CallStack(const NodeT *N = nullptr) : N(N) {}
111
112 // Implement minimum required methods for range-based for loop.
113 // The default implementation assumes we are operating on ThinLTO data
114 // structures, which have a vector of StackIdIndices. There are specialized
115 // versions provided to iterate through metadata.
117 const NodeT *N = nullptr;
118 IteratorT Iter;
119 CallStackIterator(const NodeT *N, bool End);
121 bool operator==(const CallStackIterator &rhs) { return Iter == rhs.Iter; }
122 bool operator!=(const CallStackIterator &rhs) { return !(*this == rhs); }
123 void operator++() { ++Iter; }
124 };
125
126 bool empty() const { return N == nullptr; }
127
128 CallStackIterator begin() const;
129 CallStackIterator end() const { return CallStackIterator(N, /*End*/ true); }
130 CallStackIterator beginAfterSharedPrefix(CallStack &Other);
131 uint64_t back() const;
132
133private:
134 const NodeT *N = nullptr;
135};
136
137template <class NodeT, class IteratorT>
139 const NodeT *N, bool End)
140 : N(N) {
141 if (!N) {
142 Iter = nullptr;
143 return;
144 }
145 Iter = End ? N->StackIdIndices.end() : N->StackIdIndices.begin();
146}
147
148template <class NodeT, class IteratorT>
150 assert(Iter != N->StackIdIndices.end());
151 return *Iter;
152}
153
154template <class NodeT, class IteratorT>
156 assert(N);
157 return N->StackIdIndices.back();
158}
159
160template <class NodeT, class IteratorT>
163 return CallStackIterator(N, /*End*/ false);
164}
165
166template <class NodeT, class IteratorT>
169 CallStackIterator Cur = begin();
170 for (CallStackIterator OtherCur = Other.begin();
171 Cur != end() && OtherCur != Other.end(); ++Cur, ++OtherCur)
172 assert(*Cur == *OtherCur);
173 return Cur;
174}
175
176/// Specializations for iterating through IR metadata stack contexts.
177template <>
179 const MDNode *N, bool End);
180template <>
183
184} // end namespace memprof
185} // end namespace llvm
186
187#endif
This file contains the declarations for the subclasses of Constant, which represent the different fla...
AllocType
This file contains the declarations for metadata subclasses.
ModuleSummaryIndex.h This file contains the declarations the classes that hold the module index and s...
Module.h This file contains the declarations for the Module class.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: ArrayRef.h:41
Base class for all callable instructions (InvokeInst and CallInst) Holds everything related to callin...
Definition: InstrTypes.h:1184
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
Metadata node.
Definition: Metadata.h:943
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
Class to build a trie of call stack contexts for a particular profiled allocation call,...
void addCallStack(AllocationType AllocType, ArrayRef< uint64_t > StackIds)
Add a call stack context with the given allocation type to the Trie.
bool buildAndAttachMIBMetadata(CallBase *CI)
Build and attach the minimal necessary MIB metadata.
Helper class to iterate through stack ids in both metadata (memprof MIB and callsite) and the corresp...
CallStack(const NodeT *N=nullptr)
CallStackIterator begin() const
CallStackIterator end() const
CallStackIterator beginAfterSharedPrefix(CallStack &Other)
@ C
The default llvm calling convention, compatible with C.
Definition: CallingConv.h:34
MDNode * buildCallstackMetadata(ArrayRef< uint64_t > CallStack, LLVMContext &Ctx)
Build callstack metadata from the provided list of call stack ids.
AllocationType getMIBAllocType(const MDNode *MIB)
Returns the allocation type from an MIB metadata node.
MDNode * getMIBStackNode(const MDNode *MIB)
Returns the stack node from an MIB metadata node.
AllocationType getAllocType(uint64_t MaxAccessCount, uint64_t MinSize, uint64_t MinLifetime)
Return the allocation type for a given set of memory profile values.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
#define N
bool operator!=(const CallStackIterator &rhs)
bool operator==(const CallStackIterator &rhs)