Sample profiles - Re-arrange binary format to emit head samples only on top functions.
authorDiego Novillo <dnovillo@google.com>
Fri, 16 Oct 2015 18:54:35 +0000 (18:54 +0000)
committerDiego Novillo <dnovillo@google.com>
Fri, 16 Oct 2015 18:54:35 +0000 (18:54 +0000)
The number of samples collected at the head of a function only make
sense for top-level functions (i.e., those actually called as opposed to
being inlined inside another).

Head samples essentially count the time spent inside the function's
prologue.  This clearly doesn't make sense for inlined functions, so we
were always emitting 0 in those.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@250539 91177308-0d34-0410-b5e6-96231b3b80d8

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

index e46407bde2c5e00a1354070844ff4541cf198a15..96df141e4b2556ad9543db365d78418923d99d9f 100644 (file)
@@ -61,7 +61,7 @@ static inline uint64_t SPMagic() {
          uint64_t('2') << (64 - 56) | uint64_t(0xff);
 }
 
          uint64_t('2') << (64 - 56) | uint64_t(0xff);
 }
 
-static inline uint64_t SPVersion() { return 101; }
+static inline uint64_t SPVersion() { return 102; }
 
 /// Represents the relative location of an instruction.
 ///
 
 /// Represents the relative location of an instruction.
 ///
index 02bb85af10f449fa9826a1de5f86cf839d0bb5f9..2f404be50e6ae699ec4a70462ddb2776dfb7042d 100644 (file)
 //        A NUL-separated list of SIZE strings.
 //
 // FUNCTION BODY (one for each uninlined function body present in the profile)
 //        A NUL-separated list of SIZE strings.
 //
 // FUNCTION BODY (one for each uninlined function body present in the profile)
+//    HEAD_SAMPLES (uint64_t) [only for top-level functions]
+//        Total number of samples collected at the head (prologue) of the
+//        function.
+//        NOTE: This field should only be present for top-level functions
+//              (i.e., not inlined into any caller). Inlined function calls
+//              have no prologue, so they don't need this.
 //    NAME_IDX (uint32_t)
 //        Index into the name table indicating the function name.
 //    SAMPLES (uint64_t)
 //        Total number of samples collected in this function.
 //    NAME_IDX (uint32_t)
 //        Index into the name table indicating the function name.
 //    SAMPLES (uint64_t)
 //        Total number of samples collected in this function.
-//    HEAD_SAMPLES (uint64_t)
-//        Total number of samples collected at the head of the function.
 //    NRECS (uint32_t)
 //        Total number of sampling records this function's profile.
 //    BODY RECORDS
 //    NRECS (uint32_t)
 //        Total number of sampling records this function's profile.
 //    BODY RECORDS
index 48fbe10a6ab775b7a7d319354abc39504279e408..4bd5c71e00228ad6ff31f1a11e1d01594409bab7 100644 (file)
@@ -105,6 +105,7 @@ protected:
   std::error_code
   writeHeader(const StringMap<FunctionSamples> &ProfileMap) override;
   std::error_code writeNameIdx(StringRef FName);
   std::error_code
   writeHeader(const StringMap<FunctionSamples> &ProfileMap) override;
   std::error_code writeNameIdx(StringRef FName);
+  std::error_code writeBody(StringRef FName, const FunctionSamples &S);
 
 private:
   void addName(StringRef FName);
 
 private:
   void addName(StringRef FName);
index 1ea7d2a0c4b5f295ac39560efd0844fd80d6ac27..d184969e046c8feda1a315a1cb6fe5be961b562f 100644 (file)
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ProfileData/SampleProfReader.h"
 //===----------------------------------------------------------------------===//
 
 #include "llvm/ProfileData/SampleProfReader.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorOr.h"
 #include "llvm/Support/LEB128.h"
 #include "llvm/Support/LineIterator.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/ErrorOr.h"
 #include "llvm/Support/LEB128.h"
 #include "llvm/Support/LineIterator.h"
 #include "llvm/Support/MemoryBuffer.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/SmallVector.h"
 
 using namespace llvm::sampleprof;
 using namespace llvm;
 
 using namespace llvm::sampleprof;
 using namespace llvm;
@@ -293,15 +293,10 @@ ErrorOr<StringRef> SampleProfileReaderBinary::readStringFromTable() {
 
 std::error_code
 SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
 
 std::error_code
 SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
-  auto Val = readNumber<uint64_t>();
-  if (std::error_code EC = Val.getError())
+  auto NumSamples = readNumber<uint64_t>();
+  if (std::error_code EC = NumSamples.getError())
     return EC;
     return EC;
-  FProfile.addTotalSamples(*Val);
-
-  Val = readNumber<uint64_t>();
-  if (std::error_code EC = Val.getError())
-    return EC;
-  FProfile.addHeadSamples(*Val);
+  FProfile.addTotalSamples(*NumSamples);
 
   // Read the samples in the body.
   auto NumRecords = readNumber<uint32_t>();
 
   // Read the samples in the body.
   auto NumRecords = readNumber<uint32_t>();
@@ -370,6 +365,10 @@ SampleProfileReaderBinary::readProfile(FunctionSamples &FProfile) {
 
 std::error_code SampleProfileReaderBinary::read() {
   while (!at_eof()) {
 
 std::error_code SampleProfileReaderBinary::read() {
   while (!at_eof()) {
+    auto NumHeadSamples = readNumber<uint64_t>();
+    if (std::error_code EC = NumHeadSamples.getError())
+      return EC;
+
     auto FName(readStringFromTable());
     if (std::error_code EC = FName.getError())
       return EC;
     auto FName(readStringFromTable());
     if (std::error_code EC = FName.getError())
       return EC;
@@ -377,6 +376,8 @@ std::error_code SampleProfileReaderBinary::read() {
     Profiles[*FName] = FunctionSamples();
     FunctionSamples &FProfile = Profiles[*FName];
 
     Profiles[*FName] = FunctionSamples();
     FunctionSamples &FProfile = Profiles[*FName];
 
+    FProfile.addHeadSamples(*NumHeadSamples);
+
     if (std::error_code EC = readProfile(FProfile))
       return EC;
   }
     if (std::error_code EC = readProfile(FProfile))
       return EC;
   }
index daf3783aba65bf8dfb52c0a65fb1342ef23906a8..a6e3cabd89ed762c88d9c0c5612aa7b436c5bb0a 100644 (file)
@@ -122,19 +122,15 @@ std::error_code SampleProfileWriterBinary::writeHeader(
   return sampleprof_error::success;
 }
 
   return sampleprof_error::success;
 }
 
-/// \brief Write samples to a binary file.
-///
-/// \returns true if the samples were written successfully, false otherwise.
-std::error_code SampleProfileWriterBinary::write(StringRef FName,
-                                                 const FunctionSamples &S) {
+std::error_code SampleProfileWriterBinary::writeBody(StringRef FName,
+                                                     const FunctionSamples &S) {
   if (std::error_code EC = writeNameIdx(FName))
     return EC;
 
   encodeULEB128(S.getTotalSamples(), OS);
   if (std::error_code EC = writeNameIdx(FName))
     return EC;
 
   encodeULEB128(S.getTotalSamples(), OS);
-  encodeULEB128(S.getHeadSamples(), OS);
-  encodeULEB128(S.getBodySamples().size(), OS);
 
   // Emit all the body samples.
 
   // Emit all the body samples.
+  encodeULEB128(S.getBodySamples().size(), OS);
   for (const auto &I : S.getBodySamples()) {
     LineLocation Loc = I.first;
     const SampleRecord &Sample = I.second;
   for (const auto &I : S.getBodySamples()) {
     LineLocation Loc = I.first;
     const SampleRecord &Sample = I.second;
@@ -158,13 +154,22 @@ std::error_code SampleProfileWriterBinary::write(StringRef FName,
     const FunctionSamples &CalleeSamples = J.second;
     encodeULEB128(Loc.LineOffset, OS);
     encodeULEB128(Loc.Discriminator, OS);
     const FunctionSamples &CalleeSamples = J.second;
     encodeULEB128(Loc.LineOffset, OS);
     encodeULEB128(Loc.Discriminator, OS);
-    if (std::error_code EC = write(Loc.CalleeName, CalleeSamples))
+    if (std::error_code EC = writeBody(Loc.CalleeName, CalleeSamples))
       return EC;
   }
 
   return sampleprof_error::success;
 }
 
       return EC;
   }
 
   return sampleprof_error::success;
 }
 
+/// \brief Write samples of a top-level function to a binary file.
+///
+/// \returns true if the samples were written successfully, false otherwise.
+std::error_code SampleProfileWriterBinary::write(StringRef FName,
+                                                 const FunctionSamples &S) {
+  encodeULEB128(S.getHeadSamples(), OS);
+  return writeBody(FName, S);
+}
+
 /// \brief Create a sample profile writer based on the specified format.
 ///
 /// \param Filename The file to create.
 /// \brief Create a sample profile writer based on the specified format.
 ///
 /// \param Filename The file to create.
index dc7234d8300828c853036e310bd2e83a6d651807..a074f53db945df7b0e59b7dd4b678a93ca911b89 100644 (file)
Binary files a/test/Transforms/SampleProfile/Inputs/fnptr.binprof and b/test/Transforms/SampleProfile/Inputs/fnptr.binprof differ