• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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"
18 #include "llvm/Transforms/Utils/SampleProfileLoaderBaseImpl.h"
19 
20 namespace llvm {
21 
22 // Sample profile matching - fuzzy match.
23 class SampleProfileMatcher {
24   Module &M;
25   SampleProfileReader &Reader;
26   const PseudoProbeManager *ProbeManager;
27   const ThinOrFullLTOPhase LTOPhase;
28   SampleProfileMap FlattenedProfiles;
29   // For each function, the matcher generates a map, of which each entry is a
30   // mapping from the source location of current build to the source location in
31   // the profile.
32   StringMap<LocToLocMap> FuncMappings;
33 
34   // Match state for an anchor/callsite.
35   enum class MatchState {
36     Unknown = 0,
37     // Initial match between input profile and current IR.
38     InitialMatch = 1,
39     // Initial mismatch between input profile and current IR.
40     InitialMismatch = 2,
41     // InitialMatch stays matched after fuzzy profile matching.
42     UnchangedMatch = 3,
43     // InitialMismatch stays mismatched after fuzzy profile matching.
44     UnchangedMismatch = 4,
45     // InitialMismatch is recovered after fuzzy profile matching.
46     RecoveredMismatch = 5,
47     // InitialMatch is removed and becomes mismatched after fuzzy profile
48     // matching.
49     RemovedMatch = 6,
50   };
51 
52   // For each function, store every callsite and its matching state into this
53   // map, of which each entry is a pair of callsite location and MatchState.
54   // This is used for profile staleness computation and report.
55   StringMap<std::unordered_map<LineLocation, MatchState, LineLocationHash>>
56       FuncCallsiteMatchStates;
57 
58   // Profile mismatch statstics:
59   uint64_t TotalProfiledFunc = 0;
60   // Num of checksum-mismatched function.
61   uint64_t NumStaleProfileFunc = 0;
62   uint64_t TotalProfiledCallsites = 0;
63   uint64_t NumMismatchedCallsites = 0;
64   uint64_t NumRecoveredCallsites = 0;
65   // Total samples for all profiled functions.
66   uint64_t TotalFunctionSamples = 0;
67   // Total samples for all checksum-mismatched functions.
68   uint64_t MismatchedFunctionSamples = 0;
69   uint64_t MismatchedCallsiteSamples = 0;
70   uint64_t RecoveredCallsiteSamples = 0;
71 
72   // A dummy name for unknown indirect callee, used to differentiate from a
73   // non-call instruction that also has an empty callee name.
74   static constexpr const char *UnknownIndirectCallee =
75       "unknown.indirect.callee";
76 
77 public:
SampleProfileMatcher(Module & M,SampleProfileReader & Reader,const PseudoProbeManager * ProbeManager,ThinOrFullLTOPhase LTOPhase)78   SampleProfileMatcher(Module &M, SampleProfileReader &Reader,
79                        const PseudoProbeManager *ProbeManager,
80                        ThinOrFullLTOPhase LTOPhase)
81       : M(M), Reader(Reader), ProbeManager(ProbeManager), LTOPhase(LTOPhase){};
82   void runOnModule();
clearMatchingData()83   void clearMatchingData() {
84     // Do not clear FuncMappings, it stores IRLoc to ProfLoc remappings which
85     // will be used for sample loader.
86     FuncCallsiteMatchStates.clear();
87   }
88 
89 private:
getFlattenedSamplesFor(const Function & F)90   FunctionSamples *getFlattenedSamplesFor(const Function &F) {
91     StringRef CanonFName = FunctionSamples::getCanonicalFnName(F);
92     auto It = FlattenedProfiles.find(FunctionId(CanonFName));
93     if (It != FlattenedProfiles.end())
94       return &It->second;
95     return nullptr;
96   }
97   void runOnFunction(Function &F);
98   void findIRAnchors(const Function &F,
99                      std::map<LineLocation, StringRef> &IRAnchors);
100   void findProfileAnchors(
101       const FunctionSamples &FS,
102       std::map<LineLocation, std::unordered_set<FunctionId>> &ProfileAnchors);
103   // Record the callsite match states for profile staleness report, the result
104   // is saved in FuncCallsiteMatchStates.
105   void recordCallsiteMatchStates(
106       const Function &F, const std::map<LineLocation, StringRef> &IRAnchors,
107       const std::map<LineLocation, std::unordered_set<FunctionId>>
108           &ProfileAnchors,
109       const LocToLocMap *IRToProfileLocationMap);
110 
isMismatchState(const enum MatchState & State)111   bool isMismatchState(const enum MatchState &State) {
112     return State == MatchState::InitialMismatch ||
113            State == MatchState::UnchangedMismatch ||
114            State == MatchState::RemovedMatch;
115   };
116 
isInitialState(const enum MatchState & State)117   bool isInitialState(const enum MatchState &State) {
118     return State == MatchState::InitialMatch ||
119            State == MatchState::InitialMismatch;
120   };
121 
isFinalState(const enum MatchState & State)122   bool isFinalState(const enum MatchState &State) {
123     return State == MatchState::UnchangedMatch ||
124            State == MatchState::UnchangedMismatch ||
125            State == MatchState::RecoveredMismatch ||
126            State == MatchState::RemovedMatch;
127   };
128 
129   // Count the samples of checksum mismatched function for the top-level
130   // function and all inlinees.
131   void countMismatchedFuncSamples(const FunctionSamples &FS, bool IsTopLevel);
132   // Count the number of mismatched or recovered callsites.
133   void countMismatchCallsites(const FunctionSamples &FS);
134   // Count the samples of mismatched or recovered callsites for top-level
135   // function and all inlinees.
136   void countMismatchedCallsiteSamples(const FunctionSamples &FS);
137   void computeAndReportProfileStaleness();
138 
getIRToProfileLocationMap(const Function & F)139   LocToLocMap &getIRToProfileLocationMap(const Function &F) {
140     auto Ret = FuncMappings.try_emplace(
141         FunctionSamples::getCanonicalFnName(F.getName()), LocToLocMap());
142     return Ret.first->second;
143   }
144   void distributeIRToProfileLocationMap();
145   void distributeIRToProfileLocationMap(FunctionSamples &FS);
146   void runStaleProfileMatching(
147       const Function &F, const std::map<LineLocation, StringRef> &IRAnchors,
148       const std::map<LineLocation, std::unordered_set<FunctionId>>
149           &ProfileAnchors,
150       LocToLocMap &IRToProfileLocationMap);
151   void reportOrPersistProfileStats();
152 };
153 } // end namespace llvm
154 #endif // LLVM_TRANSFORMS_IPO_SAMPLEPROFILEMATCHER_H
155