xref: /llvm-project/bolt/include/bolt/Profile/YAMLProfileWriter.h (revision cd774c873c891776403ada6962d3f1602efd4054)
1 //===- bolt/Profile/YAMLProfileWriter.h - Write profile in YAML -*- 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 #ifndef BOLT_PROFILE_YAML_PROFILE_WRITER_H
10 #define BOLT_PROFILE_YAML_PROFILE_WRITER_H
11 
12 #include "bolt/Profile/ProfileYAMLMapping.h"
13 #include "llvm/Support/raw_ostream.h"
14 #include <system_error>
15 
16 namespace llvm {
17 namespace bolt {
18 class BoltAddressTranslation;
19 class RewriteInstance;
20 
21 class YAMLProfileWriter {
22   YAMLProfileWriter() = delete;
23 
24   std::string Filename;
25 
26   std::unique_ptr<raw_fd_ostream> OS;
27 
28 public:
29   explicit YAMLProfileWriter(const std::string &Filename)
30       : Filename(Filename) {}
31 
32   /// Save execution profile for that instance.
33   std::error_code writeProfile(const RewriteInstance &RI);
34 
35   using InlineTreeMapTy =
36       DenseMap<const MCDecodedPseudoProbeInlineTree *, uint32_t>;
37   struct InlineTreeDesc {
38     template <typename T> using GUIDMapTy = std::unordered_map<uint64_t, T>;
39     using GUIDNodeMap = GUIDMapTy<const MCDecodedPseudoProbeInlineTree *>;
40     using GUIDNumMap = GUIDMapTy<uint32_t>;
41     GUIDNodeMap TopLevelGUIDToInlineTree;
42     GUIDNumMap GUIDIdxMap;
43     GUIDNumMap HashIdxMap;
44   };
45 
46   static std::tuple<std::vector<yaml::bolt::InlineTreeNode>, InlineTreeMapTy>
47   convertBFInlineTree(const MCPseudoProbeDecoder &Decoder,
48                       const InlineTreeDesc &InlineTree, uint64_t GUID);
49 
50   static std::tuple<yaml::bolt::ProfilePseudoProbeDesc, InlineTreeDesc>
51   convertPseudoProbeDesc(const MCPseudoProbeDecoder &PseudoProbeDecoder);
52 
53   static yaml::bolt::BinaryFunctionProfile
54   convert(const BinaryFunction &BF, bool UseDFS,
55           const InlineTreeDesc &InlineTree,
56           const BoltAddressTranslation *BAT = nullptr);
57 
58   /// Set CallSiteInfo destination fields from \p Symbol and return a target
59   /// BinaryFunction for that symbol.
60   static const BinaryFunction *
61   setCSIDestination(const BinaryContext &BC, yaml::bolt::CallSiteInfo &CSI,
62                     const MCSymbol *Symbol, const BoltAddressTranslation *BAT,
63                     uint32_t Offset = 0);
64 
65 private:
66   struct InlineTreeNode {
67     const MCDecodedPseudoProbeInlineTree *InlineTree;
68     uint64_t GUID;
69     uint64_t Hash;
70     uint32_t ParentId;
71     uint32_t InlineSite;
72   };
73   static std::vector<InlineTreeNode>
74   collectInlineTree(const MCPseudoProbeDecoder &Decoder,
75                     const MCDecodedPseudoProbeInlineTree &Root);
76 
77   // 0 - block probe, 1 - indirect call, 2 - direct call
78   using ProbeList = std::array<SmallVector<uint64_t, 0>, 3>;
79   using NodeIdToProbes = DenseMap<uint32_t, ProbeList>;
80   static std::vector<yaml::bolt::PseudoProbeInfo>
81   convertNodeProbes(NodeIdToProbes &NodeProbes);
82 
83 public:
84   template <typename T>
85   static std::vector<yaml::bolt::PseudoProbeInfo>
86   writeBlockProbes(T Probes, const InlineTreeMapTy &InlineTreeNodeId) {
87     NodeIdToProbes NodeProbes;
88     for (const MCDecodedPseudoProbe &Probe : Probes) {
89       auto It = InlineTreeNodeId.find(Probe.getInlineTreeNode());
90       if (It == InlineTreeNodeId.end())
91         continue;
92       NodeProbes[It->second][Probe.getType()].emplace_back(Probe.getIndex());
93     }
94     return convertNodeProbes(NodeProbes);
95   }
96 };
97 } // namespace bolt
98 } // namespace llvm
99 
100 #endif
101