summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorXinliang David Li <davidxl@google.com>2016-02-03 04:08:18 +0000
committerXinliang David Li <davidxl@google.com>2016-02-03 04:08:18 +0000
commit6c93ee8d36261e197831f024ce65c26a110369db (patch)
tree81d4123997e48bf4a44a014724f0e205fab02420 /llvm/lib
parent0c0d7e2d0fbe58eb69db383ace48e68ecfd6f050 (diff)
downloadbcm5719-llvm-6c93ee8d36261e197831f024ce65c26a110369db.tar.gz
bcm5719-llvm-6c93ee8d36261e197831f024ce65c26a110369db.zip
[PGO] Profile summary reader/writer support
With this patch, the profile summary data will be available in indexed profile data file so that profiler reader/compiler optimizer can start to make use of. Differential Revision: http://reviews.llvm.org/D16258 llvm-svn: 259626
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/ProfileData/InstrProf.cpp15
-rw-r--r--llvm/lib/ProfileData/InstrProfReader.cpp39
-rw-r--r--llvm/lib/ProfileData/InstrProfWriter.cpp63
3 files changed, 104 insertions, 13 deletions
diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp
index 0ccc16252c2..a06a4370d61 100644
--- a/llvm/lib/ProfileData/InstrProf.cpp
+++ b/llvm/lib/ProfileData/InstrProf.cpp
@@ -641,4 +641,19 @@ void ProfileSummary::computeDetailedSummary() {
}
}
+ProfileSummary::ProfileSummary(const IndexedInstrProf::Summary &S)
+ : TotalCount(S.get(IndexedInstrProf::Summary::TotalBlockCount)),
+ MaxBlockCount(S.get(IndexedInstrProf::Summary::MaxBlockCount)),
+ MaxInternalBlockCount(
+ S.get(IndexedInstrProf::Summary::MaxInternalBlockCount)),
+ MaxFunctionCount(S.get(IndexedInstrProf::Summary::MaxFunctionCount)),
+ NumBlocks(S.get(IndexedInstrProf::Summary::TotalNumBlocks)),
+ NumFunctions(S.get(IndexedInstrProf::Summary::TotalNumFunctions)) {
+ for (unsigned I = 0; I < S.NumCutoffEntries; I++) {
+ const IndexedInstrProf::Summary::Entry &Ent = S.getEntry(I);
+ DetailedSummary.emplace_back((uint32_t)Ent.Cutoff, Ent.MinBlockCount,
+ Ent.NumBlocks);
+ }
+}
+
} // end namespace llvm
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index 7e9b7ab7c8a..db6dd72870f 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -554,6 +554,41 @@ bool IndexedInstrProfReader::hasFormat(const MemoryBuffer &DataBuffer) {
return Magic == IndexedInstrProf::Magic;
}
+const unsigned char *
+IndexedInstrProfReader::readSummary(IndexedInstrProf::ProfVersion Version,
+ const unsigned char *Cur) {
+ using namespace support;
+ if (Version >= IndexedInstrProf::Version4) {
+ const IndexedInstrProf::Summary *SummaryInLE =
+ reinterpret_cast<const IndexedInstrProf::Summary *>(Cur);
+ uint64_t NFields =
+ endian::byte_swap<uint64_t, little>(SummaryInLE->NumSummaryFields);
+ uint64_t NEntries =
+ endian::byte_swap<uint64_t, little>(SummaryInLE->NumCutoffEntries);
+ uint32_t SummarySize =
+ IndexedInstrProf::Summary::getSize(NFields, NEntries);
+ std::unique_ptr<IndexedInstrProf::Summary> SummaryData =
+ IndexedInstrProf::allocSummary(SummarySize);
+
+ const uint64_t *Src = reinterpret_cast<const uint64_t *>(SummaryInLE);
+ uint64_t *Dst = reinterpret_cast<uint64_t *>(SummaryData.get());
+ for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
+ Dst[I] = endian::byte_swap<uint64_t, little>(Src[I]);
+
+ // initialize ProfileSummary using the SummaryData from disk.
+ this->Summary = llvm::make_unique<ProfileSummary>(*(SummaryData.get()));
+ return Cur + SummarySize;
+ } 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<ProfileSummary>(Cutoffs);
+ this->Summary->computeDetailedSummary();
+ return Cur;
+ }
+}
+
std::error_code IndexedInstrProfReader::readHeader() {
const unsigned char *Start =
(const unsigned char *)DataBuffer->getBufferStart();
@@ -576,9 +611,7 @@ std::error_code IndexedInstrProfReader::readHeader() {
if (FormatVersion > IndexedInstrProf::ProfVersion::CurrentVersion)
return error(instrprof_error::unsupported_version);
- // Read the maximal function count.
- MaxFunctionCount =
- endian::byte_swap<uint64_t, little>(Header->MaxFunctionCount);
+ Cur = readSummary((IndexedInstrProf::ProfVersion)FormatVersion, Cur);
// Read the hash type and start offset.
IndexedInstrProf::HashT HashType = static_cast<IndexedInstrProf::HashT>(
diff --git a/llvm/lib/ProfileData/InstrProfWriter.cpp b/llvm/lib/ProfileData/InstrProfWriter.cpp
index 204d3403c8c..4330b061030 100644
--- a/llvm/lib/ProfileData/InstrProfWriter.cpp
+++ b/llvm/lib/ProfileData/InstrProfWriter.cpp
@@ -84,6 +84,7 @@ public:
typedef uint64_t offset_type;
support::endianness ValueProfDataEndianness;
+ ProfileSummary *TheProfileSummary;
InstrProfRecordWriterTrait() : ValueProfDataEndianness(support::little) {}
static hash_value_type ComputeHash(key_type_ref K) {
@@ -122,6 +123,7 @@ public:
endian::Writer<little> LE(Out);
for (const auto &ProfileData : *V) {
const InstrProfRecord &ProfRecord = ProfileData.second;
+ TheProfileSummary->addRecord(ProfRecord);
LE.write<uint64_t>(ProfileData.first); // Function hash
LE.write<uint64_t>(ProfRecord.Counts.size());
@@ -140,7 +142,7 @@ public:
}
InstrProfWriter::InstrProfWriter(bool Sparse)
- : Sparse(Sparse), FunctionData(), MaxFunctionCount(0),
+ : Sparse(Sparse), FunctionData(),
InfoObj(new InstrProfRecordWriterTrait()) {}
InstrProfWriter::~InstrProfWriter() { delete InfoObj; }
@@ -179,11 +181,6 @@ std::error_code InstrProfWriter::addRecord(InstrProfRecord &&I,
Dest.sortValueData();
- // We keep track of the max function count as we go for simplicity.
- // Update this statistic no matter the result of the merge.
- if (Dest.Counts[0] > MaxFunctionCount)
- MaxFunctionCount = Dest.Counts[0];
-
return Result;
}
@@ -199,8 +196,32 @@ bool InstrProfWriter::shouldEncodeData(const ProfilingData &PD) {
return false;
}
+static void setSummary(IndexedInstrProf::Summary *TheSummary,
+ ProfileSummary &PS) {
+ using namespace IndexedInstrProf;
+ std::vector<ProfileSummaryEntry> &Res = PS.getDetailedSummary();
+ TheSummary->NumSummaryFields = Summary::NumKinds;
+ TheSummary->NumCutoffEntries = Res.size();
+ TheSummary->set(Summary::MaxFunctionCount, PS.getMaxFunctionCount());
+ TheSummary->set(Summary::MaxBlockCount, PS.getMaxBlockCount());
+ TheSummary->set(Summary::MaxInternalBlockCount,
+ PS.getMaxInternalBlockCount());
+ TheSummary->set(Summary::TotalBlockCount, PS.getTotalCount());
+ TheSummary->set(Summary::TotalNumBlocks, PS.getNumBlocks());
+ TheSummary->set(Summary::TotalNumFunctions, PS.getNumFunctions());
+ for (unsigned I = 0; I < Res.size(); I++)
+ TheSummary->setEntry(I, Res[I]);
+}
+
void InstrProfWriter::writeImpl(ProfOStream &OS) {
OnDiskChainedHashTableGenerator<InstrProfRecordWriterTrait> Generator;
+
+ using namespace IndexedInstrProf;
+ std::vector<uint32_t> Cutoffs(&SummaryCutoffs[0],
+ &SummaryCutoffs[NumSummaryCutoffs]);
+ ProfileSummary PS(Cutoffs);
+ InfoObj->TheProfileSummary = &PS;
+
// Populate the hash table generator.
for (const auto &I : FunctionData)
if (shouldEncodeData(I.getValue()))
@@ -209,7 +230,7 @@ void InstrProfWriter::writeImpl(ProfOStream &OS) {
IndexedInstrProf::Header Header;
Header.Magic = IndexedInstrProf::Magic;
Header.Version = IndexedInstrProf::ProfVersion::CurrentVersion;
- Header.MaxFunctionCount = MaxFunctionCount;
+ Header.Unused = 0;
Header.HashType = static_cast<uint64_t>(IndexedInstrProf::HashType);
Header.HashOffset = 0;
int N = sizeof(IndexedInstrProf::Header) / sizeof(uint64_t);
@@ -220,15 +241,37 @@ void InstrProfWriter::writeImpl(ProfOStream &OS) {
for (int I = 0; I < N - 1; I++)
OS.write(reinterpret_cast<uint64_t *>(&Header)[I]);
- // Save a space to write the hash table start location.
- uint64_t HashTableStartLoc = OS.tell();
+ // Save the location of Header.HashOffset field in \c OS.
+ uint64_t HashTableStartFieldOffset = OS.tell();
// Reserve the space for HashOffset field.
OS.write(0);
+
+ // Reserve space to write profile summary data.
+ uint32_t NumEntries = Cutoffs.size();
+ uint32_t SummarySize = Summary::getSize(Summary::NumKinds, NumEntries);
+ // Remember the summary offset.
+ uint64_t SummaryOffset = OS.tell();
+ for (unsigned I = 0; I < SummarySize / sizeof(uint64_t); I++)
+ OS.write(0);
+
// Write the hash table.
uint64_t HashTableStart = Generator.Emit(OS.OS, *InfoObj);
+ // Allocate space for data to be serialized out.
+ std::unique_ptr<IndexedInstrProf::Summary> TheSummary =
+ IndexedInstrProf::allocSummary(SummarySize);
+ // Compute the Summary and copy the data to the data
+ // structure to be serialized out (to disk or buffer).
+ setSummary(TheSummary.get(), PS);
+ InfoObj->TheProfileSummary = 0;
+
// Now do the final patch:
- PatchItem PatchItems[1] = {{HashTableStartLoc, &HashTableStart, 1}};
+ PatchItem PatchItems[] = {
+ // Patch the Header.HashOffset field.
+ {HashTableStartFieldOffset, &HashTableStart, 1},
+ // Patch the summary data.
+ {SummaryOffset, reinterpret_cast<uint64_t *>(TheSummary.get()),
+ (int)(SummarySize / sizeof(uint64_t))}};
OS.patch(PatchItems, sizeof(PatchItems) / sizeof(*PatchItems));
}
OpenPOWER on IntegriCloud