llvm.org GIT mirror llvm / 93bc746
[SampleFDO] Add a new compact binary format for sample profile. Name table occupies a big chunk of size in current binary format sample profile. In order to reduce its size, the patch changes the sample writer/reader to save/restore MD5Hash of names in the name table. Sample annotation phase will also use MD5Hash of name to query samples accordingly. Experiment shows compact binary format can reduce the size of sample profile by 2/3 compared with binary format generally. Differential Revision: https://reviews.llvm.org/D47955 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@334447 91177308-0d34-0410-b5e6-96231b3b80d8 Wei Mi 1 year, 3 months ago
10 changed file(s) with 434 addition(s) and 102 deletion(s). Raw diff Collapse all Expand all
7777 namespace llvm {
7878 namespace sampleprof {
7979
80 static inline uint64_t SPMagic() {
80 enum SampleProfileFormat {
81 SPF_None = 0,
82 SPF_Text = 0x1,
83 SPF_Compact_Binary = 0x2,
84 SPF_GCC = 0x3,
85 SPF_Raw_Binary = 0xff
86 };
87
88 static inline uint64_t SPMagic(SampleProfileFormat Format = SPF_Raw_Binary) {
8189 return uint64_t('S') << (64 - 8) | uint64_t('P') << (64 - 16) |
8290 uint64_t('R') << (64 - 24) | uint64_t('O') << (64 - 32) |
8391 uint64_t('F') << (64 - 40) | uint64_t('4') << (64 - 48) |
84 uint64_t('2') << (64 - 56) | uint64_t(0xff);
92 uint64_t('2') << (64 - 56) | uint64_t(Format);
93 }
94
95 // Get the proper representation of a string in the input Format.
96 static inline StringRef getRepInFormat(StringRef Name,
97 SampleProfileFormat Format,
98 std::string &GUIDBuf) {
99 GUIDBuf = std::to_string(Function::getGUID(Name));
100 return (Format == SPF_Compact_Binary) ? StringRef(GUIDBuf) : Name;
85101 }
86102
87103 static inline uint64_t SPVersion() { return 103; }
358374 /// GUID to \p S. Also traverse the BodySamples to add hot CallTarget's GUID
359375 /// to \p S.
360376 void findInlinedFunctions(DenseSet &S, const Module *M,
361 uint64_t Threshold) const {
377 uint64_t Threshold, bool isCompact) const {
362378 if (TotalSamples <= Threshold)
363379 return;
364380 S.insert(Function::getGUID(Name));
369385 if (TS.getValue() > Threshold) {
370386 Function *Callee = M->getFunction(TS.getKey());
371387 if (!Callee || !Callee->getSubprogram())
372 S.insert(Function::getGUID(TS.getKey()));
388 S.insert(isCompact ? std::stol(TS.getKey().data())
389 : Function::getGUID(TS.getKey()));
373390 }
374391 for (const auto &CS : CallsiteSamples)
375392 for (const auto &NameFS : CS.second)
376 NameFS.second.findInlinedFunctions(S, M, Threshold);
393 NameFS.second.findInlinedFunctions(S, M, Threshold, isCompact);
377394 }
378395
379396 /// Set the name of the function.
263263 /// compact and I/O efficient. They can both be used interchangeably.
264264 class SampleProfileReader {
265265 public:
266 SampleProfileReader(std::unique_ptr B, LLVMContext &C)
267 : Profiles(0), Ctx(C), Buffer(std::move(B)) {}
266 SampleProfileReader(std::unique_ptr B, LLVMContext &C,
267 SampleProfileFormat Format = SPF_None)
268 : Profiles(0), Ctx(C), Buffer(std::move(B)), Format(Format) {}
268269
269270 virtual ~SampleProfileReader() = default;
270271
285286 // The function name may have been updated by adding suffix. In sample
286287 // profile, the function names are all stripped, so we need to strip
287288 // the function name suffix before matching with profile.
288 if (Profiles.count(F.getName().split('.').first))
289 return &Profiles[(F.getName().split('.').first)];
289 StringRef Fname = F.getName().split('.').first;
290 std::string FGUID;
291 Fname = getRepInFormat(Fname, getFormat(), FGUID);
292 if (Profiles.count(Fname))
293 return &Profiles[Fname];
290294 return nullptr;
291295 }
292296
309313
310314 /// Return the profile summary.
311315 ProfileSummary &getSummary() { return *(Summary.get()); }
316
317 /// \brief Return the profile format.
318 SampleProfileFormat getFormat() { return Format; }
312319
313320 protected:
314321 /// Map every function to its associated profile.
329336
330337 /// Compute summary for this profile.
331338 void computeSummary();
339
340 /// \brief The format of sample.
341 SampleProfileFormat Format = SPF_None;
332342 };
333343
334344 class SampleProfileReaderText : public SampleProfileReader {
335345 public:
336346 SampleProfileReaderText(std::unique_ptr B, LLVMContext &C)
337 : SampleProfileReader(std::move(B), C) {}
347 : SampleProfileReader(std::move(B), C, SPF_Text) {}
338348
339349 /// Read and validate the file header.
340350 std::error_code readHeader() override { return sampleprof_error::success; }
348358
349359 class SampleProfileReaderBinary : public SampleProfileReader {
350360 public:
351 SampleProfileReaderBinary(std::unique_ptr B, LLVMContext &C)
352 : SampleProfileReader(std::move(B), C) {}
361 SampleProfileReaderBinary(std::unique_ptr B, LLVMContext &C,
362 SampleProfileFormat Format = SPF_None)
363 : SampleProfileReader(std::move(B), C, Format) {}
353364
354365 /// Read and validate the file header.
355366 std::error_code readHeader() override;
356367
357368 /// Read sample profiles from the associated file.
358369 std::error_code read() override;
359
360 /// Return true if \p Buffer is in the format supported by this class.
361 static bool hasFormat(const MemoryBuffer &Buffer);
362370
363371 protected:
364372 /// Read a numeric value of type T from the profile.
377385 /// \returns the read value.
378386 ErrorOr readString();
379387
380 /// Read a string indirectly via the name table.
381 ErrorOr readStringFromTable();
388 /// Read the string index and check whether it overflows the table.
389 template inline ErrorOr readStringIndex(T &Table);
382390
383391 /// Return true if we've reached the end of file.
384392 bool at_eof() const { return Data >= End; }
392400 /// Points to the end of the buffer.
393401 const uint8_t *End = nullptr;
394402
403 private:
404 std::error_code readSummaryEntry(std::vector &Entries);
405 virtual std::error_code verifySPMagic(uint64_t Magic) = 0;
406
407 /// Read profile summary.
408 std::error_code readSummary();
409
410 /// Read the whole name table.
411 virtual std::error_code readNameTable() = 0;
412
413 /// Read a string indirectly via the name table.
414 virtual ErrorOr readStringFromTable() = 0;
415 };
416
417 class SampleProfileReaderRawBinary : public SampleProfileReaderBinary {
418 private:
395419 /// Function name table.
396420 std::vector NameTable;
397
421 virtual std::error_code verifySPMagic(uint64_t Magic) override;
422 virtual std::error_code readNameTable() override;
423 /// Read a string indirectly via the name table.
424 virtual ErrorOr readStringFromTable() override;
425
426 public:
427 SampleProfileReaderRawBinary(std::unique_ptr B, LLVMContext &C)
428 : SampleProfileReaderBinary(std::move(B), C, SPF_Raw_Binary) {}
429
430 /// \brief Return true if \p Buffer is in the format supported by this class.
431 static bool hasFormat(const MemoryBuffer &Buffer);
432 };
433
434 class SampleProfileReaderCompactBinary : public SampleProfileReaderBinary {
398435 private:
399 std::error_code readSummaryEntry(std::vector &Entries);
400
401 /// Read profile summary.
402 std::error_code readSummary();
436 /// Function name table.
437 std::vector NameTable;
438 virtual std::error_code verifySPMagic(uint64_t Magic) override;
439 virtual std::error_code readNameTable() override;
440 /// Read a string indirectly via the name table.
441 virtual ErrorOr readStringFromTable() override;
442
443 public:
444 SampleProfileReaderCompactBinary(std::unique_ptr B,
445 LLVMContext &C)
446 : SampleProfileReaderBinary(std::move(B), C, SPF_Compact_Binary) {}
447
448 /// \brief Return true if \p Buffer is in the format supported by this class.
449 static bool hasFormat(const MemoryBuffer &Buffer);
403450 };
404451
405452 using InlineCallStack = SmallVector;
420467 class SampleProfileReaderGCC : public SampleProfileReader {
421468 public:
422469 SampleProfileReaderGCC(std::unique_ptr B, LLVMContext &C)
423 : SampleProfileReader(std::move(B), C), GcovBuffer(Buffer.get()) {}
470 : SampleProfileReader(std::move(B), C, SPF_GCC),
471 GcovBuffer(Buffer.get()) {}
424472
425473 /// Read and validate the file header.
426474 std::error_code readHeader() override;
2222 #include
2323 #include
2424 #include
25 #include
2526 #include
2627
2728 namespace llvm {
2829 namespace sampleprof {
29
30 enum SampleProfileFormat { SPF_None = 0, SPF_Text, SPF_Binary, SPF_GCC };
3130
3231 /// Sample-based profile writer. Base class.
3332 class SampleProfileWriter {
104103 class SampleProfileWriterBinary : public SampleProfileWriter {
105104 public:
106105 std::error_code write(const FunctionSamples &S) override;
107
108 protected:
109106 SampleProfileWriterBinary(std::unique_ptr &OS)
110107 : SampleProfileWriter(OS) {}
111108
112 std::error_code
113 writeHeader(const StringMap &ProfileMap) override;
109 protected:
110 virtual std::error_code writeNameTable() = 0;
111 virtual std::error_code writeMagicIdent() = 0;
112 std::error_code writeHeader(const StringMap &ProfileMap);
114113 std::error_code writeSummary();
115114 std::error_code writeNameIdx(StringRef FName);
116115 std::error_code writeBody(const FunctionSamples &S);
116 inline void stablizeNameTable(std::set &V);
117
118 MapVector NameTable;
117119
118120 private:
119121 void addName(StringRef FName);
120122 void addNames(const FunctionSamples &S);
121
122 MapVector NameTable;
123123
124124 friend ErrorOr>
125125 SampleProfileWriter::create(std::unique_ptr &OS,
126126 SampleProfileFormat Format);
127127 };
128128
129 class SampleProfileWriterRawBinary : public SampleProfileWriterBinary {
130 using SampleProfileWriterBinary::SampleProfileWriterBinary;
131
132 protected:
133 virtual std::error_code writeNameTable() override;
134 virtual std::error_code writeMagicIdent() override;
135 };
136
137 class SampleProfileWriterCompactBinary : public SampleProfileWriterBinary {
138 using SampleProfileWriterBinary::SampleProfileWriterBinary;
139
140 protected:
141 virtual std::error_code writeNameTable() override;
142 virtual std::error_code writeMagicIdent() override;
143 };
144
129145 } // end namespace sampleprof
130146 } // end namespace llvm
131147
318318 return Str;
319319 }
320320
321 ErrorOr SampleProfileReaderBinary::readStringFromTable() {
321 template
322 inline ErrorOr SampleProfileReaderBinary::readStringIndex(T &Table) {
322323 std::error_code EC;
323324 auto Idx = readNumber();
324325 if (std::error_code EC = Idx.getError())
325326 return EC;
326 if (*Idx >= NameTable.size())
327 if (*Idx >= Table.size())
327328 return sampleprof_error::truncated_name_table;
329 return *Idx;
330 }
331
332 ErrorOr SampleProfileReaderRawBinary::readStringFromTable() {
333 auto Idx = readStringIndex(NameTable);
334 if (std::error_code EC = Idx.getError())
335 return EC;
336
328337 return NameTable[*Idx];
338 }
339
340 ErrorOr SampleProfileReaderCompactBinary::readStringFromTable() {
341 auto Idx = readStringIndex(NameTable);
342 if (std::error_code EC = Idx.getError())
343 return EC;
344
345 return StringRef(NameTable[*Idx]);
329346 }
330347
331348 std::error_code
428445 return sampleprof_error::success;
429446 }
430447
431 std::error_code SampleProfileReaderBinary::readHeader() {
432 Data = reinterpret_cast(Buffer->getBufferStart());
433 End = Data + Buffer->getBufferSize();
434
435 // Read and check the magic identifier.
436 auto Magic = readNumber();
437 if (std::error_code EC = Magic.getError())
438 return EC;
439 else if (*Magic != SPMagic())
440 return sampleprof_error::bad_magic;
441
442 // Read the version number.
443 auto Version = readNumber();
444 if (std::error_code EC = Version.getError())
445 return EC;
446 else if (*Version != SPVersion())
447 return sampleprof_error::unsupported_version;
448
449 if (std::error_code EC = readSummary())
450 return EC;
451
452 // Read the name table.
448 std::error_code SampleProfileReaderRawBinary::verifySPMagic(uint64_t Magic) {
449 if (Magic == SPMagic())
450 return sampleprof_error::success;
451 return sampleprof_error::bad_magic;
452 }
453
454 std::error_code
455 SampleProfileReaderCompactBinary::verifySPMagic(uint64_t Magic) {
456 if (Magic == SPMagic(SPF_Compact_Binary))
457 return sampleprof_error::success;
458 return sampleprof_error::bad_magic;
459 }
460
461 std::error_code SampleProfileReaderRawBinary::readNameTable() {
453462 auto Size = readNumber();
454463 if (std::error_code EC = Size.getError())
455464 return EC;
464473 return sampleprof_error::success;
465474 }
466475
476 std::error_code SampleProfileReaderCompactBinary::readNameTable() {
477 auto Size = readNumber();
478 if (std::error_code EC = Size.getError())
479 return EC;
480 NameTable.reserve(*Size);
481 for (uint32_t I = 0; I < *Size; ++I) {
482 auto FID = readNumber();
483 if (std::error_code EC = FID.getError())
484 return EC;
485 NameTable.push_back(std::to_string(*FID));
486 }
487 return sampleprof_error::success;
488 }
489
490 std::error_code SampleProfileReaderBinary::readHeader() {
491 Data = reinterpret_cast(Buffer->getBufferStart());
492 End = Data + Buffer->getBufferSize();
493
494 // Read and check the magic identifier.
495 auto Magic = readNumber();
496 if (std::error_code EC = Magic.getError())
497 return EC;
498 else if (std::error_code EC = verifySPMagic(*Magic))
499 return sampleprof_error::bad_magic;
500
501 // Read the version number.
502 auto Version = readNumber();
503 if (std::error_code EC = Version.getError())
504 return EC;
505 else if (*Version != SPVersion())
506 return sampleprof_error::unsupported_version;
507
508 if (std::error_code EC = readSummary())
509 return EC;
510
511 if (std::error_code EC = readNameTable())
512 return EC;
513 return sampleprof_error::success;
514 }
515
467516 std::error_code SampleProfileReaderBinary::readSummaryEntry(
468517 std::vector &Entries) {
469518 auto Cutoff = readNumber();
520569 return sampleprof_error::success;
521570 }
522571
523 bool SampleProfileReaderBinary::hasFormat(const MemoryBuffer &Buffer) {
572 bool SampleProfileReaderRawBinary::hasFormat(const MemoryBuffer &Buffer) {
524573 const uint8_t *Data =
525574 reinterpret_cast(Buffer.getBufferStart());
526575 uint64_t Magic = decodeULEB128(Data);
527576 return Magic == SPMagic();
577 }
578
579 bool SampleProfileReaderCompactBinary::hasFormat(const MemoryBuffer &Buffer) {
580 const uint8_t *Data =
581 reinterpret_cast(Buffer.getBufferStart());
582 uint64_t Magic = decodeULEB128(Data);
583 return Magic == SPMagic(SPF_Compact_Binary);
528584 }
529585
530586 std::error_code SampleProfileReaderGCC::skipNextWord() {
812868 ErrorOr>
813869 SampleProfileReader::create(std::unique_ptr &B, LLVMContext &C) {
814870 std::unique_ptr Reader;
815 if (SampleProfileReaderBinary::hasFormat(*B))
816 Reader.reset(new SampleProfileReaderBinary(std::move(B), C));
871 if (SampleProfileReaderRawBinary::hasFormat(*B))
872 Reader.reset(new SampleProfileReaderRawBinary(std::move(B), C));
873 else if (SampleProfileReaderCompactBinary::hasFormat(*B))
874 Reader.reset(new SampleProfileReaderCompactBinary(std::move(B), C));
817875 else if (SampleProfileReaderGCC::hasFormat(*B))
818876 Reader.reset(new SampleProfileReaderGCC(std::move(B), C));
819877 else if (SampleProfileReaderText::hasFormat(*B))
2424 #include "llvm/Support/ErrorOr.h"
2525 #include "llvm/Support/FileSystem.h"
2626 #include "llvm/Support/LEB128.h"
27 #include "llvm/Support/MD5.h"
2728 #include "llvm/Support/raw_ostream.h"
2829 #include
2930 #include
143144 }
144145 }
145146
146 std::error_code SampleProfileWriterBinary::writeHeader(
147 const StringMap &ProfileMap) {
148 auto &OS = *OutputStream;
149
150 // Write file magic identifier.
151 encodeULEB128(SPMagic(), OS);
152 encodeULEB128(SPVersion(), OS);
153
154 computeSummary(ProfileMap);
155 if (auto EC = writeSummary())
156 return EC;
157
158 // Generate the name table for all the functions referenced in the profile.
159 for (const auto &I : ProfileMap) {
160 addName(I.first());
161 addNames(I.second);
162 }
163
164 // Sort the names to make NameTable is deterministic.
165 std::set V;
147 void SampleProfileWriterBinary::stablizeNameTable(std::set &V) {
148 // Sort the names to make NameTable deterministic.
166149 for (const auto &I : NameTable)
167150 V.insert(I.first);
168151 int i = 0;
169152 for (const StringRef &N : V)
170153 NameTable[N] = i++;
154 }
155
156 std::error_code SampleProfileWriterRawBinary::writeNameTable() {
157 auto &OS = *OutputStream;
158 std::set V;
159 stablizeNameTable(V);
171160
172161 // Write out the name table.
173162 encodeULEB128(NameTable.size(), OS);
175164 OS << N;
176165 encodeULEB128(0, OS);
177166 }
167 return sampleprof_error::success;
168 }
169
170 std::error_code SampleProfileWriterCompactBinary::writeNameTable() {
171 auto &OS = *OutputStream;
172 std::set V;
173 stablizeNameTable(V);
174
175 // Write out the name table.
176 encodeULEB128(NameTable.size(), OS);
177 for (auto N : V) {
178 encodeULEB128(MD5Hash(N), OS);
179 }
180 return sampleprof_error::success;
181 }
182
183 std::error_code SampleProfileWriterRawBinary::writeMagicIdent() {
184 auto &OS = *OutputStream;
185 // Write file magic identifier.
186 encodeULEB128(SPMagic(), OS);
187 encodeULEB128(SPVersion(), OS);
188 return sampleprof_error::success;
189 }
190
191 std::error_code SampleProfileWriterCompactBinary::writeMagicIdent() {
192 auto &OS = *OutputStream;
193 // Write file magic identifier.
194 encodeULEB128(SPMagic(SPF_Compact_Binary), OS);
195 encodeULEB128(SPVersion(), OS);
196 return sampleprof_error::success;
197 }
198
199 std::error_code SampleProfileWriterBinary::writeHeader(
200 const StringMap &ProfileMap) {
201 writeMagicIdent();
202
203 computeSummary(ProfileMap);
204 if (auto EC = writeSummary())
205 return EC;
206
207 // Generate the name table for all the functions referenced in the profile.
208 for (const auto &I : ProfileMap) {
209 addName(I.first());
210 addNames(I.second);
211 }
212
213 writeNameTable();
178214 return sampleprof_error::success;
179215 }
180216
257293 SampleProfileWriter::create(StringRef Filename, SampleProfileFormat Format) {
258294 std::error_code EC;
259295 std::unique_ptr OS;
260 if (Format == SPF_Binary)
296 if (Format == SPF_Raw_Binary || Format == SPF_Compact_Binary)
261297 OS.reset(new raw_fd_ostream(Filename, EC, sys::fs::F_None));
262298 else
263299 OS.reset(new raw_fd_ostream(Filename, EC, sys::fs::F_Text));
280316 std::error_code EC;
281317 std::unique_ptr Writer;
282318
283 if (Format == SPF_Binary)
284 Writer.reset(new SampleProfileWriterBinary(OS));
319 if (Format == SPF_Raw_Binary)
320 Writer.reset(new SampleProfileWriterRawBinary(OS));
321 else if (Format == SPF_Compact_Binary)
322 Writer.reset(new SampleProfileWriterCompactBinary(OS));
285323 else if (Format == SPF_Text)
286324 Writer.reset(new SampleProfileWriterText(OS));
287325 else if (Format == SPF_GCC)
637637 if (FS == nullptr)
638638 return nullptr;
639639
640 std::string CalleeGUID;
641 CalleeName = getRepInFormat(CalleeName, Reader->getFormat(), CalleeGUID);
640642 return FS->findFunctionSamplesAt(LineLocation(FunctionSamples::getOffset(DIL),
641643 DIL->getBaseDiscriminator()),
642644 CalleeName);
752754 Function &F, DenseSet &InlinedGUIDs) {
753755 DenseSet PromotedInsns;
754756 bool Changed = false;
757 bool isCompact = (Reader->getFormat() == SPF_Compact_Binary);
755758 while (true) {
756759 bool LocalChanged = false;
757760 SmallVector CIS;
783786 for (const auto *FS : findIndirectCallFunctionSamples(*I, Sum)) {
784787 if (IsThinLTOPreLink) {
785788 FS->findInlinedFunctions(InlinedGUIDs, F.getParent(),
786 PSI->getOrCompHotCountThreshold());
789 PSI->getOrCompHotCountThreshold(),
790 isCompact);
787791 continue;
788792 }
789793 auto CalleeFunctionName = FS->getName();
792796 // clone the caller first, and inline the cloned caller if it is
793797 // recursive. As llvm does not inline recursive calls, we will
794798 // simply ignore it instead of handling it explicitly.
795 if (CalleeFunctionName == F.getName())
799 std::string FGUID;
800 auto Fname = getRepInFormat(F.getName(), Reader->getFormat(), FGUID);
801 if (CalleeFunctionName == Fname)
796802 continue;
797803
798804 const char *Reason = "Callee function not available";
822828 LocalChanged = true;
823829 } else if (IsThinLTOPreLink) {
824830 findCalleeFunctionSamples(*I)->findInlinedFunctions(
825 InlinedGUIDs, F.getParent(), PSI->getOrCompHotCountThreshold());
831 InlinedGUIDs, F.getParent(), PSI->getOrCompHotCountThreshold(),
832 isCompact);
826833 }
827834 }
828835 if (LocalChanged) {
0 ; RUN: opt < %s -sample-profile -sample-profile-file=%S/Inputs/inline.prof -S | FileCheck %s
1 ; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/inline.prof -S | FileCheck %s
2 ; RUN: opt < %s -sample-profile -sample-profile-file=%S/Inputs/inline.compactbinary.afdo -S | FileCheck %s
3 ; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/inline.compactbinary.afdo -S | FileCheck %s
4
5 ; Original C++ test case
6 ;
7 ; #include
8 ;
9 ; int sum(int x, int y) {
10 ; return x + y;
11 ; }
12 ;
13 ; int main() {
14 ; int s, i = 0;
15 ; while (i++ < 20000 * 20000)
16 ; if (i != 100) s = sum(i, s); else s = 30;
17 ; printf("sum is %d\n", s);
18 ; return 0;
19 ; }
20 ;
21 @.str = private unnamed_addr constant [11 x i8] c"sum is %d\0A\00", align 1
22
23 ; Check sample-profile phase using compactbinary format profile will annotate
24 ; the IR with exactly the same result as using text format.
25 ; CHECK: br i1 %cmp, label %while.body, label %while.end{{.*}} !prof ![[IDX1:[0-9]*]]
26 ; CHECK: br i1 %cmp1, label %if.then, label %if.else{{.*}} !prof ![[IDX2:[0-9]*]]
27 ; CHECK: call i32 (i8*, ...) @printf{{.*}} !prof ![[IDX3:[0-9]*]]
28 ; CHECK: = !{!"TotalCount", i64 10944}
29 ; CHECK: = !{!"MaxCount", i64 5553}
30 ; CHECK: ![[IDX1]] = !{!"branch_weights", i32 5392, i32 163}
31 ; CHECK: ![[IDX2]] = !{!"branch_weights", i32 5280, i32 113}
32 ; CHECK: ![[IDX3]] = !{!"branch_weights", i32 1}
33
34 ; Function Attrs: nounwind uwtable
35 define i32 @_Z3sumii(i32 %x, i32 %y) !dbg !4 {
36 entry:
37 %x.addr = alloca i32, align 4
38 %y.addr = alloca i32, align 4
39 store i32 %x, i32* %x.addr, align 4
40 store i32 %y, i32* %y.addr, align 4
41 %0 = load i32, i32* %x.addr, align 4, !dbg !11
42 %1 = load i32, i32* %y.addr, align 4, !dbg !11
43 %add = add nsw i32 %0, %1, !dbg !11
44 ret i32 %add, !dbg !11
45 }
46
47 ; Function Attrs: uwtable
48 define i32 @main() !dbg !7 {
49 entry:
50 %retval = alloca i32, align 4
51 %s = alloca i32, align 4
52 %i = alloca i32, align 4
53 store i32 0, i32* %retval
54 store i32 0, i32* %i, align 4, !dbg !12
55 br label %while.cond, !dbg !13
56
57 while.cond: ; preds = %if.end, %entry
58 %0 = load i32, i32* %i, align 4, !dbg !14
59 %inc = add nsw i32 %0, 1, !dbg !14
60 store i32 %inc, i32* %i, align 4, !dbg !14
61 %cmp = icmp slt i32 %0, 400000000, !dbg !14
62 br i1 %cmp, label %while.body, label %while.end, !dbg !14
63
64 while.body: ; preds = %while.cond
65 %1 = load i32, i32* %i, align 4, !dbg !16
66 %cmp1 = icmp ne i32 %1, 100, !dbg !16
67 br i1 %cmp1, label %if.then, label %if.else, !dbg !16
68
69
70 if.then: ; preds = %while.body
71 %2 = load i32, i32* %i, align 4, !dbg !18
72 %3 = load i32, i32* %s, align 4, !dbg !18
73 %call = call i32 @_Z3sumii(i32 %2, i32 %3), !dbg !18
74 store i32 %call, i32* %s, align 4, !dbg !18
75 br label %if.end, !dbg !18
76
77 if.else: ; preds = %while.body
78 store i32 30, i32* %s, align 4, !dbg !20
79 br label %if.end
80
81 if.end: ; preds = %if.else, %if.then
82 br label %while.cond, !dbg !22
83
84 while.end: ; preds = %while.cond
85 %4 = load i32, i32* %s, align 4, !dbg !24
86 %call2 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([11 x i8], [11 x i8]* @.str, i32 0, i32 0), i32 %4), !dbg !24
87 ret i32 0, !dbg !25
88 }
89
90 declare i32 @printf(i8*, ...) #2
91
92 !llvm.dbg.cu = !{!0}
93 !llvm.module.flags = !{!8, !9}
94 !llvm.ident = !{!10}
95
96 !0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus, producer: "clang version 3.5 ", isOptimized: false, emissionKind: NoDebug, file: !1, enums: !2, retainedTypes: !2, globals: !2, imports: !2)
97 !1 = !DIFile(filename: "calls.cc", directory: ".")
98 !2 = !{}
99 !4 = distinct !DISubprogram(name: "sum", line: 3, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 3, file: !1, scope: !5, type: !6, retainedNodes: !2)
100 !5 = !DIFile(filename: "calls.cc", directory: ".")
101 !6 = !DISubroutineType(types: !2)
102 !7 = distinct !DISubprogram(name: "main", line: 7, isLocal: false, isDefinition: true, virtualIndex: 6, flags: DIFlagPrototyped, isOptimized: false, unit: !0, scopeLine: 7, file: !1, scope: !5, type: !6, retainedNodes: !2)
103 !8 = !{i32 2, !"Dwarf Version", i32 4}
104 !9 = !{i32 1, !"Debug Info Version", i32 3}
105 !10 = !{!"clang version 3.5 "}
106 !11 = !DILocation(line: 4, scope: !4)
107 !12 = !DILocation(line: 8, scope: !7)
108 !13 = !DILocation(line: 9, scope: !7)
109 !14 = !DILocation(line: 9, scope: !15)
110 !15 = !DILexicalBlockFile(discriminator: 2, file: !1, scope: !7)
111 !16 = !DILocation(line: 10, scope: !17)
112 !17 = distinct !DILexicalBlock(line: 10, column: 0, file: !1, scope: !7)
113 !18 = !DILocation(line: 10, scope: !19)
114 !19 = !DILexicalBlockFile(discriminator: 2, file: !1, scope: !17)
115 !20 = !DILocation(line: 10, scope: !21)
116 !21 = !DILexicalBlockFile(discriminator: 4, file: !1, scope: !17)
117 !22 = !DILocation(line: 10, scope: !23)
118 !23 = !DILexicalBlockFile(discriminator: 6, file: !1, scope: !17)
119 !24 = !DILocation(line: 11, scope: !7)
120 !25 = !DILocation(line: 12, scope: !7)
3333
3434 using namespace llvm;
3535
36 enum ProfileFormat { PF_None = 0, PF_Text, PF_Binary, PF_GCC };
36 enum ProfileFormat {
37 PF_None = 0,
38 PF_Text,
39 PF_Compact_Binary,
40 PF_GCC,
41 PF_Raw_Binary
42 };
3743
3844 static void warn(Twine Message, std::string Whence = "",
3945 std::string Hint = "") {
235241 if (OutputFilename.compare("-") == 0)
236242 exitWithError("Cannot write indexed profdata format to stdout.");
237243
238 if (OutputFormat != PF_Binary && OutputFormat != PF_Text)
244 if (OutputFormat != PF_Raw_Binary && OutputFormat != PF_Compact_Binary &&
245 OutputFormat != PF_Text)
239246 exitWithError("Unknown format is specified.");
240247
241248 std::error_code EC;
315322 }
316323
317324 static sampleprof::SampleProfileFormat FormatMap[] = {
318 sampleprof::SPF_None, sampleprof::SPF_Text, sampleprof::SPF_Binary,
319 sampleprof::SPF_GCC};
325 sampleprof::SPF_None, sampleprof::SPF_Text, sampleprof::SPF_Compact_Binary,
326 sampleprof::SPF_GCC, sampleprof::SPF_Raw_Binary};
320327
321328 static void mergeSampleProfile(const WeightedFileVector &Inputs,
322329 StringRef OutputFilename,
463470 cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
464471 clEnumVal(sample, "Sample profile")));
465472 cl::opt OutputFormat(
466 cl::desc("Format of output profile"), cl::init(PF_Binary),
467 cl::values(clEnumValN(PF_Binary, "binary", "Binary encoding (default)"),
468 clEnumValN(PF_Text, "text", "Text encoding"),
469 clEnumValN(PF_GCC, "gcc",
470 "GCC encoding (only meaningful for -sample)")));
473 cl::desc("Format of output profile"), cl::init(PF_Raw_Binary),
474 cl::values(
475 clEnumValN(PF_Raw_Binary, "binary", "Binary encoding (default)"),
476 clEnumValN(PF_Compact_Binary, "compbinary",
477 "Compact binary encoding (default)"),
478 clEnumValN(PF_Text, "text", "Text encoding"),
479 clEnumValN(PF_GCC, "gcc",
480 "GCC encoding (only meaningful for -sample)")));
471481 cl::opt OutputSparse("sparse", cl::init(false),
472482 cl::desc("Generate a sparse profile (only meaningful for -instr)"));
473483 cl::opt NumThreads(
7676 BarSamples.addTotalSamples(20301);
7777 BarSamples.addHeadSamples(1437);
7878 BarSamples.addBodySamples(1, 0, 1437);
79 BarSamples.addCalledTargetSamples(1, 0, "_M_construct", 1000);
80 BarSamples.addCalledTargetSamples(
81 1, 0, "string_view >", 437);
79 // Test how reader/writer handles unmangled names.
80 StringRef MconstructName("_M_construct");
81 StringRef StringviewName("string_view >");
82 BarSamples.addCalledTargetSamples(1, 0, MconstructName, 1000);
83 BarSamples.addCalledTargetSamples(1, 0, StringviewName, 437);
8284
8385 StringMap Profiles;
8486 Profiles[FooName] = std::move(FooSamples);
99101 StringMap &ReadProfiles = Reader->getProfiles();
100102 ASSERT_EQ(2u, ReadProfiles.size());
101103
102 FunctionSamples &ReadFooSamples = ReadProfiles[FooName];
104 std::string FooGUID;
105 StringRef FooRep = getRepInFormat(FooName, Format, FooGUID);
106 FunctionSamples &ReadFooSamples = ReadProfiles[FooRep];
103107 ASSERT_EQ(7711u, ReadFooSamples.getTotalSamples());
104108 ASSERT_EQ(610u, ReadFooSamples.getHeadSamples());
105109
106 FunctionSamples &ReadBarSamples = ReadProfiles[BarName];
110 std::string BarGUID;
111 StringRef BarRep = getRepInFormat(BarName, Format, BarGUID);
112 FunctionSamples &ReadBarSamples = ReadProfiles[BarRep];
107113 ASSERT_EQ(20301u, ReadBarSamples.getTotalSamples());
108114 ASSERT_EQ(1437u, ReadBarSamples.getHeadSamples());
109115 ErrorOr CTMap =
110116 ReadBarSamples.findCallTargetMapAt(1, 0);
111117 ASSERT_FALSE(CTMap.getError());
112 ASSERT_EQ(1000u, CTMap.get()["_M_construct"]);
113 ASSERT_EQ(437u, CTMap.get()["string_view >"]);
118
119 std::string MconstructGUID;
120 StringRef MconstructRep =
121 getRepInFormat(MconstructName, Format, MconstructGUID);
122 std::string StringviewGUID;
123 StringRef StringviewRep =
124 getRepInFormat(StringviewName, Format, StringviewGUID);
125 ASSERT_EQ(1000u, CTMap.get()[MconstructRep]);
126 ASSERT_EQ(437u, CTMap.get()[StringviewRep]);
114127
115128 auto VerifySummary = [](ProfileSummary &Summary) mutable {
116129 ASSERT_EQ(ProfileSummary::PSK_Sample, Summary.getKind());
165178 testRoundTrip(SampleProfileFormat::SPF_Text);
166179 }
167180
168 TEST_F(SampleProfTest, roundtrip_binary_profile) {
169 testRoundTrip(SampleProfileFormat::SPF_Binary);
181 TEST_F(SampleProfTest, roundtrip_raw_binary_profile) {
182 testRoundTrip(SampleProfileFormat::SPF_Raw_Binary);
183 }
184
185 TEST_F(SampleProfTest, roundtrip_compact_binary_profile) {
186 testRoundTrip(SampleProfileFormat::SPF_Compact_Binary);
170187 }
171188
172189 TEST_F(SampleProfTest, sample_overflow_saturation) {