LLVM  17.0.0git
InstrProfWriter.cpp
Go to the documentation of this file.
1 //===- InstrProfWriter.cpp - Instrumented profiling writer ----------------===//
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 support for writing profiling data for clang's
10 // instrumentation based PGO and coverage.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "llvm/ADT/STLExtras.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/IR/ProfileSummary.h"
21 #include "llvm/Support/Endian.h"
23 #include "llvm/Support/Error.h"
27 #include <cstdint>
28 #include <memory>
29 #include <string>
30 #include <tuple>
31 #include <utility>
32 #include <vector>
33 
34 using namespace llvm;
35 
36 // A struct to define how the data stream should be patched. For Indexed
37 // profiling, only uint64_t data type is needed.
38 struct PatchItem {
39  uint64_t Pos; // Where to patch.
40  uint64_t *D; // Pointer to an array of source data.
41  int N; // Number of elements in \c D array.
42 };
43 
44 namespace llvm {
45 
46 // A wrapper class to abstract writer stream with support of bytes
47 // back patching.
48 class ProfOStream {
49 public:
51  : IsFDOStream(true), OS(FD), LE(FD, support::little) {}
53  : IsFDOStream(false), OS(STR), LE(STR, support::little) {}
54 
55  uint64_t tell() { return OS.tell(); }
56  void write(uint64_t V) { LE.write<uint64_t>(V); }
57  void writeByte(uint8_t V) { LE.write<uint8_t>(V); }
58 
59  // \c patch can only be called when all data is written and flushed.
60  // For raw_string_ostream, the patch is done on the target string
61  // directly and it won't be reflected in the stream's internal buffer.
62  void patch(PatchItem *P, int NItems) {
63  using namespace support;
64 
65  if (IsFDOStream) {
66  raw_fd_ostream &FDOStream = static_cast<raw_fd_ostream &>(OS);
67  const uint64_t LastPos = FDOStream.tell();
68  for (int K = 0; K < NItems; K++) {
69  FDOStream.seek(P[K].Pos);
70  for (int I = 0; I < P[K].N; I++)
71  write(P[K].D[I]);
72  }
73  // Reset the stream to the last position after patching so that users
74  // don't accidentally overwrite data. This makes it consistent with
75  // the string stream below which replaces the data directly.
76  FDOStream.seek(LastPos);
77  } else {
78  raw_string_ostream &SOStream = static_cast<raw_string_ostream &>(OS);
79  std::string &Data = SOStream.str(); // with flush
80  for (int K = 0; K < NItems; K++) {
81  for (int I = 0; I < P[K].N; I++) {
82  uint64_t Bytes = endian::byte_swap<uint64_t, little>(P[K].D[I]);
83  Data.replace(P[K].Pos + I * sizeof(uint64_t), sizeof(uint64_t),
84  (const char *)&Bytes, sizeof(uint64_t));
85  }
86  }
87  }
88  }
89 
90  // If \c OS is an instance of \c raw_fd_ostream, this field will be
91  // true. Otherwise, \c OS will be an raw_string_ostream.
95 };
96 
98 public:
101 
104 
107 
108  support::endianness ValueProfDataEndianness = support::little;
111 
112  InstrProfRecordWriterTrait() = default;
113 
116  }
117 
118  static std::pair<offset_type, offset_type>
120  using namespace support;
121 
122  endian::Writer LE(Out, little);
123 
124  offset_type N = K.size();
125  LE.write<offset_type>(N);
126 
127  offset_type M = 0;
128  for (const auto &ProfileData : *V) {
129  const InstrProfRecord &ProfRecord = ProfileData.second;
130  M += sizeof(uint64_t); // The function hash
131  M += sizeof(uint64_t); // The size of the Counts vector
132  M += ProfRecord.Counts.size() * sizeof(uint64_t);
133 
134  // Value data
135  M += ValueProfData::getSize(ProfileData.second);
136  }
137  LE.write<offset_type>(M);
138 
139  return std::make_pair(N, M);
140  }
141 
143  Out.write(K.data(), N);
144  }
145 
147  using namespace support;
148 
149  endian::Writer LE(Out, little);
150  for (const auto &ProfileData : *V) {
151  const InstrProfRecord &ProfRecord = ProfileData.second;
152  if (NamedInstrProfRecord::hasCSFlagInHash(ProfileData.first))
153  CSSummaryBuilder->addRecord(ProfRecord);
154  else
155  SummaryBuilder->addRecord(ProfRecord);
156 
157  LE.write<uint64_t>(ProfileData.first); // Function hash
158  LE.write<uint64_t>(ProfRecord.Counts.size());
159  for (uint64_t I : ProfRecord.Counts)
160  LE.write<uint64_t>(I);
161 
162  // Write value data
163  std::unique_ptr<ValueProfData> VDataPtr =
164  ValueProfData::serializeFrom(ProfileData.second);
165  uint32_t S = VDataPtr->getSize();
166  VDataPtr->swapBytesFromHost(ValueProfDataEndianness);
167  Out.write((const char *)VDataPtr.get(), S);
168  }
169  }
170 };
171 
172 } // end namespace llvm
173 
175  : Sparse(Sparse), InfoObj(new InstrProfRecordWriterTrait()) {}
176 
178 
179 // Internal interface for testing purpose only.
183 }
184 
186  this->Sparse = Sparse;
187 }
188 
190  function_ref<void(Error)> Warn) {
191  auto Name = I.Name;
192  auto Hash = I.Hash;
193  addRecord(Name, Hash, std::move(I), Weight, Warn);
194 }
195 
197  OverlapStats &Overlap,
198  OverlapStats &FuncLevelOverlap,
199  const OverlapFuncFilters &FuncFilter) {
200  auto Name = Other.Name;
201  auto Hash = Other.Hash;
202  Other.accumulateCounts(FuncLevelOverlap.Test);
203  if (FunctionData.find(Name) == FunctionData.end()) {
204  Overlap.addOneUnique(FuncLevelOverlap.Test);
205  return;
206  }
207  if (FuncLevelOverlap.Test.CountSum < 1.0f) {
208  Overlap.Overlap.NumEntries += 1;
209  return;
210  }
211  auto &ProfileDataMap = FunctionData[Name];
212  bool NewFunc;
214  std::tie(Where, NewFunc) =
215  ProfileDataMap.insert(std::make_pair(Hash, InstrProfRecord()));
216  if (NewFunc) {
217  Overlap.addOneMismatch(FuncLevelOverlap.Test);
218  return;
219  }
220  InstrProfRecord &Dest = Where->second;
221 
222  uint64_t ValueCutoff = FuncFilter.ValueCutoff;
223  if (!FuncFilter.NameFilter.empty() && Name.contains(FuncFilter.NameFilter))
224  ValueCutoff = 0;
225 
226  Dest.overlap(Other, Overlap, FuncLevelOverlap, ValueCutoff);
227 }
228 
230  InstrProfRecord &&I, uint64_t Weight,
231  function_ref<void(Error)> Warn) {
232  auto &ProfileDataMap = FunctionData[Name];
233 
234  bool NewFunc;
236  std::tie(Where, NewFunc) =
237  ProfileDataMap.insert(std::make_pair(Hash, InstrProfRecord()));
238  InstrProfRecord &Dest = Where->second;
239 
240  auto MapWarn = [&](instrprof_error E) {
241  Warn(make_error<InstrProfError>(E));
242  };
243 
244  if (NewFunc) {
245  // We've never seen a function with this name and hash, add it.
246  Dest = std::move(I);
247  if (Weight > 1)
248  Dest.scale(Weight, 1, MapWarn);
249  } else {
250  // We're updating a function we've seen before.
251  Dest.merge(I, Weight, MapWarn);
252  }
253 
254  Dest.sortValueData();
255 }
256 
259  auto Result = MemProfRecordData.insert({Id, Record});
260  // If we inserted a new record then we are done.
261  if (Result.second) {
262  return;
263  }
264  memprof::IndexedMemProfRecord &Existing = Result.first->second;
265  Existing.merge(Record);
266 }
267 
269  const memprof::Frame &Frame,
270  function_ref<void(Error)> Warn) {
271  auto Result = MemProfFrameData.insert({Id, Frame});
272  // If a mapping already exists for the current frame id and it does not
273  // match the new mapping provided then reset the existing contents and bail
274  // out. We don't support the merging of memprof data whose Frame -> Id
275  // mapping across profiles is inconsistent.
276  if (!Result.second && Result.first->second != Frame) {
277  Warn(make_error<InstrProfError>(instrprof_error::malformed,
278  "frame to id mapping mismatch"));
279  return false;
280  }
281  return true;
282 }
283 
285  llvm::append_range(BinaryIds, BIs);
286 }
287 
289  function_ref<void(Error)> Warn) {
290  for (auto &I : IPW.FunctionData)
291  for (auto &Func : I.getValue())
292  addRecord(I.getKey(), Func.first, std::move(Func.second), 1, Warn);
293 
294  BinaryIds.reserve(BinaryIds.size() + IPW.BinaryIds.size());
295  for (auto &I : IPW.BinaryIds)
296  addBinaryIds(I);
297 
298  MemProfFrameData.reserve(IPW.MemProfFrameData.size());
299  for (auto &I : IPW.MemProfFrameData) {
300  // If we weren't able to add the frame mappings then it doesn't make sense
301  // to try to merge the records from this profile.
302  if (!addMemProfFrame(I.first, I.second, Warn))
303  return;
304  }
305 
306  MemProfRecordData.reserve(IPW.MemProfRecordData.size());
307  for (auto &I : IPW.MemProfRecordData) {
308  addMemProfRecord(I.first, I.second);
309  }
310 }
311 
312 bool InstrProfWriter::shouldEncodeData(const ProfilingData &PD) {
313  if (!Sparse)
314  return true;
315  for (const auto &Func : PD) {
316  const InstrProfRecord &IPR = Func.second;
317  if (llvm::any_of(IPR.Counts, [](uint64_t Count) { return Count > 0; }))
318  return true;
319  }
320  return false;
321 }
322 
323 static void setSummary(IndexedInstrProf::Summary *TheSummary,
324  ProfileSummary &PS) {
325  using namespace IndexedInstrProf;
326 
327  const std::vector<ProfileSummaryEntry> &Res = PS.getDetailedSummary();
328  TheSummary->NumSummaryFields = Summary::NumKinds;
329  TheSummary->NumCutoffEntries = Res.size();
331  TheSummary->set(Summary::MaxBlockCount, PS.getMaxCount());
333  TheSummary->set(Summary::TotalBlockCount, PS.getTotalCount());
334  TheSummary->set(Summary::TotalNumBlocks, PS.getNumCounts());
336  for (unsigned I = 0; I < Res.size(); I++)
337  TheSummary->setEntry(I, Res[I]);
338 }
339 
340 Error InstrProfWriter::writeImpl(ProfOStream &OS) {
341  using namespace IndexedInstrProf;
342  using namespace support;
343 
345 
347  InfoObj->SummaryBuilder = &ISB;
349  InfoObj->CSSummaryBuilder = &CSISB;
350 
351  // Populate the hash table generator.
352  for (const auto &I : FunctionData)
353  if (shouldEncodeData(I.getValue()))
354  Generator.insert(I.getKey(), &I.getValue());
355 
356  // Write the header.
358  Header.Magic = IndexedInstrProf::Magic;
360  if (static_cast<bool>(ProfileKind & InstrProfKind::IRInstrumentation))
361  Header.Version |= VARIANT_MASK_IR_PROF;
362  if (static_cast<bool>(ProfileKind & InstrProfKind::ContextSensitive))
363  Header.Version |= VARIANT_MASK_CSIR_PROF;
364  if (static_cast<bool>(ProfileKind &
366  Header.Version |= VARIANT_MASK_INSTR_ENTRY;
367  if (static_cast<bool>(ProfileKind & InstrProfKind::SingleByteCoverage))
368  Header.Version |= VARIANT_MASK_BYTE_COVERAGE;
369  if (static_cast<bool>(ProfileKind & InstrProfKind::FunctionEntryOnly))
370  Header.Version |= VARIANT_MASK_FUNCTION_ENTRY_ONLY;
371  if (static_cast<bool>(ProfileKind & InstrProfKind::MemProf))
372  Header.Version |= VARIANT_MASK_MEMPROF;
373 
374  Header.Unused = 0;
375  Header.HashType = static_cast<uint64_t>(IndexedInstrProf::HashType);
376  Header.HashOffset = 0;
377  Header.MemProfOffset = 0;
378  Header.BinaryIdOffset = 0;
379  int N = sizeof(IndexedInstrProf::Header) / sizeof(uint64_t);
380 
381  // Only write out all the fields except 'HashOffset', 'MemProfOffset' and
382  // 'BinaryIdOffset'. We need to remember the offset of these fields to allow
383  // back patching later.
384  for (int I = 0; I < N - 3; I++)
385  OS.write(reinterpret_cast<uint64_t *>(&Header)[I]);
386 
387  // Save the location of Header.HashOffset field in \c OS.
388  uint64_t HashTableStartFieldOffset = OS.tell();
389  // Reserve the space for HashOffset field.
390  OS.write(0);
391 
392  // Save the location of MemProf profile data. This is stored in two parts as
393  // the schema and as a separate on-disk chained hashtable.
394  uint64_t MemProfSectionOffset = OS.tell();
395  // Reserve space for the MemProf table field to be patched later if this
396  // profile contains memory profile information.
397  OS.write(0);
398 
399  // Save the location of binary ids section.
400  uint64_t BinaryIdSectionOffset = OS.tell();
401  // Reserve space for the BinaryIdOffset field to be patched later if this
402  // profile contains binary ids.
403  OS.write(0);
404 
405  // Reserve space to write profile summary data.
407  uint32_t SummarySize = Summary::getSize(Summary::NumKinds, NumEntries);
408  // Remember the summary offset.
409  uint64_t SummaryOffset = OS.tell();
410  for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
411  OS.write(0);
412  uint64_t CSSummaryOffset = 0;
413  uint64_t CSSummarySize = 0;
414  if (static_cast<bool>(ProfileKind & InstrProfKind::ContextSensitive)) {
415  CSSummaryOffset = OS.tell();
416  CSSummarySize = SummarySize / sizeof(uint64_t);
417  for (unsigned I = 0; I < CSSummarySize; I++)
418  OS.write(0);
419  }
420 
421  // Write the hash table.
422  uint64_t HashTableStart = Generator.Emit(OS.OS, *InfoObj);
423 
424  // Write the MemProf profile data if we have it. This includes a simple schema
425  // with the format described below followed by the hashtable:
426  // uint64_t RecordTableOffset = RecordTableGenerator.Emit
427  // uint64_t FramePayloadOffset = Stream offset before emitting the frame table
428  // uint64_t FrameTableOffset = FrameTableGenerator.Emit
429  // uint64_t Num schema entries
430  // uint64_t Schema entry 0
431  // uint64_t Schema entry 1
432  // ....
433  // uint64_t Schema entry N - 1
434  // OnDiskChainedHashTable MemProfRecordData
435  // OnDiskChainedHashTable MemProfFrameData
436  uint64_t MemProfSectionStart = 0;
437  if (static_cast<bool>(ProfileKind & InstrProfKind::MemProf)) {
438  MemProfSectionStart = OS.tell();
439  OS.write(0ULL); // Reserve space for the memprof record table offset.
440  OS.write(0ULL); // Reserve space for the memprof frame payload offset.
441  OS.write(0ULL); // Reserve space for the memprof frame table offset.
442 
444  OS.write(static_cast<uint64_t>(Schema.size()));
445  for (const auto Id : Schema) {
446  OS.write(static_cast<uint64_t>(Id));
447  }
448 
449  auto RecordWriter = std::make_unique<memprof::RecordWriterTrait>();
450  RecordWriter->Schema = &Schema;
452  RecordTableGenerator;
453  for (auto &I : MemProfRecordData) {
454  // Insert the key (func hash) and value (memprof record).
455  RecordTableGenerator.insert(I.first, I.second);
456  }
457 
458  uint64_t RecordTableOffset =
459  RecordTableGenerator.Emit(OS.OS, *RecordWriter);
460 
461  uint64_t FramePayloadOffset = OS.tell();
462 
463  auto FrameWriter = std::make_unique<memprof::FrameWriterTrait>();
465  FrameTableGenerator;
466  for (auto &I : MemProfFrameData) {
467  // Insert the key (frame id) and value (frame contents).
468  FrameTableGenerator.insert(I.first, I.second);
469  }
470 
471  uint64_t FrameTableOffset = FrameTableGenerator.Emit(OS.OS, *FrameWriter);
472 
473  PatchItem PatchItems[] = {
474  {MemProfSectionStart, &RecordTableOffset, 1},
475  {MemProfSectionStart + sizeof(uint64_t), &FramePayloadOffset, 1},
476  {MemProfSectionStart + 2 * sizeof(uint64_t), &FrameTableOffset, 1},
477  };
478  OS.patch(PatchItems, 3);
479  }
480 
481  // BinaryIdSection has two parts:
482  // 1. uint64_t BinaryIdsSectionSize
483  // 2. list of binary ids that consist of:
484  // a. uint64_t BinaryIdLength
485  // b. uint8_t BinaryIdData
486  // c. uint8_t Padding (if necessary)
487  uint64_t BinaryIdSectionStart = OS.tell();
488  // Calculate size of binary section.
489  uint64_t BinaryIdsSectionSize = 0;
490 
491  // Remove duplicate binary ids.
492  llvm::sort(BinaryIds);
493  BinaryIds.erase(std::unique(BinaryIds.begin(), BinaryIds.end()),
494  BinaryIds.end());
495 
496  for (auto BI : BinaryIds) {
497  // Increment by binary id length data type size.
498  BinaryIdsSectionSize += sizeof(uint64_t);
499  // Increment by binary id data length, aligned to 8 bytes.
500  BinaryIdsSectionSize += alignToPowerOf2(BI.size(), sizeof(uint64_t));
501  }
502  // Write binary ids section size.
503  OS.write(BinaryIdsSectionSize);
504 
505  for (auto BI : BinaryIds) {
506  uint64_t BILen = BI.size();
507  // Write binary id length.
508  OS.write(BILen);
509  // Write binary id data.
510  for (unsigned K = 0; K < BILen; K++)
511  OS.writeByte(BI[K]);
512  // Write padding if necessary.
513  uint64_t PaddingSize = alignToPowerOf2(BILen, sizeof(uint64_t)) - BILen;
514  for (unsigned K = 0; K < PaddingSize; K++)
515  OS.writeByte(0);
516  }
517 
518  // Allocate space for data to be serialized out.
519  std::unique_ptr<IndexedInstrProf::Summary> TheSummary =
520  IndexedInstrProf::allocSummary(SummarySize);
521  // Compute the Summary and copy the data to the data
522  // structure to be serialized out (to disk or buffer).
523  std::unique_ptr<ProfileSummary> PS = ISB.getSummary();
524  setSummary(TheSummary.get(), *PS);
525  InfoObj->SummaryBuilder = nullptr;
526 
527  // For Context Sensitive summary.
528  std::unique_ptr<IndexedInstrProf::Summary> TheCSSummary = nullptr;
529  if (static_cast<bool>(ProfileKind & InstrProfKind::ContextSensitive)) {
530  TheCSSummary = IndexedInstrProf::allocSummary(SummarySize);
531  std::unique_ptr<ProfileSummary> CSPS = CSISB.getSummary();
532  setSummary(TheCSSummary.get(), *CSPS);
533  }
534  InfoObj->CSSummaryBuilder = nullptr;
535 
536  // Now do the final patch:
537  PatchItem PatchItems[] = {
538  // Patch the Header.HashOffset field.
539  {HashTableStartFieldOffset, &HashTableStart, 1},
540  // Patch the Header.MemProfOffset (=0 for profiles without MemProf
541  // data).
542  {MemProfSectionOffset, &MemProfSectionStart, 1},
543  // Patch the Header.BinaryIdSectionOffset.
544  {BinaryIdSectionOffset, &BinaryIdSectionStart, 1},
545  // Patch the summary data.
546  {SummaryOffset, reinterpret_cast<uint64_t *>(TheSummary.get()),
547  (int)(SummarySize / sizeof(uint64_t))},
548  {CSSummaryOffset, reinterpret_cast<uint64_t *>(TheCSSummary.get()),
549  (int)CSSummarySize}};
550 
551  OS.patch(PatchItems, std::size(PatchItems));
552 
553  for (const auto &I : FunctionData)
554  for (const auto &F : I.getValue())
555  if (Error E = validateRecord(F.second))
556  return E;
557 
558  return Error::success();
559 }
560 
562  // Write the hash table.
563  ProfOStream POS(OS);
564  return writeImpl(POS);
565 }
566 
567 std::unique_ptr<MemoryBuffer> InstrProfWriter::writeBuffer() {
568  std::string Data;
570  ProfOStream POS(OS);
571  // Write the hash table.
572  if (Error E = writeImpl(POS))
573  return nullptr;
574  // Return this in an aligned memory buffer.
576 }
577 
578 static const char *ValueProfKindStr[] = {
579 #define VALUE_PROF_KIND(Enumerator, Value, Descr) #Enumerator,
581 };
582 
584  for (uint32_t VK = 0; VK <= IPVK_Last; VK++) {
585  uint32_t NS = Func.getNumValueSites(VK);
586  if (!NS)
587  continue;
588  for (uint32_t S = 0; S < NS; S++) {
589  uint32_t ND = Func.getNumValueDataForSite(VK, S);
590  std::unique_ptr<InstrProfValueData[]> VD = Func.getValueForSite(VK, S);
591  DenseSet<uint64_t> SeenValues;
592  for (uint32_t I = 0; I < ND; I++)
593  if ((VK != IPVK_IndirectCallTarget) && !SeenValues.insert(VD[I].Value).second)
594  return make_error<InstrProfError>(instrprof_error::invalid_prof);
595  }
596  }
597 
598  return Error::success();
599 }
600 
602  const InstrProfRecord &Func,
603  InstrProfSymtab &Symtab,
604  raw_fd_ostream &OS) {
605  OS << Name << "\n";
606  OS << "# Func Hash:\n" << Hash << "\n";
607  OS << "# Num Counters:\n" << Func.Counts.size() << "\n";
608  OS << "# Counter Values:\n";
609  for (uint64_t Count : Func.Counts)
610  OS << Count << "\n";
611 
612  uint32_t NumValueKinds = Func.getNumValueKinds();
613  if (!NumValueKinds) {
614  OS << "\n";
615  return;
616  }
617 
618  OS << "# Num Value Kinds:\n" << Func.getNumValueKinds() << "\n";
619  for (uint32_t VK = 0; VK < IPVK_Last + 1; VK++) {
620  uint32_t NS = Func.getNumValueSites(VK);
621  if (!NS)
622  continue;
623  OS << "# ValueKind = " << ValueProfKindStr[VK] << ":\n" << VK << "\n";
624  OS << "# NumValueSites:\n" << NS << "\n";
625  for (uint32_t S = 0; S < NS; S++) {
626  uint32_t ND = Func.getNumValueDataForSite(VK, S);
627  OS << ND << "\n";
628  std::unique_ptr<InstrProfValueData[]> VD = Func.getValueForSite(VK, S);
629  for (uint32_t I = 0; I < ND; I++) {
630  if (VK == IPVK_IndirectCallTarget)
631  OS << Symtab.getFuncNameOrExternalSymbol(VD[I].Value) << ":"
632  << VD[I].Count << "\n";
633  else
634  OS << VD[I].Value << ":" << VD[I].Count << "\n";
635  }
636  }
637  }
638 
639  OS << "\n";
640 }
641 
643  // Check CS first since it implies an IR level profile.
644  if (static_cast<bool>(ProfileKind & InstrProfKind::ContextSensitive))
645  OS << "# CSIR level Instrumentation Flag\n:csir\n";
646  else if (static_cast<bool>(ProfileKind & InstrProfKind::IRInstrumentation))
647  OS << "# IR level Instrumentation Flag\n:ir\n";
648 
649  if (static_cast<bool>(ProfileKind &
651  OS << "# Always instrument the function entry block\n:entry_first\n";
652  InstrProfSymtab Symtab;
653 
655  using RecordType = std::pair<StringRef, FuncPair>;
656  SmallVector<RecordType, 4> OrderedFuncData;
657 
658  for (const auto &I : FunctionData) {
659  if (shouldEncodeData(I.getValue())) {
660  if (Error E = Symtab.addFuncName(I.getKey()))
661  return E;
662  for (const auto &Func : I.getValue())
663  OrderedFuncData.push_back(std::make_pair(I.getKey(), Func));
664  }
665  }
666 
667  llvm::sort(OrderedFuncData, [](const RecordType &A, const RecordType &B) {
668  return std::tie(A.first, A.second.first) <
669  std::tie(B.first, B.second.first);
670  });
671 
672  for (const auto &record : OrderedFuncData) {
673  const StringRef &Name = record.first;
674  const FuncPair &Func = record.second;
675  writeRecordInText(Name, Func.first, Func.second, Symtab, OS);
676  }
677 
678  for (const auto &record : OrderedFuncData) {
679  const FuncPair &Func = record.second;
680  if (Error E = validateRecord(Func.second))
681  return E;
682  }
683 
684  return Error::success();
685 }
MemoryBuffer.h
llvm::raw_ostream::tell
uint64_t tell() const
tell - Return the current offset with the file.
Definition: raw_ostream.h:134
llvm::hlsl::ResourceKind::NumEntries
@ NumEntries
llvm::InstrProfWriter::writeText
Error writeText(raw_fd_ostream &OS)
Write the profile in text format to OS.
Definition: InstrProfWriter.cpp:642
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
llvm::msgpack::Endianness
constexpr support::endianness Endianness
The endianness of all multi-byte encoded values in MessagePack.
Definition: MsgPack.h:24
llvm::memprof::IndexedMemProfRecord
Definition: MemProf.h:324
llvm::InstrProfKind::FunctionEntryInstrumentation
@ FunctionEntryInstrumentation
M
We currently emits eax Perhaps this is what we really should generate is Is imull three or four cycles eax eax The current instruction priority is based on pattern complexity The former is more complex because it folds a load so the latter will not be emitted Perhaps we should use AddedComplexity to give LEA32r a higher priority We should always try to match LEA first since the LEA matching code does some estimate to determine whether the match is profitable if we care more about code then imull is better It s two bytes shorter than movl leal On a Pentium M
Definition: README.txt:252
llvm::InstrProfKind::FunctionEntryOnly
@ FunctionEntryOnly
llvm::InstrProfWriter::write
Error write(raw_fd_ostream &OS)
Write the profile to OS.
Definition: InstrProfWriter.cpp:561
llvm::OnDiskChainedHashTableGenerator
Generates an on disk hash table.
Definition: OnDiskHashTable.h:58
ProfileSummary.h
StringRef.h
P
This currently compiles esp xmm0 movsd esp eax eax esp ret We should use not the dag combiner This is because dagcombine2 needs to be able to see through the X86ISD::Wrapper which DAGCombine can t really do The code for turning x load into a single vector load is target independent and should be moved to the dag combiner The code for turning x load into a vector load can only handle a direct load from a global or a direct load from the stack It should be generalized to handle any load from P
Definition: README-SSE.txt:411
llvm::raw_string_ostream
A raw_ostream that writes to an std::string.
Definition: raw_ostream.h:642
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1199
llvm::IndexedInstrProf::ComputeHash
uint64_t ComputeHash(StringRef K)
Definition: InstrProf.h:1062
llvm::FunctionLoweringInfo::StatepointRelocationRecord
Helper object to track which of three possible relocation mechanisms are used for a particular value ...
Definition: FunctionLoweringInfo.h:95
llvm::InstrProfKind::ContextSensitive
@ ContextSensitive
llvm::memprof::PortableMemInfoBlock::getSchema
static MemProfSchema getSchema()
Definition: MemProf.h:102
llvm::ProfOStream::write
void write(uint64_t V)
Definition: InstrProfWriter.cpp:56
llvm::Error::success
static ErrorSuccess success()
Create a success value.
Definition: Error.h:330
llvm::SmallDenseMap
Definition: DenseMap.h:880
Error.h
llvm::DenseMapIterator
Definition: DenseMap.h:57
llvm::IndexedInstrProf::Summary::NumKinds
@ NumKinds
Definition: InstrProf.h:1118
llvm::OverlapStats
Definition: InstrProf.h:650
llvm::InstrProfRecord::overlap
void overlap(InstrProfRecord &Other, OverlapStats &Overlap, OverlapStats &FuncLevelOverlap, uint64_t ValueCutoff)
Compute the overlap b/w this IntrprofRecord and Other.
Definition: InstrProf.cpp:604
llvm::InstrProfRecordWriterTrait::CSSummaryBuilder
InstrProfSummaryBuilder * CSSummaryBuilder
Definition: InstrProfWriter.cpp:110
llvm::InstrProfRecordWriterTrait::ValueProfDataEndianness
support::endianness ValueProfDataEndianness
Definition: InstrProfWriter.cpp:108
llvm::ProfOStream::tell
uint64_t tell()
Definition: InstrProfWriter.cpp:55
STLExtras.h
llvm::instrprof_error::invalid_prof
@ invalid_prof
llvm::support::endian::Writer
Adapter to write values to a stream in a particular byte order.
Definition: EndianStream.h:52
llvm::detail::DenseSetImpl::insert
std::pair< iterator, bool > insert(const ValueT &V)
Definition: DenseSet.h:206
ProfileCommon.h
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::detail::DenseMapPair
Definition: DenseMap.h:42
llvm::InstrProfRecord
Profiling information for a single function.
Definition: InstrProf.h:730
new
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM ID Predecessors according to mbb< bb27, 0x8b0a7c0 > Note ADDri is not a two address instruction its result reg1037 is an operand of the PHI node in bb76 and its operand reg1039 is the result of the PHI node We should treat it as a two address code and make sure the ADDri is scheduled after any node that reads reg1039 Use info(i.e. register scavenger) to assign it a free register to allow reuse the collector could move the objects and invalidate the derived pointer This is bad enough in the first but safe points can crop up unpredictably **array_addr i32 n y store obj * new
Definition: README.txt:125
F
#define F(x, y, z)
Definition: MD5.cpp:55
InstrProfData.inc
llvm::InstrProfRecordWriterTrait
Definition: InstrProfWriter.cpp:97
InstrProfWriter.h
llvm::OverlapFuncFilters
Definition: InstrProf.h:693
llvm::X86II::PD
@ PD
Definition: X86BaseInfo.h:792
llvm::coverage::CurrentVersion
@ CurrentVersion
Definition: CoverageMapping.h:1021
PatchItem::Pos
uint64_t Pos
Definition: InstrProfWriter.cpp:39
llvm::CountSumOrPercent::CountSum
double CountSum
Definition: InstrProf.h:638
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::ProfileSummary::getNumCounts
uint32_t getNumCounts() const
Definition: ProfileSummary.h:91
llvm::support::little
@ little
Definition: Endian.h:27
llvm::InstrProfKind::IRInstrumentation
@ IRInstrumentation
llvm::InstrProfKind::SingleByteCoverage
@ SingleByteCoverage
llvm::OnDiskChainedHashTableGenerator::Emit
offset_type Emit(raw_ostream &Out)
Emit the table to Out, which must not be at offset 0.
Definition: OnDiskHashTable.h:142
OnDiskHashTable.h
llvm::InstrProfWriter::writeRecordInText
static void writeRecordInText(StringRef Name, uint64_t Hash, const InstrProfRecord &Counters, InstrProfSymtab &Symtab, raw_fd_ostream &OS)
Write Record in text format to OS.
Definition: InstrProfWriter.cpp:601
llvm::InstrProfRecordWriterTrait::EmitData
void EmitData(raw_ostream &Out, key_type_ref, data_type_ref V, offset_type)
Definition: InstrProfWriter.cpp:146
PatchItem::N
int N
Definition: InstrProfWriter.cpp:41
llvm::ProfileSummary::getNumFunctions
uint32_t getNumFunctions() const
Definition: ProfileSummary.h:89
llvm::ProfileSummary::getMaxInternalCount
uint64_t getMaxInternalCount() const
Definition: ProfileSummary.h:94
false
Definition: StackSlotColoring.cpp:141
llvm::ProfileSummary::getTotalCount
uint64_t getTotalCount() const
Definition: ProfileSummary.h:92
B
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
llvm::ProfOStream::OS
raw_ostream & OS
Definition: InstrProfWriter.cpp:93
PatchItem
Definition: InstrProfWriter.cpp:38
llvm::raw_ostream::write
raw_ostream & write(unsigned char C)
Definition: raw_ostream.cpp:218
InstrProf.h
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
llvm::StringRef::data
const char * data() const
data - Get a pointer to the start of the string (which may not be null terminated).
Definition: StringRef.h:131
llvm::IndexedInstrProf::Header
Definition: InstrProf.h:1066
llvm::raw_fd_ostream::seek
uint64_t seek(uint64_t off)
Flushes the stream and repositions the underlying file descriptor position to the offset specified fr...
Definition: raw_ostream.cpp:800
llvm::IndexedInstrProf::Summary::TotalBlockCount
@ TotalBlockCount
The sum of all instrumented block counts.
Definition: InstrProf.h:1117
ValueProfKindStr
static const char * ValueProfKindStr[]
Definition: InstrProfWriter.cpp:578
llvm::ProfileSummary::getMaxFunctionCount
uint64_t getMaxFunctionCount() const
Definition: ProfileSummary.h:90
llvm::sort
void sort(IteratorTy Start, IteratorTy End)
Definition: STLExtras.h:1683
llvm::function_ref
An efficient, type-erasing, non-owning reference to a callable.
Definition: STLFunctionalExtras.h:36
llvm::IndexedInstrProf::Summary::MaxFunctionCount
@ MaxFunctionCount
The maximal execution count among all functions.
Definition: InstrProf.h:1111
llvm::DenseSet< uint64_t >
llvm::CountSumOrPercent::NumEntries
uint64_t NumEntries
Definition: InstrProf.h:637
llvm::IndexedInstrProf::Summary::set
void set(SummaryFieldKind K, uint64_t V)
Definition: InstrProf.h:1157
llvm::InstrProfRecordWriterTrait::data_type
const InstrProfWriter::ProfilingData *const data_type
Definition: InstrProfWriter.cpp:102
llvm::ProfOStream::patch
void patch(PatchItem *P, int NItems)
Definition: InstrProfWriter.cpp:62
llvm::memprof::Frame
Definition: MemProf.h:142
llvm::InstrProfWriter
Definition: InstrProfWriter.h:37
llvm::ProfileSummary::getDetailedSummary
const SummaryEntryVector & getDetailedSummary()
Definition: ProfileSummary.h:88
uint64_t
llvm::InstrProfWriter::setValueProfDataEndianness
void setValueProfDataEndianness(support::endianness Endianness)
Definition: InstrProfWriter.cpp:180
D
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
llvm::alignToPowerOf2
uint64_t alignToPowerOf2(uint64_t Value, uint64_t Align)
Definition: MathExtras.h:476
llvm::InstrProfRecordWriterTrait::SummaryBuilder
InstrProfSummaryBuilder * SummaryBuilder
Definition: InstrProfWriter.cpp:109
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::InstrProfWriter::addMemProfFrame
bool addMemProfFrame(const memprof::FrameId, const memprof::Frame &F, function_ref< void(Error)> Warn)
Add a memprof frame identified by the hash of the contents of the frame in FrameId.
Definition: InstrProfWriter.cpp:268
true
basic Basic Alias true
Definition: BasicAliasAnalysis.cpp:1804
llvm::InstrProfSummaryBuilder
Definition: ProfileCommon.h:74
llvm::InstrProfWriter::addMemProfRecord
void addMemProfRecord(const GlobalValue::GUID Id, const memprof::IndexedMemProfRecord &Record)
Add a memprof record for a function identified by its Id.
Definition: InstrProfWriter.cpp:257
I
#define I(x, y, z)
Definition: MD5.cpp:58
llvm::instrprof_error
instrprof_error
Definition: InstrProf.h:308
size
i< reg-> size
Definition: README.txt:166
llvm::ProfileSummary
Definition: ProfileSummary.h:45
setSummary
static void setSummary(IndexedInstrProf::Summary *TheSummary, ProfileSummary &PS)
Definition: InstrProfWriter.cpp:323
llvm::InstrProfWriter::InstrProfWriter
InstrProfWriter(bool Sparse=false)
Definition: InstrProfWriter.cpp:174
llvm::IndexedInstrProf::allocSummary
std::unique_ptr< Summary > allocSummary(uint32_t TotalSize)
Definition: InstrProf.h:1171
llvm::Record
Definition: Record.h:1577
llvm::IndexedInstrProf::Summary::TotalNumFunctions
@ TotalNumFunctions
The total number of functions instrumented.
Definition: InstrProf.h:1105
getSize
static unsigned getSize(unsigned Kind)
Definition: XtensaAsmBackend.cpp:134
llvm::InstrProfKind::MemProf
@ MemProf
llvm::InstrProfWriter::addRecord
void addRecord(NamedInstrProfRecord &&I, uint64_t Weight, function_ref< void(Error)> Warn)
Add function counts for the given function.
Definition: InstrProfWriter.cpp:189
llvm::ProfOStream::ProfOStream
ProfOStream(raw_fd_ostream &FD)
Definition: InstrProfWriter.cpp:50
llvm::IndexedInstrProf::Summary::setEntry
void setEntry(uint32_t I, const ProfileSummaryEntry &E)
Definition: InstrProf.h:1163
llvm::OverlapStats::addOneUnique
void addOneUnique(const CountSumOrPercent &UniqueFunc)
Definition: InstrProf.cpp:1257
llvm::ArrayRef
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition: APInt.h:33
llvm::any_of
bool any_of(R &&range, UnaryPredicate P)
Provide wrappers to std::any_of which take ranges instead of having to pass begin/end explicitly.
Definition: STLExtras.h:1742
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
llvm::IndexedInstrProf::Magic
const uint64_t Magic
Definition: InstrProf.h:1025
llvm::support::endian::Writer::write
void write(ArrayRef< value_type > Val)
Definition: EndianStream.h:56
llvm::NamedInstrProfRecord::hasCSFlagInHash
static bool hasCSFlagInHash(uint64_t FuncHash)
Definition: InstrProf.h:923
uint32_t
llvm::append_range
void append_range(Container &C, Range &&R)
Wrapper function to append a range to a container.
Definition: STLExtras.h:2014
llvm::IndexedInstrProf::Summary::NumCutoffEntries
uint64_t NumCutoffEntries
Definition: InstrProf.h:1124
S
add sub stmia L5 ldr r0 bl L_printf $stub Instead of a and a wouldn t it be better to do three moves *Return an aggregate type is even return S
Definition: README.txt:210
llvm::unique
auto unique(Range &&R)
Definition: GenericUniformityImpl.h:56
llvm::memprof::IndexedMemProfRecord::merge
void merge(const IndexedMemProfRecord &Other)
Definition: MemProf.h:340
llvm::raw_fd_ostream
A raw_ostream that writes to a file descriptor.
Definition: raw_ostream.h:454
llvm::InstrProfRecord::merge
void merge(InstrProfRecord &Other, uint64_t Weight, function_ref< void(instrprof_error)> Warn)
Merge the counts in Other into this one.
Definition: InstrProf.cpp:708
llvm::StringRef::size
constexpr size_t size() const
size - Get the string size.
Definition: StringRef.h:137
MemProf.h
llvm::InstrProfWriter::writeBuffer
std::unique_ptr< MemoryBuffer > writeBuffer()
Write the profile, returning the raw data. For testing.
Definition: InstrProfWriter.cpp:567
llvm::ProfOStream::writeByte
void writeByte(uint8_t V)
Definition: InstrProfWriter.cpp:57
llvm::IndexedInstrProf::Summary::MaxInternalBlockCount
@ MaxInternalBlockCount
Max internal block count of the program (excluding entry blocks).
Definition: InstrProf.h:1115
llvm::InstrProfSymtab
A symbol table used for function PGO name look-up with keys (such as pointers, md5hash values) to the...
Definition: InstrProf.h:446
EndianStream.h
llvm::InstrProfWriter::~InstrProfWriter
~InstrProfWriter()
Definition: InstrProfWriter.cpp:177
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:156
llvm::InstrProfRecordWriterTrait::data_type_ref
const InstrProfWriter::ProfilingData *const data_type_ref
Definition: InstrProfWriter.cpp:103
llvm::IndexedInstrProf::Summary
Definition: InstrProf.h:1093
llvm::InstrProfWriter::validateRecord
Error validateRecord(const InstrProfRecord &Func)
Definition: InstrProfWriter.cpp:583
llvm::IndexedInstrProf::Summary::MaxBlockCount
@ MaxBlockCount
Max block count of the program.
Definition: InstrProf.h:1113
llvm::ProfOStream::LE
support::endian::Writer LE
Definition: InstrProfWriter.cpp:94
llvm::InstrProfWriter::addBinaryIds
void addBinaryIds(ArrayRef< llvm::object::BuildID > BIs)
Definition: InstrProfWriter.cpp:284
llvm::OverlapStats::Overlap
CountSumOrPercent Overlap
Definition: InstrProf.h:657
llvm::IndexedInstrProf::HashType
const HashT HashType
Definition: InstrProf.h:1060
llvm::InstrProfRecordWriterTrait::EmitKey
void EmitKey(raw_ostream &Out, key_type_ref K, offset_type N)
Definition: InstrProfWriter.cpp:142
llvm::InstrProfSymtab::addFuncName
Error addFuncName(StringRef FuncName)
Update the symtab by adding FuncName to the table.
Definition: InstrProf.h:507
llvm::DenseMapBase< SmallDenseMap< KeyT, ValueT, 4, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >, KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > >::iterator
DenseMapIterator< KeyT, ValueT, DenseMapInfo< KeyT >, llvm::detail::DenseMapPair< KeyT, ValueT > > iterator
Definition: DenseMap.h:71
Other
std::optional< std::vector< StOtherPiece > > Other
Definition: ELFYAML.cpp:1260
llvm::InstrProfRecord::sortValueData
void sortValueData()
Sort value profile data (per site) by count.
Definition: InstrProf.h:800
llvm::OverlapFuncFilters::ValueCutoff
uint64_t ValueCutoff
Definition: InstrProf.h:694
llvm::InstrProfSymtab::getFuncNameOrExternalSymbol
StringRef getFuncNameOrExternalSymbol(uint64_t FuncMD5Hash)
Just like getFuncName, except that it will return a non-empty StringRef if the function is external t...
Definition: InstrProf.h:597
N
#define N
llvm::OverlapFuncFilters::NameFilter
const std::string NameFilter
Definition: InstrProf.h:695
llvm::ArrayRef::size
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:163
support
Reimplement select in terms of SEL *We would really like to support but we need to prove that the add doesn t need to overflow between the two bit chunks *Implement pre post increment support(e.g. PR935) *Implement smarter const ant generation for binops with large immediates. A few ARMv6T2 ops should be pattern matched
Definition: README.txt:10
llvm::support::endianness
endianness
Definition: Endian.h:27
llvm::NamedInstrProfRecord
Definition: InstrProf.h:911
llvm::instrprof_error::malformed
@ malformed
llvm::InstrProfSummaryBuilder::addRecord
void addRecord(const InstrProfRecord &)
Definition: ProfileSummaryBuilder.cpp:93
llvm::InstrProfRecordWriterTrait::EmitKeyDataLength
static std::pair< offset_type, offset_type > EmitKeyDataLength(raw_ostream &Out, key_type_ref K, data_type_ref V)
Definition: InstrProfWriter.cpp:119
PatchItem::D
uint64_t * D
Definition: InstrProfWriter.cpp:40
llvm::IndexedInstrProf::Summary::TotalNumBlocks
@ TotalNumBlocks
Total number of instrumented blocks/edges.
Definition: InstrProf.h:1107
llvm::InstrProfRecordWriterTrait::ComputeHash
static hash_value_type ComputeHash(key_type_ref K)
Definition: InstrProfWriter.cpp:114
llvm::ProfOStream
Definition: InstrProfWriter.cpp:48
llvm::InstrProfWriter::setOutputSparse
void setOutputSparse(bool Sparse)
Definition: InstrProfWriter.cpp:185
raw_ostream.h
llvm::AMDGPU::VGPRIndexMode::Id
Id
Definition: SIDefines.h:247
llvm::MemoryBuffer::getMemBufferCopy
static std::unique_ptr< MemoryBuffer > getMemBufferCopy(StringRef InputData, const Twine &BufferName="")
Open the specified memory range as a MemoryBuffer, copying the contents and taking ownership of it.
Definition: MemoryBuffer.cpp:143
Endian.h
llvm::InstrProfWriter::mergeRecordsFromWriter
void mergeRecordsFromWriter(InstrProfWriter &&IPW, function_ref< void(Error)> Warn)
Merge existing function counts from the given writer.
Definition: InstrProfWriter.cpp:288
llvm::raw_string_ostream::str
std::string & str()
Returns the string's reference.
Definition: raw_ostream.h:660
llvm::IndexedInstrProf::Summary::NumSummaryFields
uint64_t NumSummaryFields
Definition: InstrProf.h:1122
llvm::ProfileSummaryBuilder::DefaultCutoffs
static const ArrayRef< uint32_t > DefaultCutoffs
A vector of useful cutoff values for detailed summary.
Definition: ProfileCommon.h:65
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::OverlapStats::addOneMismatch
void addOneMismatch(const CountSumOrPercent &MismatchFunc)
Definition: InstrProf.cpp:1247
llvm::InstrProfRecord::Counts
std::vector< uint64_t > Counts
Definition: InstrProf.h:731
llvm::ProfOStream::IsFDOStream
bool IsFDOStream
Definition: InstrProfWriter.cpp:92
llvm::OverlapStats::Test
CountSumOrPercent Test
Definition: InstrProf.h:655
llvm::ProfileSummary::getMaxCount
uint64_t getMaxCount() const
Definition: ProfileSummary.h:93
llvm::ProfOStream::ProfOStream
ProfOStream(raw_string_ostream &STR)
Definition: InstrProfWriter.cpp:52
llvm::InstrProfWriter::overlapRecord
void overlapRecord(NamedInstrProfRecord &&Other, OverlapStats &Overlap, OverlapStats &FuncLevelOverlap, const OverlapFuncFilters &FuncFilter)
Definition: InstrProfWriter.cpp:196
llvm::InstrProfRecord::scale
void scale(uint64_t N, uint64_t D, function_ref< void(instrprof_error)> Warn)
Scale up profile counts (including value profile data) by a factor of (N / D).
Definition: InstrProf.cpp:759