123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231 |
- //===--- PseudoProbe.h - Pseudo probe decoding utilities ---------*- C++-*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #ifndef LLVM_TOOLS_LLVM_PROFGEN_PSEUDOPROBE_H
- #define LLVM_TOOLS_LLVM_PROFGEN_PSEUDOPROBE_H
- #include "llvm/ADT/StringRef.h"
- #include "llvm/ADT/Twine.h"
- #include "llvm/IR/PseudoProbe.h"
- #include "llvm/Support/raw_ostream.h"
- #include "llvm/Transforms/IPO/SampleProfileProbe.h"
- #include <algorithm>
- #include <set>
- #include <sstream>
- #include <string>
- #include <unordered_map>
- #include <unordered_set>
- #include <vector>
- namespace llvm {
- namespace sampleprof {
- enum PseudoProbeAttributes { TAILCALL = 1, DANGLING = 2 };
- // Use func GUID and index as the location info of the inline site
- using InlineSite = std::tuple<uint64_t, uint32_t>;
- struct PseudoProbe;
- // Tree node to represent the inline relation and its inline site, we use a
- // dummy root in the PseudoProbeDecoder to lead the tree, the outlined
- // function will directly be the children of the dummy root. For the inlined
- // function, all the inlinee will be connected to its inlineer, then further to
- // its outlined function. Pseudo probes originating from the function stores the
- // tree's leaf node which we can process backwards to get its inline context
- class PseudoProbeInlineTree {
- std::vector<PseudoProbe *> ProbeVector;
- struct InlineSiteHash {
- uint64_t operator()(const InlineSite &Site) const {
- return std::get<0>(Site) ^ std::get<1>(Site);
- }
- };
- std::unordered_map<InlineSite, std::unique_ptr<PseudoProbeInlineTree>,
- InlineSiteHash>
- Children;
- public:
- // Inlinee function GUID
- uint64_t GUID = 0;
- // Inline site to indicate the location in its inliner. As the node could also
- // be an outlined function, it will use a dummy InlineSite whose GUID and
- // Index is 0 connected to the dummy root
- InlineSite ISite;
- // Used for decoding
- uint32_t ChildrenToProcess = 0;
- // Caller node of the inline site
- PseudoProbeInlineTree *Parent;
- PseudoProbeInlineTree(){};
- PseudoProbeInlineTree(const InlineSite &Site) : ISite(Site){};
- PseudoProbeInlineTree *getOrAddNode(const InlineSite &Site) {
- auto Ret =
- Children.emplace(Site, std::make_unique<PseudoProbeInlineTree>(Site));
- Ret.first->second->Parent = this;
- return Ret.first->second.get();
- }
- void addProbes(PseudoProbe *Probe) { ProbeVector.push_back(Probe); }
- // Return false if it's a dummy inline site
- bool hasInlineSite() const { return std::get<0>(ISite) != 0; }
- };
- // Function descriptor decoded from .pseudo_probe_desc section
- struct PseudoProbeFuncDesc {
- uint64_t FuncGUID = 0;
- uint64_t FuncHash = 0;
- std::string FuncName;
- PseudoProbeFuncDesc(uint64_t GUID, uint64_t Hash, StringRef Name)
- : FuncGUID(GUID), FuncHash(Hash), FuncName(Name){};
- void print(raw_ostream &OS);
- };
- // GUID to PseudoProbeFuncDesc map
- using GUIDProbeFunctionMap = std::unordered_map<uint64_t, PseudoProbeFuncDesc>;
- // Address to pseudo probes map.
- using AddressProbesMap = std::unordered_map<uint64_t, std::vector<PseudoProbe>>;
- /*
- A pseudo probe has the format like below:
- INDEX (ULEB128)
- TYPE (uint4)
- 0 - block probe, 1 - indirect call, 2 - direct call
- ATTRIBUTE (uint3)
- 1 - tail call, 2 - dangling
- ADDRESS_TYPE (uint1)
- 0 - code address, 1 - address delta
- CODE_ADDRESS (uint64 or ULEB128)
- code address or address delta, depending on Flag
- */
- struct PseudoProbe {
- uint64_t Address;
- uint64_t GUID;
- uint32_t Index;
- PseudoProbeType Type;
- uint8_t Attribute;
- PseudoProbeInlineTree *InlineTree;
- const static uint32_t PseudoProbeFirstId =
- static_cast<uint32_t>(PseudoProbeReservedId::Last) + 1;
- PseudoProbe(uint64_t Ad, uint64_t G, uint32_t I, PseudoProbeType K,
- uint8_t At, PseudoProbeInlineTree *Tree)
- : Address(Ad), GUID(G), Index(I), Type(K), Attribute(At),
- InlineTree(Tree){};
- bool isEntry() const { return Index == PseudoProbeFirstId; }
- bool isDangling() const {
- return Attribute & static_cast<uint8_t>(PseudoProbeAttributes::DANGLING);
- }
- bool isTailCall() const {
- return Attribute & static_cast<uint8_t>(PseudoProbeAttributes::TAILCALL);
- }
- bool isBlock() const { return Type == PseudoProbeType::Block; }
- bool isIndirectCall() const { return Type == PseudoProbeType::IndirectCall; }
- bool isDirectCall() const { return Type == PseudoProbeType::DirectCall; }
- bool isCall() const { return isIndirectCall() || isDirectCall(); }
- // Get the inlined context by traversing current inline tree backwards,
- // each tree node has its InlineSite which is taken as the context.
- // \p ContextStack is populated in root to leaf order
- void getInlineContext(SmallVectorImpl<std::string> &ContextStack,
- const GUIDProbeFunctionMap &GUID2FuncMAP,
- bool ShowName) const;
- // Helper function to get the string from context stack
- std::string getInlineContextStr(const GUIDProbeFunctionMap &GUID2FuncMAP,
- bool ShowName) const;
- // Print pseudo probe while disassembling
- void print(raw_ostream &OS, const GUIDProbeFunctionMap &GUID2FuncMAP,
- bool ShowName);
- };
- /*
- Decode pseudo probe info from ELF section, used along with ELF reader
- Two sections are decoded here:
- 1) \fn buildGUID2FunctionMap is responsible for .pseudo_probe_desc
- section which encodes all function descriptors.
- 2) \fn buildAddress2ProbeMap is responsible for .pseudoprobe section
- which encodes an inline function forest and each tree includes its
- inlined function and all pseudo probes inside the function.
- see \file MCPseudoProbe.h for the details of the section encoding format.
- */
- class PseudoProbeDecoder {
- // GUID to PseudoProbeFuncDesc map.
- GUIDProbeFunctionMap GUID2FuncDescMap;
- // Address to probes map.
- AddressProbesMap Address2ProbesMap;
- // The dummy root of the inline trie, all the outlined function will directly
- // be the children of the dummy root, all the inlined function will be the
- // children of its inlineer. So the relation would be like:
- // DummyRoot --> OutlinedFunc --> InlinedFunc1 --> InlinedFunc2
- PseudoProbeInlineTree DummyInlineRoot;
- /// Points to the current location in the buffer.
- const uint8_t *Data = nullptr;
- /// Points to the end of the buffer.
- const uint8_t *End = nullptr;
- /// SectionName used for debug
- std::string SectionName;
- // Decoding helper function
- template <typename T> T readUnencodedNumber();
- template <typename T> T readUnsignedNumber();
- template <typename T> T readSignedNumber();
- StringRef readString(uint32_t Size);
- public:
- // Decode pseudo_probe_desc section to build GUID to PseudoProbeFuncDesc map.
- void buildGUID2FuncDescMap(const uint8_t *Start, std::size_t Size);
- // Decode pseudo_probe section to build address to probes map.
- void buildAddress2ProbeMap(const uint8_t *Start, std::size_t Size);
- // Print pseudo_probe_desc section info
- void printGUID2FuncDescMap(raw_ostream &OS);
- // Print pseudo_probe section info, used along with show-disassembly
- void printProbeForAddress(raw_ostream &OS, uint64_t Address);
- // Look up the probe of a call for the input address
- const PseudoProbe *getCallProbeForAddr(uint64_t Address) const;
- const PseudoProbeFuncDesc *getFuncDescForGUID(uint64_t GUID) const;
- // Helper function to populate one probe's inline stack into
- // \p InlineContextStack.
- // Current leaf location info will be added if IncludeLeaf is true
- // Example:
- // Current probe(bar:3) inlined at foo:2 then inlined at main:1
- // IncludeLeaf = true, Output: [main:1, foo:2, bar:3]
- // IncludeLeaf = false, Output: [main:1, foo:2]
- void
- getInlineContextForProbe(const PseudoProbe *Probe,
- SmallVectorImpl<std::string> &InlineContextStack,
- bool IncludeLeaf) const;
- const AddressProbesMap &getAddress2ProbesMap() const {
- return Address2ProbesMap;
- }
- const PseudoProbeFuncDesc *
- getInlinerDescForProbe(const PseudoProbe *Probe) const;
- };
- } // end namespace sampleprof
- } // end namespace llvm
- #endif
|