[llvm] r257921 - [PGO] Commonize (more) index profile file and buffer writer.
Evgenii Stepanov via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 15 11:23:24 PST 2016
On Fri, Jan 15, 2016 at 11:01 AM, Xinliang David Li via llvm-commits
<llvm-commits at lists.llvm.org> wrote:
> Author: davidxl
> Date: Fri Jan 15 13:01:04 2016
> New Revision: 257921
>
> URL: http://llvm.org/viewvc/llvm-project?rev=257921&view=rev
> Log:
> [PGO] Commonize (more) index profile file and buffer writer.
>
> The file and buffer writer code are mostly shared except for the
> stream back-patching. This is because raw_string_ostream does not
> support seek like interface. The result is that the data patching
> code needs to be pushed to the caller which is not quite readable
> (passing around offset, value etc). This also makes future enhancement
> (which needs more patching) more difficult (and can make impl messy).
>
> In this patch, two types of streams needed by the writer are now
> unified with same set of interfaces under ProfOStream class. The patch
> method is added so that common implementation becomes cleaner. It
> also enables future enhancement. Should be NFC.
>
>
>
> Modified:
> llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h
> llvm/trunk/lib/ProfileData/InstrProfWriter.cpp
>
> Modified: llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h?rev=257921&r1=257920&r2=257921&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h (original)
> +++ llvm/trunk/include/llvm/ProfileData/InstrProfWriter.h Fri Jan 15 13:01:04 2016
> @@ -24,6 +24,7 @@
> namespace llvm {
>
> /// Writer for instrumentation based profile data.
> +class ProfOStream;
error: 'ProfOStream' defined as a struct here but previously declared
as a class [-Werror,-Wmismatched-tags]
> class InstrProfWriter {
> public:
> typedef SmallDenseMap<uint64_t, InstrProfRecord, 1> ProfilingData;
> @@ -53,7 +54,7 @@ public:
> void setValueProfDataEndianness(support::endianness Endianness);
>
> private:
> - std::pair<uint64_t, uint64_t> writeImpl(raw_ostream &OS);
> + void writeImpl(ProfOStream &OS);
> };
>
> } // end namespace llvm
>
> Modified: llvm/trunk/lib/ProfileData/InstrProfWriter.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/InstrProfWriter.cpp?rev=257921&r1=257920&r2=257921&view=diff
> ==============================================================================
> --- llvm/trunk/lib/ProfileData/InstrProfWriter.cpp (original)
> +++ llvm/trunk/lib/ProfileData/InstrProfWriter.cpp Fri Jan 15 13:01:04 2016
> @@ -20,6 +20,58 @@
>
> using namespace llvm;
>
> +// A struct to define how the data stream should be patched. For Indexed
> +// profiling, only uint64_t data type is needed.
> +struct PatchItem {
> + uint64_t Pos; // Where to patch.
> + uint64_t *D; // Pointer to an array of source data.
> + int N; // Number of elements in \c D array.
> +};
> +
> +namespace llvm {
> +// A wrapper class to abstract writer stream with support of bytes
> +// back patching.
> +struct ProfOStream {
> +
> + ProfOStream(llvm::raw_fd_ostream &FD) : IsFDOStream(true), OS(FD), LE(FD) {}
> + ProfOStream(llvm::raw_string_ostream &STR)
> + : IsFDOStream(false), OS(STR), LE(STR) {}
> +
> + uint64_t tell() { return OS.tell(); }
> + void write(uint64_t V) { LE.write<uint64_t>(V); }
> + // \c patch can only be called when all data is written and flushed.
> + // For raw_string_ostream, the patch is done on the target string
> + // directly and it won't be reflected in the stream's internal buffer.
> + void patch(PatchItem *P, int NItems) {
> + using namespace support;
> + if (IsFDOStream) {
> + llvm::raw_fd_ostream &FDOStream = static_cast<llvm::raw_fd_ostream &>(OS);
> + for (int K = 0; K < NItems; K++) {
> + FDOStream.seek(P[K].Pos);
> + for (int I = 0; I < P[K].N; I++)
> + write(P[K].D[I]);
> + }
> + } else {
> + llvm::raw_string_ostream &SOStream =
> + static_cast<llvm::raw_string_ostream &>(OS);
> + std::string &Data = SOStream.str(); // with flush
> + for (int K = 0; K < NItems; K++) {
> + for (int I = 0; I < P[K].N; I++) {
> + uint64_t Bytes = endian::byte_swap<uint64_t, little>(P[K].D[I]);
> + Data.replace(P[K].Pos + I * sizeof(uint64_t), sizeof(uint64_t),
> + (const char *)&Bytes, sizeof(uint64_t));
> + }
> + }
> + }
> + }
> + // If \c OS is an instance of \c raw_fd_ostream, this field will be
> + // true. Otherwise, \c OS will be an raw_string_ostream.
> + bool IsFDOStream;
> + raw_ostream &OS;
> + support::endian::Writer<support::little> LE;
> +};
> +}
> +
> namespace {
> static support::endianness ValueProfDataEndianness = support::little;
>
> @@ -127,16 +179,11 @@ std::error_code InstrProfWriter::addReco
> return Result;
> }
>
> -std::pair<uint64_t, uint64_t> InstrProfWriter::writeImpl(raw_ostream &OS) {
> +void InstrProfWriter::writeImpl(ProfOStream &OS) {
> OnDiskChainedHashTableGenerator<InstrProfRecordTrait> Generator;
> -
> // Populate the hash table generator.
> for (const auto &I : FunctionData)
> Generator.insert(I.getKey(), &I.getValue());
> -
> - using namespace llvm::support;
> - endian::Writer<little> LE(OS);
> -
> // Write the header.
> IndexedInstrProf::Header Header;
> Header.Magic = IndexedInstrProf::Magic;
> @@ -150,27 +197,34 @@ std::pair<uint64_t, uint64_t> InstrProfW
> // to remember the offset of that field to allow back patching
> // later.
> for (int I = 0; I < N - 1; I++)
> - LE.write<uint64_t>(reinterpret_cast<uint64_t *>(&Header)[I]);
> + OS.write(reinterpret_cast<uint64_t *>(&Header)[I]);
>
> // Save a space to write the hash table start location.
> uint64_t HashTableStartLoc = OS.tell();
> // Reserve the space for HashOffset field.
> - LE.write<uint64_t>(0);
> + OS.write(0);
> // Write the hash table.
> - uint64_t HashTableStart = Generator.Emit(OS);
> + uint64_t HashTableStart = Generator.Emit(OS.OS);
>
> - return std::make_pair(HashTableStartLoc, HashTableStart);
> + // Now do the final patch:
> + PatchItem PatchItems[1] = {{HashTableStartLoc, &HashTableStart, 1}};
> + OS.patch(PatchItems, sizeof(PatchItems) / sizeof(*PatchItems));
> }
>
> void InstrProfWriter::write(raw_fd_ostream &OS) {
> // Write the hash table.
> - auto TableStart = writeImpl(OS);
> + ProfOStream POS(OS);
> + writeImpl(POS);
> +}
>
> - // Go back and fill in the hash table start.
> - using namespace support;
> - OS.seek(TableStart.first);
> - // Now patch the HashOffset field previously reserved.
> - endian::Writer<little>(OS).write<uint64_t>(TableStart.second);
> +std::unique_ptr<MemoryBuffer> InstrProfWriter::writeBuffer() {
> + std::string Data;
> + llvm::raw_string_ostream OS(Data);
> + ProfOStream POS(OS);
> + // Write the hash table.
> + writeImpl(POS);
> + // Return this in an aligned memory buffer.
> + return MemoryBuffer::getMemBufferCopy(Data);
> }
>
> static const char *ValueProfKindStr[] = {
> @@ -227,20 +281,3 @@ void InstrProfWriter::writeText(raw_fd_o
> for (const auto &Func : I.getValue())
> writeRecordInText(Func.second, Symtab, OS);
> }
> -
> -std::unique_ptr<MemoryBuffer> InstrProfWriter::writeBuffer() {
> - std::string Data;
> - llvm::raw_string_ostream OS(Data);
> - // Write the hash table.
> - auto TableStart = writeImpl(OS);
> - OS.flush();
> -
> - // Go back and fill in the hash table start.
> - using namespace support;
> - uint64_t Bytes = endian::byte_swap<uint64_t, little>(TableStart.second);
> - Data.replace(TableStart.first, sizeof(uint64_t), (const char *)&Bytes,
> - sizeof(uint64_t));
> -
> - // Return this in an aligned memory buffer.
> - return MemoryBuffer::getMemBufferCopy(Data);
> -}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list