Revert "Handle inline stacks in gcov-encoded sample profiles."
authorDiego Novillo <dnovillo@google.com>
Thu, 8 Oct 2015 01:17:26 +0000 (01:17 +0000)
committerDiego Novillo <dnovillo@google.com>
Thu, 8 Oct 2015 01:17:26 +0000 (01:17 +0000)
This reverts commit r249644.

The buildbots are failing the new test I added. Investigating.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@249648 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/tools/llvm-profdata/Inputs/gcc-sample-profile.gcov [deleted file]
test/tools/llvm-profdata/gcc-gcov-sample-profile.test [deleted file]

index aa715df162fabbb37c55af4770fecffd82e21191..ef5afc7eb3b0b39dfc03f5f08a93356a3c95b148 100644 (file)
@@ -208,7 +208,7 @@ typedef DenseMap<CallsiteLocation, FunctionSamples> CallsiteSampleMap;
 class FunctionSamples {
 public:
   FunctionSamples() : TotalSamples(0), TotalHeadSamples(0) {}
-  void print(raw_ostream &OS = dbgs(), unsigned Indent = 0) const;
+  void print(raw_ostream &OS = dbgs());
   void addTotalSamples(unsigned Num) { TotalSamples += Num; }
   void addHeadSamples(unsigned Num) { TotalHeadSamples += Num; }
   void addBodySamples(int LineOffset, unsigned Discriminator, unsigned Num) {
@@ -302,22 +302,6 @@ private:
   /// are an offset from the start of the function.
   BodySampleMap BodySamples;
 
-  /// Map call sites to collected samples for the called function.
-  ///
-  /// Each entry in this map corresponds to all the samples
-  /// collected for the inlined function call at the given
-  /// location. For example, given:
-  ///
-  ///     void foo() {
-  ///  1    bar();
-  ///  ...
-  ///  8    baz();
-  ///     }
-  ///
-  /// If the bar() and baz() calls were inlined inside foo(), this
-  /// map will contain two entries.  One for all the samples collected
-  /// in the call to bar() at line offset 1, the other for all the samples
-  /// collected in the call to baz() at line offset 8.
   CallsiteSampleMap CallsiteSamples;
 };
 
index 9f4d53902e1c4e1687c1f418f944321423448352..87c871f855b353a2efed9e38cda0baa63fac7b01 100644 (file)
@@ -189,7 +189,7 @@ struct SourceInfo {
   uint32_t Discriminator;
 };
 
-typedef SmallVector<FunctionSamples *, 10> InlineCallStack;
+typedef std::vector<SourceInfo> SourceStack;
 
 // Supported histogram types in GCC.  Currently, we only need support for
 // call target histograms.
@@ -220,8 +220,9 @@ public:
 
 protected:
   std::error_code readNameTable();
-  std::error_code readOneFunctionProfile(const InlineCallStack &InlineStack,
-                                         bool Update, uint32_t Offset);
+  std::error_code addSourceCount(StringRef Name, const SourceStack &Src,
+                                 uint64_t Count);
+  std::error_code readOneFunctionProfile(const SourceStack &Stack, bool Update);
   std::error_code readFunctionProfiles();
   std::error_code skipNextWord();
   template <typename T> ErrorOr<T> readNumber();
index d3fa7429a6d4afb0326ec38b2db4800de02c077c..302a82d3286122d044cb3eb10ef908e828bde8bc 100644 (file)
@@ -84,18 +84,12 @@ protected:
 class SampleProfileWriterText : public SampleProfileWriter {
 public:
   SampleProfileWriterText(StringRef F, std::error_code &EC)
-      : SampleProfileWriter(F, EC, sys::fs::F_Text), Indent(0) {}
+      : SampleProfileWriter(F, EC, sys::fs::F_Text) {}
 
   bool write(StringRef FName, const FunctionSamples &S) override;
   bool write(const Module &M, StringMap<FunctionSamples> &P) {
     return SampleProfileWriter::write(M, P);
   }
-
-private:
-  /// Indent level to use when writing.
-  ///
-  /// This is used when printing inlined callees.
-  unsigned Indent;
 };
 
 /// \brief Sample-based profile writer (binary format).
index 6d7d182e46c8325a3a5ac1ef6149b6c6dffbd9b4..94f87996bea57fe58e930ff5b27d4e0a2f105bb2 100644 (file)
@@ -132,14 +132,13 @@ using namespace llvm;
 /// \brief Print the samples collected for a function on stream \p OS.
 ///
 /// \param OS Stream to emit the output to.
-void FunctionSamples::print(raw_ostream &OS, unsigned Indent) const {
+void FunctionSamples::print(raw_ostream &OS) {
   OS << TotalSamples << ", " << TotalHeadSamples << ", " << BodySamples.size()
      << " sampled lines\n";
   for (const auto &SI : BodySamples) {
     LineLocation Loc = SI.first;
     const SampleRecord &Sample = SI.second;
-    OS.indent(Indent);
-    OS << "line offset: " << Loc.LineOffset
+    OS << "\tline offset: " << Loc.LineOffset
        << ", discriminator: " << Loc.Discriminator
        << ", number of samples: " << Sample.getSamples();
     if (Sample.hasCalls()) {
@@ -149,15 +148,7 @@ void FunctionSamples::print(raw_ostream &OS, unsigned Indent) const {
     }
     OS << "\n";
   }
-  for (const auto &CS : CallsiteSamples) {
-    CallsiteLocation Loc = CS.first;
-    const FunctionSamples &CalleeSamples = CS.second;
-    OS.indent(Indent);
-    OS << "line offset: " << Loc.LineOffset
-       << ", discriminator: " << Loc.Discriminator
-       << ", inlined callee: " << Loc.CalleeName << ": ";
-    CalleeSamples.print(OS, Indent + 2);
-  }
+  OS << "\n";
 }
 
 /// \brief Dump the function profile for \p FName.
@@ -275,7 +266,7 @@ static bool ParseLine(const StringRef &Input, bool &IsCallsite, unsigned &Depth,
 std::error_code SampleProfileReaderText::read() {
   line_iterator LineIt(*Buffer, /*SkipBlanks=*/true, '#');
 
-  InlineCallStack InlineStack;
+  SmallVector<FunctionSamples *, 10> InlineStack;
 
   for (; !LineIt.is_at_eof(); ++LineIt) {
     if ((*LineIt)[(*LineIt).find_first_not_of(' ')] == '#')
@@ -568,18 +559,31 @@ std::error_code SampleProfileReaderGCC::readFunctionProfiles() {
   if (!GcovBuffer.readInt(NumFunctions))
     return sampleprof_error::truncated;
 
-  InlineCallStack Stack;
+  SourceStack Stack;
   for (uint32_t I = 0; I < NumFunctions; ++I)
-    if (std::error_code EC = readOneFunctionProfile(Stack, true, 0))
+    if (std::error_code EC = readOneFunctionProfile(Stack, true))
       return EC;
 
   return sampleprof_error::success;
 }
 
-std::error_code SampleProfileReaderGCC::readOneFunctionProfile(
-    const InlineCallStack &InlineStack, bool Update, uint32_t Offset) {
+std::error_code SampleProfileReaderGCC::addSourceCount(StringRef Name,
+                                                       const SourceStack &Src,
+                                                       uint64_t Count) {
+  if (Src.size() == 0 || Src[0].Malformed())
+    return sampleprof_error::malformed;
+  FunctionSamples &FProfile = Profiles[Name];
+  FProfile.addTotalSamples(Count);
+  // FIXME(dnovillo) - Properly update inline stack for FnName.
+  FProfile.addBodySamples(Src[0].Line, Src[0].Discriminator, Count);
+  return sampleprof_error::success;
+}
+
+std::error_code
+SampleProfileReaderGCC::readOneFunctionProfile(const SourceStack &Stack,
+                                               bool Update) {
   uint64_t HeadCount = 0;
-  if (InlineStack.size() == 0)
+  if (Stack.size() == 0)
     if (!GcovBuffer.readInt64(HeadCount))
       return sampleprof_error::truncated;
 
@@ -593,31 +597,15 @@ std::error_code SampleProfileReaderGCC::readOneFunctionProfile(
   if (!GcovBuffer.readInt(NumPosCounts))
     return sampleprof_error::truncated;
 
-  uint32_t NumCallsites;
-  if (!GcovBuffer.readInt(NumCallsites))
+  uint32_t NumCallSites;
+  if (!GcovBuffer.readInt(NumCallSites))
     return sampleprof_error::truncated;
 
-  FunctionSamples *FProfile = nullptr;
-  if (InlineStack.size() == 0) {
-    // If this is a top function that we have already processed, do not
-    // update its profile again.  This happens in the presence of
-    // function aliases.  Since these aliases share the same function
-    // body, there will be identical replicated profiles for the
-    // original function.  In this case, we simply not bother updating
-    // the profile of the original function.
-    FProfile = &Profiles[Name];
-    FProfile->addHeadSamples(HeadCount);
-    if (FProfile->getTotalSamples() > 0)
+  if (Stack.size() == 0) {
+    FunctionSamples &FProfile = Profiles[Name];
+    FProfile.addHeadSamples(HeadCount);
+    if (FProfile.getTotalSamples() > 0)
       Update = false;
-  } else {
-    // Otherwise, we are reading an inlined instance. The top of the
-    // inline stack contains the profile of the caller. Insert this
-    // callee in the caller's CallsiteMap.
-    FunctionSamples *CallerProfile = InlineStack.front();
-    uint32_t LineOffset = Offset >> 16;
-    uint32_t Discriminator = Offset & 0xffff;
-    FProfile = &CallerProfile->functionSamplesAt(
-        CallsiteLocation(LineOffset, Discriminator, Name));
   }
 
   for (uint32_t I = 0; I < NumPosCounts; ++I) {
@@ -633,28 +621,13 @@ std::error_code SampleProfileReaderGCC::readOneFunctionProfile(
     if (!GcovBuffer.readInt64(Count))
       return sampleprof_error::truncated;
 
-    // The line location is encoded in the offset as:
-    //   high 16 bits: line offset to the start of the function.
-    //   low 16 bits: discriminator.
-    uint32_t LineOffset = Offset >> 16;
-    uint32_t Discriminator = Offset & 0xffff;
-
-    InlineCallStack NewStack;
-    NewStack.push_back(FProfile);
-    NewStack.insert(NewStack.end(), InlineStack.begin(), InlineStack.end());
-    if (Update) {
-      // Walk up the inline stack, adding the samples on this line to
-      // the total sample count of the callers in the chain.
-      for (auto CallerProfile : NewStack)
-        CallerProfile->addTotalSamples(Count);
-
-      // Update the body samples for the current profile.
-      FProfile->addBodySamples(LineOffset, Discriminator, Count);
-    }
+    SourceInfo Info(Name, "", "", 0, Offset >> 16, Offset & 0xffff);
+    SourceStack NewStack;
+    NewStack.push_back(Info);
+    NewStack.insert(NewStack.end(), Stack.begin(), Stack.end());
+    if (Update)
+      addSourceCount(NewStack[NewStack.size() - 1].FuncName, NewStack, Count);
 
-    // Process the list of functions called at an indirect call site.
-    // These are all the targets that a function pointer (or virtual
-    // function) resolved at runtime.
     for (uint32_t J = 0; J < NumTargets; J++) {
       uint32_t HistVal;
       if (!GcovBuffer.readInt(HistVal))
@@ -674,25 +647,24 @@ std::error_code SampleProfileReaderGCC::readOneFunctionProfile(
 
       if (Update) {
         FunctionSamples &TargetProfile = Profiles[TargetName];
-        TargetProfile.addCalledTargetSamples(LineOffset, Discriminator,
-                                             TargetName, TargetCount);
+        TargetProfile.addBodySamples(NewStack[0].Line,
+                                     NewStack[0].Discriminator, TargetCount);
       }
     }
   }
 
-  // Process all the inlined callers into the current function. These
-  // are all the callsites that were inlined into this function.
-  for (uint32_t I = 0; I < NumCallsites; I++) {
+  for (uint32_t I = 0; I < NumCallSites; I++) {
     // The offset is encoded as:
     //   high 16 bits: line offset to the start of the function.
     //   low 16 bits: discriminator.
     uint32_t Offset;
     if (!GcovBuffer.readInt(Offset))
       return sampleprof_error::truncated;
-    InlineCallStack NewStack;
-    NewStack.push_back(FProfile);
-    NewStack.insert(NewStack.end(), InlineStack.begin(), InlineStack.end());
-    if (std::error_code EC = readOneFunctionProfile(NewStack, Update, Offset))
+    SourceInfo Info(Name, "", "", 0, Offset >> 16, Offset & 0xffff);
+    SourceStack NewStack;
+    NewStack.push_back(Info);
+    NewStack.insert(NewStack.end(), Stack.begin(), Stack.end());
+    if (std::error_code EC = readOneFunctionProfile(NewStack, Update))
       return EC;
   }
 
index e6a4d7d132103aba5c527203e6ea399728851411..c95267ad976b896d8b69d85e755fe7529c2077cb 100644 (file)
@@ -31,15 +31,15 @@ using namespace llvm;
 
 /// \brief Write samples to a text file.
 bool SampleProfileWriterText::write(StringRef FName, const FunctionSamples &S) {
-  OS << FName << ":" << S.getTotalSamples();
-  if (Indent == 0)
-    OS << ":" << S.getHeadSamples();
-  OS << "\n";
+  if (S.empty())
+    return true;
+
+  OS << FName << ":" << S.getTotalSamples() << ":" << S.getHeadSamples()
+     << "\n";
 
   for (const auto &I : S.getBodySamples()) {
     LineLocation Loc = I.first;
     const SampleRecord &Sample = I.second;
-    OS.indent(Indent + 1);
     if (Loc.Discriminator == 0)
       OS << Loc.LineOffset << ": ";
     else
@@ -52,19 +52,6 @@ bool SampleProfileWriterText::write(StringRef FName, const FunctionSamples &S) {
     OS << "\n";
   }
 
-  Indent += 1;
-  for (const auto &I : S.getCallsiteSamples()) {
-    CallsiteLocation Loc = I.first;
-    const FunctionSamples &CalleeSamples = I.second;
-    OS.indent(Indent);
-    if (Loc.Discriminator == 0)
-      OS << Loc.LineOffset << ": ";
-    else
-      OS << Loc.LineOffset << "." << Loc.Discriminator << ": ";
-    write(Loc.CalleeName, CalleeSamples);
-  }
-  Indent -= 1;
-
   return true;
 }
 
diff --git a/test/tools/llvm-profdata/Inputs/gcc-sample-profile.gcov b/test/tools/llvm-profdata/Inputs/gcc-sample-profile.gcov
deleted file mode 100644 (file)
index 0099280..0000000
Binary files a/test/tools/llvm-profdata/Inputs/gcc-sample-profile.gcov and /dev/null differ
diff --git a/test/tools/llvm-profdata/gcc-gcov-sample-profile.test b/test/tools/llvm-profdata/gcc-gcov-sample-profile.test
deleted file mode 100644 (file)
index 5d9c30f..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-Tests for sample profiles encoded in GCC's gcov format.
-
-1- Show all functions. This profile has a single main() function with several
-   inlined callees.
-RUN: llvm-profdata show --sample %p/Inputs/gcc-sample-profile.gcov | FileCheck %s --check-prefix=SHOW1
-SHOW1: Function: main: 364084, 0, 6 sampled lines
-SHOW1: line offset: 2, discriminator: 3, inlined callee: _Z3fool: 243786, 0, 3 sampled lines
-SHOW1:   line offset: 1, discriminator: 3, inlined callee: _Z3bari: 0, 0, 2 sampled lines
-SHOW1:   line offset: 1, discriminator: 8, inlined callee: _Z3bari: 0, 0, 2 sampled lines
-SHOW1:   line offset: 1, discriminator: 7, inlined callee: _Z3bari: 98558, 0, 2 sampled lines
-
-2- Convert the profile to text encoding and check that they are both
-   identical.
-RUN: llvm-profdata merge --sample %p/Inputs/gcc-sample-profile.gcov --text -o - | llvm-profdata show --sample - -o %t-text
-RUN: llvm-profdata show --sample %p/Inputs/gcc-sample-profile.gcov -o %t-gcov
-RUN: diff %t-text %t-gcov
-
-4- Merge the gcov and text encodings of the profile and check that the
-   counters have doubled.
-RUN: llvm-profdata merge --sample --text %p/Inputs/gcc-sample-profile.gcov -o %t-gcov
-RUN: llvm-profdata merge --sample --text %p/Inputs/gcc-sample-profile.gcov %t-gcov -o - | FileCheck %s --check-prefix=MERGE1
-MERGE1: main:728168:0
-MERGE1: 2.3: 120298
-MERGE1: 2.3: _Z3fool:487572