diff options
Diffstat (limited to 'llvm/lib/ProfileData')
-rw-r--r-- | llvm/lib/ProfileData/InstrProfReader.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/ProfileData/InstrProfWriter.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/ProfileData/ProfileSummary.cpp | 21 | ||||
-rw-r--r-- | llvm/lib/ProfileData/SampleProfReader.cpp | 74 | ||||
-rw-r--r-- | llvm/lib/ProfileData/SampleProfWriter.cpp | 31 |
5 files changed, 128 insertions, 9 deletions
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp index 9c17d4e082d..b00c1392eb8 100644 --- a/llvm/lib/ProfileData/InstrProfReader.cpp +++ b/llvm/lib/ProfileData/InstrProfReader.cpp @@ -595,9 +595,8 @@ IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version, } else { // For older version of profile data, we need to compute on the fly: using namespace IndexedInstrProf; - std::vector<uint32_t> Cutoffs(&SummaryCutoffs[0], - &SummaryCutoffs[NumSummaryCutoffs]); - this->Summary = llvm::make_unique<InstrProfSummary>(Cutoffs); + this->Summary = + llvm::make_unique<InstrProfSummary>(ProfileSummary::DefaultCutoffs); this->Summary->computeDetailedSummary(); return Cur; } diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp index 19a16b82932..69b19580d4f 100644 --- a/llvm/lib/ProfileData/InstrProfWriter.cpp +++ b/llvm/lib/ProfileData/InstrProfWriter.cpp @@ -217,9 +217,7 @@ void InstrProfWriter::writeImpl(ProfOStream &OS) { OnDiskChainedHashTableGenerator<InstrProfRecordWriterTrait> Generator; using namespace IndexedInstrProf; - std::vector<uint32_t> Cutoffs(&SummaryCutoffs[0], - &SummaryCutoffs[NumSummaryCutoffs]); - InstrProfSummary PS(Cutoffs); + InstrProfSummary PS(ProfileSummary::DefaultCutoffs); InfoObj->TheProfileSummary = &PS; // Populate the hash table generator. @@ -249,7 +247,7 @@ void InstrProfWriter::writeImpl(ProfOStream &OS) { OS.write(0); // Reserve space to write profile summary data. - uint32_t NumEntries = Cutoffs.size(); + uint32_t NumEntries = ProfileSummary::DefaultCutoffs.size(); uint32_t SummarySize = Summary::getSize(Summary::NumKinds, NumEntries); // Remember the summary offset. uint64_t SummaryOffset = OS.tell(); diff --git a/llvm/lib/ProfileData/ProfileSummary.cpp b/llvm/lib/ProfileData/ProfileSummary.cpp index 716c39e4354..0e2c43e5e91 100644 --- a/llvm/lib/ProfileData/ProfileSummary.cpp +++ b/llvm/lib/ProfileData/ProfileSummary.cpp @@ -11,17 +11,36 @@ // //===----------------------------------------------------------------------===// -#include "llvm/ProfileData/ProfileCommon.h" #include "llvm/ProfileData/InstrProf.h" +#include "llvm/ProfileData/ProfileCommon.h" +#include "llvm/ProfileData/SampleProf.h" using namespace llvm; +// A set of cutoff values. Each value, when divided by ProfileSummary::Scale +// (which is 1000000) is a desired percentile of total counts. +const std::vector<uint32_t> ProfileSummary::DefaultCutoffs( + {10000, /* 1% */ + 100000, /* 10% */ + 200000, 300000, 400000, 500000, 600000, 500000, 600000, 700000, 800000, + 900000, 950000, 990000, 999000, 999900, 999990, 999999}); + void InstrProfSummary::addRecord(const InstrProfRecord &R) { addEntryCount(R.Counts[0]); for (size_t I = 1, E = R.Counts.size(); I < E; ++I) addInternalCount(R.Counts[I]); } +// To compute the detailed summary, we consider each line containing samples as +// equivalent to a block with a count in the instrumented profile. +void SampleProfileSummary::addRecord(const sampleprof::FunctionSamples &FS) { + NumFunctions++; + if (FS.getHeadSamples() > MaxHeadSamples) + MaxHeadSamples = FS.getHeadSamples(); + for (const auto &I : FS.getBodySamples()) + addCount(I.second.getSamples()); +} + // The argument to this method is a vector of cutoff percentages and the return // value is a vector of (Cutoff, MinCount, NumCounts) triplets. void ProfileSummary::computeDetailedSummary() { diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp index 93cd87bb82f..205e34d390f 100644 --- a/llvm/lib/ProfileData/SampleProfReader.cpp +++ b/llvm/lib/ProfileData/SampleProfReader.cpp @@ -22,6 +22,7 @@ #include "llvm/ProfileData/SampleProfReader.h" #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorOr.h" @@ -220,6 +221,8 @@ std::error_code SampleProfileReaderText::read() { } } } + if (Result == sampleprof_error::success) + computeSummary(); return Result; } @@ -400,6 +403,9 @@ std::error_code SampleProfileReaderBinary::readHeader() { else if (*Version != SPVersion()) return sampleprof_error::unsupported_version; + if (std::error_code EC = readSummary()) + return EC; + // Read the name table. auto Size = readNumber<uint32_t>(); if (std::error_code EC = Size.getError()) @@ -415,6 +421,62 @@ std::error_code SampleProfileReaderBinary::readHeader() { return sampleprof_error::success; } +std::error_code SampleProfileReaderBinary::readSummaryEntry( + std::vector<ProfileSummaryEntry> &Entries) { + auto Cutoff = readNumber<uint64_t>(); + if (std::error_code EC = Cutoff.getError()) + return EC; + + auto MinBlockCount = readNumber<uint64_t>(); + if (std::error_code EC = MinBlockCount.getError()) + return EC; + + auto NumBlocks = readNumber<uint64_t>(); + if (std::error_code EC = NumBlocks.getError()) + return EC; + + Entries.emplace_back(*Cutoff, *MinBlockCount, *NumBlocks); + return sampleprof_error::success; +} + +std::error_code SampleProfileReaderBinary::readSummary() { + auto TotalCount = readNumber<uint64_t>(); + if (std::error_code EC = TotalCount.getError()) + return EC; + + auto MaxBlockCount = readNumber<uint64_t>(); + if (std::error_code EC = MaxBlockCount.getError()) + return EC; + + auto MaxFunctionCount = readNumber<uint64_t>(); + if (std::error_code EC = MaxFunctionCount.getError()) + return EC; + + auto NumBlocks = readNumber<uint64_t>(); + if (std::error_code EC = NumBlocks.getError()) + return EC; + + auto NumFunctions = readNumber<uint64_t>(); + if (std::error_code EC = NumFunctions.getError()) + return EC; + + auto NumSummaryEntries = readNumber<uint64_t>(); + if (std::error_code EC = NumSummaryEntries.getError()) + return EC; + + std::vector<ProfileSummaryEntry> Entries; + for (unsigned i = 0; i < *NumSummaryEntries; i++) { + std::error_code EC = readSummaryEntry(Entries); + if (EC != sampleprof_error::success) + return EC; + } + Summary = llvm::make_unique<SampleProfileSummary>( + *TotalCount, *MaxBlockCount, *MaxFunctionCount, *NumBlocks, *NumFunctions, + Entries); + + return sampleprof_error::success; +} + bool SampleProfileReaderBinary::hasFormat(const MemoryBuffer &Buffer) { const uint8_t *Data = reinterpret_cast<const uint8_t *>(Buffer.getBufferStart()); @@ -518,6 +580,7 @@ std::error_code SampleProfileReaderGCC::readFunctionProfiles() { if (std::error_code EC = readOneFunctionProfile(Stack, true, 0)) return EC; + computeSummary(); return sampleprof_error::success; } @@ -725,3 +788,14 @@ SampleProfileReader::create(std::unique_ptr<MemoryBuffer> &B, LLVMContext &C) { return std::move(Reader); } + +// For text and GCC file formats, we compute the summary after reading the +// profile. Binary format has the profile summary in its header. +void SampleProfileReader::computeSummary() { + Summary.reset(new SampleProfileSummary(ProfileSummary::DefaultCutoffs)); + for (const auto &I : Profiles) { + const FunctionSamples &Profile = I.second; + Summary->addRecord(Profile); + } + Summary->computeDetailedSummary(); +} diff --git a/llvm/lib/ProfileData/SampleProfWriter.cpp b/llvm/lib/ProfileData/SampleProfWriter.cpp index 51feee5ad7d..a8c542cf200 100644 --- a/llvm/lib/ProfileData/SampleProfWriter.cpp +++ b/llvm/lib/ProfileData/SampleProfWriter.cpp @@ -120,6 +120,10 @@ std::error_code SampleProfileWriterBinary::writeHeader( encodeULEB128(SPMagic(), OS); encodeULEB128(SPVersion(), OS); + computeSummary(ProfileMap); + if (auto EC = writeSummary()) + return EC; + // Generate the name table for all the functions referenced in the profile. for (const auto &I : ProfileMap) { addName(I.first()); @@ -132,10 +136,25 @@ std::error_code SampleProfileWriterBinary::writeHeader( OS << N.first; encodeULEB128(0, OS); } - return sampleprof_error::success; } +std::error_code SampleProfileWriterBinary::writeSummary() { + auto &OS = *OutputStream; + encodeULEB128(Summary->getTotalSamples(), OS); + encodeULEB128(Summary->getMaxSamplesPerLine(), OS); + encodeULEB128(Summary->getMaxHeadSamples(), OS); + encodeULEB128(Summary->getNumLinesWithSamples(), OS); + encodeULEB128(Summary->getNumFunctions(), OS); + std::vector<ProfileSummaryEntry> &Entries = Summary->getDetailedSummary(); + encodeULEB128(Entries.size(), OS); + for (auto Entry : Entries) { + encodeULEB128(Entry.Cutoff, OS); + encodeULEB128(Entry.MinCount, OS); + encodeULEB128(Entry.NumCounts, OS); + } + return sampleprof_error::success; +} std::error_code SampleProfileWriterBinary::writeBody(StringRef FName, const FunctionSamples &S) { auto &OS = *OutputStream; @@ -238,3 +257,13 @@ SampleProfileWriter::create(std::unique_ptr<raw_ostream> &OS, return std::move(Writer); } + +void SampleProfileWriter::computeSummary( + const StringMap<FunctionSamples> &ProfileMap) { + Summary.reset(new SampleProfileSummary(ProfileSummary::DefaultCutoffs)); + for (const auto &I : ProfileMap) { + const FunctionSamples &Profile = I.second; + Summary->addRecord(Profile); + } + Summary->computeDetailedSummary(); +} |