diff options
| -rw-r--r-- | llvm/include/llvm/ProfileData/SampleProfReader.h | 3 | ||||
| -rw-r--r-- | llvm/lib/ProfileData/SampleProfReader.cpp | 112 | ||||
| -rw-r--r-- | llvm/lib/ProfileData/SampleProfWriter.cpp | 15 | ||||
| -rw-r--r-- | llvm/test/Transforms/SampleProfile/Inputs/fnptr.binprof | bin | 112 -> 115 bytes | |||
| -rw-r--r-- | llvm/test/tools/llvm-profdata/Inputs/inline-samples.afdo | 20 | ||||
| -rw-r--r-- | llvm/test/tools/llvm-profdata/inline-samples.test | 30 |
6 files changed, 137 insertions, 43 deletions
diff --git a/llvm/include/llvm/ProfileData/SampleProfReader.h b/llvm/include/llvm/ProfileData/SampleProfReader.h index 9f4d53902e1..e2976e2efab 100644 --- a/llvm/include/llvm/ProfileData/SampleProfReader.h +++ b/llvm/include/llvm/ProfileData/SampleProfReader.h @@ -157,6 +157,9 @@ protected: /// \brief Return true if we've reached the end of file. bool at_eof() const { return Data >= End; } + /// Read the contents of the given profile instance. + std::error_code readProfile(FunctionSamples &FProfile); + /// \brief Points to the current location in the buffer. const uint8_t *Data; diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp index 6d7d182e46c..c620d4ca84a 100644 --- a/llvm/lib/ProfileData/SampleProfReader.cpp +++ b/llvm/lib/ProfileData/SampleProfReader.cpp @@ -378,62 +378,94 @@ ErrorOr<StringRef> SampleProfileReaderBinary::readString() { return Str; } -std::error_code SampleProfileReaderBinary::read() { - while (!at_eof()) { - auto FName(readString()); - if (std::error_code EC = FName.getError()) - return EC; +std::error_code +SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) { + auto Val = readNumber<unsigned>(); + if (std::error_code EC = Val.getError()) + return EC; + FProfile.addTotalSamples(*Val); - Profiles[*FName] = FunctionSamples(); - FunctionSamples &FProfile = Profiles[*FName]; + Val = readNumber<unsigned>(); + if (std::error_code EC = Val.getError()) + return EC; + FProfile.addHeadSamples(*Val); + + // Read the samples in the body. + auto NumRecords = readNumber<unsigned>(); + if (std::error_code EC = NumRecords.getError()) + return EC; - auto Val = readNumber<unsigned>(); - if (std::error_code EC = Val.getError()) + for (unsigned I = 0; I < *NumRecords; ++I) { + auto LineOffset = readNumber<uint64_t>(); + if (std::error_code EC = LineOffset.getError()) return EC; - FProfile.addTotalSamples(*Val); - Val = readNumber<unsigned>(); - if (std::error_code EC = Val.getError()) + auto Discriminator = readNumber<uint64_t>(); + if (std::error_code EC = Discriminator.getError()) return EC; - FProfile.addHeadSamples(*Val); - // Read the samples in the body. - auto NumRecords = readNumber<unsigned>(); - if (std::error_code EC = NumRecords.getError()) + auto NumSamples = readNumber<uint64_t>(); + if (std::error_code EC = NumSamples.getError()) return EC; - for (unsigned I = 0; I < *NumRecords; ++I) { - auto LineOffset = readNumber<uint64_t>(); - if (std::error_code EC = LineOffset.getError()) - return EC; - auto Discriminator = readNumber<uint64_t>(); - if (std::error_code EC = Discriminator.getError()) - return EC; + auto NumCalls = readNumber<unsigned>(); + if (std::error_code EC = NumCalls.getError()) + return EC; - auto NumSamples = readNumber<uint64_t>(); - if (std::error_code EC = NumSamples.getError()) + for (unsigned J = 0; J < *NumCalls; ++J) { + auto CalledFunction(readString()); + if (std::error_code EC = CalledFunction.getError()) return EC; - auto NumCalls = readNumber<unsigned>(); - if (std::error_code EC = NumCalls.getError()) + auto CalledFunctionSamples = readNumber<uint64_t>(); + if (std::error_code EC = CalledFunctionSamples.getError()) return EC; - for (unsigned J = 0; J < *NumCalls; ++J) { - auto CalledFunction(readString()); - if (std::error_code EC = CalledFunction.getError()) - return EC; + FProfile.addCalledTargetSamples(*LineOffset, *Discriminator, + *CalledFunction, *CalledFunctionSamples); + } - auto CalledFunctionSamples = readNumber<uint64_t>(); - if (std::error_code EC = CalledFunctionSamples.getError()) - return EC; + FProfile.addBodySamples(*LineOffset, *Discriminator, *NumSamples); + } - FProfile.addCalledTargetSamples(*LineOffset, *Discriminator, - *CalledFunction, - *CalledFunctionSamples); - } + // Read all the samples for inlined function calls. + auto NumCallsites = readNumber<unsigned>(); + if (std::error_code EC = NumCallsites.getError()) + return EC; - FProfile.addBodySamples(*LineOffset, *Discriminator, *NumSamples); - } + for (unsigned J = 0; J < *NumCallsites; ++J) { + auto LineOffset = readNumber<uint64_t>(); + if (std::error_code EC = LineOffset.getError()) + return EC; + + auto Discriminator = readNumber<uint64_t>(); + if (std::error_code EC = Discriminator.getError()) + return EC; + + auto FName(readString()); + if (std::error_code EC = FName.getError()) + return EC; + + FunctionSamples &CalleeProfile = FProfile.functionSamplesAt( + CallsiteLocation(*LineOffset, *Discriminator, *FName)); + if (std::error_code EC = readProfile(CalleeProfile)) + return EC; + } + + return sampleprof_error::success; +} + +std::error_code SampleProfileReaderBinary::read() { + while (!at_eof()) { + auto FName(readString()); + if (std::error_code EC = FName.getError()) + return EC; + + Profiles[*FName] = FunctionSamples(); + FunctionSamples &FProfile = Profiles[*FName]; + + if (std::error_code EC = readProfile(FProfile)) + return EC; } return sampleprof_error::success; diff --git a/llvm/lib/ProfileData/SampleProfWriter.cpp b/llvm/lib/ProfileData/SampleProfWriter.cpp index e6a4d7d1321..6be884b13e0 100644 --- a/llvm/lib/ProfileData/SampleProfWriter.cpp +++ b/llvm/lib/ProfileData/SampleProfWriter.cpp @@ -84,14 +84,13 @@ SampleProfileWriterBinary::SampleProfileWriterBinary(StringRef F, /// \returns true if the samples were written successfully, false otherwise. bool SampleProfileWriterBinary::write(StringRef FName, const FunctionSamples &S) { - if (S.empty()) - return true; - OS << FName; encodeULEB128(0, OS); encodeULEB128(S.getTotalSamples(), OS); encodeULEB128(S.getHeadSamples(), OS); encodeULEB128(S.getBodySamples().size(), OS); + + // Emit all the body samples. for (const auto &I : S.getBodySamples()) { LineLocation Loc = I.first; const SampleRecord &Sample = I.second; @@ -108,6 +107,16 @@ bool SampleProfileWriterBinary::write(StringRef FName, } } + // Recursively emit all the callsite samples. + encodeULEB128(S.getCallsiteSamples().size(), OS); + for (const auto &J : S.getCallsiteSamples()) { + CallsiteLocation Loc = J.first; + const FunctionSamples &CalleeSamples = J.second; + encodeULEB128(Loc.LineOffset, OS); + encodeULEB128(Loc.Discriminator, OS); + write(Loc.CalleeName, CalleeSamples); + } + return true; } diff --git a/llvm/test/Transforms/SampleProfile/Inputs/fnptr.binprof b/llvm/test/Transforms/SampleProfile/Inputs/fnptr.binprof Binary files differindex 14d7fd555da..8cbe646c16e 100644 --- a/llvm/test/Transforms/SampleProfile/Inputs/fnptr.binprof +++ b/llvm/test/Transforms/SampleProfile/Inputs/fnptr.binprof diff --git a/llvm/test/tools/llvm-profdata/Inputs/inline-samples.afdo b/llvm/test/tools/llvm-profdata/Inputs/inline-samples.afdo new file mode 100644 index 00000000000..f8680d86fcb --- /dev/null +++ b/llvm/test/tools/llvm-profdata/Inputs/inline-samples.afdo @@ -0,0 +1,20 @@ +main:366846:0 + 2.1: 60401 + 4: 0 + 3: 0 + 0: 0 + 2.3: 60401 + 1: 0 + 2.3: _Z3fool:246044 + 1.2: 39280 + 1.4: 46871 + 1: 60401 + 1.3: _Z3bari:0 + 1.2: 0 + 1.1: 0 + 1.8: _Z3bari:0 + 1.2: 0 + 1.1: 0 + 1.7: _Z3bari:99492 + 1.2: 46732 + 1.1: 52760 diff --git a/llvm/test/tools/llvm-profdata/inline-samples.test b/llvm/test/tools/llvm-profdata/inline-samples.test new file mode 100644 index 00000000000..b16ac488234 --- /dev/null +++ b/llvm/test/tools/llvm-profdata/inline-samples.test @@ -0,0 +1,30 @@ +Tests for conversion between text and binary encoded sample profiles. + +1- Encode the original profile into binary form. All the tests below will use + the binary profile. +RUN: llvm-profdata merge --sample %p/Inputs/inline-samples.afdo -o %t.profbin + +2- Show all functions. This profile has a single main() function with several + inlined callees. +RUN: llvm-profdata show --sample %t.profbin | FileCheck %s --check-prefix=SHOW1 +SHOW1: Function: main: 366846, 0, 6 sampled lines +SHOW1: line offset: 2, discriminator: 3, inlined callee: _Z3fool: 246044, 0, 3 sampled lines +SHOW1: line offset: 1, discriminator: 3, inlined callee: _Z3bari: 0, 0, 2 sampled lines +SHOW1: line offset: 1, discriminator: 8, inlined callee: _Z3bari: 0, 0, 2 sampled lines +SHOW1: line offset: 1, discriminator: 7, inlined callee: _Z3bari: 99492, 0, 2 sampled lines +SHOW1: line offset: 1, discriminator: 2, number of samples: 46732 + +3- Convert the binary profile to text encoding and check that they are both + identical. +RUN: llvm-profdata merge --sample %t.profbin --text -o - | llvm-profdata show --sample - -o %t-bintext +RUN: llvm-profdata show --sample %p/Inputs/inline-samples.afdo -o %t-text +RUN: diff %t-bintext %t-text + +4- Merge the binary and text encodings of the profile and check that the + counters have doubled. +RUN: llvm-profdata merge --sample --text %t.profbin %p/Inputs/inline-samples.afdo -o - | FileCheck %s --check-prefix=MERGE1 +MERGE1: main:733692:0 +MERGE1: 2.3: 120802 +MERGE1: 2.3: _Z3fool:492088 +MERGE1: 1.7: _Z3bari:198984 +MERGE1: 1.1: 105520 |

