From 7308c418b819d597e474f4914d8cb7c1e4602db9 Mon Sep 17 00:00:00 2001 From: Diego Novillo Date: Thu, 8 Oct 2015 01:17:26 +0000 Subject: [PATCH] Revert "Handle inline stacks in gcov-encoded sample profiles." 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 | 18 +-- include/llvm/ProfileData/SampleProfReader.h | 7 +- include/llvm/ProfileData/SampleProfWriter.h | 8 +- lib/ProfileData/SampleProfReader.cpp | 112 +++++++----------- lib/ProfileData/SampleProfWriter.cpp | 23 +--- .../Inputs/gcc-sample-profile.gcov | Bin 1960 -> 0 bytes .../gcc-gcov-sample-profile.test | 24 ---- 7 files changed, 53 insertions(+), 139 deletions(-) delete mode 100644 test/tools/llvm-profdata/Inputs/gcc-sample-profile.gcov delete mode 100644 test/tools/llvm-profdata/gcc-gcov-sample-profile.test diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h index aa715df162f..ef5afc7eb3b 100644 --- a/include/llvm/ProfileData/SampleProf.h +++ b/include/llvm/ProfileData/SampleProf.h @@ -208,7 +208,7 @@ typedef DenseMap 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; }; diff --git a/include/llvm/ProfileData/SampleProfReader.h b/include/llvm/ProfileData/SampleProfReader.h index 9f4d53902e1..87c871f855b 100644 --- a/include/llvm/ProfileData/SampleProfReader.h +++ b/include/llvm/ProfileData/SampleProfReader.h @@ -189,7 +189,7 @@ struct SourceInfo { uint32_t Discriminator; }; -typedef SmallVector InlineCallStack; +typedef std::vector 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 ErrorOr readNumber(); diff --git a/include/llvm/ProfileData/SampleProfWriter.h b/include/llvm/ProfileData/SampleProfWriter.h index d3fa7429a6d..302a82d3286 100644 --- a/include/llvm/ProfileData/SampleProfWriter.h +++ b/include/llvm/ProfileData/SampleProfWriter.h @@ -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 &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). diff --git a/lib/ProfileData/SampleProfReader.cpp b/lib/ProfileData/SampleProfReader.cpp index 6d7d182e46c..94f87996bea 100644 --- a/lib/ProfileData/SampleProfReader.cpp +++ b/lib/ProfileData/SampleProfReader.cpp @@ -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 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; } diff --git a/lib/ProfileData/SampleProfWriter.cpp b/lib/ProfileData/SampleProfWriter.cpp index e6a4d7d1321..c95267ad976 100644 --- a/lib/ProfileData/SampleProfWriter.cpp +++ b/lib/ProfileData/SampleProfWriter.cpp @@ -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 index 0099280af2f9ebf9b78efcca8d015f59ce663147..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1960 zcmYdHNlw=?H!xvJOZS$ivjzZHDlfaj1vLg3Lj6F9(V0f#$43GGToK zlml}=$evL)B(w>I11RWVYDU?RFe5b_K=}d|h9jMgC=(bM2(dwB5lqc+V8hB&kYC7U egX$KTUSip>au=kYo@`kC0J4`{HY<`|O4tB4*X#QL 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 index 5d9c30f9fd6..00000000000 --- a/test/tools/llvm-profdata/gcc-gcov-sample-profile.test +++ /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 -- 2.34.1