File indexing completed on 2026-05-10 08:44:41
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014 #ifndef LLVM_TRANSFORMS_IPO_SAMPLEPROFILEMATCHER_H
0015 #define LLVM_TRANSFORMS_IPO_SAMPLEPROFILEMATCHER_H
0016
0017 #include "llvm/ADT/StringSet.h"
0018 #include "llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h"
0019
0020 namespace llvm {
0021
0022 using AnchorList = std::vector<std::pair<LineLocation, FunctionId>>;
0023 using AnchorMap = std::map<LineLocation, FunctionId>;
0024
0025
0026 class SampleProfileMatcher {
0027 Module &M;
0028 SampleProfileReader &Reader;
0029 LazyCallGraph &CG;
0030 const PseudoProbeManager *ProbeManager;
0031 const ThinOrFullLTOPhase LTOPhase;
0032 SampleProfileMap FlattenedProfiles;
0033
0034
0035
0036 StringMap<LocToLocMap> FuncMappings;
0037
0038
0039 enum class MatchState {
0040 Unknown = 0,
0041
0042 InitialMatch = 1,
0043
0044 InitialMismatch = 2,
0045
0046 UnchangedMatch = 3,
0047
0048 UnchangedMismatch = 4,
0049
0050 RecoveredMismatch = 5,
0051
0052
0053 RemovedMatch = 6,
0054 };
0055
0056
0057
0058
0059 StringMap<std::unordered_map<LineLocation, MatchState, LineLocationHash>>
0060 FuncCallsiteMatchStates;
0061
0062 struct FuncToProfileNameMapHash {
0063 uint64_t
0064 operator()(const std::pair<const Function *, FunctionId> &P) const {
0065 return hash_combine(P.first, P.second);
0066 }
0067 };
0068
0069
0070
0071 std::unordered_map<std::pair<const Function *, FunctionId>, bool,
0072 FuncToProfileNameMapHash>
0073 FuncProfileMatchCache;
0074
0075
0076
0077 std::unordered_map<Function *, FunctionId> FuncToProfileNameMap;
0078
0079
0080
0081
0082 HashKeyMap<std::unordered_map, FunctionId, FunctionId> *FuncNameToProfNameMap;
0083
0084
0085
0086
0087 HashKeyMap<std::unordered_map, FunctionId, Function *> *SymbolMap;
0088
0089
0090 HashKeyMap<std::unordered_map, FunctionId, Function *>
0091 FunctionsWithoutProfile;
0092
0093
0094 std::shared_ptr<ProfileSymbolList> PSL;
0095
0096
0097 uint64_t TotalProfiledFunc = 0;
0098
0099 uint64_t NumStaleProfileFunc = 0;
0100 uint64_t TotalProfiledCallsites = 0;
0101 uint64_t NumMismatchedCallsites = 0;
0102 uint64_t NumRecoveredCallsites = 0;
0103
0104 uint64_t TotalFunctionSamples = 0;
0105
0106 uint64_t MismatchedFunctionSamples = 0;
0107 uint64_t MismatchedCallsiteSamples = 0;
0108 uint64_t RecoveredCallsiteSamples = 0;
0109
0110
0111 uint64_t NumCallGraphRecoveredProfiledFunc = 0;
0112 uint64_t NumCallGraphRecoveredFuncSamples = 0;
0113
0114
0115
0116 static constexpr const char *UnknownIndirectCallee =
0117 "unknown.indirect.callee";
0118
0119 public:
0120 SampleProfileMatcher(
0121 Module &M, SampleProfileReader &Reader, LazyCallGraph &CG,
0122 const PseudoProbeManager *ProbeManager, ThinOrFullLTOPhase LTOPhase,
0123 HashKeyMap<std::unordered_map, FunctionId, Function *> &SymMap,
0124 std::shared_ptr<ProfileSymbolList> PSL,
0125 HashKeyMap<std::unordered_map, FunctionId, FunctionId>
0126 &FuncNameToProfNameMap)
0127 : M(M), Reader(Reader), CG(CG), ProbeManager(ProbeManager),
0128 LTOPhase(LTOPhase), FuncNameToProfNameMap(&FuncNameToProfNameMap),
0129 SymbolMap(&SymMap), PSL(PSL) {};
0130 void runOnModule();
0131 void clearMatchingData() {
0132
0133
0134
0135
0136
0137 freeContainer(FuncCallsiteMatchStates);
0138 freeContainer(FunctionsWithoutProfile);
0139 freeContainer(FuncToProfileNameMap);
0140 }
0141
0142 private:
0143 FunctionSamples *getFlattenedSamplesFor(const FunctionId &Fname) {
0144 auto It = FlattenedProfiles.find(Fname);
0145 if (It != FlattenedProfiles.end())
0146 return &It->second;
0147 return nullptr;
0148 }
0149 FunctionSamples *getFlattenedSamplesFor(const Function &F) {
0150 StringRef CanonFName = FunctionSamples::getCanonicalFnName(F);
0151 return getFlattenedSamplesFor(FunctionId(CanonFName));
0152 }
0153 template <typename T> inline void freeContainer(T &C) {
0154 T Empty;
0155 std::swap(C, Empty);
0156 }
0157 void getFilteredAnchorList(const AnchorMap &IRAnchors,
0158 const AnchorMap &ProfileAnchors,
0159 AnchorList &FilteredIRAnchorsList,
0160 AnchorList &FilteredProfileAnchorList);
0161 void runOnFunction(Function &F);
0162 void findIRAnchors(const Function &F, AnchorMap &IRAnchors) const;
0163 void findProfileAnchors(const FunctionSamples &FS,
0164 AnchorMap &ProfileAnchors) const;
0165
0166
0167 void recordCallsiteMatchStates(const Function &F, const AnchorMap &IRAnchors,
0168 const AnchorMap &ProfileAnchors,
0169 const LocToLocMap *IRToProfileLocationMap);
0170
0171 bool isMismatchState(const enum MatchState &State) {
0172 return State == MatchState::InitialMismatch ||
0173 State == MatchState::UnchangedMismatch ||
0174 State == MatchState::RemovedMatch;
0175 };
0176
0177 bool isInitialState(const enum MatchState &State) {
0178 return State == MatchState::InitialMatch ||
0179 State == MatchState::InitialMismatch;
0180 };
0181
0182 bool isFinalState(const enum MatchState &State) {
0183 return State == MatchState::UnchangedMatch ||
0184 State == MatchState::UnchangedMismatch ||
0185 State == MatchState::RecoveredMismatch ||
0186 State == MatchState::RemovedMatch;
0187 };
0188
0189 void countCallGraphRecoveredSamples(
0190 const FunctionSamples &FS,
0191 std::unordered_set<FunctionId> &MatchedUnusedProfile);
0192
0193
0194 void countMismatchedFuncSamples(const FunctionSamples &FS, bool IsTopLevel);
0195
0196 void countMismatchCallsites(const FunctionSamples &FS);
0197
0198
0199 void countMismatchedCallsiteSamples(const FunctionSamples &FS);
0200 void computeAndReportProfileStaleness();
0201 void UpdateWithSalvagedProfiles();
0202
0203 LocToLocMap &getIRToProfileLocationMap(const Function &F) {
0204 return FuncMappings[FunctionSamples::getCanonicalFnName(F.getName())];
0205 }
0206 void distributeIRToProfileLocationMap();
0207 void distributeIRToProfileLocationMap(FunctionSamples &FS);
0208 LocToLocMap longestCommonSequence(const AnchorList &IRCallsiteAnchors,
0209 const AnchorList &ProfileCallsiteAnchors,
0210 bool MatchUnusedFunction);
0211 void matchNonCallsiteLocs(const LocToLocMap &AnchorMatchings,
0212 const AnchorMap &IRAnchors,
0213 LocToLocMap &IRToProfileLocationMap);
0214 void runStaleProfileMatching(const Function &F, const AnchorMap &IRAnchors,
0215 const AnchorMap &ProfileAnchors,
0216 LocToLocMap &IRToProfileLocationMap,
0217 bool RunCFGMatching, bool RunCGMatching);
0218
0219 bool functionHasProfile(const FunctionId &IRFuncName,
0220 Function *&FuncWithoutProfile);
0221 bool isProfileUnused(const FunctionId &ProfileFuncName);
0222 bool functionMatchesProfileHelper(const Function &IRFunc,
0223 const FunctionId &ProfFunc);
0224
0225
0226
0227 bool functionMatchesProfile(const FunctionId &IRFuncName,
0228 const FunctionId &ProfileFuncName,
0229 bool FindMatchedProfileOnly);
0230
0231
0232
0233 bool functionMatchesProfile(Function &IRFunc, const FunctionId &ProfFunc,
0234 bool FindMatchedProfileOnly);
0235
0236
0237
0238 void findFunctionsWithoutProfile();
0239 void reportOrPersistProfileStats();
0240 };
0241 }
0242 #endif