diff --git a/llvm/test/tools/llvm-profgen/Inputs/noinline-cs-noprobe.aggperfscript b/llvm/test/tools/llvm-profgen/Inputs/noinline-cs-noprobe.aggperfscript new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-profgen/Inputs/noinline-cs-noprobe.aggperfscript @@ -0,0 +1,11 @@ +2 + 4005dc + 400634 + 400684 + 7f68c5788793 + 0x4005c8/0x4005dc/P/-/-/0 0x40062f/0x4005b0/P/-/-/0 0x400645/0x4005ff/P/-/-/0 0x400637/0x400645/P/-/-/0 0x4005e9/0x400634/P/-/-/0 0x4005d7/0x4005e5/P/-/-/0 0x40062f/0x4005b0/P/-/-/0 0x400645/0x4005ff/P/-/-/0 0x400637/0x400645/P/-/-/0 0x4005e9/0x400634/P/-/-/0 0x4005d7/0x4005e5/P/-/-/0 0x40062f/0x4005b0/P/-/-/0 0x400645/0x4005ff/P/-/-/0 0x400637/0x400645/P/-/-/0 0x4005e9/0x400634/P/-/-/0 0x4005c8/0x4005dc/P/-/-/0 +2 + 4005b0 + 400684 + 7f68c5788793 + 0x40062f/0x4005b0/P/-/-/0 0x400645/0x4005ff/P/-/-/0 0x400637/0x400645/P/-/-/0 0x4005e9/0x400634/P/-/-/0 0x4005c8/0x4005dc/P/-/-/0 0x40062f/0x4005b0/P/-/-/0 0x400645/0x4005ff/P/-/-/0 0x400637/0x400645/P/-/-/0 0x4005e9/0x400634/P/-/-/0 0x4005d7/0x4005e5/P/-/-/0 0x40062f/0x4005b0/P/-/-/0 0x400645/0x4005ff/P/-/-/0 0x400637/0x400645/P/-/-/0 0x4005e9/0x400634/P/-/-/0 0x4005d7/0x4005e5/P/-/-/0 0x40062f/0x4005b0/P/-/-/0 diff --git a/llvm/test/tools/llvm-profgen/Inputs/noinline-cs-pseudoprobe.aggperfscript b/llvm/test/tools/llvm-profgen/Inputs/noinline-cs-pseudoprobe.aggperfscript new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-profgen/Inputs/noinline-cs-pseudoprobe.aggperfscript @@ -0,0 +1,18 @@ +1 + 20179e + 2017f9 + 7f83e84e7793 + 5541f689495641d7 + 0x2017cf/0x20179e/P/-/-/0 0x20177f/0x2017c4/P/-/-/0 0x2017bf/0x201760/P/-/-/0 0x2017cf/0x20179e/P/-/-/0 0x20177f/0x2017c4/P/-/-/0 0x2017bf/0x201760/P/-/-/0 0x2017cf/0x20179e/P/-/-/0 0x20177f/0x2017c4/P/-/-/0 0x2017bf/0x201760/P/-/-/0 0x2017cf/0x20179e/P/-/-/0 0x20177f/0x2017c4/P/-/-/0 0x2017bf/0x201760/P/-/-/0 0x2017cf/0x20179e/P/-/-/0 0x20177f/0x2017c4/P/-/-/0 0x2017bf/0x201760/P/-/-/0 0x2017cf/0x20179e/P/-/-/0 +1 + 2017c4 + 2017f9 + 7f83e84e7793 + 5541f689495641d7 + 0x20177f/0x2017c4/P/-/-/0 0x2017bf/0x201760/P/-/-/0 0x2017cf/0x20179e/P/-/-/0 0x20177f/0x2017c4/P/-/-/0 0x2017bf/0x201760/P/-/-/0 0x2017cf/0x20179e/P/-/-/0 0x20177f/0x2017c4/P/-/-/0 0x2017bf/0x201760/P/-/-/0 0x2017cf/0x20179e/P/-/-/0 0x20177f/0x2017c4/P/-/-/0 0x2017bf/0x201760/P/-/-/0 0x2017cf/0x20179e/P/-/-/0 0x20177f/0x2017c4/P/-/-/0 0x2017bf/0x201760/P/-/-/0 0x2017cf/0x20179e/P/-/-/0 0x20177f/0x2017c4/P/-/-/0 +1 + 2017c4 + 2017f9 + 7f83e84e7793 + 5541f689495641d7 + 0x20177f/0x2017c4/P/-/-/0 0x2017bf/0x201760/P/-/-/0 0x2017cf/0x20179e/P/-/-/0 0x20177f/0x2017c4/P/-/-/0 0x2017bf/0x201760/P/-/-/0 0x2017cf/0x20179e/P/-/-/0 0x20177f/0x2017c4/P/-/-/0 0x2017bf/0x201760/P/-/-/0 0x2017cf/0x20179e/P/-/-/0 0x20177f/0x2017c4/P/-/-/0 0x2017bf/0x201760/P/-/-/0 0x2017cf/0x20179e/P/-/-/0 0x20177f/0x2017c4/P/-/-/0 0x2017bf/0x201760/P/-/-/0 0x2017cf/0x20179e/P/-/-/0 0x20177f/0x2017c4/P/-/-/0 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 @@ -1,5 +1,40 @@ ; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/noinline-cs-noprobe.perfscript --binary=%S/Inputs/noinline-cs-noprobe.perfbin --output=%t --show-unwinder-output --profile-summary-cold-count=0 | FileCheck %s --check-prefix=CHECK-UNWINDER ; RUN: FileCheck %s --input-file %t +; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/noinline-cs-noprobe.aggperfscript --binary=%S/Inputs/noinline-cs-noprobe.perfbin --output=%t --show-unwinder-output --profile-summary-cold-count=0 | FileCheck %s --check-prefix=CHECK-AGG-UNWINDER +; RUN: FileCheck %s --input-file %t --check-prefix=CHECK-AGG + +; CHECK-AGG:[main:1 @ foo]:108:0 +; CHECK-AGG: 2: 6 +; CHECK-AGG: 3: 6 bar:6 +; CHECK-AGG:[main:1 @ foo:3 @ bar]:100:6 +; CHECK-AGG: 0: 6 +; CHECK-AGG: 1: 6 +; CHECK-AGG: 2: 4 +; CHECK-AGG: 4: 2 +; CHECK-AGG: 5: 6 + +; CHECK-AGG-UNWINDER: Binary(noinline-cs-noprobe.perfbin)'s Range Counter: +; CHECK-AGG-UNWINDER: main:1 @ foo +; CHECK-AGG-UNWINDER: (5ff, 62f): 6 +; CHECK-AGG-UNWINDER: (634, 637): 6 +; CHECK-AGG-UNWINDER: (645, 645): 6 +; CHECK-AGG-UNWINDER: main:1 @ foo:3 @ bar +; CHECK-AGG-UNWINDER: (5b0, 5c8): 2 +; CHECK-AGG-UNWINDER: (5b0, 5d7): 4 +; CHECK-AGG-UNWINDER: (5dc, 5e9): 2 +; CHECK-AGG-UNWINDER: (5e5, 5e9): 4 + +; CHECK-AGG-UNWINDER: Binary(noinline-cs-noprobe.perfbin)'s Branch Counter: +; CHECK-AGG-UNWINDER: main:1 @ foo +; CHECK-AGG-UNWINDER: (62f, 5b0): 6 +; CHECK-AGG-UNWINDER: (637, 645): 6 +; CHECK-AGG-UNWINDER: (645, 5ff): 6 +; CHECK-AGG-UNWINDER: main:1 @ foo:3 @ bar +; CHECK-AGG-UNWINDER: (5c8, 5dc): 4 +; CHECK-AGG-UNWINDER: (5d7, 5e5): 4 +; CHECK-AGG-UNWINDER: (5e9, 634): 6 + + ; CHECK:[main:1 @ foo]:54:0 ; CHECK: 2: 3 @@ -37,7 +72,6 @@ - ; original code: ; clang -O0 -g test.c -o a.out #include diff --git a/llvm/test/tools/llvm-profgen/noinline-cs-pseudoprobe.test b/llvm/test/tools/llvm-profgen/noinline-cs-pseudoprobe.test --- a/llvm/test/tools/llvm-profgen/noinline-cs-pseudoprobe.test +++ b/llvm/test/tools/llvm-profgen/noinline-cs-pseudoprobe.test @@ -1,5 +1,8 @@ ; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/noinline-cs-pseudoprobe.perfscript --binary=%S/Inputs/noinline-cs-pseudoprobe.perfbin --output=%t --show-unwinder-output --profile-summary-cold-count=0 | FileCheck %s --check-prefix=CHECK-UNWINDER ; RUN: FileCheck %s --input-file %t +; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/noinline-cs-pseudoprobe.aggperfscript --binary=%S/Inputs/noinline-cs-pseudoprobe.perfbin --output=%t --show-unwinder-output --profile-summary-cold-count=0 | FileCheck %s --check-prefix=CHECK-UNWINDER +; RUN: FileCheck %s --input-file %t + ; CHECK: [main:2 @ foo]:75:0 ; CHECK-NEXT: 1: 0 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 @@ -61,8 +61,9 @@ enum PerfScriptType { PERF_UNKNOWN = 0, PERF_INVALID = 1, - PERF_LBR = 2, // Only LBR sample - PERF_LBR_STACK = 3, // Hybrid sample including call stack and LBR stack. + PERF_LBR = 2, // Only LBR sample + PERF_LBR_STACK = 3, // Hybrid sample including call stack and LBR stack. + PERF_LBR_STACK_AGG = 4, // Aggregated hybrid sample perf }; // The parsed LBR sample entry. @@ -562,6 +563,13 @@ return false; } + static bool isAggHybridSample(StringRef Line) { + uint64_t Count = 0; + if (Line.getAsInteger(10, Count)) + return false; + return true; + } + // The raw hybird sample is like // e.g. // 4005dc # call stack leaf @@ -574,6 +582,10 @@ // a LBR sample static PerfScriptType checkPerfScriptType(StringRef FileName) { TraceStream TraceIt(FileName); + + if (!TraceIt.isAtEoF() && isAggHybridSample(TraceIt.getCurrentLine())) + return PERF_LBR_STACK_AGG; + uint64_t FrameAddr = 0; while (!TraceIt.isAtEoF()) { int32_t Count = 0; @@ -675,13 +687,27 @@ PerfType = PERF_LBR_STACK; }; // Parse the hybrid sample including the call and LBR line - void parseSample(TraceStream &TraceIt) override; + virtual void parseSample(TraceStream &TraceIt) override; void generateRawProfile() override; -private: +protected: // Unwind the hybrid samples after aggregration void unwindSamples(); void printUnwinderOutput(); + void parseHybridSample(TraceStream &TraceIt, uint64_t Count = 1); +}; + +class AggregatedHybridPerfReader : public HybridPerfReader { +public: + AggregatedHybridPerfReader(cl::list &BinaryFilenames) + : HybridPerfReader(BinaryFilenames) { + PerfType = PERF_LBR_STACK_AGG; + }; + // Parse the hybrid sample including the call and LBR line + void parseSample(TraceStream &TraceIt) override; + +private: + bool parseAggregatedCount(TraceStream &TraceIt, uint64_t &Count); }; } // end namespace sampleprof 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 @@ -285,6 +285,8 @@ std::unique_ptr PerfReader; if (PerfType == PERF_LBR_STACK) { PerfReader.reset(new HybridPerfReader(BinaryFilenames)); + } else if (PerfType == PERF_LBR_STACK_AGG) { + PerfReader.reset(new AggregatedHybridPerfReader(BinaryFilenames)); } else if (PerfType == PERF_LBR) { // TODO: exitWithError("Unsupported perfscript!"); @@ -623,6 +625,10 @@ } void HybridPerfReader::parseSample(TraceStream &TraceIt) { + parseHybridSample(TraceIt); +} + +void HybridPerfReader::parseHybridSample(TraceStream &TraceIt, uint64_t Count) { // The raw hybird sample started with call stack in FILO order and followed // intermediately by LBR sample // e.g. @@ -652,7 +658,7 @@ Sample->CallStack.front() = Sample->LBRStack[0].Target; // Record samples by aggregation Sample->genHashCode(); - AggregatedSamples[Hashable(Sample)]++; + AggregatedSamples[Hashable(Sample)] += Count; } } else { // LBR sample is encoded in single line after stack sample @@ -765,5 +771,22 @@ generateRawProfile(); } +bool AggregatedHybridPerfReader::parseAggregatedCount(TraceStream &TraceIt, + uint64_t &Count) { + if (TraceIt.getCurrentLine().getAsInteger(10, Count)) { + TraceIt.advance(); + return false; + } + TraceIt.advance(); + return true; +} + +void AggregatedHybridPerfReader::parseSample(TraceStream &TraceIt) { + uint64_t Count = 0; + if (!parseAggregatedCount(TraceIt, Count)) + return; + parseHybridSample(TraceIt, Count); +} + } // end namespace sampleprof } // end namespace llvm diff --git a/llvm/tools/llvm-profgen/ProfileGenerator.cpp b/llvm/tools/llvm-profgen/ProfileGenerator.cpp --- a/llvm/tools/llvm-profgen/ProfileGenerator.cpp +++ b/llvm/tools/llvm-profgen/ProfileGenerator.cpp @@ -74,7 +74,7 @@ ProfileGenerator::create(const BinarySampleCounterMap &BinarySampleCounters, enum PerfScriptType SampleType) { std::unique_ptr ProfileGenerator; - if (SampleType == PERF_LBR_STACK) { + if (SampleType == PERF_LBR_STACK || SampleType == PERF_LBR_STACK_AGG) { if (usePseudoProbes(BinarySampleCounters)) { ProfileGenerator.reset( new PseudoProbeCSProfileGenerator(BinarySampleCounters));