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/CallGraphSCCPass.h" 20 #include "llvm/Analysis/LazyCallGraph.h" 21 #include "llvm/Analysis/LoopInfo.h" 22 #include "llvm/IR/PassInstrumentation.h" 23 #include "llvm/IR/PassManager.h" 24 #include "llvm/IR/PseudoProbe.h" 25 #include "llvm/ProfileData/SampleProf.h" 26 #include "llvm/Target/TargetMachine.h" 27 #include <unordered_map> 28 29 namespace llvm { 30 31 class Module; 32 33 using namespace sampleprof; 34 using BlockIdMap = std::unordered_map<BasicBlock *, uint32_t>; 35 using InstructionIdMap = std::unordered_map<Instruction *, uint32_t>; 36 using ProbeFactorMap = std::unordered_map<uint64_t, float>; 37 using FuncProbeFactorMap = StringMap<ProbeFactorMap>; 38 39 enum class PseudoProbeReservedId { Invalid = 0, Last = Invalid }; 40 41 class PseudoProbeDescriptor { 42 uint64_t FunctionGUID; 43 uint64_t FunctionHash; 44 45 public: 46 PseudoProbeDescriptor(uint64_t GUID, uint64_t Hash) 47 : FunctionGUID(GUID), FunctionHash(Hash) {} 48 uint64_t getFunctionGUID() const { return FunctionGUID; } 49 uint64_t getFunctionHash() const { return FunctionHash; } 50 }; 51 52 // A pseudo probe verifier that can be run after each IR passes to detect the 53 // violation of updating probe factors. In principle, the sum of distribution 54 // factor for a probe should be identical before and after a pass. For a 55 // function pass, the factor sum for a probe would be typically 100%. 56 class PseudoProbeVerifier { 57 public: 58 void registerCallbacks(PassInstrumentationCallbacks &PIC); 59 60 // Implementation of pass instrumentation callbacks for new pass manager. 61 void runAfterPass(StringRef PassID, Any IR); 62 63 private: 64 // Allow a little bias due the rounding to integral factors. 65 constexpr static float DistributionFactorVariance = 0.02f; 66 // Distribution factors from last pass. 67 FuncProbeFactorMap FunctionProbeFactors; 68 69 void collectProbeFactors(const BasicBlock *BB, ProbeFactorMap &ProbeFactors); 70 void runAfterPass(const Module *M); 71 void runAfterPass(const LazyCallGraph::SCC *C); 72 void runAfterPass(const Function *F); 73 void runAfterPass(const Loop *L); 74 bool shouldVerifyFunction(const Function *F); 75 void verifyProbeFactors(const Function *F, 76 const ProbeFactorMap &ProbeFactors); 77 }; 78 79 // This class serves sample counts correlation for SampleProfileLoader by 80 // analyzing pseudo probes and their function descriptors injected by 81 // SampleProfileProber. 82 class PseudoProbeManager { 83 DenseMap<uint64_t, PseudoProbeDescriptor> GUIDToProbeDescMap; 84 85 const PseudoProbeDescriptor *getDesc(const Function &F) const; 86 87 public: 88 PseudoProbeManager(const Module &M); 89 bool moduleIsProbed(const Module &M) const; 90 bool profileIsValid(const Function &F, const FunctionSamples &Samples) const; 91 }; 92 93 /// Sample profile pseudo prober. 94 /// 95 /// Insert pseudo probes for block sampling and value sampling. 96 class SampleProfileProber { 97 public: 98 // Give an empty module id when the prober is not used for instrumentation. 99 SampleProfileProber(Function &F, const std::string &CurModuleUniqueId); 100 void instrumentOneFunc(Function &F, TargetMachine *TM); 101 102 private: 103 Function *getFunction() const { return F; } 104 uint64_t getFunctionHash() const { return FunctionHash; } 105 uint32_t getBlockId(const BasicBlock *BB) const; 106 uint32_t getCallsiteId(const Instruction *Call) const; 107 void computeCFGHash(); 108 void computeProbeIdForBlocks(); 109 void computeProbeIdForCallsites(); 110 111 Function *F; 112 113 /// The current module ID that is used to name a static object as a comdat 114 /// group. 115 std::string CurModuleUniqueId; 116 117 /// A CFG hash code used to identify a function code changes. 118 uint64_t FunctionHash; 119 120 /// Map basic blocks to the their pseudo probe ids. 121 BlockIdMap BlockProbeIds; 122 123 /// Map indirect calls to the their pseudo probe ids. 124 InstructionIdMap CallProbeIds; 125 126 /// The ID of the last probe, Can be used to number a new probe. 127 uint32_t LastProbeId; 128 }; 129 130 class SampleProfileProbePass : public PassInfoMixin<SampleProfileProbePass> { 131 TargetMachine *TM; 132 133 public: 134 SampleProfileProbePass(TargetMachine *TM) : TM(TM) {} 135 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); 136 }; 137 138 class PseudoProbeUpdatePass : public PassInfoMixin<PseudoProbeUpdatePass> { 139 void runOnFunction(Function &F, FunctionAnalysisManager &FAM); 140 141 public: 142 PseudoProbeUpdatePass() {} 143 PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); 144 }; 145 146 } // end namespace llvm 147 #endif // LLVM_TRANSFORMS_IPO_SAMPLEPROFILEPROBE_H 148