Index: llvm/include/llvm/IR/ProfileSummary.h =================================================================== --- llvm/include/llvm/IR/ProfileSummary.h +++ llvm/include/llvm/IR/ProfileSummary.h @@ -49,6 +49,12 @@ SummaryEntryVector DetailedSummary; uint64_t TotalCount, MaxCount, MaxInternalCount, MaxFunctionCount; uint32_t NumCounts, NumFunctions; + /// If 'Partial' is false, it means the profile being used to optimize + /// a target is collected from the same target. + /// If 'Partial' is true, it means the profile is for common/shared + /// code. The common profile is usually merged from profiles collected + /// from running other targets. + bool Partial = false; /// Return detailed summary as metadata. Metadata *getDetailedSummaryMD(LLVMContext &Context); @@ -76,6 +82,8 @@ uint64_t getTotalCount() { return TotalCount; } uint64_t getMaxCount() { return MaxCount; } uint64_t getMaxInternalCount() { return MaxInternalCount; } + void setPartialProfile(bool PP) { Partial = PP; } + bool isPartialProfile() { return Partial; } }; } // end namespace llvm Index: llvm/include/llvm/ProfileData/SampleProf.h =================================================================== --- llvm/include/llvm/ProfileData/SampleProf.h +++ llvm/include/llvm/ProfileData/SampleProf.h @@ -169,6 +169,13 @@ SecFlagInValid = 0, SecFlagMD5Name = (1 << 0) }; +enum class SecProfSummaryFlags : uint32_t { + SecFlagInValid = 0, + /// SecFlagPartial means the profile is for common/shared code. + /// The common profile is usually merged from profiles collected + /// from running other targets. + SecFlagPartial = (1 << 0) +}; // Verify section specific flag is used for the correct section. template @@ -183,6 +190,9 @@ case SecNameTable: IsFlagLegal = std::is_same(); break; + case SecProfSummary: + IsFlagLegal = std::is_same(); + break; default: break; } Index: llvm/include/llvm/ProfileData/SampleProfWriter.h =================================================================== --- llvm/include/llvm/ProfileData/SampleProfWriter.h +++ llvm/include/llvm/ProfileData/SampleProfWriter.h @@ -59,6 +59,7 @@ virtual void setProfileSymbolList(ProfileSymbolList *PSL) {} virtual void setToCompressAllSections() {} virtual void setUseMD5() {} + virtual void setPartialProfile() {} protected: SampleProfileWriter(std::unique_ptr &OS) @@ -217,6 +218,13 @@ addSectionFlag(SecNameTable, SecNameTableFlags::SecFlagMD5Name); } + // Set the profile to be partial. It means the profile is for + // common/shared code. The common profile is usually merged from + // profiles collected from running other targets. + virtual void setPartialProfile() override { + addSectionFlag(SecProfSummary, SecProfSummaryFlags::SecFlagPartial); + } + private: virtual void initSectionHdrLayout() override { // Note that SecFuncOffsetTable section is written after SecLBRProfile Index: llvm/lib/ProfileData/SampleProfReader.cpp =================================================================== --- llvm/lib/ProfileData/SampleProfReader.cpp +++ llvm/lib/ProfileData/SampleProfReader.cpp @@ -478,6 +478,8 @@ case SecProfSummary: if (std::error_code EC = readSummary()) return EC; + if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagPartial)) + Summary->setPartialProfile(true); break; case SecNameTable: if (std::error_code EC = readNameTableSec( @@ -831,11 +833,40 @@ return FileSize; } +static std::string getSecFlagsStr(const SecHdrTableEntry &Entry) { + std::string Flags; + if (hasSecFlag(Entry, SecCommonFlags::SecFlagCompress)) + Flags.append("{compressed,"); + else + Flags.append("{"); + + switch (Entry.Type) { + case SecNameTable: + if (hasSecFlag(Entry, SecNameTableFlags::SecFlagMD5Name)) + Flags.append("md5,"); + break; + case SecProfSummary: + if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagPartial)) + Flags.append("partial,"); + break; + default: + break; + } + char &last = Flags.back(); + if (last == ',') + last = '}'; + else + Flags.append("}"); + return Flags; +} + 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"; + << ", Size: " << Entry.Size << ", Flags: " << getSecFlagsStr(Entry) + << "\n"; + ; TotalSecsSize += getSectionSize(Entry.Type); } uint64_t HeaderSize = SecHdrTable.front().Offset; Index: llvm/test/tools/llvm-profdata/show-prof-info.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-profdata/show-prof-info.test @@ -0,0 +1,11 @@ +; RUN: llvm-profdata merge -sample -extbinary -use-md5 -compress-all-sections -partial-profile -prof-sym-list=%S/Inputs/profile-symbol-list-1.text %S/Inputs/sample-profile.proftext -o %t.1.output +; RUN: wc -c < %t.1.output > %t.txt +; RUN: llvm-profdata show -sample -show-sec-info-only %t.1.output >> %t.txt +; RUN: FileCheck %s --input-file=%t.txt +; CHECK: [[FILESIZE:.*]] +; To check llvm-profdata shows the correct flags for ProfileSummarySection. +; CHECK: ProfileSummarySection {{.*}} Flags: {compressed,partial} +; To check llvm-profdata shows the correct flags for NameTableSection. +; CHECK: NameTableSection {{.*}} Flags: {compressed,md5} +; To check llvm-profdata shows the correct file size. +; CHECK: [[FILESIZE]] Index: llvm/test/tools/llvm-profdata/show-prof-size.test =================================================================== --- llvm/test/tools/llvm-profdata/show-prof-size.test +++ /dev/null @@ -1,7 +0,0 @@ -; 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: wc -c < %t.1.output > %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: llvm/tools/llvm-profdata/llvm-profdata.cpp =================================================================== --- llvm/tools/llvm-profdata/llvm-profdata.cpp +++ llvm/tools/llvm-profdata/llvm-profdata.cpp @@ -448,7 +448,8 @@ ProfileFormat OutputFormat, MemoryBuffer *Buffer, sampleprof::ProfileSymbolList &WriterList, - bool CompressAllSections, bool UseMD5) { + bool CompressAllSections, bool UseMD5, + bool PartialProfile) { populateProfileSymbolList(Buffer, WriterList); if (WriterList.size() > 0 && OutputFormat != PF_Ext_Binary) warn("Profile Symbol list is not empty but the output format is not " @@ -468,13 +469,19 @@ else Writer.setUseMD5(); } + if (PartialProfile) { + if (OutputFormat != PF_Ext_Binary) + warn("-partial-profile is ignored. Specify -extbinary to enable it"); + else + Writer.setPartialProfile(); + } } static void mergeSampleProfile(const WeightedFileVector &Inputs, SymbolRemapper *Remapper, StringRef OutputFilename, ProfileFormat OutputFormat, StringRef ProfileSymbolListFile, bool CompressAllSections, - bool UseMD5, FailureMode FailMode) { + bool UseMD5, bool PartialProfile, FailureMode FailMode) { using namespace sampleprof; StringMap ProfileMap; SmallVector, 5> Readers; @@ -531,7 +538,7 @@ // Make sure Buffer lives as long as WriterList. auto Buffer = getInputFileBuf(ProfileSymbolListFile); handleExtBinaryWriter(*Writer, OutputFormat, Buffer.get(), WriterList, - CompressAllSections, UseMD5); + CompressAllSections, UseMD5, PartialProfile); Writer->write(ProfileMap); } @@ -663,6 +670,10 @@ "use-md5", cl::init(false), cl::Hidden, cl::desc("Choose to use MD5 to represent string in name table (only " "meaningful for -extbinary)")); + cl::opt PartialProfile( + "partial-profile", cl::init(false), cl::Hidden, + cl::desc("Set the profile to be a partial profile (only meaningful " + "for -extbinary)")); cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n"); @@ -697,7 +708,7 @@ else mergeSampleProfile(WeightedInputs, Remapper.get(), OutputFilename, OutputFormat, ProfileSymbolListFile, CompressAllSections, - UseMD5, FailureMode); + UseMD5, PartialProfile, FailureMode); return 0; }