diff --git a/llvm/include/llvm/ProfileData/SampleProfReader.h b/llvm/include/llvm/ProfileData/SampleProfReader.h --- a/llvm/include/llvm/ProfileData/SampleProfReader.h +++ b/llvm/include/llvm/ProfileData/SampleProfReader.h @@ -598,40 +598,23 @@ protected: std::vector SecHdrTable; - std::unique_ptr ProfSymList; std::error_code readSecHdrTableEntry(); std::error_code readSecHdrTable(); - virtual std::error_code readHeader() override; - virtual std::error_code verifySPMagic(uint64_t Magic) override = 0; - virtual std::error_code readOneSection(const uint8_t *Start, uint64_t Size, - const SecHdrTableEntry &Entry) = 0; - -public: - SampleProfileReaderExtBinaryBase(std::unique_ptr B, - LLVMContext &C, SampleProfileFormat Format) - : SampleProfileReaderBinary(std::move(B), C, Format) {} - /// Read sample profiles in extensible format from the associated file. - std::error_code readImpl() 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 { -private: - virtual std::error_code verifySPMagic(uint64_t Magic) override; - virtual std::error_code - readOneSection(const uint8_t *Start, uint64_t Size, - const SecHdrTableEntry &Entry) override; - std::error_code readProfileSymbolList(); std::error_code readFuncOffsetTable(); std::error_code readFuncProfiles(); std::error_code readMD5NameTable(); std::error_code readNameTableSec(bool IsMD5); + std::error_code readProfileSymbolList(); + + virtual std::error_code readHeader() override; + virtual std::error_code verifySPMagic(uint64_t Magic) override = 0; + virtual std::error_code readOneSection(const uint8_t *Start, uint64_t Size, + const SecHdrTableEntry &Entry); + // placeholder for subclasses to dispatch their own section readers. + virtual std::error_code readCustomSection(const SecHdrTableEntry &Entry) = 0; + + std::unique_ptr ProfSymList; /// The table mapping from function name to the offset of its FunctionSample /// towards file start. @@ -651,16 +634,18 @@ std::unique_ptr> MD5StringBuf; public: - SampleProfileReaderExtBinary(std::unique_ptr B, LLVMContext &C, - SampleProfileFormat Format = SPF_Ext_Binary) - : SampleProfileReaderExtBinaryBase(std::move(B), C, Format) {} + SampleProfileReaderExtBinaryBase(std::unique_ptr B, + LLVMContext &C, SampleProfileFormat Format) + : SampleProfileReaderBinary(std::move(B), C, Format) {} - /// \brief Return true if \p Buffer is in the format supported by this class. - static bool hasFormat(const MemoryBuffer &Buffer); + /// Read sample profiles in extensible format from the associated file. + std::error_code readImpl() override; - virtual std::unique_ptr getProfileSymbolList() override { - return std::move(ProfSymList); - }; + /// 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; /// Collect functions with definitions in Module \p M. void collectFuncsFrom(const Module &M) override; @@ -670,6 +655,27 @@ assert(!NameTable.empty() && "NameTable should have been initialized"); return MD5StringBuf && !MD5StringBuf->empty(); } + + virtual std::unique_ptr getProfileSymbolList() override { + return std::move(ProfSymList); + }; +}; + +class SampleProfileReaderExtBinary : public SampleProfileReaderExtBinaryBase { +private: + virtual std::error_code verifySPMagic(uint64_t Magic) override; + virtual std::error_code + readCustomSection(const SecHdrTableEntry &Entry) override { + return sampleprof_error::success; + }; + +public: + SampleProfileReaderExtBinary(std::unique_ptr B, LLVMContext &C, + SampleProfileFormat Format = SPF_Ext_Binary) + : SampleProfileReaderExtBinaryBase(std::move(B), C, Format) {} + + /// \brief Return true if \p Buffer is in the format supported by this class. + static bool hasFormat(const MemoryBuffer &Buffer); }; class SampleProfileReaderCompactBinary : public SampleProfileReaderBinary { diff --git a/llvm/include/llvm/ProfileData/SampleProfWriter.h b/llvm/include/llvm/ProfileData/SampleProfWriter.h --- a/llvm/include/llvm/ProfileData/SampleProfWriter.h +++ b/llvm/include/llvm/ProfileData/SampleProfWriter.h @@ -152,6 +152,24 @@ virtual void setToCompressAllSections() override; void setToCompressSection(SecType Type); + virtual std::error_code writeSample(const FunctionSamples &S) override; + + // Set to use MD5 to represent string in NameTable. + virtual void setUseMD5() override { + UseMD5 = true; + 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); + } + + virtual void setProfileSymbolList(ProfileSymbolList *PSL) override { + ProfSymList = PSL; + }; protected: uint64_t markSectionStart(SecType Type); @@ -164,16 +182,38 @@ } } + // placeholder for subclasses to dispatch their own section writers. + virtual std::error_code writeCustomSection(SecType Type) = 0; + virtual void initSectionHdrLayout() = 0; + // specify the order to write sections. virtual std::error_code writeSections(const StringMap &ProfileMap) = 0; + // Dispatch section writer for each section. + virtual std::error_code + writeOneSection(SecType Type, const StringMap &ProfileMap); + + // Helper function to write name table. + virtual std::error_code writeNameTable() override; + + // Functions to write various kinds of sections. + std::error_code + writeNameTableSection(const StringMap &ProfileMap); + std::error_code writeFuncOffsetTable(); + std::error_code writeProfileSymbolListSection(); + // Specifiy the order of sections in section header table. Note // the order of sections in the profile may be different that the // order in SectionHdrLayout. sample Reader will follow the order // in SectionHdrLayout to read each section. SmallVector SectionHdrLayout; + // Save the start of SecLBRProfile so we can compute the offset to the + // start of SecLBRProfile for each Function's Profile and will keep it + // in FuncOffsetTable. + uint64_t SecLBRProfileStart = 0; + private: void allocSecHdrTable(); std::error_code writeSecHdrTable(); @@ -198,6 +238,14 @@ uint64_t SecHdrTableOffset; // Initial Section Flags setting. std::vector SecHdrTable; + + // FuncOffsetTable maps function name to its profile offset in SecLBRProfile + // section. It is used to load function profile on demand. + MapVector FuncOffsetTable; + // Whether to use MD5 to represent string. + bool UseMD5 = false; + + ProfileSymbolList *ProfSymList = nullptr; }; class SampleProfileWriterExtBinary : public SampleProfileWriterExtBinaryBase { @@ -207,24 +255,6 @@ initSectionHdrLayout(); } - virtual std::error_code writeSample(const FunctionSamples &S) override; - virtual void setProfileSymbolList(ProfileSymbolList *PSL) override { - ProfSymList = PSL; - }; - - // Set to use MD5 to represent string in NameTable. - virtual void setUseMD5() override { - UseMD5 = true; - 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 @@ -246,20 +276,9 @@ virtual std::error_code writeSections(const StringMap &ProfileMap) override; - std::error_code writeFuncOffsetTable(); - virtual std::error_code writeNameTable() override; - - ProfileSymbolList *ProfSymList = nullptr; - - // Save the start of SecLBRProfile so we can compute the offset to the - // start of SecLBRProfile for each Function's Profile and will keep it - // in FuncOffsetTable. - uint64_t SecLBRProfileStart = 0; - // FuncOffsetTable maps function name to its profile offset in SecLBRProfile - // section. It is used to load function profile on demand. - MapVector FuncOffsetTable; - // Whether to use MD5 to represent string. - bool UseMD5 = false; + virtual std::error_code writeCustomSection(SecType Type) override { + return sampleprof_error::success; + }; }; // CompactBinary is a compact format of binary profile which both reduces diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp --- a/llvm/lib/ProfileData/SampleProfReader.cpp +++ b/llvm/lib/ProfileData/SampleProfReader.cpp @@ -470,7 +470,7 @@ return sampleprof_error::success; } -std::error_code SampleProfileReaderExtBinary::readOneSection( +std::error_code SampleProfileReaderExtBinaryBase::readOneSection( const uint8_t *Start, uint64_t Size, const SecHdrTableEntry &Entry) { Data = Start; End = Start + Size; @@ -490,28 +490,30 @@ if (std::error_code EC = readFuncProfiles()) return EC; break; - case SecProfileSymbolList: - if (std::error_code EC = readProfileSymbolList()) - return EC; - break; case SecFuncOffsetTable: if (std::error_code EC = readFuncOffsetTable()) return EC; break; + case SecProfileSymbolList: + if (std::error_code EC = readProfileSymbolList()) + return EC; + break; default: + if (std::error_code EC = readCustomSection(Entry)) + return EC; break; } return sampleprof_error::success; } -void SampleProfileReaderExtBinary::collectFuncsFrom(const Module &M) { +void SampleProfileReaderExtBinaryBase::collectFuncsFrom(const Module &M) { UseAllFuncs = false; FuncsToUse.clear(); for (auto &F : M) FuncsToUse.insert(FunctionSamples::getCanonicalFnName(F)); } -std::error_code SampleProfileReaderExtBinary::readFuncOffsetTable() { +std::error_code SampleProfileReaderExtBinaryBase::readFuncOffsetTable() { auto Size = readNumber(); if (std::error_code EC = Size.getError()) return EC; @@ -531,7 +533,7 @@ return sampleprof_error::success; } -std::error_code SampleProfileReaderExtBinary::readFuncProfiles() { +std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() { const uint8_t *Start = Data; if (UseAllFuncs) { while (Data < End) { @@ -576,7 +578,7 @@ return sampleprof_error::success; } -std::error_code SampleProfileReaderExtBinary::readProfileSymbolList() { +std::error_code SampleProfileReaderExtBinaryBase::readProfileSymbolList() { if (!ProfSymList) ProfSymList = std::make_unique(); @@ -720,7 +722,7 @@ return sampleprof_error::success; } -std::error_code SampleProfileReaderExtBinary::readMD5NameTable() { +std::error_code SampleProfileReaderExtBinaryBase::readMD5NameTable() { auto Size = readNumber(); if (std::error_code EC = Size.getError()) return EC; @@ -739,7 +741,7 @@ return sampleprof_error::success; } -std::error_code SampleProfileReaderExtBinary::readNameTableSec(bool IsMD5) { +std::error_code SampleProfileReaderExtBinaryBase::readNameTableSec(bool IsMD5) { if (IsMD5) return readMD5NameTable(); return SampleProfileReaderBinary::readNameTable(); diff --git a/llvm/lib/ProfileData/SampleProfWriter.cpp b/llvm/lib/ProfileData/SampleProfWriter.cpp --- a/llvm/lib/ProfileData/SampleProfWriter.cpp +++ b/llvm/lib/ProfileData/SampleProfWriter.cpp @@ -144,7 +144,7 @@ } std::error_code -SampleProfileWriterExtBinary::writeSample(const FunctionSamples &S) { +SampleProfileWriterExtBinaryBase::writeSample(const FunctionSamples &S) { uint64_t Offset = OutputStream->tell(); StringRef Name = S.getName(); FuncOffsetTable[Name] = Offset - SecLBRProfileStart; @@ -152,7 +152,7 @@ return writeBody(S); } -std::error_code SampleProfileWriterExtBinary::writeFuncOffsetTable() { +std::error_code SampleProfileWriterExtBinaryBase::writeFuncOffsetTable() { auto &OS = *OutputStream; // Write out the table size. @@ -166,7 +166,7 @@ return sampleprof_error::success; } -std::error_code SampleProfileWriterExtBinary::writeNameTable() { +std::error_code SampleProfileWriterExtBinaryBase::writeNameTable() { if (!UseMD5) return SampleProfileWriterBinary::writeNameTable(); @@ -182,48 +182,78 @@ return sampleprof_error::success; } -std::error_code SampleProfileWriterExtBinary::writeSections( +std::error_code SampleProfileWriterExtBinaryBase::writeNameTableSection( const StringMap &ProfileMap) { - uint64_t SectionStart = markSectionStart(SecProfSummary); - computeSummary(ProfileMap); - if (auto EC = writeSummary()) - return EC; - if (std::error_code EC = addNewSection(SecProfSummary, SectionStart)) - return EC; - - // Generate the name table for all the functions referenced in the profile. - SectionStart = markSectionStart(SecNameTable); for (const auto &I : ProfileMap) { addName(I.first()); addNames(I.second); } - writeNameTable(); - if (std::error_code EC = addNewSection(SecNameTable, SectionStart)) + if (auto EC = writeNameTable()) return EC; + return sampleprof_error::success; +} - SectionStart = markSectionStart(SecLBRProfile); - SecLBRProfileStart = OutputStream->tell(); - if (std::error_code EC = writeFuncProfiles(ProfileMap)) - return EC; - if (std::error_code EC = addNewSection(SecLBRProfile, SectionStart)) - return EC; +std::error_code +SampleProfileWriterExtBinaryBase::writeProfileSymbolListSection() { + if (ProfSymList && ProfSymList->size() > 0) + if (std::error_code EC = ProfSymList->write(*OutputStream)) + return EC; - if (ProfSymList && ProfSymList->toCompress()) + return sampleprof_error::success; +} + +std::error_code SampleProfileWriterExtBinaryBase::writeOneSection( + SecType Type, const StringMap &ProfileMap) { + // The setting of SecFlagCompress should happen before markSectionStart. + if (Type == SecProfileSymbolList && ProfSymList && ProfSymList->toCompress()) setToCompressSection(SecProfileSymbolList); - SectionStart = markSectionStart(SecProfileSymbolList); - if (ProfSymList && ProfSymList->size() > 0) - if (std::error_code EC = ProfSymList->write(*OutputStream)) + uint64_t SectionStart = markSectionStart(Type); + switch (Type) { + case SecProfSummary: + computeSummary(ProfileMap); + if (auto EC = writeSummary()) + return EC; + break; + case SecNameTable: + if (auto EC = writeNameTableSection(ProfileMap)) + return EC; + break; + case SecLBRProfile: + SecLBRProfileStart = OutputStream->tell(); + if (std::error_code EC = writeFuncProfiles(ProfileMap)) return EC; - if (std::error_code EC = addNewSection(SecProfileSymbolList, SectionStart)) + break; + case SecFuncOffsetTable: + if (auto EC = writeFuncOffsetTable()) + return EC; + break; + case SecProfileSymbolList: + if (auto EC = writeProfileSymbolListSection()) + return EC; + break; + default: + if (auto EC = writeCustomSection(Type)) + return EC; + break; + } + if (std::error_code EC = addNewSection(Type, SectionStart)) return EC; + return sampleprof_error::success; +} - SectionStart = markSectionStart(SecFuncOffsetTable); - if (std::error_code EC = writeFuncOffsetTable()) +std::error_code SampleProfileWriterExtBinary::writeSections( + const StringMap &ProfileMap) { + if (auto EC = writeOneSection(SecProfSummary, ProfileMap)) return EC; - if (std::error_code EC = addNewSection(SecFuncOffsetTable, SectionStart)) + if (auto EC = writeOneSection(SecNameTable, ProfileMap)) + return EC; + if (auto EC = writeOneSection(SecLBRProfile, ProfileMap)) + return EC; + if (auto EC = writeOneSection(SecProfileSymbolList, ProfileMap)) + return EC; + if (auto EC = writeOneSection(SecFuncOffsetTable, ProfileMap)) return EC; - return sampleprof_error::success; }