summaryrefslogtreecommitdiffstats
path: root/llvm/lib/ProfileData
diff options
context:
space:
mode:
authorWei Mi <wmi@google.com>2019-08-31 02:27:26 +0000
committerWei Mi <wmi@google.com>2019-08-31 02:27:26 +0000
commit798e59b81fb7a92cd5f3b1bb0761283f99adcd46 (patch)
tree4d889c8c277676ff95bf9885a5a80ded011b3a07 /llvm/lib/ProfileData
parent0377ca641c9af0262270d091578cab19523b1bc6 (diff)
downloadbcm5719-llvm-798e59b81fb7a92cd5f3b1bb0761283f99adcd46.tar.gz
bcm5719-llvm-798e59b81fb7a92cd5f3b1bb0761283f99adcd46.zip
[SampleFDO] Add profile symbol list section to discriminate function being
cold versus function being newly added. This is the second half of https://reviews.llvm.org/D66374. Profile symbol list is the collection of function symbols showing up in the binary which generates the current profile. It is used to discriminate function being cold versus function being newly added. Profile symbol list is only added for profile with ExtBinary format. During profile use compilation, when profile-sample-accurate is enabled, a function without profile will be regarded as cold only when it is contained in that list. Differential Revision: https://reviews.llvm.org/D66766 llvm-svn: 370563
Diffstat (limited to 'llvm/lib/ProfileData')
-rw-r--r--llvm/lib/ProfileData/SampleProf.cpp81
-rw-r--r--llvm/lib/ProfileData/SampleProfReader.cpp28
-rw-r--r--llvm/lib/ProfileData/SampleProfWriter.cpp7
3 files changed, 115 insertions, 1 deletions
diff --git a/llvm/lib/ProfileData/SampleProf.cpp b/llvm/lib/ProfileData/SampleProf.cpp
index ce0f537f8d5..36c39c12432 100644
--- a/llvm/lib/ProfileData/SampleProf.cpp
+++ b/llvm/lib/ProfileData/SampleProf.cpp
@@ -15,8 +15,11 @@
#include "llvm/Config/llvm-config.h"
#include "llvm/IR/DebugInfoMetadata.h"
#include "llvm/Support/Compiler.h"
+#include "llvm/Support/Compression.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/LEB128.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/raw_ostream.h"
#include <string>
@@ -66,6 +69,12 @@ class SampleProfErrorCategoryType : public std::error_category {
return "Counter overflow";
case sampleprof_error::ostream_seek_unsupported:
return "Ostream does not support seek";
+ case sampleprof_error::compress_failed:
+ return "Compress failure";
+ case sampleprof_error::uncompress_failed:
+ return "Uncompress failure";
+ case sampleprof_error::zlib_unavailable:
+ return "Zlib is unavailable";
}
llvm_unreachable("A value of sampleprof_error has no message.");
}
@@ -188,3 +197,75 @@ FunctionSamples::findFunctionSamples(const DILocation *DIL) const {
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
LLVM_DUMP_METHOD void FunctionSamples::dump() const { print(dbgs(), 0); }
#endif
+
+std::error_code ProfileSymbolList::read(uint64_t CompressSize,
+ uint64_t UncompressSize,
+ const uint8_t *Data) {
+ const char *ListStart = reinterpret_cast<const char *>(Data);
+ // CompressSize being non-zero means the profile is compressed and
+ // needs to be uncompressed first.
+ if (CompressSize) {
+ if (!llvm::zlib::isAvailable())
+ return sampleprof_error::zlib_unavailable;
+
+ StringRef CompressedStrings(reinterpret_cast<const char *>(Data),
+ CompressSize);
+ char *Buffer = Allocator.Allocate<char>(UncompressSize);
+ llvm::Error E = zlib::uncompress(CompressedStrings, Buffer, UncompressSize);
+ if (E)
+ return sampleprof_error::uncompress_failed;
+ ListStart = Buffer;
+ }
+
+ uint64_t Size = 0;
+ while (Size < UncompressSize) {
+ StringRef Str(ListStart + Size);
+ add(Str);
+ Size += Str.size() + 1;
+ }
+ return sampleprof_error::success;
+}
+
+std::error_code ProfileSymbolList::write(raw_ostream &OS) {
+ // Sort the symbols before doing compression. It will make the
+ // compression much more effective.
+ std::vector<StringRef> SortedList;
+ SortedList.insert(SortedList.begin(), Syms.begin(), Syms.end());
+ llvm::sort(SortedList);
+
+ std::string UncompressedStrings;
+ for (auto &Sym : SortedList) {
+ UncompressedStrings.append(Sym.str());
+ UncompressedStrings.append(1, '\0');
+ }
+
+ if (ToCompress) {
+ if (!llvm::zlib::isAvailable())
+ return sampleprof_error::zlib_unavailable;
+ SmallString<128> CompressedStrings;
+ llvm::Error E = zlib::compress(UncompressedStrings, CompressedStrings,
+ zlib::BestSizeCompression);
+ if (E)
+ return sampleprof_error::compress_failed;
+ encodeULEB128(UncompressedStrings.size(), OS);
+ encodeULEB128(CompressedStrings.size(), OS);
+ OS << CompressedStrings.str();
+ } else {
+ encodeULEB128(UncompressedStrings.size(), OS);
+ // If profile symbol list is not compressed, we will still save
+ // a compressed size value, but the value of the size is 0.
+ encodeULEB128(0, OS);
+ OS << UncompressedStrings;
+ }
+ return sampleprof_error::success;
+}
+
+void ProfileSymbolList::dump(raw_ostream &OS) const {
+ OS << "======== Dump profile symbol list ========\n";
+ std::vector<StringRef> SortedList;
+ SortedList.insert(SortedList.begin(), Syms.begin(), Syms.end());
+ llvm::sort(SortedList);
+
+ for (auto &Sym : SortedList)
+ OS << Sym << "\n";
+}
diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp
index e309d5b270a..f6b33d96261 100644
--- a/llvm/lib/ProfileData/SampleProfReader.cpp
+++ b/llvm/lib/ProfileData/SampleProfReader.cpp
@@ -486,12 +486,40 @@ SampleProfileReaderExtBinary::readOneSection(const uint8_t *Start,
return EC;
}
break;
+ case SecProfileSymbolList:
+ if (std::error_code EC = readProfileSymbolList())
+ return EC;
+ break;
default:
break;
}
return sampleprof_error::success;
}
+std::error_code SampleProfileReaderExtBinary::readProfileSymbolList() {
+ auto UncompressSize = readNumber<uint64_t>();
+ if (std::error_code EC = UncompressSize.getError())
+ return EC;
+
+ auto CompressSize = readNumber<uint64_t>();
+ if (std::error_code EC = CompressSize.getError())
+ return EC;
+
+ if (!ProfSymList)
+ ProfSymList = std::make_unique<ProfileSymbolList>();
+
+ if (std::error_code EC =
+ ProfSymList->read(*CompressSize, *UncompressSize, Data))
+ return EC;
+
+ // CompressSize is zero only when ProfileSymbolList is not compressed.
+ if (*CompressSize == 0)
+ Data = Data + *UncompressSize;
+ else
+ Data = Data + *CompressSize;
+ return sampleprof_error::success;
+}
+
std::error_code SampleProfileReaderExtBinaryBase::read() {
const uint8_t *BufStart =
reinterpret_cast<const uint8_t *>(Buffer->getBufferStart());
diff --git a/llvm/lib/ProfileData/SampleProfWriter.cpp b/llvm/lib/ProfileData/SampleProfWriter.cpp
index 47f97de2a3b..068ce5bf959 100644
--- a/llvm/lib/ProfileData/SampleProfWriter.cpp
+++ b/llvm/lib/ProfileData/SampleProfWriter.cpp
@@ -121,7 +121,12 @@ std::error_code SampleProfileWriterExtBinary::writeSections(
if (std::error_code EC = writeFuncProfiles(ProfileMap))
return EC;
- addNewSection(SecLBRProfile, SectionStart);
+ SectionStart = addNewSection(SecLBRProfile, SectionStart);
+
+ if (ProfSymList && ProfSymList->size() > 0)
+ if (std::error_code EC = ProfSymList->write(*OutputStream))
+ return EC;
+ addNewSection(SecProfileSymbolList, SectionStart);
return sampleprof_error::success;
}
OpenPOWER on IntegriCloud