Subversion Repositories QNX 8.QNX8 LLVM/Clang compiler suite

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
14 pmbaty 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's source name which may be different from the
19
//        actual binary linkage name. This GUID will be used to decode and
20
//        generate a profile against the source function name.
21
//    NPROBES (ULEB128)
22
//        Number of probes originating from this function.
23
//    NUM_INLINED_FUNCTIONS (ULEB128)
24
//        Number of callees inlined into this function, aka number of
25
//        first-level inlinees
26
//    PROBE RECORDS
27
//        A list of NPROBES entries. Each entry contains:
28
//          INDEX (ULEB128)
29
//          TYPE (uint4)
30
//            0 - block probe, 1 - indirect call, 2 - direct call
31
//          ATTRIBUTE (uint3)
32
//            1 - reserved
33
//          ADDRESS_TYPE (uint1)
34
//            0 - code address for regular probes (for downwards compatibility)
35
//              - GUID of linkage name for sentinel probes
36
//            1 - address delta
37
//          CODE_ADDRESS (uint64 or ULEB128)
38
//            code address or address delta, depending on ADDRESS_TYPE
39
//    INLINED FUNCTION RECORDS
40
//        A list of NUM_INLINED_FUNCTIONS entries describing each of the inlined
41
//        callees.  Each record contains:
42
//          INLINE SITE
43
//            ID of the callsite probe (ULEB128)
44
//          FUNCTION BODY
45
//            A FUNCTION BODY entry describing the inlined function.
46
//
47
// TODO: retire the ADDRESS_TYPE encoding for code addresses once compatibility
48
// is no longer an issue.
49
//===----------------------------------------------------------------------===//
50
 
51
#ifndef LLVM_MC_MCPSEUDOPROBE_H
52
#define LLVM_MC_MCPSEUDOPROBE_H
53
 
54
#include "llvm/ADT/DenseSet.h"
55
#include "llvm/ADT/SmallVector.h"
56
#include "llvm/ADT/StringRef.h"
57
#include "llvm/IR/PseudoProbe.h"
58
#include "llvm/Support/ErrorOr.h"
59
#include <list>
60
#include <map>
61
#include <memory>
62
#include <string>
63
#include <tuple>
64
#include <type_traits>
65
#include <unordered_map>
66
#include <unordered_set>
67
#include <vector>
68
 
69
namespace llvm {
70
 
71
class MCSymbol;
72
class MCObjectStreamer;
73
class raw_ostream;
74
 
75
enum class MCPseudoProbeFlag {
76
  // If set, indicates that the probe is encoded as an address delta
77
  // instead of a real code address.
78
  AddressDelta = 0x1,
79
};
80
 
81
// Function descriptor decoded from .pseudo_probe_desc section
82
struct MCPseudoProbeFuncDesc {
83
  uint64_t FuncGUID = 0;
84
  uint64_t FuncHash = 0;
85
  std::string FuncName;
86
 
87
  MCPseudoProbeFuncDesc(uint64_t GUID, uint64_t Hash, StringRef Name)
88
      : FuncGUID(GUID), FuncHash(Hash), FuncName(Name){};
89
 
90
  void print(raw_ostream &OS);
91
};
92
 
93
class MCDecodedPseudoProbe;
94
 
95
// An inline frame has the form <CalleeGuid, ProbeID>
96
using InlineSite = std::tuple<uint64_t, uint32_t>;
97
using MCPseudoProbeInlineStack = SmallVector<InlineSite, 8>;
98
// GUID to PseudoProbeFuncDesc map
99
using GUIDProbeFunctionMap =
100
    std::unordered_map<uint64_t, MCPseudoProbeFuncDesc>;
101
// Address to pseudo probes map.
102
using AddressProbesMap =
103
    std::unordered_map<uint64_t, std::list<MCDecodedPseudoProbe>>;
104
 
105
class MCDecodedPseudoProbeInlineTree;
106
 
107
class MCPseudoProbeBase {
108
protected:
109
  uint64_t Guid;
110
  uint64_t Index;
111
  uint8_t Attributes;
112
  uint8_t Type;
113
  // The value should be equal to PseudoProbeReservedId::Last + 1 which is
114
  // defined in SampleProfileProbe.h. The header file is not included here to
115
  // reduce the dependency from MC to IPO.
116
  const static uint32_t PseudoProbeFirstId = 1;
117
 
118
public:
119
  MCPseudoProbeBase(uint64_t G, uint64_t I, uint64_t At, uint8_t T)
120
      : Guid(G), Index(I), Attributes(At), Type(T) {}
121
 
122
  bool isEntry() const { return Index == PseudoProbeFirstId; }
123
 
124
  uint64_t getGuid() const { return Guid; }
125
 
126
  uint64_t getIndex() const { return Index; }
127
 
128
  uint8_t getAttributes() const { return Attributes; }
129
 
130
  uint8_t getType() const { return Type; }
131
 
132
  bool isBlock() const {
133
    return Type == static_cast<uint8_t>(PseudoProbeType::Block);
134
  }
135
 
136
  bool isIndirectCall() const {
137
    return Type == static_cast<uint8_t>(PseudoProbeType::IndirectCall);
138
  }
139
 
140
  bool isDirectCall() const {
141
    return Type == static_cast<uint8_t>(PseudoProbeType::DirectCall);
142
  }
143
 
144
  bool isCall() const { return isIndirectCall() || isDirectCall(); }
145
 
146
  void setAttributes(uint8_t Attr) { Attributes = Attr; }
147
};
148
 
149
/// Instances of this class represent a pseudo probe instance for a pseudo probe
150
/// table entry, which is created during a machine instruction is assembled and
151
/// uses an address from a temporary label created at the current address in the
152
/// current section.
153
class MCPseudoProbe : public MCPseudoProbeBase {
154
  MCSymbol *Label;
155
 
156
public:
157
  MCPseudoProbe(MCSymbol *Label, uint64_t Guid, uint64_t Index, uint64_t Type,
158
                uint64_t Attributes)
159
      : MCPseudoProbeBase(Guid, Index, Attributes, Type), Label(Label) {
160
    assert(Type <= 0xFF && "Probe type too big to encode, exceeding 2^8");
161
    assert(Attributes <= 0xFF &&
162
           "Probe attributes too big to encode, exceeding 2^16");
163
  }
164
 
165
  MCSymbol *getLabel() const { return Label; }
166
  void emit(MCObjectStreamer *MCOS, const MCPseudoProbe *LastProbe) const;
167
};
168
 
169
// Represents a callsite with caller function name and probe id
170
using MCPseduoProbeFrameLocation = std::pair<StringRef, uint32_t>;
171
 
172
class MCDecodedPseudoProbe : public MCPseudoProbeBase {
173
  uint64_t Address;
174
  MCDecodedPseudoProbeInlineTree *InlineTree;
175
 
176
public:
177
  MCDecodedPseudoProbe(uint64_t Ad, uint64_t G, uint32_t I, PseudoProbeType K,
178
                       uint8_t At, MCDecodedPseudoProbeInlineTree *Tree)
179
      : MCPseudoProbeBase(G, I, At, static_cast<uint8_t>(K)), Address(Ad),
180
        InlineTree(Tree){};
181
 
182
  uint64_t getAddress() const { return Address; }
183
 
184
  void setAddress(uint64_t Addr) { Address = Addr; }
185
 
186
  MCDecodedPseudoProbeInlineTree *getInlineTreeNode() const {
187
    return InlineTree;
188
  }
189
 
190
  // Get the inlined context by traversing current inline tree backwards,
191
  // each tree node has its InlineSite which is taken as the context.
192
  // \p ContextStack is populated in root to leaf order
193
  void
194
  getInlineContext(SmallVectorImpl<MCPseduoProbeFrameLocation> &ContextStack,
195
                   const GUIDProbeFunctionMap &GUID2FuncMAP) const;
196
 
197
  // Helper function to get the string from context stack
198
  std::string
199
  getInlineContextStr(const GUIDProbeFunctionMap &GUID2FuncMAP) const;
200
 
201
  // Print pseudo probe while disassembling
202
  void print(raw_ostream &OS, const GUIDProbeFunctionMap &GUID2FuncMAP,
203
             bool ShowName) const;
204
};
205
 
206
template <typename ProbeType, typename DerivedProbeInlineTreeType>
207
class MCPseudoProbeInlineTreeBase {
208
  struct InlineSiteHash {
209
    uint64_t operator()(const InlineSite &Site) const {
210
      return std::get<0>(Site) ^ std::get<1>(Site);
211
    }
212
  };
213
 
214
protected:
215
  // Track children (e.g. inlinees) of current context
216
  using InlinedProbeTreeMap = std::unordered_map<
217
      InlineSite, std::unique_ptr<DerivedProbeInlineTreeType>, InlineSiteHash>;
218
  InlinedProbeTreeMap Children;
219
  // Set of probes that come with the function.
220
  std::vector<ProbeType> Probes;
221
  MCPseudoProbeInlineTreeBase() {
222
    static_assert(std::is_base_of<MCPseudoProbeInlineTreeBase,
223
                                  DerivedProbeInlineTreeType>::value,
224
                  "DerivedProbeInlineTreeType must be subclass of "
225
                  "MCPseudoProbeInlineTreeBase");
226
  }
227
 
228
public:
229
  uint64_t Guid = 0;
230
 
231
  // Root node has a GUID 0.
232
  bool isRoot() const { return Guid == 0; }
233
  InlinedProbeTreeMap &getChildren() { return Children; }
234
  const InlinedProbeTreeMap &getChildren() const { return Children; }
235
  std::vector<ProbeType> &getProbes() { return Probes; }
236
  void addProbes(ProbeType Probe) { Probes.push_back(Probe); }
237
  // Caller node of the inline site
238
  MCPseudoProbeInlineTreeBase<ProbeType, DerivedProbeInlineTreeType> *Parent;
239
  DerivedProbeInlineTreeType *getOrAddNode(const InlineSite &Site) {
240
    auto Ret = Children.emplace(
241
        Site, std::make_unique<DerivedProbeInlineTreeType>(Site));
242
    Ret.first->second->Parent = this;
243
    return Ret.first->second.get();
244
  };
245
};
246
 
247
// A Tri-tree based data structure to group probes by inline stack.
248
// A tree is allocated for a standalone .text section. A fake
249
// instance is created as the root of a tree.
250
// A real instance of this class is created for each function, either a
251
// not inlined function that has code in .text section or an inlined function.
252
class MCPseudoProbeInlineTree
253
    : public MCPseudoProbeInlineTreeBase<MCPseudoProbe,
254
                                         MCPseudoProbeInlineTree> {
255
public:
256
  MCPseudoProbeInlineTree() = default;
257
  MCPseudoProbeInlineTree(uint64_t Guid) { this->Guid = Guid; }
258
  MCPseudoProbeInlineTree(const InlineSite &Site) {
259
    this->Guid = std::get<0>(Site);
260
  }
261
 
262
  // MCPseudoProbeInlineTree method based on Inlinees
263
  void addPseudoProbe(const MCPseudoProbe &Probe,
264
                      const MCPseudoProbeInlineStack &InlineStack);
265
  void emit(MCObjectStreamer *MCOS, const MCPseudoProbe *&LastProbe);
266
};
267
 
268
// inline tree node for the decoded pseudo probe
269
class MCDecodedPseudoProbeInlineTree
270
    : public MCPseudoProbeInlineTreeBase<MCDecodedPseudoProbe *,
271
                                         MCDecodedPseudoProbeInlineTree> {
272
public:
273
  InlineSite ISite;
274
  // Used for decoding
275
  uint32_t ChildrenToProcess = 0;
276
 
277
  MCDecodedPseudoProbeInlineTree() = default;
278
  MCDecodedPseudoProbeInlineTree(const InlineSite &Site) : ISite(Site){};
279
 
280
  // Return false if it's a dummy inline site
281
  bool hasInlineSite() const { return !isRoot() && !Parent->isRoot(); }
282
};
283
 
284
/// Instances of this class represent the pseudo probes inserted into a compile
285
/// unit.
286
class MCPseudoProbeSections {
287
public:
288
  void addPseudoProbe(MCSymbol *FuncSym, const MCPseudoProbe &Probe,
289
                      const MCPseudoProbeInlineStack &InlineStack) {
290
    MCProbeDivisions[FuncSym].addPseudoProbe(Probe, InlineStack);
291
  }
292
 
293
  // TODO: Sort by getOrdinal to ensure a determinstic section order
294
  using MCProbeDivisionMap = std::map<MCSymbol *, MCPseudoProbeInlineTree>;
295
 
296
private:
297
  // A collection of MCPseudoProbe for each function. The MCPseudoProbes are
298
  // grouped by GUIDs due to inlining that can bring probes from different
299
  // functions into one function.
300
  MCProbeDivisionMap MCProbeDivisions;
301
 
302
public:
303
  const MCProbeDivisionMap &getMCProbes() const { return MCProbeDivisions; }
304
 
305
  bool empty() const { return MCProbeDivisions.empty(); }
306
 
307
  void emit(MCObjectStreamer *MCOS);
308
};
309
 
310
class MCPseudoProbeTable {
311
  // A collection of MCPseudoProbe in the current module grouped by
312
  // functions. MCPseudoProbes will be encoded into a corresponding
313
  // .pseudoprobe section. With functions emitted as separate comdats,
314
  // a text section really only contains the code of a function solely, and the
315
  // probes associated with the text section will be emitted into a standalone
316
  // .pseudoprobe section that shares the same comdat group with the function.
317
  MCPseudoProbeSections MCProbeSections;
318
 
319
public:
320
  static void emit(MCObjectStreamer *MCOS);
321
 
322
  MCPseudoProbeSections &getProbeSections() { return MCProbeSections; }
323
 
324
#ifndef NDEBUG
325
  static int DdgPrintIndent;
326
#endif
327
};
328
 
329
class MCPseudoProbeDecoder {
330
  // GUID to PseudoProbeFuncDesc map.
331
  GUIDProbeFunctionMap GUID2FuncDescMap;
332
 
333
  // Address to probes map.
334
  AddressProbesMap Address2ProbesMap;
335
 
336
  // The dummy root of the inline trie, all the outlined function will directly
337
  // be the children of the dummy root, all the inlined function will be the
338
  // children of its inlineer. So the relation would be like:
339
  // DummyRoot --> OutlinedFunc --> InlinedFunc1 --> InlinedFunc2
340
  MCDecodedPseudoProbeInlineTree DummyInlineRoot;
341
 
342
  /// Points to the current location in the buffer.
343
  const uint8_t *Data = nullptr;
344
 
345
  /// Points to the end of the buffer.
346
  const uint8_t *End = nullptr;
347
 
348
  /// Whether encoding is based on a starting probe with absolute code address.
349
  bool EncodingIsAddrBased = false;
350
 
351
  // Decoding helper function
352
  template <typename T> ErrorOr<T> readUnencodedNumber();
353
  template <typename T> ErrorOr<T> readUnsignedNumber();
354
  template <typename T> ErrorOr<T> readSignedNumber();
355
  ErrorOr<StringRef> readString(uint32_t Size);
356
 
357
public:
358
  using Uint64Set = DenseSet<uint64_t>;
359
  using Uint64Map = DenseMap<uint64_t, uint64_t>;
360
 
361
  // Decode pseudo_probe_desc section to build GUID to PseudoProbeFuncDesc map.
362
  bool buildGUID2FuncDescMap(const uint8_t *Start, std::size_t Size);
363
 
364
  // Decode pseudo_probe section to build address to probes map for specifed
365
  // functions only.
366
  bool buildAddress2ProbeMap(const uint8_t *Start, std::size_t Size,
367
                             const Uint64Set &GuildFilter,
368
                             const Uint64Map &FuncStartAddrs);
369
 
370
  bool buildAddress2ProbeMap(MCDecodedPseudoProbeInlineTree *Cur,
371
                             uint64_t &LastAddr, const Uint64Set &GuildFilter,
372
                             const Uint64Map &FuncStartAddrs);
373
 
374
  // Print pseudo_probe_desc section info
375
  void printGUID2FuncDescMap(raw_ostream &OS);
376
 
377
  // Print pseudo_probe section info, used along with show-disassembly
378
  void printProbeForAddress(raw_ostream &OS, uint64_t Address);
379
 
380
  // do printProbeForAddress for all addresses
381
  void printProbesForAllAddresses(raw_ostream &OS);
382
 
383
  // Look up the probe of a call for the input address
384
  const MCDecodedPseudoProbe *getCallProbeForAddr(uint64_t Address) const;
385
 
386
  const MCPseudoProbeFuncDesc *getFuncDescForGUID(uint64_t GUID) const;
387
 
388
  // Helper function to populate one probe's inline stack into
389
  // \p InlineContextStack.
390
  // Current leaf location info will be added if IncludeLeaf is true
391
  // Example:
392
  //  Current probe(bar:3) inlined at foo:2 then inlined at main:1
393
  //  IncludeLeaf = true,  Output: [main:1, foo:2, bar:3]
394
  //  IncludeLeaf = false, Output: [main:1, foo:2]
395
  void getInlineContextForProbe(
396
      const MCDecodedPseudoProbe *Probe,
397
      SmallVectorImpl<MCPseduoProbeFrameLocation> &InlineContextStack,
398
      bool IncludeLeaf) const;
399
 
400
  const AddressProbesMap &getAddress2ProbesMap() const {
401
    return Address2ProbesMap;
402
  }
403
 
404
  AddressProbesMap &getAddress2ProbesMap() { return Address2ProbesMap; }
405
 
406
  const GUIDProbeFunctionMap &getGUID2FuncDescMap() const {
407
    return GUID2FuncDescMap;
408
  }
409
 
410
  const MCPseudoProbeFuncDesc *
411
  getInlinerDescForProbe(const MCDecodedPseudoProbe *Probe) const;
412
 
413
  const MCDecodedPseudoProbeInlineTree &getDummyInlineRoot() const {
414
    return DummyInlineRoot;
415
  }
416
};
417
 
418
} // end namespace llvm
419
 
420
#endif // LLVM_MC_MCPSEUDOPROBE_H