LLVM  10.0.0svn
SampleProf.cpp
Go to the documentation of this file.
1 //=-- SampleProf.cpp - Sample profiling format support --------------------===//
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 common definitions used in the reading and writing of
10 // sample profile data.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "llvm/Config/llvm-config.h"
17 #include "llvm/Support/Compiler.h"
19 #include "llvm/Support/Debug.h"
20 #include "llvm/Support/Error.h"
22 #include "llvm/Support/LEB128.h"
25 #include <string>
26 #include <system_error>
27 
28 using namespace llvm;
29 using namespace sampleprof;
30 
31 namespace llvm {
32 namespace sampleprof {
34 } // namespace sampleprof
35 } // namespace llvm
36 
37 namespace {
38 
39 // FIXME: This class is only here to support the transition to llvm::Error. It
40 // will be removed once this transition is complete. Clients should prefer to
41 // deal with the Error value directly, rather than converting to error_code.
42 class SampleProfErrorCategoryType : public std::error_category {
43  const char *name() const noexcept override { return "llvm.sampleprof"; }
44 
45  std::string message(int IE) const override {
46  sampleprof_error E = static_cast<sampleprof_error>(IE);
47  switch (E) {
49  return "Success";
51  return "Invalid sample profile data (bad magic)";
53  return "Unsupported sample profile format version";
55  return "Too much profile data";
57  return "Truncated profile data";
59  return "Malformed sample profile data";
61  return "Unrecognized sample profile encoding format";
63  return "Profile encoding format unsupported for writing operations";
65  return "Truncated function name table";
67  return "Unimplemented feature";
69  return "Counter overflow";
71  return "Ostream does not support seek";
73  return "Compress failure";
75  return "Uncompress failure";
77  return "Zlib is unavailable";
78  }
79  llvm_unreachable("A value of sampleprof_error has no message.");
80  }
81 };
82 
83 } // end anonymous namespace
84 
86 
88  return *ErrorCategory;
89 }
90 
92  OS << LineOffset;
93  if (Discriminator > 0)
94  OS << "." << Discriminator;
95 }
96 
98  const LineLocation &Loc) {
99  Loc.print(OS);
100  return OS;
101 }
102 
103 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
105 #endif
106 
107 /// Print the sample record to the stream \p OS indented by \p Indent.
108 void SampleRecord::print(raw_ostream &OS, unsigned Indent) const {
109  OS << NumSamples;
110  if (hasCalls()) {
111  OS << ", calls:";
112  for (const auto &I : getSortedCallTargets())
113  OS << " " << I.first << ":" << I.second;
114  }
115  OS << "\n";
116 }
117 
118 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
120 #endif
121 
123  const SampleRecord &Sample) {
124  Sample.print(OS, 0);
125  return OS;
126 }
127 
128 /// Print the samples collected for a function on stream \p OS.
129 void FunctionSamples::print(raw_ostream &OS, unsigned Indent) const {
130  OS << TotalSamples << ", " << TotalHeadSamples << ", " << BodySamples.size()
131  << " sampled lines\n";
132 
133  OS.indent(Indent);
134  if (!BodySamples.empty()) {
135  OS << "Samples collected in the function's body {\n";
136  SampleSorter<LineLocation, SampleRecord> SortedBodySamples(BodySamples);
137  for (const auto &SI : SortedBodySamples.get()) {
138  OS.indent(Indent + 2);
139  OS << SI->first << ": " << SI->second;
140  }
141  OS.indent(Indent);
142  OS << "}\n";
143  } else {
144  OS << "No samples collected in the function's body\n";
145  }
146 
147  OS.indent(Indent);
148  if (!CallsiteSamples.empty()) {
149  OS << "Samples collected in inlined callsites {\n";
151  CallsiteSamples);
152  for (const auto &CS : SortedCallsiteSamples.get()) {
153  for (const auto &FS : CS->second) {
154  OS.indent(Indent + 2);
155  OS << CS->first << ": inlined callee: " << FS.second.getName() << ": ";
156  FS.second.print(OS, Indent + 4);
157  }
158  }
159  OS << "}\n";
160  } else {
161  OS << "No inlined callsites in this function\n";
162  }
163 }
164 
166  const FunctionSamples &FS) {
167  FS.print(OS);
168  return OS;
169 }
170 
172  return (DIL->getLine() - DIL->getScope()->getSubprogram()->getLine()) &
173  0xffff;
174 }
175 
176 const FunctionSamples *
178  assert(DIL);
180 
181  const DILocation *PrevDIL = DIL;
182  for (DIL = DIL->getInlinedAt(); DIL; DIL = DIL->getInlinedAt()) {
183  S.push_back(std::make_pair(
185  PrevDIL->getScope()->getSubprogram()->getLinkageName()));
186  PrevDIL = DIL;
187  }
188  if (S.size() == 0)
189  return this;
190  const FunctionSamples *FS = this;
191  for (int i = S.size() - 1; i >= 0 && FS != nullptr; i--) {
192  FS = FS->findFunctionSamplesAt(S[i].first, S[i].second);
193  }
194  return FS;
195 }
196 
197 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
199 #endif
200 
201 std::error_code ProfileSymbolList::read(uint64_t CompressSize,
202  uint64_t UncompressSize,
203  const uint8_t *Data) {
204  const char *ListStart = reinterpret_cast<const char *>(Data);
205  // CompressSize being non-zero means the profile is compressed and
206  // needs to be uncompressed first.
207  if (CompressSize) {
210 
211  StringRef CompressedStrings(reinterpret_cast<const char *>(Data),
212  CompressSize);
213  char *Buffer = Allocator.Allocate<char>(UncompressSize);
214  size_t UCSize = UncompressSize;
215  llvm::Error E = zlib::uncompress(CompressedStrings, Buffer, UCSize);
216  if (E)
218  ListStart = Buffer;
219  }
220 
221  uint64_t Size = 0;
222  while (Size < UncompressSize) {
223  StringRef Str(ListStart + Size);
224  add(Str);
225  Size += Str.size() + 1;
226  }
228 }
229 
230 std::error_code ProfileSymbolList::write(raw_ostream &OS) {
231  // Sort the symbols before doing compression. It will make the
232  // compression much more effective.
233  std::vector<StringRef> SortedList;
234  SortedList.insert(SortedList.begin(), Syms.begin(), Syms.end());
235  llvm::sort(SortedList);
236 
237  std::string UncompressedStrings;
238  for (auto &Sym : SortedList) {
239  UncompressedStrings.append(Sym.str());
240  UncompressedStrings.append(1, '\0');
241  }
242 
243  if (ToCompress) {
246  SmallString<128> CompressedStrings;
247  llvm::Error E = zlib::compress(UncompressedStrings, CompressedStrings,
249  if (E)
251  encodeULEB128(UncompressedStrings.size(), OS);
252  encodeULEB128(CompressedStrings.size(), OS);
253  OS << CompressedStrings.str();
254  } else {
255  encodeULEB128(UncompressedStrings.size(), OS);
256  // If profile symbol list is not compressed, we will still save
257  // a compressed size value, but the value of the size is 0.
258  encodeULEB128(0, OS);
259  OS << UncompressedStrings;
260  }
262 }
263 
265  OS << "======== Dump profile symbol list ========\n";
266  std::vector<StringRef> SortedList;
267  SortedList.insert(SortedList.begin(), Syms.begin(), Syms.end());
268  llvm::sort(SortedList);
269 
270  for (auto &Sym : SortedList)
271  OS << Sym << "\n";
272 }
raw_ostream & operator<<(raw_ostream &OS, const LineLocation &Loc)
Definition: SampleProf.cpp:97
This class represents lattice values for constants.
Definition: AllocatorList.h:23
#define LLVM_DUMP_METHOD
Mark debug helper function definitions like dump() that should not be stripped from debug builds...
Definition: Compiler.h:476
raw_ostream & indent(unsigned NumSpaces)
indent - Insert &#39;NumSpaces&#39; spaces.
unsigned second
static SampleProfileFormat Format
Definition: SampleProf.h:524
Representation of the samples collected for a function.
Definition: SampleProf.h:267
void print(raw_ostream &OS=dbgs(), unsigned Indent=0) const
Print the samples collected for a function on stream OS.
Definition: SampleProf.cpp:129
Error compress(StringRef InputBuffer, SmallVectorImpl< char > &CompressedBuffer, int Level=DefaultCompression)
Definition: Compression.cpp:49
StringRef str() const
Explicit conversion to StringRef.
Definition: SmallString.h:266
void print(raw_ostream &OS, unsigned Indent) const
Print the sample record to the stream OS indented by Indent.
Definition: SampleProf.cpp:108
Representation of a single sample record.
Definition: SampleProf.h:173
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:144
static Error getOffset(const SymbolRef &Sym, SectionRef Sec, uint64_t &Result)
static constexpr int BestSizeCompression
Definition: Compression.h:28
const SamplesWithLocList & get() const
Definition: SampleProf.h:598
Debug location.
Sort a LocationT->SampleT map by LocationT.
Definition: SampleProf.h:585
std::error_code read(uint64_t CompressSize, uint64_t UncompressSize, const uint8_t *Data)
Definition: SampleProf.cpp:201
void dump(raw_ostream &OS=dbgs()) const
Definition: SampleProf.cpp:264
const FunctionSamples * findFunctionSamples(const DILocation *DIL) const
Get the FunctionSamples of the inline instance where DIL originates from.
Definition: SampleProf.cpp:177
bool isAvailable()
Definition: Compression.cpp:47
sampleprof_error
Definition: SampleProf.h:43
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
static ManagedStatic< _object_error_category > error_category
Definition: Error.cpp:74
static void print(raw_ostream &Out, object::Archive::Kind Kind, T Val)
size_t size() const
Definition: SmallVector.h:52
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned first
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1095
const FunctionSamples * findFunctionSamplesAt(const LineLocation &Loc, StringRef CalleeName) const
Returns a pointer to FunctionSamples at the given callsite location Loc with callee CalleeName...
Definition: SampleProf.h:345
Basic Register Allocator
unsigned encodeULEB128(uint64_t Value, raw_ostream &OS, unsigned PadTo=0)
Utility function to encode a ULEB128 value to an output stream.
Definition: LEB128.h:80
static uint64_t add(uint64_t LeftOp, uint64_t RightOp)
Definition: FileCheck.cpp:214
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:837
static unsigned getOffset(const DILocation *DIL)
Returns the line offset to the start line of the subprogram.
Definition: SampleProf.cpp:171
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
const std::error_category & sampleprof_category()
Definition: SampleProf.cpp:87
void print(raw_ostream &OS) const
Definition: SampleProf.cpp:91
static ManagedStatic< SampleProfErrorCategoryType > ErrorCategory
Definition: SampleProf.cpp:85
unsigned getBaseDiscriminator() const
Returns the base discriminator stored in the discriminator.
Represents the relative location of an instruction.
Definition: SampleProf.h:146
#define I(x, y, z)
Definition: MD5.cpp:58
std::error_code write(raw_ostream &OS)
Definition: SampleProf.cpp:230
uint32_t Size
Definition: Profile.cpp:46
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
aarch64 promote const
static const char * name
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:45
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...
Definition: ManagedStatic.h:83
Error uncompress(StringRef InputBuffer, char *UncompressedBuffer, size_t &UncompressedSize)
Definition: Compression.cpp:63