From dbe26eba863fd648eaba1ef881259731eea21a5b Mon Sep 17 00:00:00 2001 From: Diego Novillo Date: Fri, 13 Nov 2015 20:24:28 +0000 Subject: [PATCH] SamplePGO - Add dump routines for LineLocation, SampleRecord and FunctionSamples git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@253071 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/ProfileData/SampleProf.h | 37 +++++++++++++++++++ lib/ProfileData/SampleProf.cpp | 35 ++++++++---------- lib/ProfileData/SampleProfReader.cpp | 3 +- lib/ProfileData/SampleProfWriter.cpp | 7 ++++ .../gcc-gcov-sample-profile.test | 8 ++-- test/tools/llvm-profdata/inline-samples.test | 10 ++--- .../llvm-profdata/sample-profile-basic.test | 6 +-- 7 files changed, 73 insertions(+), 33 deletions(-) diff --git a/include/llvm/ProfileData/SampleProf.h b/include/llvm/ProfileData/SampleProf.h index 7b7e6c46cd8..52cbba396a3 100644 --- a/include/llvm/ProfileData/SampleProf.h +++ b/include/llvm/ProfileData/SampleProf.h @@ -75,10 +75,22 @@ static inline uint64_t SPVersion() { return 102; } /// (e.g., the two post-increment instructions in "if (p) x++; else y++;"). struct LineLocation { LineLocation(uint32_t L, uint32_t D) : LineOffset(L), Discriminator(D) {} + void print(raw_ostream &OS) const { + OS << LineOffset; + if (Discriminator > 0) + OS << "." << Discriminator; + } + void dump() const { print(dbgs()); } + uint32_t LineOffset; uint32_t Discriminator; }; +inline raw_ostream &operator<<(raw_ostream &OS, const LineLocation &Loc) { + Loc.print(OS); + return OS; +} + /// Represents the relative location of a callsite. /// /// Callsite locations are specified by the line offset from the @@ -89,8 +101,19 @@ struct CallsiteLocation : public LineLocation { CallsiteLocation(uint32_t L, uint32_t D, StringRef N) : LineLocation(L, D), CalleeName(N) {} StringRef CalleeName; + + void print(raw_ostream &OS) const { + LineLocation::print(OS); + OS << ": inlined callee: " << CalleeName; + } + void dump() const { print(dbgs()); } }; +inline raw_ostream &operator<<(raw_ostream &OS, const CallsiteLocation &Loc) { + Loc.print(OS); + return OS; +} + } // End namespace sampleprof template <> struct DenseMapInfo { @@ -194,11 +217,19 @@ public: addCalledTarget(I.first(), I.second); } + void print(raw_ostream &OS, unsigned Indent) const; + void dump() const { print(dbgs(), 0); } + private: uint64_t NumSamples; CallTargetMap CallTargets; }; +inline raw_ostream &operator<<(raw_ostream &OS, const SampleRecord &Sample) { + Sample.print(OS, 0); + return OS; +} + typedef DenseMap BodySampleMap; class FunctionSamples; typedef DenseMap CallsiteSampleMap; @@ -212,6 +243,7 @@ class FunctionSamples { public: FunctionSamples() : TotalSamples(0), TotalHeadSamples(0) {} void print(raw_ostream &OS = dbgs(), unsigned Indent = 0) const; + void dump(void) const { print(); } void addTotalSamples(uint64_t Num) { TotalSamples += Num; } void addHeadSamples(uint64_t Num) { TotalHeadSamples += Num; } void addBodySamples(uint32_t LineOffset, uint32_t Discriminator, @@ -323,6 +355,11 @@ private: CallsiteSampleMap CallsiteSamples; }; +inline raw_ostream &operator<<(raw_ostream &OS, const FunctionSamples &FS) { + FS.print(OS); + return OS; +} + } // end namespace sampleprof } // end namespace llvm diff --git a/lib/ProfileData/SampleProf.cpp b/lib/ProfileData/SampleProf.cpp index 856923e164b..b3ee61a7b97 100644 --- a/lib/ProfileData/SampleProf.cpp +++ b/lib/ProfileData/SampleProf.cpp @@ -57,33 +57,30 @@ const std::error_category &llvm::sampleprof_category() { return *ErrorCategory; } +/// \brief Print the sample record to the stream \p OS indented by \p Indent. +void SampleRecord::print(raw_ostream &OS, unsigned Indent) const { + OS << NumSamples; + if (hasCalls()) { + OS << ", calls:"; + for (const auto &I : getCallTargets()) + OS << " " << I.first() << ":" << I.second; + } + OS << "\n"; +} + /// \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 { 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 - << ", discriminator: " << Loc.Discriminator - << ", number of samples: " << Sample.getSamples(); - if (Sample.hasCalls()) { - OS << ", calls:"; - for (const auto &I : Sample.getCallTargets()) - OS << " " << I.first() << ":" << I.second; - } - OS << "\n"; + OS << SI.first << ": " << SI.second; } + 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 << CS.first << ": "; + CS.second.print(OS, Indent + 2); } } diff --git a/lib/ProfileData/SampleProfReader.cpp b/lib/ProfileData/SampleProfReader.cpp index 0bed4f09f1f..e71d0bae07b 100644 --- a/lib/ProfileData/SampleProfReader.cpp +++ b/lib/ProfileData/SampleProfReader.cpp @@ -38,8 +38,7 @@ using namespace llvm; /// \param OS Stream to emit the output to. void SampleProfileReader::dumpFunctionProfile(StringRef FName, raw_ostream &OS) { - OS << "Function: " << FName << ": "; - Profiles[FName].print(OS); + OS << "Function: " << FName << ": " << Profiles[FName]; } /// \brief Dump all the function profiles found on stream \p OS. diff --git a/lib/ProfileData/SampleProfWriter.cpp b/lib/ProfileData/SampleProfWriter.cpp index a6e3cabd89e..b7f6db5eb33 100644 --- a/lib/ProfileData/SampleProfWriter.cpp +++ b/lib/ProfileData/SampleProfWriter.cpp @@ -30,6 +30,13 @@ using namespace llvm::sampleprof; using namespace llvm; /// \brief Write samples to a text file. +/// +/// Note: it may be tempting to implement this in terms of +/// FunctionSamples::dump(). Please don't. The dump functionality is intended +/// for debugging and has no specified form. +/// +/// The format used here is more structured and deliberate because +/// it needs to be parsed by the SampleProfileReaderText class. std::error_code SampleProfileWriterText::write(StringRef FName, const FunctionSamples &S) { OS << FName << ":" << S.getTotalSamples(); diff --git a/test/tools/llvm-profdata/gcc-gcov-sample-profile.test b/test/tools/llvm-profdata/gcc-gcov-sample-profile.test index 723d547555b..609569a8fe1 100644 --- a/test/tools/llvm-profdata/gcc-gcov-sample-profile.test +++ b/test/tools/llvm-profdata/gcc-gcov-sample-profile.test @@ -9,10 +9,10 @@ Tests for sample profiles encoded in GCC's gcov format. 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 +SHOW1: 2.3: inlined callee: _Z3fool: 243786, 0, 3 sampled lines +SHOW1: 1.3: inlined callee: _Z3bari: 0, 0, 2 sampled lines +SHOW1: 1.8: inlined callee: _Z3bari: 0, 0, 2 sampled lines +SHOW1: 1.7: inlined callee: _Z3bari: 98558, 0, 2 sampled lines 2- Convert the profile to text encoding and check that they are both identical. diff --git a/test/tools/llvm-profdata/inline-samples.test b/test/tools/llvm-profdata/inline-samples.test index b16ac488234..156dc15aeef 100644 --- a/test/tools/llvm-profdata/inline-samples.test +++ b/test/tools/llvm-profdata/inline-samples.test @@ -8,11 +8,11 @@ RUN: llvm-profdata merge --sample %p/Inputs/inline-samples.afdo -o %t.profbin inlined callees. RUN: llvm-profdata show --sample %t.profbin | FileCheck %s --check-prefix=SHOW1 SHOW1: Function: main: 366846, 0, 6 sampled lines -SHOW1: line offset: 2, discriminator: 3, inlined callee: _Z3fool: 246044, 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: 99492, 0, 2 sampled lines -SHOW1: line offset: 1, discriminator: 2, number of samples: 46732 +SHOW1: 2.3: inlined callee: _Z3fool: 246044, 0, 3 sampled lines +SHOW1: 1.3: inlined callee: _Z3bari: 0, 0, 2 sampled lines +SHOW1: 1.8: inlined callee: _Z3bari: 0, 0, 2 sampled lines +SHOW1: 1.7: inlined callee: _Z3bari: 99492, 0, 2 sampled lines +SHOW1: 1.2: 46732 3- Convert the binary profile to text encoding and check that they are both identical. diff --git a/test/tools/llvm-profdata/sample-profile-basic.test b/test/tools/llvm-profdata/sample-profile-basic.test index 9981d4204c4..5116b98f333 100644 --- a/test/tools/llvm-profdata/sample-profile-basic.test +++ b/test/tools/llvm-profdata/sample-profile-basic.test @@ -3,15 +3,15 @@ Basic tests for sample profiles. 1- Show all functions RUN: llvm-profdata show --sample %p/Inputs/sample-profile.proftext | FileCheck %s --check-prefix=SHOW1 SHOW1: Function: main: 184019, 0, 7 sampled lines -SHOW1: line offset: 9, discriminator: 0, number of samples: 2064, calls: _Z3fooi:631 _Z3bari:1471 +SHOW1: 9: 2064, calls: _Z3fooi:631 _Z3bari:1471 SHOW1: Function: _Z3fooi: 7711, 610, 1 sampled lines SHOW1: Function: _Z3bari: 20301, 1437, 1 sampled lines -SHOW1: line offset: 1, discriminator: 0, number of samples: 1437 +SHOW1: 1: 1437 2- Show only bar RUN: llvm-profdata show --sample --function=_Z3bari %p/Inputs/sample-profile.proftext | FileCheck %s --check-prefix=SHOW2 SHOW2: Function: _Z3bari: 20301, 1437, 1 sampled lines -SHOW2: line offset: 1, discriminator: 0, number of samples: 1437 +SHOW2: 1: 1437 SHOW2-NOT: Function: main: 184019, 0, 7 sampled lines SHOW2-NOT: Function: _Z3fooi: 7711, 610, 1 sampled lines -- 2.34.1