SampleProfileProbe.h 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. #pragma once
  2. #ifdef __GNUC__
  3. #pragma GCC diagnostic push
  4. #pragma GCC diagnostic ignored "-Wunused-parameter"
  5. #endif
  6. //===- Transforms/IPO/SampleProfileProbe.h ----------*- C++ -*-===//
  7. //
  8. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  9. // See https://llvm.org/LICENSE.txt for license information.
  10. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  11. //
  12. //===----------------------------------------------------------------------===//
  13. //
  14. /// \file
  15. /// This file provides the interface for the pseudo probe implementation for
  16. /// AutoFDO.
  17. //
  18. //===----------------------------------------------------------------------===//
  19. #ifndef LLVM_TRANSFORMS_IPO_SAMPLEPROFILEPROBE_H
  20. #define LLVM_TRANSFORMS_IPO_SAMPLEPROFILEPROBE_H
  21. #include "llvm/ADT/DenseMap.h"
  22. #include "llvm/Analysis/LazyCallGraph.h"
  23. #include "llvm/IR/PassManager.h"
  24. #include "llvm/ProfileData/SampleProf.h"
  25. #include <unordered_map>
  26. namespace llvm {
  27. class Any;
  28. class BasicBlock;
  29. class Function;
  30. class Instruction;
  31. class Loop;
  32. class PassInstrumentationCallbacks;
  33. class TargetMachine;
  34. class Module;
  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. class PseudoProbeDescriptor {
  44. uint64_t FunctionGUID;
  45. uint64_t FunctionHash;
  46. public:
  47. PseudoProbeDescriptor(uint64_t GUID, uint64_t Hash)
  48. : FunctionGUID(GUID), FunctionHash(Hash) {}
  49. uint64_t getFunctionGUID() const { return FunctionGUID; }
  50. uint64_t getFunctionHash() const { return FunctionHash; }
  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. // Implementation of pass instrumentation callbacks for new pass manager.
  60. void runAfterPass(StringRef PassID, Any IR);
  61. private:
  62. // Allow a little bias due the rounding to integral factors.
  63. constexpr static float DistributionFactorVariance = 0.02f;
  64. // Distribution factors from last pass.
  65. FuncProbeFactorMap FunctionProbeFactors;
  66. void collectProbeFactors(const BasicBlock *BB, ProbeFactorMap &ProbeFactors);
  67. void runAfterPass(const Module *M);
  68. void runAfterPass(const LazyCallGraph::SCC *C);
  69. void runAfterPass(const Function *F);
  70. void runAfterPass(const Loop *L);
  71. bool shouldVerifyFunction(const Function *F);
  72. void verifyProbeFactors(const Function *F,
  73. const ProbeFactorMap &ProbeFactors);
  74. };
  75. // This class serves sample counts correlation for SampleProfileLoader by
  76. // analyzing pseudo probes and their function descriptors injected by
  77. // SampleProfileProber.
  78. class PseudoProbeManager {
  79. DenseMap<uint64_t, PseudoProbeDescriptor> GUIDToProbeDescMap;
  80. const PseudoProbeDescriptor *getDesc(const Function &F) const;
  81. public:
  82. PseudoProbeManager(const Module &M);
  83. bool moduleIsProbed(const Module &M) const;
  84. bool profileIsValid(const Function &F, const FunctionSamples &Samples) const;
  85. };
  86. /// Sample profile pseudo prober.
  87. ///
  88. /// Insert pseudo probes for block sampling and value sampling.
  89. class SampleProfileProber {
  90. public:
  91. // Give an empty module id when the prober is not used for instrumentation.
  92. SampleProfileProber(Function &F, const std::string &CurModuleUniqueId);
  93. void instrumentOneFunc(Function &F, TargetMachine *TM);
  94. private:
  95. Function *getFunction() const { return F; }
  96. uint64_t getFunctionHash() const { return FunctionHash; }
  97. uint32_t getBlockId(const BasicBlock *BB) const;
  98. uint32_t getCallsiteId(const Instruction *Call) const;
  99. void computeCFGHash();
  100. void computeProbeIdForBlocks();
  101. void computeProbeIdForCallsites();
  102. Function *F;
  103. /// The current module ID that is used to name a static object as a comdat
  104. /// group.
  105. std::string CurModuleUniqueId;
  106. /// A CFG hash code used to identify a function code changes.
  107. uint64_t FunctionHash;
  108. /// Map basic blocks to the their pseudo probe ids.
  109. BlockIdMap BlockProbeIds;
  110. /// Map indirect calls to the their pseudo probe ids.
  111. InstructionIdMap CallProbeIds;
  112. /// The ID of the last probe, Can be used to number a new probe.
  113. uint32_t LastProbeId;
  114. };
  115. class SampleProfileProbePass : public PassInfoMixin<SampleProfileProbePass> {
  116. TargetMachine *TM;
  117. public:
  118. SampleProfileProbePass(TargetMachine *TM) : TM(TM) {}
  119. PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
  120. };
  121. // Pseudo probe distribution factor updater.
  122. // Sample profile annotation can happen in both LTO prelink and postlink. The
  123. // postlink-time re-annotation can degrade profile quality because of prelink
  124. // code duplication transformation, such as loop unrolling, jump threading,
  125. // indirect call promotion etc. As such, samples corresponding to a source
  126. // location may be aggregated multiple times in postlink. With a concept of
  127. // distribution factor for pseudo probes, samples can be distributed among
  128. // duplicated probes reasonable based on the assumption that optimizations
  129. // duplicating code well-maintain the branch frequency information (BFI). This
  130. // pass updates distribution factors for each pseudo probe at the end of the
  131. // prelink pipeline, to reflect an estimated portion of the real execution
  132. // count.
  133. class PseudoProbeUpdatePass : public PassInfoMixin<PseudoProbeUpdatePass> {
  134. void runOnFunction(Function &F, FunctionAnalysisManager &FAM);
  135. public:
  136. PseudoProbeUpdatePass() = default;
  137. PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM);
  138. };
  139. } // end namespace llvm
  140. #endif // LLVM_TRANSFORMS_IPO_SAMPLEPROFILEPROBE_H
  141. #ifdef __GNUC__
  142. #pragma GCC diagnostic pop
  143. #endif