File indexing completed on 2026-05-10 08:44:40
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #ifndef LLVM_TRANSFORMS_IPO_SAMPLECONTEXTTRACKER_H
0016 #define LLVM_TRANSFORMS_IPO_SAMPLECONTEXTTRACKER_H
0017
0018 #include "llvm/ADT/StringRef.h"
0019 #include "llvm/ADT/iterator.h"
0020 #include "llvm/ProfileData/SampleProf.h"
0021 #include <map>
0022 #include <queue>
0023 #include <vector>
0024
0025 namespace llvm {
0026 class CallBase;
0027 class DILocation;
0028 class Function;
0029 class Instruction;
0030
0031
0032
0033
0034 class ContextTrieNode {
0035 public:
0036 ContextTrieNode(ContextTrieNode *Parent = nullptr,
0037 FunctionId FName = FunctionId(),
0038 FunctionSamples *FSamples = nullptr,
0039 LineLocation CallLoc = {0, 0})
0040 : ParentContext(Parent), FuncName(FName), FuncSamples(FSamples),
0041 CallSiteLoc(CallLoc){};
0042 ContextTrieNode *getChildContext(const LineLocation &CallSite,
0043 FunctionId ChildName);
0044 ContextTrieNode *getHottestChildContext(const LineLocation &CallSite);
0045 ContextTrieNode *getOrCreateChildContext(const LineLocation &CallSite,
0046 FunctionId ChildName,
0047 bool AllowCreate = true);
0048 void removeChildContext(const LineLocation &CallSite, FunctionId ChildName);
0049 std::map<uint64_t, ContextTrieNode> &getAllChildContext();
0050 FunctionId getFuncName() const;
0051 FunctionSamples *getFunctionSamples() const;
0052 void setFunctionSamples(FunctionSamples *FSamples);
0053 std::optional<uint32_t> getFunctionSize() const;
0054 void addFunctionSize(uint32_t FSize);
0055 LineLocation getCallSiteLoc() const;
0056 ContextTrieNode *getParentContext() const;
0057 void setParentContext(ContextTrieNode *Parent);
0058 void setCallSiteLoc(const LineLocation &Loc);
0059 void dumpNode();
0060 void dumpTree();
0061
0062 private:
0063
0064 std::map<uint64_t, ContextTrieNode> AllChildContext;
0065
0066
0067 ContextTrieNode *ParentContext;
0068
0069
0070 FunctionId FuncName;
0071
0072
0073 FunctionSamples *FuncSamples;
0074
0075
0076 std::optional<uint32_t> FuncSize;
0077
0078
0079 LineLocation CallSiteLoc;
0080 };
0081
0082
0083
0084
0085
0086
0087
0088
0089 class SampleContextTracker {
0090 public:
0091 using ContextSamplesTy = std::vector<FunctionSamples *>;
0092
0093 SampleContextTracker() = default;
0094 SampleContextTracker(SampleProfileMap &Profiles,
0095 const DenseMap<uint64_t, StringRef> *GUIDToFuncNameMap);
0096
0097 void populateFuncToCtxtMap();
0098
0099
0100 FunctionSamples *getCalleeContextSamplesFor(const CallBase &Inst,
0101 StringRef CalleeName);
0102
0103 std::vector<const FunctionSamples *>
0104 getIndirectCalleeContextSamplesFor(const DILocation *DIL);
0105
0106
0107 FunctionSamples *getContextSamplesFor(const DILocation *DIL);
0108
0109 FunctionSamples *getContextSamplesFor(const SampleContext &Context);
0110
0111 ContextSamplesTy &getAllContextSamplesFor(const Function &Func);
0112 ContextSamplesTy &getAllContextSamplesFor(StringRef Name);
0113 ContextTrieNode *getOrCreateContextPath(const SampleContext &Context,
0114 bool AllowCreate);
0115
0116
0117 FunctionSamples *getBaseSamplesFor(const Function &Func,
0118 bool MergeContext = true);
0119
0120 FunctionSamples *getBaseSamplesFor(FunctionId Name,
0121 bool MergeContext = true);
0122
0123 ContextTrieNode *getContextFor(const SampleContext &Context);
0124
0125 StringRef getFuncNameFor(ContextTrieNode *Node) const;
0126
0127
0128
0129 void markContextSamplesInlined(const FunctionSamples *InlinedSamples);
0130 ContextTrieNode &getRootContext();
0131 void promoteMergeContextSamplesTree(const Instruction &Inst,
0132 FunctionId CalleeName);
0133
0134
0135 void createContextLessProfileMap(SampleProfileMap &ContextLessProfiles);
0136 ContextTrieNode *
0137 getContextNodeForProfile(const FunctionSamples *FSamples) const {
0138 auto I = ProfileToNodeMap.find(FSamples);
0139 if (I == ProfileToNodeMap.end())
0140 return nullptr;
0141 return I->second;
0142 }
0143 HashKeyMap<std::unordered_map, FunctionId, ContextSamplesTy>
0144 &getFuncToCtxtProfiles() {
0145 return FuncToCtxtProfiles;
0146 }
0147
0148 class Iterator : public llvm::iterator_facade_base<
0149 Iterator, std::forward_iterator_tag, ContextTrieNode *,
0150 std::ptrdiff_t, ContextTrieNode **, ContextTrieNode *> {
0151 std::queue<ContextTrieNode *> NodeQueue;
0152
0153 public:
0154 explicit Iterator() = default;
0155 explicit Iterator(ContextTrieNode *Node) { NodeQueue.push(Node); }
0156 Iterator &operator++() {
0157 assert(!NodeQueue.empty() && "Iterator already at the end");
0158 ContextTrieNode *Node = NodeQueue.front();
0159 NodeQueue.pop();
0160 for (auto &It : Node->getAllChildContext())
0161 NodeQueue.push(&It.second);
0162 return *this;
0163 }
0164
0165 bool operator==(const Iterator &Other) const {
0166 if (NodeQueue.empty() && Other.NodeQueue.empty())
0167 return true;
0168 if (NodeQueue.empty() || Other.NodeQueue.empty())
0169 return false;
0170 return NodeQueue.front() == Other.NodeQueue.front();
0171 }
0172
0173 ContextTrieNode *operator*() const {
0174 assert(!NodeQueue.empty() && "Invalid access to end iterator");
0175 return NodeQueue.front();
0176 }
0177 };
0178
0179 Iterator begin() { return Iterator(&RootContext); }
0180 Iterator end() { return Iterator(); }
0181
0182 #ifndef NDEBUG
0183
0184 std::string getContextString(const FunctionSamples &FSamples) const;
0185 std::string getContextString(ContextTrieNode *Node) const;
0186 #endif
0187
0188 void dump();
0189
0190 private:
0191 ContextTrieNode *getContextFor(const DILocation *DIL);
0192 ContextTrieNode *getCalleeContextFor(const DILocation *DIL,
0193 FunctionId CalleeName);
0194 ContextTrieNode *getTopLevelContextNode(FunctionId FName);
0195 ContextTrieNode &addTopLevelContextNode(FunctionId FName);
0196 ContextTrieNode &promoteMergeContextSamplesTree(ContextTrieNode &NodeToPromo);
0197 void mergeContextNode(ContextTrieNode &FromNode, ContextTrieNode &ToNode);
0198 ContextTrieNode &
0199 promoteMergeContextSamplesTree(ContextTrieNode &FromNode,
0200 ContextTrieNode &ToNodeParent);
0201 ContextTrieNode &moveContextSamples(ContextTrieNode &ToNodeParent,
0202 const LineLocation &CallSite,
0203 ContextTrieNode &&NodeToMove);
0204 void setContextNode(const FunctionSamples *FSample, ContextTrieNode *Node) {
0205 ProfileToNodeMap[FSample] = Node;
0206 }
0207
0208 HashKeyMap<std::unordered_map, FunctionId, ContextSamplesTy>
0209 FuncToCtxtProfiles;
0210
0211
0212 std::unordered_map<const FunctionSamples *, ContextTrieNode *>
0213 ProfileToNodeMap;
0214
0215
0216 const DenseMap<uint64_t, StringRef> *GUIDToFuncNameMap;
0217
0218
0219 ContextTrieNode RootContext;
0220 };
0221
0222 }
0223 #endif