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