diff --git a/llvm/include/llvm/ProfileData/SampleProf.h b/llvm/include/llvm/ProfileData/SampleProf.h index e46407bde2c5..96df141e4b25 100644 --- a/llvm/include/llvm/ProfileData/SampleProf.h +++ b/llvm/include/llvm/ProfileData/SampleProf.h @@ -61,7 +61,7 @@ static inline uint64_t SPMagic() { uint64_t('2') << (64 - 56) | uint64_t(0xff); } -static inline uint64_t SPVersion() { return 101; } +static inline uint64_t SPVersion() { return 102; } /// Represents the relative location of an instruction. /// diff --git a/llvm/include/llvm/ProfileData/SampleProfReader.h b/llvm/include/llvm/ProfileData/SampleProfReader.h index 02bb85af10f4..2f404be50e6a 100644 --- a/llvm/include/llvm/ProfileData/SampleProfReader.h +++ b/llvm/include/llvm/ProfileData/SampleProfReader.h @@ -136,12 +136,16 @@ // A NUL-separated list of SIZE strings. // // FUNCTION BODY (one for each uninlined function body present in the profile) +// HEAD_SAMPLES (uint64_t) [only for top-level functions] +// Total number of samples collected at the head (prologue) of the +// function. +// NOTE: This field should only be present for top-level functions +// (i.e., not inlined into any caller). Inlined function calls +// have no prologue, so they don't need this. // NAME_IDX (uint32_t) // Index into the name table indicating the function name. // SAMPLES (uint64_t) // Total number of samples collected in this function. -// HEAD_SAMPLES (uint64_t) -// Total number of samples collected at the head of the function. // NRECS (uint32_t) // Total number of sampling records this function's profile. // BODY RECORDS diff --git a/llvm/include/llvm/ProfileData/SampleProfWriter.h b/llvm/include/llvm/ProfileData/SampleProfWriter.h index 48fbe10a6ab7..4bd5c71e0022 100644 --- a/llvm/include/llvm/ProfileData/SampleProfWriter.h +++ b/llvm/include/llvm/ProfileData/SampleProfWriter.h @@ -105,6 +105,7 @@ protected: std::error_code writeHeader(const StringMap &ProfileMap) override; std::error_code writeNameIdx(StringRef FName); + std::error_code writeBody(StringRef FName, const FunctionSamples &S); private: void addName(StringRef FName); diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp index 1ea7d2a0c4b5..d184969e046c 100644 --- a/llvm/lib/ProfileData/SampleProfReader.cpp +++ b/llvm/lib/ProfileData/SampleProfReader.cpp @@ -21,13 +21,13 @@ //===----------------------------------------------------------------------===// #include "llvm/ProfileData/SampleProfReader.h" +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/SmallVector.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorOr.h" #include "llvm/Support/LEB128.h" #include "llvm/Support/LineIterator.h" #include "llvm/Support/MemoryBuffer.h" -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/SmallVector.h" using namespace llvm::sampleprof; using namespace llvm; @@ -293,15 +293,10 @@ ErrorOr SampleProfileReaderBinary::readStringFromTable() { std::error_code SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) { - auto Val = readNumber(); - if (std::error_code EC = Val.getError()) + auto NumSamples = readNumber(); + if (std::error_code EC = NumSamples.getError()) return EC; - FProfile.addTotalSamples(*Val); - - Val = readNumber(); - if (std::error_code EC = Val.getError()) - return EC; - FProfile.addHeadSamples(*Val); + FProfile.addTotalSamples(*NumSamples); // Read the samples in the body. auto NumRecords = readNumber(); @@ -370,6 +365,10 @@ SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) { std::error_code SampleProfileReaderBinary::read() { while (!at_eof()) { + auto NumHeadSamples = readNumber(); + if (std::error_code EC = NumHeadSamples.getError()) + return EC; + auto FName(readStringFromTable()); if (std::error_code EC = FName.getError()) return EC; @@ -377,6 +376,8 @@ std::error_code SampleProfileReaderBinary::read() { Profiles[*FName] = FunctionSamples(); FunctionSamples &FProfile = Profiles[*FName]; + FProfile.addHeadSamples(*NumHeadSamples); + if (std::error_code EC = readProfile(FProfile)) return EC; } diff --git a/llvm/lib/ProfileData/SampleProfWriter.cpp b/llvm/lib/ProfileData/SampleProfWriter.cpp index daf3783aba65..a6e3cabd89ed 100644 --- a/llvm/lib/ProfileData/SampleProfWriter.cpp +++ b/llvm/lib/ProfileData/SampleProfWriter.cpp @@ -122,19 +122,15 @@ std::error_code SampleProfileWriterBinary::writeHeader( return sampleprof_error::success; } -/// \brief Write samples to a binary file. -/// -/// \returns true if the samples were written successfully, false otherwise. -std::error_code SampleProfileWriterBinary::write(StringRef FName, - const FunctionSamples &S) { +std::error_code SampleProfileWriterBinary::writeBody(StringRef FName, + const FunctionSamples &S) { if (std::error_code EC = writeNameIdx(FName)) return EC; encodeULEB128(S.getTotalSamples(), OS); - encodeULEB128(S.getHeadSamples(), OS); - encodeULEB128(S.getBodySamples().size(), OS); // Emit all the body samples. + encodeULEB128(S.getBodySamples().size(), OS); for (const auto &I : S.getBodySamples()) { LineLocation Loc = I.first; const SampleRecord &Sample = I.second; @@ -158,13 +154,22 @@ std::error_code SampleProfileWriterBinary::write(StringRef FName, const FunctionSamples &CalleeSamples = J.second; encodeULEB128(Loc.LineOffset, OS); encodeULEB128(Loc.Discriminator, OS); - if (std::error_code EC = write(Loc.CalleeName, CalleeSamples)) + if (std::error_code EC = writeBody(Loc.CalleeName, CalleeSamples)) return EC; } return sampleprof_error::success; } +/// \brief Write samples of a top-level function to a binary file. +/// +/// \returns true if the samples were written successfully, false otherwise. +std::error_code SampleProfileWriterBinary::write(StringRef FName, + const FunctionSamples &S) { + encodeULEB128(S.getHeadSamples(), OS); + return writeBody(FName, S); +} + /// \brief Create a sample profile writer based on the specified format. /// /// \param Filename The file to create. diff --git a/llvm/test/Transforms/SampleProfile/Inputs/fnptr.binprof b/llvm/test/Transforms/SampleProfile/Inputs/fnptr.binprof index dc7234d83008..a074f53db945 100644 Binary files a/llvm/test/Transforms/SampleProfile/Inputs/fnptr.binprof and b/llvm/test/Transforms/SampleProfile/Inputs/fnptr.binprof differ