diff --git a/llvm/test/tools/llvm-profgen/inline-cs-noprobe.test b/llvm/test/tools/llvm-profgen/inline-cs-noprobe.test --- a/llvm/test/tools/llvm-profgen/inline-cs-noprobe.test +++ b/llvm/test/tools/llvm-profgen/inline-cs-noprobe.test @@ -2,6 +2,8 @@ | FileCheck %s --input-file %t --check-prefix=CHECK-UNWINDER ; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/inline-cs-noprobe.perfscript --binary=%S/Inputs/inline-cs-noprobe.perfbin --output=%t --profile-summary-cold-count=0 ; RUN: FileCheck %s --input-file %t +; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/inline-cs-noprobe.perfscript --binary=%S/Inputs/inline-cs-noprobe.perfbin --output=%t --profile-summary-cold-count=0 --strip-context +; RUN: FileCheck %s --input-file %t --check-prefix=CHECK-STRIP-CTX ; CHECK:[main:1 @ foo]:309:0 ; CHECK: 2.1: 14 @@ -11,6 +13,18 @@ ; CHECK:[main:1 @ foo:3.1 @ bar]:84:0 ; CHECK: 1: 14 +; CHECK-STRIP-CTX: main:379:0 +; CHECK-STRIP-CTX: 0: 0 +; CHECK-STRIP-CTX: 2: 0 +; CHECK-STRIP-CTX: 1: foo:379 +; CHECK-STRIP-CTX: 2.1: 14 +; CHECK-STRIP-CTX: 3: 15 +; CHECK-STRIP-CTX: 3.2: 1 +; CHECK-STRIP-CTX: 4: 0 +; CHECK-STRIP-CTX: 7: 0 +; CHECK-STRIP-CTX: 3.1: bar:84 +; CHECK-STRIP-CTX: 1: 14 + ; CHECK-UNWINDER: Binary(inline-cs-noprobe.perfbin)'s Range Counter: ; CHECK-UNWINDER: main:1 @ foo ; CHECK-UNWINDER: (670, 6ad): 1 diff --git a/llvm/test/tools/llvm-profgen/noinline-cs-noprobe.test b/llvm/test/tools/llvm-profgen/noinline-cs-noprobe.test --- a/llvm/test/tools/llvm-profgen/noinline-cs-noprobe.test +++ b/llvm/test/tools/llvm-profgen/noinline-cs-noprobe.test @@ -4,6 +4,8 @@ ; RUN: FileCheck %s --input-file %t --check-prefix=CHECK-UNWINDER ; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/noinline-cs-noprobe.perfscript --binary=%S/Inputs/noinline-cs-noprobe.perfbin --output=%t --profile-summary-cold-count=0 ; RUN: FileCheck %s --input-file %t +; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/noinline-cs-noprobe.perfscript --binary=%S/Inputs/noinline-cs-noprobe.perfbin --output=%t --profile-summary-cold-count=0 --strip-context +; RUN: FileCheck %s --input-file %t --check-prefix=CHECK-STRIP-CTX ; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/noinline-cs-noprobe.aggperfscript --binary=%S/Inputs/noinline-cs-noprobe.perfbin --output=%t --skip-symbolization --profile-summary-cold-count=0 ; RUN: FileCheck %s --input-file %t --check-prefix=CHECK-AGG-UNWINDER ; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/noinline-cs-noprobe.aggperfscript --binary=%S/Inputs/noinline-cs-noprobe.perfbin --output=%t --profile-summary-cold-count=0 @@ -58,6 +60,21 @@ ; CHECK: 4: 1 ; CHECK: 5: 3 +; CHECK-STRIP-CTX: foo:57:0 +; CHECK-STRIP-CTX: 0: 0 +; CHECK-STRIP-CTX: 1: 0 +; CHECK-STRIP-CTX: 2: 3 +; CHECK-STRIP-CTX: 3: 3 bar:3 +; CHECK-STRIP-CTX: 4: 0 +; CHECK-STRIP-CTX: 5: 0 +; CHECK-STRIP-CTX: bar:50:3 +; CHECK-STRIP-CTX: 0: 3 +; CHECK-STRIP-CTX: 1: 3 +; CHECK-STRIP-CTX: 2: 2 +; CHECK-STRIP-CTX: 4: 1 +; CHECK-STRIP-CTX: 5: 3 +; CHECK-STRIP-CTX: main:0:0 +; CHECK-STRIP-CTX: 0: 0 ; CHECK-UNWINDER: [main:1 @ foo] ; CHECK-UNWINDER-NEXT: 3 diff --git a/llvm/tools/llvm-profgen/PerfReader.h b/llvm/tools/llvm-profgen/PerfReader.h --- a/llvm/tools/llvm-profgen/PerfReader.h +++ b/llvm/tools/llvm-profgen/PerfReader.h @@ -620,6 +620,25 @@ PerfScriptType PerfType = PERF_UNKNOWN; }; +/* + The reader of LBR only perf script. + A typical LBR sample is like: + 40062f 0x4005c8/0x4005dc/P/-/-/0 0x40062f/0x4005b0/P/-/-/0 ... + ... 0x4005c8/0x4005dc/P/-/-/0 +*/ +class LBRPerfReader : public PerfReaderBase { +public: + LBRPerfReader(ProfiledBinary *Binary) : PerfReaderBase(Binary) { + PerfType = PERF_LBR; + }; + // Parse the LBR only sample. + virtual void parseSample(TraceStream &TraceIt, uint64_t Count) override; + virtual void generateRawProfile() override; + +protected: + void computeCounterFromLBR(const PerfSample *Sample, uint64_t Repeat); +}; + /* Hybrid perf script includes a group of hybrid samples(LBRs + call stack), which is used to generate CS profile. An example of hybrid sample: @@ -629,9 +648,9 @@ 0x4005c8/0x4005dc/P/-/-/0 0x40062f/0x4005b0/P/-/-/0 ... ... 0x4005c8/0x4005dc/P/-/-/0 # LBR Entries */ -class HybridPerfReader : public PerfReaderBase { +class HybridPerfReader : public LBRPerfReader { public: - HybridPerfReader(ProfiledBinary *Binary) : PerfReaderBase(Binary) { + HybridPerfReader(ProfiledBinary *Binary) : LBRPerfReader(Binary) { PerfType = PERF_LBR_STACK; }; // Parse the hybrid sample including the call and LBR line @@ -643,32 +662,6 @@ void unwindSamples(); }; -/* - The reader of LBR only perf script. - A typical LBR sample is like: - 40062f 0x4005c8/0x4005dc/P/-/-/0 0x40062f/0x4005b0/P/-/-/0 ... - ... 0x4005c8/0x4005dc/P/-/-/0 -*/ -class LBRPerfReader : public PerfReaderBase { -public: - LBRPerfReader(ProfiledBinary *Binary) : PerfReaderBase(Binary) { - // There is no context for LBR only sample, so initialize one entry with - // fake "empty" context key. - std::shared_ptr Key = - std::make_shared(); - Key->genHashCode(); - SampleCounters.emplace(Hashable(Key), SampleCounter()); - PerfType = PERF_LBR; - }; - - // Parse the LBR only sample. - void parseSample(TraceStream &TraceIt, uint64_t Count) override; - void generateRawProfile() override; - -private: - void computeCounterFromLBR(const PerfSample *Sample, uint64_t Repeat); -}; - } // end namespace sampleprof } // end namespace llvm diff --git a/llvm/tools/llvm-profgen/PerfReader.cpp b/llvm/tools/llvm-profgen/PerfReader.cpp --- a/llvm/tools/llvm-profgen/PerfReader.cpp +++ b/llvm/tools/llvm-profgen/PerfReader.cpp @@ -22,6 +22,11 @@ "show-relative-address", cl::ReallyHidden, cl::init(true), cl::ZeroOrMore, cl::desc("Work with `--skip-symbolization` to dump the relative address to " "image base instead of virtual address.")); +cl::opt + StripContext("strip-context", cl::ReallyHidden, cl::init(false), + cl::ZeroOrMore, + cl::desc("Strip call stack sample for hybrid sample and " + "produce context-insensitive profile.")); extern cl::opt ShowDisassemblyOnly; extern cl::opt ShowSourceLocations; @@ -645,7 +650,12 @@ } void LBRPerfReader::generateRawProfile() { - assert(SampleCounters.size() == 1 && "Must have one entry of sample counter"); + // There is no context for LBR only sample, so initialize one entry with + // fake "empty" context key. + std::shared_ptr Key = + std::make_shared(); + Key->genHashCode(); + SampleCounters.emplace(Hashable(Key), SampleCounter()); for (const auto &Item : AggregatedSamples) { const PerfSample *Sample = Item.first.getPtr(); computeCounterFromLBR(Sample, Item.second); @@ -744,7 +754,13 @@ return PerfType; } -void HybridPerfReader::generateRawProfile() { unwindSamples(); } +void HybridPerfReader::generateRawProfile() { + if (StripContext) { + PerfType = PERF_LBR; + LBRPerfReader::generateRawProfile(); + } else + unwindSamples(); +} void PerfReaderBase::parsePerfTraces( cl::list &PerfTraceFilenames) {