[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