Index: llvm/include/llvm/ProfileData/SampleProfWriter.h =================================================================== --- llvm/include/llvm/ProfileData/SampleProfWriter.h +++ llvm/include/llvm/ProfileData/SampleProfWriter.h @@ -175,8 +175,9 @@ }; protected: - uint64_t markSectionStart(SecType Type); - std::error_code addNewSection(SecType Sec, uint64_t SectionStart); + uint64_t markSectionStart(SecType Type, uint32_t LayoutIdx); + std::error_code addNewSection(SecType Sec, uint32_t LayoutIdx, + uint64_t SectionStart); template void addSectionFlag(SecType Type, SecFlagType Flag) { for (auto &Entry : SectionHdrLayout) { @@ -195,7 +196,8 @@ // Dispatch section writer for each section. virtual std::error_code - writeOneSection(SecType Type, const StringMap &ProfileMap); + writeOneSection(SecType Type, uint32_t LayoutIdx, + const StringMap &ProfileMap); // Helper function to write name table. virtual std::error_code writeNameTable() override; @@ -222,7 +224,6 @@ std::error_code writeSecHdrTable(); virtual std::error_code writeHeader(const StringMap &ProfileMap) override; - SecHdrTableEntry &getEntryInLayout(SecType Type); std::error_code compressAndOutput(); // We will swap the raw_ostream held by LocalBufStream and that @@ -239,8 +240,14 @@ // The location in the output stream where the SecHdrTable should be // written to. uint64_t SecHdrTableOffset; - // Initial Section Flags setting. - std::vector SecHdrTable; + // The entry recording the section information to write. + struct SecHdrEntryType { + SecHdrTableEntry SecEntry; + // The index indicating the location in SectionHdrLayout table for the + // current section. + uint32_t LayoutIndex; + }; + std::vector SecHdrTable; // FuncOffsetTable maps function name to its profile offset in SecLBRProfile // section. It is used to load function profile on demand. Index: llvm/lib/ProfileData/SampleProfReader.cpp =================================================================== --- llvm/lib/ProfileData/SampleProfReader.cpp +++ llvm/lib/ProfileData/SampleProfReader.cpp @@ -560,6 +560,11 @@ } std::error_code SampleProfileReaderExtBinaryBase::readFuncOffsetTable() { + // If there are more than one FuncOffsetTable, the profile read associated + // with previous FuncOffsetTable has to be done before next FuncOffsetTable + // is read. + FuncOffsetTable.clear(); + auto Size = readNumber(); if (std::error_code EC = Size.getError()) return EC; @@ -757,7 +762,7 @@ auto Size = readNumber(); if (std::error_code EC = Size.getError()) return EC; - NameTable.reserve(*Size); + NameTable.reserve(*Size + NameTable.size()); for (uint32_t I = 0; I < *Size; ++I) { auto Name(readString()); if (std::error_code EC = Name.getError()) @@ -872,11 +877,12 @@ } uint64_t SampleProfileReaderExtBinaryBase::getSectionSize(SecType Type) { + uint64_t Size = 0; for (auto &Entry : SecHdrTable) { if (Entry.Type == Type) - return Entry.Size; + Size += Entry.Size; } - return 0; + return Size; } uint64_t SampleProfileReaderExtBinaryBase::getFileSize() { @@ -928,7 +934,7 @@ << ", Size: " << Entry.Size << ", Flags: " << getSecFlagsStr(Entry) << "\n"; ; - TotalSecsSize += getSectionSize(Entry.Type); + TotalSecsSize += Entry.Size; } uint64_t HeaderSize = SecHdrTable.front().Offset; assert(HeaderSize + TotalSecsSize == getFileSize() && Index: llvm/lib/ProfileData/SampleProfWriter.cpp =================================================================== --- llvm/lib/ProfileData/SampleProfWriter.cpp +++ llvm/lib/ProfileData/SampleProfWriter.cpp @@ -73,19 +73,15 @@ return sampleprof_error::success; } -SecHdrTableEntry & -SampleProfileWriterExtBinaryBase::getEntryInLayout(SecType Type) { - auto SecIt = std::find_if( - SectionHdrLayout.begin(), SectionHdrLayout.end(), - [=](const auto &Entry) -> bool { return Entry.Type == Type; }); - return *SecIt; -} - /// Return the current position and prepare to use it as the start -/// position of a section. -uint64_t SampleProfileWriterExtBinaryBase::markSectionStart(SecType Type) { +/// position of a section given the section type \p Type and its position +/// \p LayoutIdx in SectionHdrLayout. +uint64_t +SampleProfileWriterExtBinaryBase::markSectionStart(SecType Type, + uint32_t LayoutIdx) { uint64_t SectionStart = OutputStream->tell(); - auto &Entry = getEntryInLayout(Type); + const auto &Entry = SectionHdrLayout[LayoutIdx]; + assert(Entry.Type == Type && "Unexpected section type"); // Use LocalBuf as a temporary output for writting data. if (hasSecFlag(Entry, SecCommonFlags::SecFlagCompress)) LocalBufStream.swap(OutputStream); @@ -112,18 +108,21 @@ return sampleprof_error::success; } -/// Add a new section into section header table. -std::error_code -SampleProfileWriterExtBinaryBase::addNewSection(SecType Type, - uint64_t SectionStart) { - auto Entry = getEntryInLayout(Type); +/// Add a new section into section header table given the section type +/// \p Type, its position \p LayoutIdx in SectionHdrLayout and the +/// location \p SectionStart where the section should be written to. +std::error_code SampleProfileWriterExtBinaryBase::addNewSection( + SecType Type, uint32_t LayoutIdx, uint64_t SectionStart) { + const auto &Entry = SectionHdrLayout[LayoutIdx]; + assert(Entry.Type == Type && "Unexpected section type"); if (hasSecFlag(Entry, SecCommonFlags::SecFlagCompress)) { LocalBufStream.swap(OutputStream); if (std::error_code EC = compressAndOutput()) return EC; } - SecHdrTable.push_back({Type, Entry.Flags, SectionStart - FileStart, - OutputStream->tell() - SectionStart}); + SecHdrTable.push_back({{Type, Entry.Flags, SectionStart - FileStart, + OutputStream->tell() - SectionStart}, + LayoutIdx}); return sampleprof_error::success; } @@ -163,6 +162,7 @@ writeNameIdx(entry.first); encodeULEB128(entry.second, OS); } + FuncOffsetTable.clear(); return sampleprof_error::success; } @@ -205,12 +205,13 @@ } std::error_code SampleProfileWriterExtBinaryBase::writeOneSection( - SecType Type, const StringMap &ProfileMap) { + SecType Type, uint32_t LayoutIdx, + const StringMap &ProfileMap) { // The setting of SecFlagCompress should happen before markSectionStart. if (Type == SecProfileSymbolList && ProfSymList && ProfSymList->toCompress()) setToCompressSection(SecProfileSymbolList); - uint64_t SectionStart = markSectionStart(Type); + uint64_t SectionStart = markSectionStart(Type, LayoutIdx); switch (Type) { case SecProfSummary: computeSummary(ProfileMap); @@ -239,22 +240,22 @@ return EC; break; } - if (std::error_code EC = addNewSection(Type, SectionStart)) + if (std::error_code EC = addNewSection(Type, LayoutIdx, SectionStart)) return EC; return sampleprof_error::success; } std::error_code SampleProfileWriterExtBinary::writeSections( const StringMap &ProfileMap) { - if (auto EC = writeOneSection(SecProfSummary, ProfileMap)) + if (auto EC = writeOneSection(SecProfSummary, 0, ProfileMap)) return EC; - if (auto EC = writeOneSection(SecNameTable, ProfileMap)) + if (auto EC = writeOneSection(SecNameTable, 1, ProfileMap)) return EC; - if (auto EC = writeOneSection(SecLBRProfile, ProfileMap)) + if (auto EC = writeOneSection(SecLBRProfile, 3, ProfileMap)) return EC; - if (auto EC = writeOneSection(SecProfileSymbolList, ProfileMap)) + if (auto EC = writeOneSection(SecProfileSymbolList, 2, ProfileMap)) return EC; - if (auto EC = writeOneSection(SecFuncOffsetTable, ProfileMap)) + if (auto EC = writeOneSection(SecFuncOffsetTable, 4, ProfileMap)) return EC; return sampleprof_error::success; } @@ -470,24 +471,31 @@ return sampleprof_error::ostream_seek_unsupported; support::endian::Writer Writer(*OutputStream, support::little); - DenseMap IndexMap; - for (uint32_t i = 0; i < SecHdrTable.size(); i++) { - IndexMap.insert({static_cast(SecHdrTable[i].Type), i}); + assert(SecHdrTable.size() == SectionHdrLayout.size() && + "SecHdrTable entries doesn't match SectionHdrLayout"); + SmallVector IndexMap(SecHdrTable.size(), -1); + for (uint32_t TableIdx = 0; TableIdx < SecHdrTable.size(); TableIdx++) { + IndexMap[SecHdrTable[TableIdx].LayoutIndex] = TableIdx; } // Write the section header table in the order specified in - // SectionHdrLayout. That is the sections order Reader will see. - // Note that the sections order in which Reader expects to read - // may be different from the order in which Writer is able to - // write, so we need to adjust the order in SecHdrTable to be - // consistent with SectionHdrLayout when we write SecHdrTable - // to the memory. - for (uint32_t i = 0; i < SectionHdrLayout.size(); i++) { - uint32_t idx = IndexMap[static_cast(SectionHdrLayout[i].Type)]; - Writer.write(static_cast(SecHdrTable[idx].Type)); - Writer.write(static_cast(SecHdrTable[idx].Flags)); - Writer.write(static_cast(SecHdrTable[idx].Offset)); - Writer.write(static_cast(SecHdrTable[idx].Size)); + // SectionHdrLayout. SectionHdrLayout specifies the sections + // order in which profile reader expect to read, so the section + // header table should be written in the order in SectionHdrLayout. + // Note that the section order in SecHdrTable may be different + // from the order in SectionHdrLayout, for example, SecFuncOffsetTable + // needs to be computed after SecLBRProfile (the order in SecHdrTable), + // but it needs to be read before SecLBRProfile (the order in + // SectionHdrLayout). So we use IndexMap above to switch the order. + for (uint32_t LayoutIdx = 0; LayoutIdx < SectionHdrLayout.size(); + LayoutIdx++) { + assert(IndexMap[LayoutIdx] < SecHdrTable.size() && + "Incorrect LayoutIdx in SecHdrTable"); + auto Entry = SecHdrTable[IndexMap[LayoutIdx]].SecEntry; + Writer.write(static_cast(Entry.Type)); + Writer.write(static_cast(Entry.Flags)); + Writer.write(static_cast(Entry.Offset)); + Writer.write(static_cast(Entry.Size)); } // Reset OutputStream.