PseudoProbe.h 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. //===--- PseudoProbe.h - Pseudo probe decoding utilities ---------*- 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_PSEUDOPROBE_H
  9. #define LLVM_TOOLS_LLVM_PROFGEN_PSEUDOPROBE_H
  10. #include "llvm/ADT/StringRef.h"
  11. #include "llvm/ADT/Twine.h"
  12. #include "llvm/IR/PseudoProbe.h"
  13. #include "llvm/Support/raw_ostream.h"
  14. #include "llvm/Transforms/IPO/SampleProfileProbe.h"
  15. #include <algorithm>
  16. #include <set>
  17. #include <sstream>
  18. #include <string>
  19. #include <unordered_map>
  20. #include <unordered_set>
  21. #include <vector>
  22. namespace llvm {
  23. namespace sampleprof {
  24. enum PseudoProbeAttributes { TAILCALL = 1, DANGLING = 2 };
  25. // Use func GUID and index as the location info of the inline site
  26. using InlineSite = std::tuple<uint64_t, uint32_t>;
  27. struct PseudoProbe;
  28. // Tree node to represent the inline relation and its inline site, we use a
  29. // dummy root in the PseudoProbeDecoder to lead the tree, the outlined
  30. // function will directly be the children of the dummy root. For the inlined
  31. // function, all the inlinee will be connected to its inlineer, then further to
  32. // its outlined function. Pseudo probes originating from the function stores the
  33. // tree's leaf node which we can process backwards to get its inline context
  34. class PseudoProbeInlineTree {
  35. std::vector<PseudoProbe *> ProbeVector;
  36. struct InlineSiteHash {
  37. uint64_t operator()(const InlineSite &Site) const {
  38. return std::get<0>(Site) ^ std::get<1>(Site);
  39. }
  40. };
  41. std::unordered_map<InlineSite, std::unique_ptr<PseudoProbeInlineTree>,
  42. InlineSiteHash>
  43. Children;
  44. public:
  45. // Inlinee function GUID
  46. uint64_t GUID = 0;
  47. // Inline site to indicate the location in its inliner. As the node could also
  48. // be an outlined function, it will use a dummy InlineSite whose GUID and
  49. // Index is 0 connected to the dummy root
  50. InlineSite ISite;
  51. // Used for decoding
  52. uint32_t ChildrenToProcess = 0;
  53. // Caller node of the inline site
  54. PseudoProbeInlineTree *Parent;
  55. PseudoProbeInlineTree(){};
  56. PseudoProbeInlineTree(const InlineSite &Site) : ISite(Site){};
  57. PseudoProbeInlineTree *getOrAddNode(const InlineSite &Site) {
  58. auto Ret =
  59. Children.emplace(Site, std::make_unique<PseudoProbeInlineTree>(Site));
  60. Ret.first->second->Parent = this;
  61. return Ret.first->second.get();
  62. }
  63. void addProbes(PseudoProbe *Probe) { ProbeVector.push_back(Probe); }
  64. // Return false if it's a dummy inline site
  65. bool hasInlineSite() const { return std::get<0>(ISite) != 0; }
  66. };
  67. // Function descriptor decoded from .pseudo_probe_desc section
  68. struct PseudoProbeFuncDesc {
  69. uint64_t FuncGUID = 0;
  70. uint64_t FuncHash = 0;
  71. std::string FuncName;
  72. PseudoProbeFuncDesc(uint64_t GUID, uint64_t Hash, StringRef Name)
  73. : FuncGUID(GUID), FuncHash(Hash), FuncName(Name){};
  74. void print(raw_ostream &OS);
  75. };
  76. // GUID to PseudoProbeFuncDesc map
  77. using GUIDProbeFunctionMap = std::unordered_map<uint64_t, PseudoProbeFuncDesc>;
  78. // Address to pseudo probes map.
  79. using AddressProbesMap = std::unordered_map<uint64_t, std::vector<PseudoProbe>>;
  80. /*
  81. A pseudo probe has the format like below:
  82. INDEX (ULEB128)
  83. TYPE (uint4)
  84. 0 - block probe, 1 - indirect call, 2 - direct call
  85. ATTRIBUTE (uint3)
  86. 1 - tail call, 2 - dangling
  87. ADDRESS_TYPE (uint1)
  88. 0 - code address, 1 - address delta
  89. CODE_ADDRESS (uint64 or ULEB128)
  90. code address or address delta, depending on Flag
  91. */
  92. struct PseudoProbe {
  93. uint64_t Address;
  94. uint64_t GUID;
  95. uint32_t Index;
  96. PseudoProbeType Type;
  97. uint8_t Attribute;
  98. PseudoProbeInlineTree *InlineTree;
  99. const static uint32_t PseudoProbeFirstId =
  100. static_cast<uint32_t>(PseudoProbeReservedId::Last) + 1;
  101. PseudoProbe(uint64_t Ad, uint64_t G, uint32_t I, PseudoProbeType K,
  102. uint8_t At, PseudoProbeInlineTree *Tree)
  103. : Address(Ad), GUID(G), Index(I), Type(K), Attribute(At),
  104. InlineTree(Tree){};
  105. bool isEntry() const { return Index == PseudoProbeFirstId; }
  106. bool isDangling() const {
  107. return Attribute & static_cast<uint8_t>(PseudoProbeAttributes::DANGLING);
  108. }
  109. bool isTailCall() const {
  110. return Attribute & static_cast<uint8_t>(PseudoProbeAttributes::TAILCALL);
  111. }
  112. bool isBlock() const { return Type == PseudoProbeType::Block; }
  113. bool isIndirectCall() const { return Type == PseudoProbeType::IndirectCall; }
  114. bool isDirectCall() const { return Type == PseudoProbeType::DirectCall; }
  115. bool isCall() const { return isIndirectCall() || isDirectCall(); }
  116. // Get the inlined context by traversing current inline tree backwards,
  117. // each tree node has its InlineSite which is taken as the context.
  118. // \p ContextStack is populated in root to leaf order
  119. void getInlineContext(SmallVectorImpl<std::string> &ContextStack,
  120. const GUIDProbeFunctionMap &GUID2FuncMAP,
  121. bool ShowName) const;
  122. // Helper function to get the string from context stack
  123. std::string getInlineContextStr(const GUIDProbeFunctionMap &GUID2FuncMAP,
  124. bool ShowName) const;
  125. // Print pseudo probe while disassembling
  126. void print(raw_ostream &OS, const GUIDProbeFunctionMap &GUID2FuncMAP,
  127. bool ShowName);
  128. };
  129. /*
  130. Decode pseudo probe info from ELF section, used along with ELF reader
  131. Two sections are decoded here:
  132. 1) \fn buildGUID2FunctionMap is responsible for .pseudo_probe_desc
  133. section which encodes all function descriptors.
  134. 2) \fn buildAddress2ProbeMap is responsible for .pseudoprobe section
  135. which encodes an inline function forest and each tree includes its
  136. inlined function and all pseudo probes inside the function.
  137. see \file MCPseudoProbe.h for the details of the section encoding format.
  138. */
  139. class PseudoProbeDecoder {
  140. // GUID to PseudoProbeFuncDesc map.
  141. GUIDProbeFunctionMap GUID2FuncDescMap;
  142. // Address to probes map.
  143. AddressProbesMap Address2ProbesMap;
  144. // The dummy root of the inline trie, all the outlined function will directly
  145. // be the children of the dummy root, all the inlined function will be the
  146. // children of its inlineer. So the relation would be like:
  147. // DummyRoot --> OutlinedFunc --> InlinedFunc1 --> InlinedFunc2
  148. PseudoProbeInlineTree DummyInlineRoot;
  149. /// Points to the current location in the buffer.
  150. const uint8_t *Data = nullptr;
  151. /// Points to the end of the buffer.
  152. const uint8_t *End = nullptr;
  153. /// SectionName used for debug
  154. std::string SectionName;
  155. // Decoding helper function
  156. template <typename T> T readUnencodedNumber();
  157. template <typename T> T readUnsignedNumber();
  158. template <typename T> T readSignedNumber();
  159. StringRef readString(uint32_t Size);
  160. public:
  161. // Decode pseudo_probe_desc section to build GUID to PseudoProbeFuncDesc map.
  162. void buildGUID2FuncDescMap(const uint8_t *Start, std::size_t Size);
  163. // Decode pseudo_probe section to build address to probes map.
  164. void buildAddress2ProbeMap(const uint8_t *Start, std::size_t Size);
  165. // Print pseudo_probe_desc section info
  166. void printGUID2FuncDescMap(raw_ostream &OS);
  167. // Print pseudo_probe section info, used along with show-disassembly
  168. void printProbeForAddress(raw_ostream &OS, uint64_t Address);
  169. // Look up the probe of a call for the input address
  170. const PseudoProbe *getCallProbeForAddr(uint64_t Address) const;
  171. const PseudoProbeFuncDesc *getFuncDescForGUID(uint64_t GUID) const;
  172. // Helper function to populate one probe's inline stack into
  173. // \p InlineContextStack.
  174. // Current leaf location info will be added if IncludeLeaf is true
  175. // Example:
  176. // Current probe(bar:3) inlined at foo:2 then inlined at main:1
  177. // IncludeLeaf = true, Output: [main:1, foo:2, bar:3]
  178. // IncludeLeaf = false, Output: [main:1, foo:2]
  179. void
  180. getInlineContextForProbe(const PseudoProbe *Probe,
  181. SmallVectorImpl<std::string> &InlineContextStack,
  182. bool IncludeLeaf) const;
  183. const AddressProbesMap &getAddress2ProbesMap() const {
  184. return Address2ProbesMap;
  185. }
  186. const PseudoProbeFuncDesc *
  187. getInlinerDescForProbe(const PseudoProbe *Probe) const;
  188. };
  189. } // end namespace sampleprof
  190. } // end namespace llvm
  191. #endif