MissingFrameInferrer.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. //===-- MissingFrameInferrer.h - Missing frame inferrer ---------- 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. #ifndef LLVM_TOOLS_LLVM_PROFGEN_MISSINGFRAMEINFERRER_H
  9. #define LLVM_TOOLS_LLVM_PROFGEN_MISSINGFRAMEINFERRER_H
  10. #include "PerfReader.h"
  11. #include "llvm/ADT/DenseSet.h"
  12. #include "llvm/ADT/SmallVector.h"
  13. #include "llvm/ADT/Statistic.h"
  14. #include <unordered_map>
  15. #include <unordered_set>
  16. namespace llvm {
  17. namespace sampleprof {
  18. class ProfiledBinary;
  19. struct BinaryFunction;
  20. class MissingFrameInferrer {
  21. public:
  22. MissingFrameInferrer(ProfiledBinary *Binary) : Binary(Binary) {}
  23. // Defininig a frame transition from a caller function to the callee function.
  24. using CallerCalleePair = std::pair<BinaryFunction *, BinaryFunction *>;
  25. void initialize(const ContextSampleCounterMap *SampleCounters);
  26. // Given an input `Context`, output `NewContext` with inferred missing tail
  27. // call frames.
  28. void inferMissingFrames(const SmallVectorImpl<uint64_t> &Context,
  29. SmallVectorImpl<uint64_t> &NewContext);
  30. private:
  31. friend class ProfiledBinary;
  32. // Compute a unique tail call path for a pair of source frame address and
  33. // target frame address. Append the unique path prefix (not including `To`) to
  34. // `UniquePath` if exists. Return the whether this's a unqiue tail call
  35. // path. The source/dest frame will typically be a pair of adjacent frame
  36. // entries of call stack samples.
  37. bool inferMissingFrames(uint64_t From, uint64_t To,
  38. SmallVectorImpl<uint64_t> &UniquePath);
  39. // Compute a unique tail call path from the source frame address to the target
  40. // function. Output the unique path prefix (not including `To`) in
  41. // `UniquePath` if exists. Return the number of possibly availabe tail call
  42. // paths.
  43. uint64_t computeUniqueTailCallPath(uint64_t From, BinaryFunction *To,
  44. SmallVectorImpl<uint64_t> &UniquePath);
  45. // Compute a unique tail call path from the source function to the target
  46. // function. Output the unique path prefix (not including `To`) in
  47. // `UniquePath` if exists. Return the number of possibly availabe tail call
  48. // paths.
  49. uint64_t computeUniqueTailCallPath(BinaryFunction *From, BinaryFunction *To,
  50. SmallVectorImpl<uint64_t> &UniquePath);
  51. ProfiledBinary *Binary;
  52. // A map of call instructions to their target addresses. This is first
  53. // populated with static call edges but then trimmed down to dynamic call
  54. // edges based on LBR samples.
  55. std::unordered_map<uint64_t, std::unordered_set<uint64_t>> CallEdges;
  56. // A map of tail call instructions to their target addresses. This is first
  57. // populated with static call edges but then trimmed down to dynamic call
  58. // edges based on LBR samples.
  59. std::unordered_map<uint64_t, std::unordered_set<uint64_t>> TailCallEdges;
  60. // Dynamic call targets in terms of BinaryFunction for any calls.
  61. std::unordered_map<uint64_t, std::unordered_set<BinaryFunction *>> CallEdgesF;
  62. // Dynamic call targets in terms of BinaryFunction for tail calls.
  63. std::unordered_map<uint64_t, std::unordered_set<BinaryFunction *>>
  64. TailCallEdgesF;
  65. // Dynamic tail call targets of caller functions.
  66. std::unordered_map<BinaryFunction *, std::vector<uint64_t>> FuncToTailCallMap;
  67. // Functions that are reachable via tail calls.
  68. DenseSet<const BinaryFunction *> TailCallTargetFuncs;
  69. struct PairHash {
  70. std::size_t operator()(
  71. const std::pair<BinaryFunction *, BinaryFunction *> &Pair) const {
  72. return std::hash<BinaryFunction *>()(Pair.first) ^
  73. std::hash<BinaryFunction *>()(Pair.second);
  74. }
  75. };
  76. // Cached results from a CallerCalleePair to a unique call path between them.
  77. std::unordered_map<CallerCalleePair, std::vector<uint64_t>, PairHash>
  78. UniquePaths;
  79. // Cached results from CallerCalleePair to the number of available call paths.
  80. std::unordered_map<CallerCalleePair, uint64_t, PairHash> NonUniquePaths;
  81. DenseSet<BinaryFunction *> Visiting;
  82. uint32_t CurSearchingDepth = 0;
  83. #if LLVM_ENABLE_STATS
  84. DenseSet<std::pair<uint64_t, uint64_t>> ReachableViaUniquePaths;
  85. DenseSet<std::pair<uint64_t, uint64_t>> Unreachables;
  86. DenseSet<std::pair<uint64_t, uint64_t>> ReachableViaMultiPaths;
  87. #endif
  88. };
  89. } // end namespace sampleprof
  90. } // end namespace llvm
  91. #endif