Index: llvm/include/llvm/ProfileData/SampleProfReader.h =================================================================== --- llvm/include/llvm/ProfileData/SampleProfReader.h +++ llvm/include/llvm/ProfileData/SampleProfReader.h @@ -598,13 +598,36 @@ protected: std::vector SecHdrTable; - std::unique_ptr ProfSymList; std::error_code readSecHdrTableEntry(); std::error_code readSecHdrTable(); + + std::error_code readFuncOffsetTable(); + std::error_code readFuncProfiles(); + std::error_code readMD5NameTable(); + std::error_code readNameTableSec(bool IsMD5); + 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; + const SecHdrTableEntry &Entry); + virtual std::error_code readOtherSection(const SecHdrTableEntry &Entry) = 0; + + /// The table mapping from function name to the offset of its FunctionSample + /// towards file start. + DenseMap FuncOffsetTable; + /// The set containing the functions to use when compiling a module. + DenseSet FuncsToUse; + /// Use all functions from the input profile. + bool UseAllFuncs = true; + + /// If MD5 is used in NameTable section, the section saves uint64_t data. + /// The uint64_t data has to be converted to a string and then the string + /// will be used to initialize StringRef in NameTable. + /// Note NameTable contains StringRef so it needs another buffer to own + /// the string data. MD5StringBuf serves as the string buffer that is + /// referenced by NameTable (vector of StringRef). We make sure + /// the lifetime of MD5StringBuf is not shorter than that of NameTable. + std::unique_ptr> MD5StringBuf; public: SampleProfileReaderExtBinaryBase(std::unique_ptr B, @@ -619,36 +642,25 @@ /// 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; + + /// Return whether names in the profile are all MD5 numbers. + virtual bool useMD5() override { + assert(!NameTable.empty() && "NameTable should have been initialized"); + return MD5StringBuf && !MD5StringBuf->empty(); + } }; 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; + readOtherSection(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); - - /// The table mapping from function name to the offset of its FunctionSample - /// towards file start. - DenseMap FuncOffsetTable; - /// The set containing the functions to use when compiling a module. - DenseSet FuncsToUse; - /// Use all functions from the input profile. - bool UseAllFuncs = true; - /// If MD5 is used in NameTable section, the section saves uint64_t data. - /// The uint64_t data has to be converted to a string and then the string - /// will be used to initialize StringRef in NameTable. - /// Note NameTable contains StringRef so it needs another buffer to own - /// the string data. MD5StringBuf serves as the string buffer that is - /// referenced by NameTable (vector of StringRef). We make sure - /// the lifetime of MD5StringBuf is not shorter than that of NameTable. - std::unique_ptr> MD5StringBuf; + std::unique_ptr ProfSymList; public: SampleProfileReaderExtBinary(std::unique_ptr B, LLVMContext &C, @@ -661,15 +673,6 @@ virtual std::unique_ptr getProfileSymbolList() override { return std::move(ProfSymList); }; - - /// Collect functions with definitions in Module \p M. - void collectFuncsFrom(const Module &M) override; - - /// Return whether names in the profile are all MD5 numbers. - virtual bool useMD5() override { - assert(!NameTable.empty() && "NameTable should have been initialized"); - return MD5StringBuf && !MD5StringBuf->empty(); - } }; class SampleProfileReaderCompactBinary : public SampleProfileReaderBinary { Index: llvm/include/llvm/ProfileData/SampleProfWriter.h =================================================================== --- llvm/include/llvm/ProfileData/SampleProfWriter.h +++ llvm/include/llvm/ProfileData/SampleProfWriter.h @@ -152,6 +152,20 @@ 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); + } protected: uint64_t markSectionStart(SecType Type); @@ -163,17 +177,36 @@ addSecFlag(Entry, Flag); } } + // placeholder for subclasses to dispatch their own section writers. + virtual std::error_code writeOtherSection(SecType Type) { + return sampleprof_error::success; + }; 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); + virtual std::error_code writeNameTable() override; + + std::error_code + writeNameTableSection(const StringMap &ProfileMap); + std::error_code writeFuncOffsetTable(); + // 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 +231,12 @@ 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; }; class SampleProfileWriterExtBinary : public SampleProfileWriterExtBinaryBase { @@ -207,24 +246,10 @@ 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 @@ -245,21 +270,11 @@ }; virtual std::error_code writeSections(const StringMap &ProfileMap) override; + virtual std::error_code writeOtherSection(SecType Type) override; - std::error_code writeFuncOffsetTable(); - virtual std::error_code writeNameTable() override; + std::error_code writeProfileSymbolListSection(); 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; }; // CompactBinary is a compact format of binary profile which both reduces Index: llvm/lib/ProfileData/SampleProfReader.cpp =================================================================== --- llvm/lib/ProfileData/SampleProfReader.cpp +++ 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,39 @@ 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; + default: + if (std::error_code EC = readOtherSection(Entry)) + return EC; + break; + } + return sampleprof_error::success; +} + +std::error_code +SampleProfileReaderExtBinary::readOtherSection(const SecHdrTableEntry &Entry) { + switch (Entry.Type) { + case SecProfileSymbolList: + if (std::error_code EC = readProfileSymbolList()) + return EC; + break; default: 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 +542,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) { @@ -720,7 +731,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 +750,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(); Index: llvm/lib/ProfileData/SampleProfWriter.cpp =================================================================== --- llvm/lib/ProfileData/SampleProfWriter.cpp +++ 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,84 @@ 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)) - return EC; - - SectionStart = markSectionStart(SecLBRProfile); - SecLBRProfileStart = OutputStream->tell(); - if (std::error_code EC = writeFuncProfiles(ProfileMap)) + if (auto EC = writeNameTable()) return EC; - if (std::error_code EC = addNewSection(SecLBRProfile, SectionStart)) - return EC; - - if (ProfSymList && ProfSymList->toCompress()) - setToCompressSection(SecProfileSymbolList); + return sampleprof_error::success; +} - SectionStart = markSectionStart(SecProfileSymbolList); +std::error_code SampleProfileWriterExtBinary::writeProfileSymbolListSection() { if (ProfSymList && ProfSymList->size() > 0) if (std::error_code EC = ProfSymList->write(*OutputStream)) return EC; - if (std::error_code EC = addNewSection(SecProfileSymbolList, SectionStart)) + + return sampleprof_error::success; +} + +std::error_code SampleProfileWriterExtBinary::writeOtherSection(SecType Type) { + switch (Type) { + case SecProfileSymbolList: + if (auto EC = writeProfileSymbolListSection()) + return EC; + break; + default: + break; + } + return sampleprof_error::success; +} + +std::error_code SampleProfileWriterExtBinaryBase::writeOneSection( + SecType Type, const StringMap &ProfileMap) { + 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; + break; + case SecFuncOffsetTable: + if (auto EC = writeFuncOffsetTable()) + return EC; + break; + default: + if (auto EC = writeOtherSection(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; + // The setting about the section flag should happen before writeOneSection. + if (ProfSymList && ProfSymList->toCompress()) + setToCompressSection(SecProfileSymbolList); + if (auto EC = writeOneSection(SecProfileSymbolList, ProfileMap)) + return EC; + if (auto EC = writeOneSection(SecFuncOffsetTable, ProfileMap)) return EC; - return sampleprof_error::success; }