summaryrefslogtreecommitdiffstats
path: root/llvm/lib/ProfileData
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/ProfileData')
-rw-r--r--llvm/lib/ProfileData/InstrProfReader.cpp5
-rw-r--r--llvm/lib/ProfileData/InstrProfWriter.cpp6
-rw-r--r--llvm/lib/ProfileData/ProfileSummary.cpp21
-rw-r--r--llvm/lib/ProfileData/SampleProfReader.cpp74
-rw-r--r--llvm/lib/ProfileData/SampleProfWriter.cpp31
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();
+}
OpenPOWER on IntegriCloud