summaryrefslogtreecommitdiffstats
path: root/llvm/lib/ProfileData
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/ProfileData')
-rw-r--r--llvm/lib/ProfileData/SampleProf.cpp2
-rw-r--r--llvm/lib/ProfileData/SampleProfReader.cpp111
-rw-r--r--llvm/lib/ProfileData/SampleProfWriter.cpp57
3 files changed, 157 insertions, 13 deletions
diff --git a/llvm/lib/ProfileData/SampleProf.cpp b/llvm/lib/ProfileData/SampleProf.cpp
index b0818d12475..1a124415f17 100644
--- a/llvm/lib/ProfileData/SampleProf.cpp
+++ b/llvm/lib/ProfileData/SampleProf.cpp
@@ -67,6 +67,8 @@ class SampleProfErrorCategoryType : public std::error_category {
return "Unimplemented feature";
case sampleprof_error::counter_overflow:
return "Counter overflow";
+ case sampleprof_error::ostream_seek_unsupported:
+ return "Ostream does not support seek";
}
llvm_unreachable("A value of sampleprof_error has no message.");
}
diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp
index 5503104c1ef..2b4551b9849 100644
--- a/llvm/lib/ProfileData/SampleProfReader.cpp
+++ b/llvm/lib/ProfileData/SampleProfReader.cpp
@@ -30,6 +30,7 @@
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/LEB128.h"
#include "llvm/Support/LineIterator.h"
+#include "llvm/Support/MD5.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
@@ -320,6 +321,21 @@ ErrorOr<StringRef> SampleProfileReaderBinary::readString() {
}
template <typename T>
+ErrorOr<T> SampleProfileReaderBinary::readUnencodedNumber() {
+ std::error_code EC;
+
+ if (Data + sizeof(T) > End) {
+ EC = sampleprof_error::truncated;
+ reportError(0, EC.message());
+ return EC;
+ }
+
+ using namespace support;
+ T Val = endian::readNext<T, little, unaligned>(Data);
+ return Val;
+}
+
+template <typename T>
inline ErrorOr<uint32_t> SampleProfileReaderBinary::readStringIndex(T &Table) {
std::error_code EC;
auto Idx = readNumber<uint32_t>();
@@ -423,29 +439,51 @@ SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
return sampleprof_error::success;
}
-std::error_code SampleProfileReaderBinary::read() {
- while (!at_eof()) {
- auto NumHeadSamples = readNumber<uint64_t>();
- if (std::error_code EC = NumHeadSamples.getError())
- return EC;
+std::error_code SampleProfileReaderBinary::readFuncProfile() {
+ auto NumHeadSamples = readNumber<uint64_t>();
+ if (std::error_code EC = NumHeadSamples.getError())
+ return EC;
- auto FName(readStringFromTable());
- if (std::error_code EC = FName.getError())
- return EC;
+ auto FName(readStringFromTable());
+ if (std::error_code EC = FName.getError())
+ return EC;
- Profiles[*FName] = FunctionSamples();
- FunctionSamples &FProfile = Profiles[*FName];
- FProfile.setName(*FName);
+ Profiles[*FName] = FunctionSamples();
+ FunctionSamples &FProfile = Profiles[*FName];
+ FProfile.setName(*FName);
- FProfile.addHeadSamples(*NumHeadSamples);
+ FProfile.addHeadSamples(*NumHeadSamples);
+
+ if (std::error_code EC = readProfile(FProfile))
+ return EC;
+ return sampleprof_error::success;
+}
- if (std::error_code EC = readProfile(FProfile))
+std::error_code SampleProfileReaderBinary::read() {
+ while (!at_eof()) {
+ if (std::error_code EC = readFuncProfile())
return EC;
}
return sampleprof_error::success;
}
+std::error_code SampleProfileReaderCompactBinary::read() {
+ for (auto Name : FuncsToUse) {
+ auto GUID = std::to_string(MD5Hash(Name));
+ auto iter = FuncOffsetTable.find(StringRef(GUID));
+ if (iter == FuncOffsetTable.end())
+ continue;
+ const uint8_t *SavedData = Data;
+ Data = reinterpret_cast<const uint8_t *>(Buffer->getBufferStart()) +
+ iter->second;
+ if (std::error_code EC = readFuncProfile())
+ return EC;
+ Data = SavedData;
+ }
+ return sampleprof_error::success;
+}
+
std::error_code SampleProfileReaderRawBinary::verifySPMagic(uint64_t Magic) {
if (Magic == SPMagic())
return sampleprof_error::success;
@@ -514,6 +552,53 @@ std::error_code SampleProfileReaderBinary::readHeader() {
return sampleprof_error::success;
}
+std::error_code SampleProfileReaderCompactBinary::readHeader() {
+ SampleProfileReaderBinary::readHeader();
+ if (std::error_code EC = readFuncOffsetTable())
+ return EC;
+ return sampleprof_error::success;
+}
+
+std::error_code SampleProfileReaderCompactBinary::readFuncOffsetTable() {
+ auto TableOffset = readUnencodedNumber<uint64_t>();
+ if (std::error_code EC = TableOffset.getError())
+ return EC;
+
+ const uint8_t *SavedData = Data;
+ const uint8_t *TableStart =
+ reinterpret_cast<const uint8_t *>(Buffer->getBufferStart()) +
+ *TableOffset;
+ Data = TableStart;
+
+ auto Size = readNumber<uint64_t>();
+ if (std::error_code EC = Size.getError())
+ return EC;
+
+ FuncOffsetTable.reserve(*Size);
+ for (uint32_t I = 0; I < *Size; ++I) {
+ auto FName(readStringFromTable());
+ if (std::error_code EC = FName.getError())
+ return EC;
+
+ auto Offset = readNumber<uint64_t>();
+ if (std::error_code EC = Offset.getError())
+ return EC;
+
+ FuncOffsetTable[*FName] = *Offset;
+ }
+ End = TableStart;
+ Data = SavedData;
+ return sampleprof_error::success;
+}
+
+void SampleProfileReaderCompactBinary::collectFuncsToUse(const Module &M) {
+ FuncsToUse.clear();
+ for (auto &F : M) {
+ StringRef Fname = F.getName().split('.').first;
+ FuncsToUse.insert(Fname);
+ }
+}
+
std::error_code SampleProfileReaderBinary::readSummaryEntry(
std::vector<ProfileSummaryEntry> &Entries) {
auto Cutoff = readNumber<uint64_t>();
diff --git a/llvm/lib/ProfileData/SampleProfWriter.cpp b/llvm/lib/ProfileData/SampleProfWriter.cpp
index b4de30118b8..b1c669ec31c 100644
--- a/llvm/lib/ProfileData/SampleProfWriter.cpp
+++ b/llvm/lib/ProfileData/SampleProfWriter.cpp
@@ -22,6 +22,8 @@
#include "llvm/ADT/StringRef.h"
#include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/ProfileData/SampleProf.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/EndianStream.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/LEB128.h"
@@ -64,6 +66,15 @@ SampleProfileWriter::write(const StringMap<FunctionSamples> &ProfileMap) {
return sampleprof_error::success;
}
+std::error_code SampleProfileWriterCompactBinary::write(
+ const StringMap<FunctionSamples> &ProfileMap) {
+ if (std::error_code EC = SampleProfileWriter::write(ProfileMap))
+ return EC;
+ if (std::error_code EC = writeFuncOffsetTable())
+ return EC;
+ return sampleprof_error::success;
+}
+
/// Write samples to a text file.
///
/// Note: it may be tempting to implement this in terms of
@@ -168,6 +179,30 @@ std::error_code SampleProfileWriterRawBinary::writeNameTable() {
return sampleprof_error::success;
}
+std::error_code SampleProfileWriterCompactBinary::writeFuncOffsetTable() {
+ auto &OS = *OutputStream;
+
+ // Fill the slot remembered by TableOffset with the offset of FuncOffsetTable.
+ auto &OFS = static_cast<raw_fd_ostream &>(OS);
+ uint64_t FuncOffsetTableStart = OS.tell();
+ if (OFS.seek(TableOffset) == (uint64_t)-1)
+ return sampleprof_error::ostream_seek_unsupported;
+ support::endian::Writer Writer(*OutputStream, support::little);
+ Writer.write(FuncOffsetTableStart);
+ if (OFS.seek(FuncOffsetTableStart) == (uint64_t)-1)
+ return sampleprof_error::ostream_seek_unsupported;
+
+ // Write out the table size.
+ encodeULEB128(FuncOffsetTable.size(), OS);
+
+ // Write out FuncOffsetTable.
+ for (auto entry : FuncOffsetTable) {
+ writeNameIdx(entry.first);
+ encodeULEB128(entry.second, OS);
+ }
+ return sampleprof_error::success;
+}
+
std::error_code SampleProfileWriterCompactBinary::writeNameTable() {
auto &OS = *OutputStream;
std::set<StringRef> V;
@@ -215,6 +250,19 @@ std::error_code SampleProfileWriterBinary::writeHeader(
return sampleprof_error::success;
}
+std::error_code SampleProfileWriterCompactBinary::writeHeader(
+ const StringMap<FunctionSamples> &ProfileMap) {
+ support::endian::Writer Writer(*OutputStream, support::little);
+ if (auto EC = SampleProfileWriterBinary::writeHeader(ProfileMap))
+ return EC;
+
+ // Reserve a slot for the offset of function offset table. The slot will
+ // be populated with the offset of FuncOffsetTable later.
+ TableOffset = OutputStream->tell();
+ Writer.write(static_cast<uint64_t>(-2));
+ return sampleprof_error::success;
+}
+
std::error_code SampleProfileWriterBinary::writeSummary() {
auto &OS = *OutputStream;
encodeULEB128(Summary->getTotalCount(), OS);
@@ -283,6 +331,15 @@ std::error_code SampleProfileWriterBinary::write(const FunctionSamples &S) {
return writeBody(S);
}
+std::error_code
+SampleProfileWriterCompactBinary::write(const FunctionSamples &S) {
+ uint64_t Offset = OutputStream->tell();
+ StringRef Name = S.getName();
+ FuncOffsetTable[Name] = Offset;
+ encodeULEB128(S.getHeadSamples(), *OutputStream);
+ return writeBody(S);
+}
+
/// Create a sample profile file writer based on the specified format.
///
/// \param Filename The file to create.
OpenPOWER on IntegriCloud