1 //===- bolt/Profile/ProfileYAMLMapping.h ------------------------*- 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 // Implement mapping between binary function profile and YAML representation.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef BOLT_PROFILE_PROFILEYAMLMAPPING_H
14 #define BOLT_PROFILE_PROFILEYAMLMAPPING_H
15 
16 #include "bolt/Core/BinaryFunction.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/Support/YAMLTraits.h"
19 #include <vector>
20 
21 using llvm::bolt::BinaryFunction;
22 
23 namespace llvm {
24 namespace yaml {
25 
26 namespace bolt {
27 struct CallSiteInfo {
28   llvm::yaml::Hex32 Offset{0};
29   uint32_t DestId{0};
30   uint32_t EntryDiscriminator{0}; /// multiple entry discriminator
31   uint64_t Count{0};
32   uint64_t Mispreds{0};
33 
34   bool operator==(const CallSiteInfo &Other) const {
35     return Offset == Other.Offset && DestId == Other.DestId &&
36            EntryDiscriminator == Other.EntryDiscriminator;
37   }
38 
39   bool operator!=(const CallSiteInfo &Other) const { return !(*this == Other); }
40 
41   bool operator<(const CallSiteInfo &Other) const {
42     if (Offset < Other.Offset)
43       return true;
44     if (Offset > Other.Offset)
45       return false;
46 
47     if (DestId < Other.DestId)
48       return true;
49     if (DestId > Other.DestId)
50       return false;
51 
52     if (EntryDiscriminator < Other.EntryDiscriminator)
53       return true;
54 
55     return false;
56   }
57 };
58 } // end namespace bolt
59 
60 template <> struct MappingTraits<bolt::CallSiteInfo> {
61   static void mapping(IO &YamlIO, bolt::CallSiteInfo &CSI) {
62     YamlIO.mapRequired("off", CSI.Offset);
63     YamlIO.mapRequired("fid", CSI.DestId);
64     YamlIO.mapOptional("disc", CSI.EntryDiscriminator, (uint32_t)0);
65     YamlIO.mapRequired("cnt", CSI.Count);
66     YamlIO.mapOptional("mis", CSI.Mispreds, (uint64_t)0);
67   }
68 
69   static const bool flow = true;
70 };
71 
72 namespace bolt {
73 struct SuccessorInfo {
74   uint32_t Index{0};
75   uint64_t Count{0};
76   uint64_t Mispreds{0};
77 
78   bool operator==(const SuccessorInfo &Other) const {
79     return Index == Other.Index;
80   }
81   bool operator!=(const SuccessorInfo &Other) const {
82     return !(*this == Other);
83   }
84 };
85 } // end namespace bolt
86 
87 template <> struct MappingTraits<bolt::SuccessorInfo> {
88   static void mapping(IO &YamlIO, bolt::SuccessorInfo &SI) {
89     YamlIO.mapRequired("bid", SI.Index);
90     YamlIO.mapRequired("cnt", SI.Count);
91     YamlIO.mapOptional("mis", SI.Mispreds, (uint64_t)0);
92   }
93 
94   static const bool flow = true;
95 };
96 
97 } // end namespace yaml
98 } // end namespace llvm
99 
100 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::bolt::CallSiteInfo)
101 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(llvm::yaml::bolt::SuccessorInfo)
102 
103 namespace llvm {
104 namespace yaml {
105 
106 namespace bolt {
107 struct BinaryBasicBlockProfile {
108   uint32_t Index{0};
109   uint32_t NumInstructions{0};
110   llvm::yaml::Hex64 Hash{0};
111   uint64_t ExecCount{0};
112   uint64_t EventCount{0};
113   std::vector<CallSiteInfo> CallSites;
114   std::vector<SuccessorInfo> Successors;
115 
116   bool operator==(const BinaryBasicBlockProfile &Other) const {
117     return Index == Other.Index;
118   }
119   bool operator!=(const BinaryBasicBlockProfile &Other) const {
120     return !(*this == Other);
121   }
122 };
123 } // end namespace bolt
124 
125 template <> struct MappingTraits<bolt::BinaryBasicBlockProfile> {
126   static void mapping(IO &YamlIO, bolt::BinaryBasicBlockProfile &BBP) {
127     YamlIO.mapRequired("bid", BBP.Index);
128     YamlIO.mapRequired("insns", BBP.NumInstructions);
129     YamlIO.mapOptional("exec", BBP.ExecCount, (uint64_t)0);
130     YamlIO.mapOptional("events", BBP.EventCount, (uint64_t)0);
131     YamlIO.mapOptional("calls", BBP.CallSites,
132                        std::vector<bolt::CallSiteInfo>());
133     YamlIO.mapOptional("succ", BBP.Successors,
134                        std::vector<bolt::SuccessorInfo>());
135   }
136 };
137 
138 } // end namespace yaml
139 } // end namespace llvm
140 
141 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::bolt::BinaryBasicBlockProfile)
142 
143 namespace llvm {
144 namespace yaml {
145 
146 namespace bolt {
147 struct BinaryFunctionProfile {
148   std::string Name;
149   uint32_t NumBasicBlocks{0};
150   uint32_t Id{0};
151   llvm::yaml::Hex64 Hash{0};
152   uint64_t ExecCount{0};
153   std::vector<BinaryBasicBlockProfile> Blocks;
154   bool Used{false};
155 };
156 } // end namespace bolt
157 
158 template <> struct MappingTraits<bolt::BinaryFunctionProfile> {
159   static void mapping(IO &YamlIO, bolt::BinaryFunctionProfile &BFP) {
160     YamlIO.mapRequired("name", BFP.Name);
161     YamlIO.mapRequired("fid", BFP.Id);
162     YamlIO.mapRequired("hash", BFP.Hash);
163     YamlIO.mapRequired("exec", BFP.ExecCount);
164     YamlIO.mapRequired("nblocks", BFP.NumBasicBlocks);
165     YamlIO.mapOptional("blocks", BFP.Blocks,
166                        std::vector<bolt::BinaryBasicBlockProfile>());
167   }
168 };
169 
170 LLVM_YAML_STRONG_TYPEDEF(uint16_t, PROFILE_PF)
171 
172 template <> struct ScalarBitSetTraits<PROFILE_PF> {
173   static void bitset(IO &io, PROFILE_PF &value) {
174     io.bitSetCase(value, "lbr", BinaryFunction::PF_LBR);
175     io.bitSetCase(value, "sample", BinaryFunction::PF_SAMPLE);
176     io.bitSetCase(value, "memevent", BinaryFunction::PF_MEMEVENT);
177   }
178 };
179 
180 namespace bolt {
181 struct BinaryProfileHeader {
182   uint32_t Version{1};
183   std::string FileName; // Name of the profiled binary.
184   std::string Id;       // BuildID.
185   PROFILE_PF Flags{BinaryFunction::PF_NONE};
186   // Type of the profile.
187   std::string Origin;     // How the profile was obtained.
188   std::string EventNames; // Events used for sample profile.
189 };
190 } // end namespace bolt
191 
192 template <> struct MappingTraits<bolt::BinaryProfileHeader> {
193   static void mapping(IO &YamlIO, bolt::BinaryProfileHeader &Header) {
194     YamlIO.mapRequired("profile-version", Header.Version);
195     YamlIO.mapRequired("binary-name", Header.FileName);
196     YamlIO.mapOptional("binary-build-id", Header.Id);
197     YamlIO.mapRequired("profile-flags", Header.Flags);
198     YamlIO.mapOptional("profile-origin", Header.Origin);
199     YamlIO.mapOptional("profile-events", Header.EventNames);
200   }
201 };
202 
203 } // end namespace yaml
204 } // end namespace llvm
205 
206 LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::yaml::bolt::BinaryFunctionProfile)
207 
208 namespace llvm {
209 namespace yaml {
210 
211 namespace bolt {
212 struct BinaryProfile {
213   BinaryProfileHeader Header;
214   std::vector<BinaryFunctionProfile> Functions;
215 };
216 } // namespace bolt
217 
218 template <> struct MappingTraits<bolt::BinaryProfile> {
219   static void mapping(IO &YamlIO, bolt::BinaryProfile &BP) {
220     YamlIO.mapRequired("header", BP.Header);
221     YamlIO.mapRequired("functions", BP.Functions);
222   }
223 };
224 
225 } // end namespace yaml
226 } // end namespace llvm
227 
228 #endif
229