MCPseudoProbe.h 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. //===- MCPseudoProbe.h - Pseudo probe encoding support ---------*- 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. // This file contains the declaration of the MCPseudoProbe to support the pseudo
  10. // probe encoding for AutoFDO. Pseudo probes together with their inline context
  11. // are encoded in a DFS recursive way in the .pseudoprobe sections. For each
  12. // .pseudoprobe section, the encoded binary data consist of a single or mutiple
  13. // function records each for one outlined function. A function record has the
  14. // following format :
  15. //
  16. // FUNCTION BODY (one for each outlined function present in the text section)
  17. // GUID (uint64)
  18. // GUID of the function
  19. // NPROBES (ULEB128)
  20. // Number of probes originating from this function.
  21. // NUM_INLINED_FUNCTIONS (ULEB128)
  22. // Number of callees inlined into this function, aka number of
  23. // first-level inlinees
  24. // PROBE RECORDS
  25. // A list of NPROBES entries. Each entry contains:
  26. // INDEX (ULEB128)
  27. // TYPE (uint4)
  28. // 0 - block probe, 1 - indirect call, 2 - direct call
  29. // ATTRIBUTE (uint3)
  30. // 1 - reserved, 2 - dangling
  31. // ADDRESS_TYPE (uint1)
  32. // 0 - code address, 1 - address delta
  33. // CODE_ADDRESS (uint64 or ULEB128)
  34. // code address or address delta, depending on ADDRESS_TYPE
  35. // INLINED FUNCTION RECORDS
  36. // A list of NUM_INLINED_FUNCTIONS entries describing each of the inlined
  37. // callees. Each record contains:
  38. // INLINE SITE
  39. // ID of the callsite probe (ULEB128)
  40. // FUNCTION BODY
  41. // A FUNCTION BODY entry describing the inlined function.
  42. //===----------------------------------------------------------------------===//
  43. #ifndef LLVM_MC_MCPSEUDOPROBE_H
  44. #define LLVM_MC_MCPSEUDOPROBE_H
  45. #include "llvm/ADT/MapVector.h"
  46. #include "llvm/MC/MCSection.h"
  47. #include <functional>
  48. #include <map>
  49. #include <vector>
  50. namespace llvm {
  51. class MCStreamer;
  52. class MCSymbol;
  53. class MCObjectStreamer;
  54. enum class MCPseudoProbeFlag {
  55. // If set, indicates that the probe is encoded as an address delta
  56. // instead of a real code address.
  57. AddressDelta = 0x1,
  58. };
  59. /// Instances of this class represent a pseudo probe instance for a pseudo probe
  60. /// table entry, which is created during a machine instruction is assembled and
  61. /// uses an address from a temporary label created at the current address in the
  62. /// current section.
  63. class MCPseudoProbe {
  64. MCSymbol *Label;
  65. uint64_t Guid;
  66. uint64_t Index;
  67. uint8_t Type;
  68. uint8_t Attributes;
  69. public:
  70. MCPseudoProbe(MCSymbol *Label, uint64_t Guid, uint64_t Index, uint64_t Type,
  71. uint64_t Attributes)
  72. : Label(Label), Guid(Guid), Index(Index), Type(Type),
  73. Attributes(Attributes) {
  74. assert(Type <= 0xFF && "Probe type too big to encode, exceeding 2^8");
  75. assert(Attributes <= 0xFF &&
  76. "Probe attributes too big to encode, exceeding 2^16");
  77. }
  78. MCSymbol *getLabel() const { return Label; }
  79. uint64_t getGuid() const { return Guid; }
  80. uint64_t getIndex() const { return Index; }
  81. uint8_t getType() const { return Type; }
  82. uint8_t getAttributes() const { return Attributes; }
  83. void emit(MCObjectStreamer *MCOS, const MCPseudoProbe *LastProbe) const;
  84. };
  85. // An inline frame has the form <Guid, ProbeID>
  86. using InlineSite = std::tuple<uint64_t, uint32_t>;
  87. using MCPseudoProbeInlineStack = SmallVector<InlineSite, 8>;
  88. // A Tri-tree based data structure to group probes by inline stack.
  89. // A tree is allocated for a standalone .text section. A fake
  90. // instance is created as the root of a tree.
  91. // A real instance of this class is created for each function, either an
  92. // unlined function that has code in .text section or an inlined function.
  93. class MCPseudoProbeInlineTree {
  94. uint64_t Guid;
  95. // Set of probes that come with the function.
  96. std::vector<MCPseudoProbe> Probes;
  97. // Use std::map for a deterministic output.
  98. std::map<InlineSite, MCPseudoProbeInlineTree *> Inlinees;
  99. // Root node has a GUID 0.
  100. bool isRoot() { return Guid == 0; }
  101. MCPseudoProbeInlineTree *getOrAddNode(InlineSite Site);
  102. public:
  103. MCPseudoProbeInlineTree() = default;
  104. MCPseudoProbeInlineTree(uint64_t Guid) : Guid(Guid) {}
  105. ~MCPseudoProbeInlineTree();
  106. void addPseudoProbe(const MCPseudoProbe &Probe,
  107. const MCPseudoProbeInlineStack &InlineStack);
  108. void emit(MCObjectStreamer *MCOS, const MCPseudoProbe *&LastProbe);
  109. };
  110. /// Instances of this class represent the pseudo probes inserted into a compile
  111. /// unit.
  112. class MCPseudoProbeSection {
  113. public:
  114. void addPseudoProbe(MCSection *Sec, const MCPseudoProbe &Probe,
  115. const MCPseudoProbeInlineStack &InlineStack) {
  116. MCProbeDivisions[Sec].addPseudoProbe(Probe, InlineStack);
  117. }
  118. // TODO: Sort by getOrdinal to ensure a determinstic section order
  119. using MCProbeDivisionMap = std::map<MCSection *, MCPseudoProbeInlineTree>;
  120. private:
  121. // A collection of MCPseudoProbe for each text section. The MCPseudoProbes
  122. // are grouped by GUID of the functions where they are from and will be
  123. // encoded by groups. In the comdat scenario where a text section really only
  124. // contains the code of a function solely, the probes associated with a comdat
  125. // function are still grouped by GUIDs due to inlining that can bring probes
  126. // from different functions into one function.
  127. MCProbeDivisionMap MCProbeDivisions;
  128. public:
  129. const MCProbeDivisionMap &getMCProbes() const { return MCProbeDivisions; }
  130. bool empty() const { return MCProbeDivisions.empty(); }
  131. void emit(MCObjectStreamer *MCOS);
  132. };
  133. class MCPseudoProbeTable {
  134. // A collection of MCPseudoProbe in the current module grouped by text
  135. // sections. MCPseudoProbes will be encoded into a corresponding
  136. // .pseudoprobe section. With functions emitted as separate comdats,
  137. // a text section really only contains the code of a function solely, and the
  138. // probes associated with the text section will be emitted into a standalone
  139. // .pseudoprobe section that shares the same comdat group with the function.
  140. MCPseudoProbeSection MCProbeSections;
  141. public:
  142. static void emit(MCObjectStreamer *MCOS);
  143. MCPseudoProbeSection &getProbeSections() { return MCProbeSections; }
  144. #ifndef NDEBUG
  145. static int DdgPrintIndent;
  146. #endif
  147. };
  148. } // end namespace llvm
  149. #endif // LLVM_MC_MCPSEUDOPROBE_H