1 //===- Transforms/IPO/SampleProfileProbe.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 the pseudo probe implementation for 11 /// AutoFDO. 12 // 13 //===----------------------------------------------------------------------===// 14 15 #ifndef LLVM_TRANSFORMS_IPO_SAMPLEPROFILEPROBE_H 16 #define LLVM_TRANSFORMS_IPO_SAMPLEPROFILEPROBE_H 17 18 #include "llvm/ADT/DenseMap.h" 19 #include "llvm/Analysis/LazyCallGraph.h" 20 #include "llvm/IR/PassManager.h" 21 #include "llvm/ProfileData/SampleProf.h" 22 #include <unordered_map> 23 24 namespace llvm { 25 class Any; 26 class BasicBlock; 27 class Function; 28 class Instruction; 29 class Loop; 30 class PassInstrumentationCallbacks; 31 class TargetMachine; 32 33 class Module; 34 35 using namespace sampleprof; 36 using BlockIdMap = std::unordered_map<BasicBlock *, uint32_t>; 37 using InstructionIdMap = std::unordered_map<Instruction *, uint32_t>; 38 // Map from tuples of Probe id and inline stack hash code to distribution 39 // factors. 40 using ProbeFactorMap = std::unordered_map<std::pair<uint64_t, uint64_t>, float, 41 pair_hash<uint64_t, uint64_t>>; 42 using FuncProbeFactorMap = StringMap<ProbeFactorMap>; 43 44 class PseudoProbeDescriptor { 45 uint64_t FunctionGUID; 46 uint64_t FunctionHash; 47 48 public: 49 PseudoProbeDescriptor(uint64_t GUID, uint64_t Hash) 50 : FunctionGUID(GUID), FunctionHash(Hash) {} 51 uint64_t getFunctionGUID() const { return FunctionGUID; } 52 uint64_t getFunctionHash() const { return FunctionHash; } 53 }; 54 55 // A pseudo probe verifier that can be run after each IR passes to detect the 56 // violation of updating probe factors. In principle, the sum of distribution 57 // factor for a probe should be identical before and after a pass. For a 58 // function pass, the factor sum for a probe would be typically 100%. 59 class PseudoProbeVerifier { 60 public: 61 void registerCallbacks(PassInstrumentationCallbacks &PIC); 62 63 // Implementation of pass instrumentation callbacks for new pass manager. 64 void runAfterPass(StringRef PassID, Any IR); 65 66 private: 67 // Allow a little bias due the rounding to integral factors. 68 constexpr static float DistributionFactorVariance = 0.02f; 69 // Distribution factors from last pass. 70 FuncProbeFactorMap FunctionProbeFactors; 71 72 void collectProbeFactors(const BasicBlock *BB, ProbeFactorMap &ProbeFactors); 73 void runAfterPass(const Module *M); 74 void runAfterPass(const LazyCallGraph::SCC *C); 75 void runAfterPass(const Function *F); 76 void runAfterPass(const Loop *L); 77 bool shouldVerifyFunction(const Function *F); 78 void verifyProbeFactors(const Function *F, 79 const ProbeFactorMap &ProbeFactors); 80 }; 81 82 // This class serves sample counts correlation for SampleProfileLoader by 83 // analyzing pseudo probes and their function descriptors injected by 84 // SampleProfileProber. 85 class PseudoProbeManager { 86 DenseMap<uint64_t, PseudoProbeDescriptor> GUIDToProbeDescMap; 87 88 const PseudoProbeDescriptor *getDesc(const Function &F) const; 89 90 public: 91 PseudoProbeManager(const Module &M); 92 bool moduleIsProbed(const Module &M) const; 93 bool profileIsValid(const Function &F, const FunctionSamples &Samples) const; 94 }; 95 96 /// Sample profile pseudo prober. 97 /// 98 /// Insert pseudo probes for block sampling and value sampling. 99 class SampleProfileProber { 100 public: 101 // Give an empty module id when the prober is not used for instrumentation. 102 SampleProfileProber(Function &F, const std::string &CurModuleUniqueId); 103 void instrumentOneFunc(Function &F, TargetMachine *TM); 104 105 private: 106 Function *getFunction() const { return F; } 107 uint64_t getFunctionHash() const { return FunctionHash; } 108 uint32_t getBlockId(const BasicBlock *BB) const; 109 uint32_t getCallsiteId(const Instruction *Call) const; 110 void computeCFGHash(); 111 void computeProbeIdForBlocks(); 112 void computeProbeIdForCallsites(); 113 114 Function *F; 115 116 /// The current module ID that is used to name a static object as a comdat 117 /// group. 118 std::string CurModuleUniqueId; 119 120 /// A CFG hash code used to identify a function code changes. 121 uint64_t FunctionHash; 122 123 /// Map basic blocks to the their pseudo probe ids. 124 BlockIdMap BlockProbeIds; 125 126 /// Map indirect calls to the their pseudo probe ids. 127 InstructionIdMap CallProbeIds; 128 129 /// The ID of the last probe, Can be used to number a new probe. 130 uint32_t LastProbeId; 131 }; 132 133 class SampleProfileProbePass : public PassInfoMixin<SampleProfileProbePass> { 134 TargetMachine *TM; 135 136 public: 137 SampleProfileProbePass(TargetMachine *TM) : TM(TM) {} 138 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); 139 }; 140 141 // Pseudo probe distribution factor updater. 142 // Sample profile annotation can happen in both LTO prelink and postlink. The 143 // postlink-time re-annotation can degrade profile quality because of prelink 144 // code duplication transformation, such as loop unrolling, jump threading, 145 // indirect call promotion etc. As such, samples corresponding to a source 146 // location may be aggregated multiple times in postlink. With a concept of 147 // distribution factor for pseudo probes, samples can be distributed among 148 // duplicated probes reasonable based on the assumption that optimizations 149 // duplicating code well-maintain the branch frequency information (BFI). This 150 // pass updates distribution factors for each pseudo probe at the end of the 151 // prelink pipeline, to reflect an estimated portion of the real execution 152 // count. 153 class PseudoProbeUpdatePass : public PassInfoMixin<PseudoProbeUpdatePass> { 154 void runOnFunction(Function &F, FunctionAnalysisManager &FAM); 155 156 public: 157 PseudoProbeUpdatePass() = default; 158 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); 159 }; 160 161 } // end namespace llvm 162 #endif // LLVM_TRANSFORMS_IPO_SAMPLEPROFILEPROBE_H 163