LLVM 22.0.0git
SampleProfileMatcher.h
Go to the documentation of this file.
1//===- Transforms/IPO/SampleProfileMatcher.h ----------*- 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/// \file
10/// This file provides the interface for SampleProfileMatcher.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_TRANSFORMS_IPO_SAMPLEPROFILEMATCHER_H
15#define LLVM_TRANSFORMS_IPO_SAMPLEPROFILEMATCHER_H
16
17#include "llvm/ADT/StringSet.h"
19
20#include <unordered_set>
21
22namespace llvm {
23
24using AnchorList = std::vector<std::pair<LineLocation, FunctionId>>;
25using AnchorMap = std::map<LineLocation, FunctionId>;
26
27// Sample profile matching - fuzzy match.
29 Module &M;
30 SampleProfileReader &Reader;
31 LazyCallGraph &CG;
32 const PseudoProbeManager *ProbeManager;
33 const ThinOrFullLTOPhase LTOPhase;
34 SampleProfileMap FlattenedProfiles;
35 // For each function, the matcher generates a map, of which each entry is a
36 // mapping from the source location of current build to the source location
37 // in the profile.
38 StringMap<LocToLocMap> FuncMappings;
39
40 // Match state for an anchor/callsite.
41 enum class MatchState {
42 Unknown = 0,
43 // Initial match between input profile and current IR.
44 InitialMatch = 1,
45 // Initial mismatch between input profile and current IR.
46 InitialMismatch = 2,
47 // InitialMatch stays matched after fuzzy profile matching.
48 UnchangedMatch = 3,
49 // InitialMismatch stays mismatched after fuzzy profile matching.
50 UnchangedMismatch = 4,
51 // InitialMismatch is recovered after fuzzy profile matching.
52 RecoveredMismatch = 5,
53 // InitialMatch is removed and becomes mismatched after fuzzy profile
54 // matching.
55 RemovedMatch = 6,
56 };
57
58 // For each function, store every callsite and its matching state into this
59 // map, of which each entry is a pair of callsite location and MatchState.
60 // This is used for profile staleness computation and report.
62 FuncCallsiteMatchStates;
63
64 struct FuncToProfileNameMapHash {
66 operator()(const std::pair<const Function *, FunctionId> &P) const {
67 return hash_combine(P.first, P.second);
68 }
69 };
70 // A map from a pair of function and profile name to a boolean value
71 // indicating whether they are matched. This is used as a cache for the
72 // matching result.
73 std::unordered_map<std::pair<const Function *, FunctionId>, bool,
74 FuncToProfileNameMapHash>
75 FuncProfileMatchCache;
76 // The new functions found by the call graph matching. The map's key is the
77 // the new(renamed) function pointer and the value is old(unused) profile
78 // name.
79 std::unordered_map<Function *, FunctionId> FuncToProfileNameMap;
80
81 // A map pointer to the FuncNameToProfNameMap in SampleProfileLoader,
82 // which maps the function name to the matched profile name. This is used
83 // for sample loader to look up profile using the new name.
85
86 // A map pointer to the SymbolMap in SampleProfileLoader, which stores all
87 // the original matched symbols before the matching. this is to determine if
88 // the profile is unused(to be matched) or not.
90
91 // The new functions from IR.
93 FunctionsWithoutProfile;
94
95 // Pointer to the Profile Symbol List in the reader.
96 std::shared_ptr<ProfileSymbolList> PSL;
97
98 // Profile mismatch statstics:
99 uint64_t TotalProfiledFunc = 0;
100 // Num of checksum-mismatched function.
101 uint64_t NumStaleProfileFunc = 0;
102 uint64_t TotalProfiledCallsites = 0;
103 uint64_t NumMismatchedCallsites = 0;
104 uint64_t NumRecoveredCallsites = 0;
105 // Total samples for all profiled functions.
106 uint64_t TotalFunctionSamples = 0;
107 // Total samples for all checksum-mismatched functions.
108 uint64_t MismatchedFunctionSamples = 0;
109 uint64_t MismatchedCallsiteSamples = 0;
110 uint64_t RecoveredCallsiteSamples = 0;
111
112 // Profile call-graph matching statstics:
113 uint64_t NumCallGraphRecoveredProfiledFunc = 0;
114 uint64_t NumCallGraphRecoveredFuncSamples = 0;
115
116 // A dummy name for unknown indirect callee, used to differentiate from a
117 // non-call instruction that also has an empty callee name.
118 static constexpr const char *UnknownIndirectCallee =
119 "unknown.indirect.callee";
120
121public:
124 const PseudoProbeManager *ProbeManager, ThinOrFullLTOPhase LTOPhase,
126 std::shared_ptr<ProfileSymbolList> PSL,
128 &FuncNameToProfNameMap)
129 : M(M), Reader(Reader), CG(CG), ProbeManager(ProbeManager),
130 LTOPhase(LTOPhase), FuncNameToProfNameMap(&FuncNameToProfNameMap),
131 SymbolMap(&SymMap), PSL(PSL) {};
132 void runOnModule();
134 // Do not clear FuncMappings, it stores IRLoc to ProfLoc remappings which
135 // will be used for sample loader.
136 // Do not clear FlattenedProfiles as it contains function names referenced
137 // by FuncNameToProfNameMap. Clearing this memory could lead to a
138 // use-after-free error.
139 freeContainer(FuncCallsiteMatchStates);
140 freeContainer(FunctionsWithoutProfile);
141 freeContainer(FuncToProfileNameMap);
142 }
143
144private:
145 FunctionSamples *getFlattenedSamplesFor(const FunctionId &Fname) {
146 auto It = FlattenedProfiles.find(Fname);
147 if (It != FlattenedProfiles.end())
148 return &It->second;
149 return nullptr;
150 }
151 FunctionSamples *getFlattenedSamplesFor(const Function &F) {
152 StringRef CanonFName = FunctionSamples::getCanonicalFnName(F);
153 return getFlattenedSamplesFor(FunctionId(CanonFName));
154 }
155 template <typename T> inline void freeContainer(T &C) {
156 T Empty;
157 std::swap(C, Empty);
158 }
159 void getFilteredAnchorList(const AnchorMap &IRAnchors,
160 const AnchorMap &ProfileAnchors,
161 AnchorList &FilteredIRAnchorsList,
162 AnchorList &FilteredProfileAnchorList);
163 void runOnFunction(Function &F);
164 void findIRAnchors(const Function &F, AnchorMap &IRAnchors) const;
165 void findProfileAnchors(const FunctionSamples &FS,
166 AnchorMap &ProfileAnchors) const;
167 // Record the callsite match states for profile staleness report, the result
168 // is saved in FuncCallsiteMatchStates.
169 void recordCallsiteMatchStates(const Function &F, const AnchorMap &IRAnchors,
170 const AnchorMap &ProfileAnchors,
171 const LocToLocMap *IRToProfileLocationMap);
172
173 bool isMismatchState(const enum MatchState &State) {
174 return State == MatchState::InitialMismatch ||
175 State == MatchState::UnchangedMismatch ||
176 State == MatchState::RemovedMatch;
177 };
178
179 bool isInitialState(const enum MatchState &State) {
180 return State == MatchState::InitialMatch ||
181 State == MatchState::InitialMismatch;
182 };
183
184 bool isFinalState(const enum MatchState &State) {
185 return State == MatchState::UnchangedMatch ||
186 State == MatchState::UnchangedMismatch ||
187 State == MatchState::RecoveredMismatch ||
188 State == MatchState::RemovedMatch;
189 };
190
191 void countCallGraphRecoveredSamples(
192 const FunctionSamples &FS,
193 std::unordered_set<FunctionId> &MatchedUnusedProfile);
194 // Count the samples of checksum mismatched function for the top-level
195 // function and all inlinees.
196 void countMismatchedFuncSamples(const FunctionSamples &FS, bool IsTopLevel);
197 // Count the number of mismatched or recovered callsites.
198 void countMismatchCallsites(const FunctionSamples &FS);
199 // Count the samples of mismatched or recovered callsites for top-level
200 // function and all inlinees.
201 void countMismatchedCallsiteSamples(const FunctionSamples &FS);
202 void computeAndReportProfileStaleness();
203 void UpdateWithSalvagedProfiles();
204
205 LocToLocMap &getIRToProfileLocationMap(const Function &F) {
206 return FuncMappings[FunctionSamples::getCanonicalFnName(F.getName())];
207 }
208 void distributeIRToProfileLocationMap();
209 void distributeIRToProfileLocationMap(FunctionSamples &FS);
210 LocToLocMap longestCommonSequence(const AnchorList &IRCallsiteAnchors,
211 const AnchorList &ProfileCallsiteAnchors,
212 bool MatchUnusedFunction);
213 void matchNonCallsiteLocs(const LocToLocMap &AnchorMatchings,
214 const AnchorMap &IRAnchors,
215 LocToLocMap &IRToProfileLocationMap);
216 void runStaleProfileMatching(const Function &F, const AnchorMap &IRAnchors,
217 const AnchorMap &ProfileAnchors,
218 LocToLocMap &IRToProfileLocationMap,
219 bool RunCFGMatching, bool RunCGMatching);
220 // If the function doesn't have profile, return the pointer to the function.
221 bool functionHasProfile(const FunctionId &IRFuncName,
222 Function *&FuncWithoutProfile);
223 bool isProfileUnused(const FunctionId &ProfileFuncName);
224 bool functionMatchesProfileHelper(const Function &IRFunc,
225 const FunctionId &ProfFunc);
226 // Determine if the function matches profile. If FindMatchedProfileOnly is
227 // set, only search the existing matched function. Otherwise, try matching the
228 // two functions.
229 bool functionMatchesProfile(const FunctionId &IRFuncName,
230 const FunctionId &ProfileFuncName,
231 bool FindMatchedProfileOnly);
232 // Determine if the function matches profile by computing a similarity ratio
233 // between two sequences of callsite anchors extracted from function and
234 // profile. If it's above the threshold, the function matches the profile.
235 bool functionMatchesProfile(Function &IRFunc, const FunctionId &ProfFunc,
236 bool FindMatchedProfileOnly);
237 // Find functions that don't show in the profile or profile symbol list,
238 // which are supposed to be new functions. We use them as the targets for
239 // call graph matching.
240 void findFunctionsWithoutProfile();
241 void reportOrPersistProfileStats();
242};
243} // end namespace llvm
244#endif // LLVM_TRANSFORMS_IPO_SAMPLEPROFILEMATCHER_H
#define F(x, y, z)
Definition MD5.cpp:54
#define T
#define P(N)
This file provides the interface for the sampled PGO profile loader base implementation.
StringSet - A set-like wrapper for the StringMap.
LocallyHashedType DenseMapInfo< LocallyHashedType >::Empty
A lazily constructed view of the call graph of a module.
A Module instance is used to store all the information related to an LLVM module.
Definition Module.h:67
SampleProfileMatcher(Module &M, SampleProfileReader &Reader, LazyCallGraph &CG, const PseudoProbeManager *ProbeManager, ThinOrFullLTOPhase LTOPhase, HashKeyMap< std::unordered_map, FunctionId, Function * > &SymMap, std::shared_ptr< ProfileSymbolList > PSL, HashKeyMap< std::unordered_map, FunctionId, FunctionId > &FuncNameToProfNameMap)
StringMap - This is an unconventional map that is specialized for handling keys that are "strings",...
Definition StringMap.h:133
This class represents a function that is read from a sample profile.
Definition FunctionId.h:36
Representation of the samples collected for a function.
Definition SampleProf.h:777
static StringRef getCanonicalFnName(const Function &F)
Return the canonical name for a function, taking into account suffix elision policy attributes.
This class is a wrapper to associative container MapT<KeyT, ValueT> using the hash value of the origi...
Definition HashKeyMap.h:52
This class provides operator overloads to the map container using MD5 as the key type,...
iterator find(const SampleContext &Ctx)
@ C
The default llvm calling convention, compatible with C.
Definition CallingConv.h:34
std::unordered_map< LineLocation, LineLocation, LineLocationHash > LocToLocMap
Definition SampleProf.h:769
This is an optimization pass for GlobalISel generic memory operations.
std::map< LineLocation, FunctionId > AnchorMap
ThinOrFullLTOPhase
This enumerates the LLVM full LTO or ThinLTO optimization phases.
Definition Pass.h:77
std::vector< std::pair< LineLocation, FunctionId > > AnchorList
hash_code hash_combine(const Ts &...args)
Combine values into a single hash_code.
Definition Hashing.h:592
void swap(llvm::BitVector &LHS, llvm::BitVector &RHS)
Implement std::swap in terms of BitVector swap.
Definition BitVector.h:869