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