[llvm] r250241 - Sample profiles - Add a name table to the binary encoding.

Diego Novillo via llvm-commits llvm-commits at lists.llvm.org
Tue Oct 13 15:48:46 PDT 2015


Author: dnovillo
Date: Tue Oct 13 17:48:46 2015
New Revision: 250241

URL: http://llvm.org/viewvc/llvm-project?rev=250241&view=rev
Log:
Sample profiles - Add a name table to the binary encoding.

Binary encoded profiles used to encode all function names inline at
every reference.  This is clearly suboptimal in terms of space.  This
patch fixes this by adding a name table to the header of the file.

Modified:
    llvm/trunk/include/llvm/ProfileData/SampleProf.h
    llvm/trunk/include/llvm/ProfileData/SampleProfReader.h
    llvm/trunk/include/llvm/ProfileData/SampleProfWriter.h
    llvm/trunk/lib/ProfileData/SampleProf.cpp
    llvm/trunk/lib/ProfileData/SampleProfReader.cpp
    llvm/trunk/lib/ProfileData/SampleProfWriter.cpp
    llvm/trunk/test/Transforms/SampleProfile/Inputs/fnptr.binprof

Modified: llvm/trunk/include/llvm/ProfileData/SampleProf.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/SampleProf.h?rev=250241&r1=250240&r2=250241&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ProfileData/SampleProf.h (original)
+++ llvm/trunk/include/llvm/ProfileData/SampleProf.h Tue Oct 13 17:48:46 2015
@@ -34,6 +34,8 @@ enum class sampleprof_error {
   truncated,
   malformed,
   unrecognized_format,
+  unsupported_writing_format,
+  truncated_name_table,
   not_implemented
 };
 
@@ -59,7 +61,7 @@ static inline uint64_t SPMagic() {
          uint64_t('2') << (64 - 56) | uint64_t(0xff);
 }
 
-static inline uint64_t SPVersion() { return 100; }
+static inline uint64_t SPVersion() { return 101; }
 
 /// Represents the relative location of an instruction.
 ///

Modified: llvm/trunk/include/llvm/ProfileData/SampleProfReader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/SampleProfReader.h?rev=250241&r1=250240&r2=250241&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ProfileData/SampleProfReader.h (original)
+++ llvm/trunk/include/llvm/ProfileData/SampleProfReader.h Tue Oct 13 17:48:46 2015
@@ -154,6 +154,9 @@ protected:
   /// \returns the read value.
   ErrorOr<StringRef> readString();
 
+  /// Read a string indirectly via the name table.
+  ErrorOr<StringRef> readStringFromTable();
+
   /// \brief Return true if we've reached the end of file.
   bool at_eof() const { return Data >= End; }
 
@@ -165,6 +168,9 @@ protected:
 
   /// \brief Points to the end of the buffer.
   const uint8_t *End;
+
+  /// Function name table.
+  std::vector<StringRef> NameTable;
 };
 
 // Represents the source position in GCC sample profiles.

Modified: llvm/trunk/include/llvm/ProfileData/SampleProfWriter.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ProfileData/SampleProfWriter.h?rev=250241&r1=250240&r2=250241&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ProfileData/SampleProfWriter.h (original)
+++ llvm/trunk/include/llvm/ProfileData/SampleProfWriter.h Tue Oct 13 17:48:46 2015
@@ -13,6 +13,7 @@
 #ifndef LLVM_PROFILEDATA_SAMPLEPROFWRITER_H
 #define LLVM_PROFILEDATA_SAMPLEPROFWRITER_H
 
+#include "llvm/ADT/MapVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/IR/Function.h"
 #include "llvm/IR/Module.h"
@@ -35,30 +36,38 @@ public:
       : OS(Filename, EC, Flags) {}
   virtual ~SampleProfileWriter() {}
 
-  /// \brief Write sample profiles in \p S for function \p FName.
+  /// Write sample profiles in \p S for function \p FName.
   ///
-  /// \returns true if the file was updated successfully. False, otherwise.
-  virtual bool write(StringRef FName, const FunctionSamples &S) = 0;
+  /// \returns status code of the file update operation.
+  virtual std::error_code write(StringRef FName, const FunctionSamples &S) = 0;
 
-  /// \brief Write all the sample profiles in the given map of samples.
+  /// Write all the sample profiles in the given map of samples.
   ///
-  /// \returns true if the file was updated successfully. False, otherwise.
-  bool write(StringMap<FunctionSamples> &ProfileMap) {
-    for (auto &I : ProfileMap) {
+  /// \returns status code of the file update operation.
+  std::error_code write(const StringMap<FunctionSamples> &ProfileMap) {
+    if (std::error_code EC = writeHeader(ProfileMap))
+      return EC;
+
+    for (const auto &I : ProfileMap) {
       StringRef FName = I.first();
-      FunctionSamples &Profile = I.second;
-      if (!write(FName, Profile))
-        return false;
+      const FunctionSamples &Profile = I.second;
+      if (std::error_code EC = write(FName, Profile))
+        return EC;
     }
-    return true;
+    return sampleprof_error::success;
   }
 
-  /// \brief Profile writer factory. Create a new writer based on the value of
-  /// \p Format.
+  /// Profile writer factory.
+  ///
+  /// Create a new writer based on the value of \p Format.
   static ErrorOr<std::unique_ptr<SampleProfileWriter>>
   create(StringRef Filename, SampleProfileFormat Format);
 
 protected:
+  /// \brief Write a file header for the profile file.
+  virtual std::error_code
+  writeHeader(const StringMap<FunctionSamples> &ProfileMap) = 0;
+
   /// \brief Output stream where to emit the profile to.
   raw_fd_ostream OS;
 };
@@ -69,7 +78,13 @@ public:
   SampleProfileWriterText(StringRef F, std::error_code &EC)
       : SampleProfileWriter(F, EC, sys::fs::F_Text), Indent(0) {}
 
-  bool write(StringRef FName, const FunctionSamples &S) override;
+  std::error_code write(StringRef FName, const FunctionSamples &S) override;
+
+protected:
+  std::error_code
+  writeHeader(const StringMap<FunctionSamples> &ProfileMap) override {
+    return sampleprof_error::success;
+  }
 
 private:
   /// Indent level to use when writing.
@@ -81,9 +96,21 @@ private:
 /// \brief Sample-based profile writer (binary format).
 class SampleProfileWriterBinary : public SampleProfileWriter {
 public:
-  SampleProfileWriterBinary(StringRef F, std::error_code &EC);
+  SampleProfileWriterBinary(StringRef F, std::error_code &EC)
+      : SampleProfileWriter(F, EC, sys::fs::F_None), NameTable() {}
+
+  std::error_code write(StringRef F, const FunctionSamples &S) override;
+
+protected:
+  std::error_code
+  writeHeader(const StringMap<FunctionSamples> &ProfileMap) override;
+  std::error_code writeNameIdx(StringRef FName);
+
+private:
+  void addName(StringRef FName);
+  void addNames(const FunctionSamples &S);
 
-  bool write(StringRef F, const FunctionSamples &S) override;
+  MapVector<StringRef, unsigned> NameTable;
 };
 
 } // End namespace sampleprof

Modified: llvm/trunk/lib/ProfileData/SampleProf.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/SampleProf.cpp?rev=250241&r1=250240&r2=250241&view=diff
==============================================================================
--- llvm/trunk/lib/ProfileData/SampleProf.cpp (original)
+++ llvm/trunk/lib/ProfileData/SampleProf.cpp Tue Oct 13 17:48:46 2015
@@ -38,6 +38,10 @@ class SampleProfErrorCategoryType : publ
       return "Malformed profile data";
     case sampleprof_error::unrecognized_format:
       return "Unrecognized profile encoding format";
+    case sampleprof_error::unsupported_writing_format:
+      return "Profile encoding format unsupported for writing operations";
+    case sampleprof_error::truncated_name_table:
+      return "Truncated function name table";
     case sampleprof_error::not_implemented:
       return "Unimplemented feature";
     }

Modified: llvm/trunk/lib/ProfileData/SampleProfReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/SampleProfReader.cpp?rev=250241&r1=250240&r2=250241&view=diff
==============================================================================
--- llvm/trunk/lib/ProfileData/SampleProfReader.cpp (original)
+++ llvm/trunk/lib/ProfileData/SampleProfReader.cpp Tue Oct 13 17:48:46 2015
@@ -378,6 +378,16 @@ ErrorOr<StringRef> SampleProfileReaderBi
   return Str;
 }
 
+ErrorOr<StringRef> SampleProfileReaderBinary::readStringFromTable() {
+  std::error_code EC;
+  auto Idx = readNumber<unsigned>();
+  if (std::error_code EC = Idx.getError())
+    return EC;
+  if (*Idx >= NameTable.size())
+    return sampleprof_error::truncated_name_table;
+  return NameTable[*Idx];
+}
+
 std::error_code
 SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
   auto Val = readNumber<unsigned>();
@@ -413,7 +423,7 @@ SampleProfileReaderBinary::readProfile(F
       return EC;
 
     for (unsigned J = 0; J < *NumCalls; ++J) {
-      auto CalledFunction(readString());
+      auto CalledFunction(readStringFromTable());
       if (std::error_code EC = CalledFunction.getError())
         return EC;
 
@@ -442,7 +452,7 @@ SampleProfileReaderBinary::readProfile(F
     if (std::error_code EC = Discriminator.getError())
       return EC;
 
-    auto FName(readString());
+    auto FName(readStringFromTable());
     if (std::error_code EC = FName.getError())
       return EC;
 
@@ -457,7 +467,7 @@ SampleProfileReaderBinary::readProfile(F
 
 std::error_code SampleProfileReaderBinary::read() {
   while (!at_eof()) {
-    auto FName(readString());
+    auto FName(readStringFromTable());
     if (std::error_code EC = FName.getError())
       return EC;
 
@@ -489,6 +499,18 @@ std::error_code SampleProfileReaderBinar
   else if (*Version != SPVersion())
     return sampleprof_error::unsupported_version;
 
+  // Read the name table.
+  auto Size = readNumber<size_t>();
+  if (std::error_code EC = Size.getError())
+    return EC;
+  NameTable.reserve(*Size);
+  for (size_t I = 0; I < *Size; ++I) {
+    auto Name(readString());
+    if (std::error_code EC = Name.getError())
+      return EC;
+    NameTable.push_back(*Name);
+  }
+
   return sampleprof_error::success;
 }
 

Modified: llvm/trunk/lib/ProfileData/SampleProfWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ProfileData/SampleProfWriter.cpp?rev=250241&r1=250240&r2=250241&view=diff
==============================================================================
--- llvm/trunk/lib/ProfileData/SampleProfWriter.cpp (original)
+++ llvm/trunk/lib/ProfileData/SampleProfWriter.cpp Tue Oct 13 17:48:46 2015
@@ -30,7 +30,8 @@ using namespace llvm::sampleprof;
 using namespace llvm;
 
 /// \brief Write samples to a text file.
-bool SampleProfileWriterText::write(StringRef FName, const FunctionSamples &S) {
+std::error_code SampleProfileWriterText::write(StringRef FName,
+                                               const FunctionSamples &S) {
   OS << FName << ":" << S.getTotalSamples();
   if (Indent == 0)
     OS << ":" << S.getHeadSamples();
@@ -61,31 +62,74 @@ bool SampleProfileWriterText::write(Stri
       OS << Loc.LineOffset << ": ";
     else
       OS << Loc.LineOffset << "." << Loc.Discriminator << ": ";
-    write(Loc.CalleeName, CalleeSamples);
+    if (std::error_code EC = write(Loc.CalleeName, CalleeSamples))
+      return EC;
   }
   Indent -= 1;
 
-  return true;
+  return sampleprof_error::success;
 }
 
-SampleProfileWriterBinary::SampleProfileWriterBinary(StringRef F,
-                                                     std::error_code &EC)
-    : SampleProfileWriter(F, EC, sys::fs::F_None) {
-  if (EC)
-    return;
+std::error_code SampleProfileWriterBinary::writeNameIdx(StringRef FName) {
+  const auto &ret = NameTable.find(FName);
+  if (ret == NameTable.end())
+    return sampleprof_error::truncated_name_table;
+  encodeULEB128(ret->second, OS);
+  return sampleprof_error::success;
+}
+
+void SampleProfileWriterBinary::addName(StringRef FName) {
+  auto NextIdx = NameTable.size();
+  NameTable.insert(std::make_pair(FName, NextIdx));
+}
+
+void SampleProfileWriterBinary::addNames(const FunctionSamples &S) {
+  // Add all the names in indirect call targets.
+  for (const auto &I : S.getBodySamples()) {
+    const SampleRecord &Sample = I.second;
+    for (const auto &J : Sample.getCallTargets())
+      addName(J.first());
+  }
+
+  // Recursively add all the names for inlined callsites.
+  for (const auto &J : S.getCallsiteSamples()) {
+    CallsiteLocation Loc = J.first;
+    const FunctionSamples &CalleeSamples = J.second;
+    addName(Loc.CalleeName);
+    addNames(CalleeSamples);
+  }
+}
 
-  // Write the file header.
+std::error_code SampleProfileWriterBinary::writeHeader(
+    const StringMap<FunctionSamples> &ProfileMap) {
+  // Write file magic identifier.
   encodeULEB128(SPMagic(), OS);
   encodeULEB128(SPVersion(), OS);
+
+  // Generate the name table for all the functions referenced in the profile.
+  for (const auto &I : ProfileMap) {
+    addName(I.first());
+    addNames(I.second);
+  }
+
+  // Write out the name table.
+  encodeULEB128(NameTable.size(), OS);
+  for (auto N : NameTable) {
+    OS << N.first;
+    encodeULEB128(0, OS);
+  }
+
+  return sampleprof_error::success;
 }
 
 /// \brief Write samples to a binary file.
 ///
 /// \returns true if the samples were written successfully, false otherwise.
-bool SampleProfileWriterBinary::write(StringRef FName,
-                                      const FunctionSamples &S) {
-  OS << FName;
-  encodeULEB128(0, OS);
+std::error_code SampleProfileWriterBinary::write(StringRef FName,
+                                                 const FunctionSamples &S) {
+  if (std::error_code EC = writeNameIdx(FName))
+    return EC;
+
   encodeULEB128(S.getTotalSamples(), OS);
   encodeULEB128(S.getHeadSamples(), OS);
   encodeULEB128(S.getBodySamples().size(), OS);
@@ -99,10 +143,10 @@ bool SampleProfileWriterBinary::write(St
     encodeULEB128(Sample.getSamples(), OS);
     encodeULEB128(Sample.getCallTargets().size(), OS);
     for (const auto &J : Sample.getCallTargets()) {
-      std::string Callee = J.first();
+      StringRef Callee = J.first();
       unsigned CalleeSamples = J.second;
-      OS << Callee;
-      encodeULEB128(0, OS);
+      if (std::error_code EC = writeNameIdx(Callee))
+        return EC;
       encodeULEB128(CalleeSamples, OS);
     }
   }
@@ -114,10 +158,11 @@ bool SampleProfileWriterBinary::write(St
     const FunctionSamples &CalleeSamples = J.second;
     encodeULEB128(Loc.LineOffset, OS);
     encodeULEB128(Loc.Discriminator, OS);
-    write(Loc.CalleeName, CalleeSamples);
+    if (std::error_code EC = write(Loc.CalleeName, CalleeSamples))
+      return EC;
   }
 
-  return true;
+  return sampleprof_error::success;
 }
 
 /// \brief Create a sample profile writer based on the specified format.
@@ -138,6 +183,8 @@ SampleProfileWriter::create(StringRef Fi
     Writer.reset(new SampleProfileWriterBinary(Filename, EC));
   else if (Format == SPF_Text)
     Writer.reset(new SampleProfileWriterText(Filename, EC));
+  else if (Format == SPF_GCC)
+    EC = sampleprof_error::unsupported_writing_format;
   else
     EC = sampleprof_error::unrecognized_format;
 

Modified: llvm/trunk/test/Transforms/SampleProfile/Inputs/fnptr.binprof
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SampleProfile/Inputs/fnptr.binprof?rev=250241&r1=250240&r2=250241&view=diff
==============================================================================
Binary files llvm/trunk/test/Transforms/SampleProfile/Inputs/fnptr.binprof (original) and llvm/trunk/test/Transforms/SampleProfile/Inputs/fnptr.binprof Tue Oct 13 17:48:46 2015 differ




More information about the llvm-commits mailing list