Index: include/llvm/ProfileData/SampleProf.h =================================================================== --- include/llvm/ProfileData/SampleProf.h +++ include/llvm/ProfileData/SampleProf.h @@ -125,6 +125,22 @@ SecLBRProfile = SecFuncProfileFirst }; +static inline std::string getSecName(SecType Type) { + switch (Type) { + case SecInValid: + return "InvalidSection"; + case SecProfSummary: + return "ProfileSummarySection"; + case SecNameTable: + return "NameTableSection"; + case SecProfileSymbolList: + return "ProfileSymbolListSection"; + case SecLBRProfile: + return "LBRProfileSection"; + } + llvm_unreachable("A SecType has no name for output"); +} + // Entry type of section header table used by SampleProfileExtBinaryBaseReader // and SampleProfileExtBinaryBaseWriter. struct SecHdrTableEntry { Index: include/llvm/ProfileData/SampleProfReader.h =================================================================== --- include/llvm/ProfileData/SampleProfReader.h +++ include/llvm/ProfileData/SampleProfReader.h @@ -333,6 +333,7 @@ /// It includes all the names that have samples either in outline instance /// or inline instance. virtual std::vector *getNameTable() { return nullptr; } + virtual bool dumpSectionInfo(raw_ostream &OS = dbgs()) { return false; }; protected: /// Map every function to its associated profile. @@ -504,6 +505,12 @@ /// Read sample profiles in extensible format from the associated file. std::error_code read() override; + + /// Get the total size of all \p Type sections. + uint64_t getSectionSize(SecType Type); + /// Get the total size of header and all sections. + uint64_t getFileSize(); + virtual bool dumpSectionInfo(raw_ostream &OS = dbgs()) override; }; class SampleProfileReaderExtBinary : public SampleProfileReaderExtBinaryBase { Index: lib/ProfileData/SampleProfReader.cpp =================================================================== --- lib/ProfileData/SampleProfReader.cpp +++ lib/ProfileData/SampleProfReader.cpp @@ -667,6 +667,36 @@ return sampleprof_error::success; } +uint64_t SampleProfileReaderExtBinaryBase::getSectionSize(SecType Type) { + for (auto &Entry : SecHdrTable) { + if (Entry.Type == Type) + return Entry.Size; + } + return 0; +} + +uint64_t SampleProfileReaderExtBinaryBase::getFileSize() { + auto &LastEntry = SecHdrTable.back(); + return LastEntry.Offset + LastEntry.Size; +} + +bool SampleProfileReaderExtBinaryBase::dumpSectionInfo(raw_ostream &OS) { + uint64_t TotalSecsSize = 0; + for (auto &Entry : SecHdrTable) { + OS << getSecName(Entry.Type) << " - Offset: " << Entry.Offset + << ", Size: " << Entry.Size << "\n"; + TotalSecsSize += getSectionSize(Entry.Type); + } + uint64_t HeaderSize = SecHdrTable.front().Offset; + assert(HeaderSize + TotalSecsSize == getFileSize() && + "Size of 'header + sections' doesn't match the total size of profile"); + + OS << "Header Size: " << HeaderSize << "\n"; + OS << "Total Sections Size: " << TotalSecsSize << "\n"; + OS << "File Size: " << getFileSize() << "\n"; + return true; +} + std::error_code SampleProfileReaderBinary::readMagicIdent() { // Read and check the magic identifier. auto Magic = readNumber(); Index: test/tools/llvm-profdata/show-prof-size.test =================================================================== --- test/tools/llvm-profdata/show-prof-size.test +++ test/tools/llvm-profdata/show-prof-size.test @@ -0,0 +1,7 @@ +; RUN: llvm-profdata merge -sample -extbinary -prof-sym-list=%S/Inputs/profile-symbol-list-1.text %S/Inputs/sample-profile.proftext -o %t.1.output +; RUN: ls -l %t.1.output |cut -f5 -d ' ' > %t.txt +; RUN: llvm-profdata show -sample -show-sec-info-only %t.1.output >> %t.txt +; RUN: FileCheck %s --input-file=%t.txt +; Check llvm-profdata shows the correct file size. +; CHECK: [[FILESIZE:.*]] +; CHECK: [[FILESIZE]] Index: tools/llvm-profdata/llvm-profdata.cpp =================================================================== --- tools/llvm-profdata/llvm-profdata.cpp +++ tools/llvm-profdata/llvm-profdata.cpp @@ -982,10 +982,21 @@ return 0; } +static void showSectionInfo(sampleprof::SampleProfileReader *Reader, + raw_fd_ostream &OS) { + if (!Reader->dumpSectionInfo(OS)) { + WithColor::warning() << "-show-sec-info-only is only supported for " + << "sample profile in extbinary format and is " + << "ignored for other formats.\n"; + return; + } +} + static int showSampleProfile(const std::string &Filename, bool ShowCounts, bool ShowAllFunctions, const std::string &ShowFunction, - bool ShowProfileSymbolList, raw_fd_ostream &OS) { + bool ShowProfileSymbolList, + bool ShowSectionInfoOnly, raw_fd_ostream &OS) { using namespace sampleprof; LLVMContext Context; auto ReaderOrErr = SampleProfileReader::create(Filename, Context); @@ -993,6 +1004,12 @@ exitWithErrorCode(EC, Filename); auto Reader = std::move(ReaderOrErr.get()); + + if (ShowSectionInfoOnly) { + showSectionInfo(Reader.get(), OS); + return 0; + } + if (std::error_code EC = Reader->read()) exitWithErrorCode(EC, Filename); @@ -1062,6 +1079,11 @@ cl::opt ShowProfileSymbolList( "show-prof-sym-list", cl::init(false), cl::desc("Show profile symbol list if it exists in the profile. ")); + cl::opt ShowSectionInfoOnly( + "show-sec-info-only", cl::init(false), + cl::desc("Show the information of each section in the sample profile. " + "The flag is only usable when the sample profile is in " + "extbinary format")); cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n"); @@ -1090,7 +1112,8 @@ OnlyListBelow, ShowFunction, TextFormat, OS); else return showSampleProfile(Filename, ShowCounts, ShowAllFunctions, - ShowFunction, ShowProfileSymbolList, OS); + ShowFunction, ShowProfileSymbolList, + ShowSectionInfoOnly, OS); } int main(int argc, const char *argv[]) {