[llvm] 937924e - [llvm-profgen] Read sample profiles for post-processing.

Hongtao Yu via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 30 13:51:22 PDT 2022


Author: Hongtao Yu
Date: 2022-03-30T13:51:16-07:00
New Revision: 937924eb4956ac4a85424cb495f91f34d42eb02a

URL: https://github.com/llvm/llvm-project/commit/937924eb4956ac4a85424cb495f91f34d42eb02a
DIFF: https://github.com/llvm/llvm-project/commit/937924eb4956ac4a85424cb495f91f34d42eb02a.diff

LOG: [llvm-profgen] Read sample profiles for post-processing.

Sometimes we would like to run post-processing repeatedly on the original sample profile for tuning. In order to avoid regenerating the original profile from scratch every time, this change adds the support of reading in the original profile (called symbolized profile) and running the post-processor on it.

Reviewed By: wenlei

Differential Revision: https://reviews.llvm.org/D121655

Added: 
    llvm/test/tools/llvm-profgen/cold-profile-trimming-symbolized.test
    llvm/test/tools/llvm-profgen/cs-preinline-sample-profile.test

Modified: 
    llvm/tools/llvm-profgen/ProfileGenerator.cpp
    llvm/tools/llvm-profgen/ProfileGenerator.h
    llvm/tools/llvm-profgen/llvm-profgen.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-profgen/cold-profile-trimming-symbolized.test b/llvm/test/tools/llvm-profgen/cold-profile-trimming-symbolized.test
new file mode 100644
index 0000000000000..77faec6bcf15b
--- /dev/null
+++ b/llvm/test/tools/llvm-profgen/cold-profile-trimming-symbolized.test
@@ -0,0 +1,63 @@
+; RUN: llvm-profgen --format=text --unsymbolized-profile=%S/Inputs/cold-profile-trimming.raw.prof --binary=%S/Inputs/inline-noprobe2.perfbin --output=%t1 --use-offset=0
+; RUN: llvm-profgen --format=text --llvm-sample-profile=%t1 --binary=%S/Inputs/inline-noprobe2.perfbin --output=%t2 --trim-cold-profile=1 --profile-summary-cold-count=1000
+; RUN: FileCheck %s --input-file %t2 --check-prefix=CHECK-TRIM
+
+
+;CHECK-TRIM: partition_pivot_last:5187:7
+;CHECK-TRIM: partition_pivot_first:3010:5
+;CHECK-TRIM-NOT: quick_sort:903:25
+;CHECK-TRIM-NOT: main:820:0
+
+; original code:
+; clang -O3 -g -fno-optimize-sibling-calls -fdebug-info-for-profiling qsort.c -o a.out
+#include <stdio.h>
+#include <stdlib.h>
+
+void swap(int *a, int *b) {
+	int t = *a;
+	*a = *b;
+	*b = t;
+}
+
+int partition_pivot_last(int* array, int low, int high) {
+	int pivot = array[high];
+	int i = low - 1;
+	for (int j = low; j < high; j++)
+		if (array[j] < pivot)
+			swap(&array[++i], &array[j]);
+	swap(&array[i + 1], &array[high]);
+	return (i + 1);
+}
+
+int partition_pivot_first(int* array, int low, int high) {
+	int pivot = array[low];
+	int i = low + 1;
+	for (int j = low + 1; j <= high; j++)
+		if (array[j] < pivot) { if (j != i) swap(&array[i], &array[j]); i++;}
+	swap(&array[i - 1], &array[low]);
+	return i - 1;
+}
+
+void quick_sort(int* array, int low, int high, int (*partition_func)(int *, int, int)) {
+	if (low < high) {
+		int pi = (*partition_func)(array, low, high);
+		quick_sort(array, low, pi - 1, partition_func);
+		quick_sort(array, pi + 1, high, partition_func);
+	}
+}
+
+int main() {
+	const int size = 200;
+	int sum = 0;
+	int *array = malloc(size * sizeof(int));
+	for(int i = 0; i < 100 * 1000; i++) {
+		for(int j = 0; j < size; j++)
+			array[j] = j % 10 ? rand() % size: j;
+		int (*fptr)(int *, int, int) = i % 3 ? partition_pivot_last : partition_pivot_first;
+		quick_sort(array, 0, size - 1, fptr);
+		sum += array[i % size];
+	}
+	printf("sum=%d\n", sum);
+
+	return 0;
+}

diff  --git a/llvm/test/tools/llvm-profgen/cs-preinline-sample-profile.test b/llvm/test/tools/llvm-profgen/cs-preinline-sample-profile.test
new file mode 100644
index 0000000000000..b5aeb70968e05
--- /dev/null
+++ b/llvm/test/tools/llvm-profgen/cs-preinline-sample-profile.test
@@ -0,0 +1,43 @@
+; Test default llvm-profgen with preinline off
+; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/inline-cs-noprobe.perfscript --binary=%S/Inputs/inline-cs-noprobe.perfbin --csspgo-preinliner=0 --gen-cs-nested-profile=0 --output=%t1
+
+; Test llvm-profgen with preinliner on will merge not inlinable profile into base profile.
+; RUN: llvm-profgen --format=text --llvm-sample-profile=%t1 --binary=%S/Inputs/inline-cs-noprobe.perfbin --csspgo-preinliner=1 --gen-cs-nested-profile=0 --sample-profile-hot-inline-threshold=3000 --sample-profile-cold-inline-threshold=45 --output=%t2
+; RUN: FileCheck %s --input-file %t2 --check-prefix=CHECK-PREINL
+
+; Test default llvm-profgen with preinline off
+; RUN: llvm-profgen --format=text --perfscript=%S/Inputs/inline-cs-pseudoprobe.perfscript --binary=%S/Inputs/inline-cs-pseudoprobe.perfbin --csspgo-preinliner=0 --gen-cs-nested-profile=0 --output=%t3
+
+; Test llvm-profgen with preinliner on will merge not inlinable profile into base profile.
+; RUN: llvm-profgen --format=text --llvm-sample-profile=%t3 --binary=%S/Inputs/inline-cs-pseudoprobe.perfbin --csspgo-preinliner=1 --gen-cs-nested-profile=0 --sample-profile-hot-inline-threshold=3000 --sample-profile-cold-inline-threshold=45 --output=%t4
+; RUN: FileCheck %s --input-file %t4 --check-prefix=CHECK-PREINL-PROBE
+
+; CHECK-PREINL:     [foo]:309:0
+; CHECK-PREINL-NEXT: 2.1: 14
+; CHECK-PREINL-NEXT: 3: 15
+; CHECK-PREINL-NEXT: 3.1: 14 bar:14
+; CHECK-PREINL-NEXT: 3.2: 1
+; CHECK-PREINL-NEXT: 65526: 14
+; CHECK-PREINL-NEXT: !Attributes: 1
+; CHECK-PREINL-NEXT:[foo:3.1 @ bar]:84:0
+; CHECK-PREINL-NEXT: 1: 14
+; CHECK-PREINL-NEXT: !Attributes: 3
+
+
+; CHECK-PREINL-PROBE:     [foo]:74:0
+; CHECK-PREINL-PROBE-NEXT: 1: 0
+; CHECK-PREINL-PROBE-NEXT: 2: 15
+; CHECK-PREINL-PROBE-NEXT: 3: 15
+; CHECK-PREINL-PROBE-NEXT: 4: 14
+; CHECK-PREINL-PROBE-NEXT: 5: 1
+; CHECK-PREINL-PROBE-NEXT: 6: 15
+; CHECK-PREINL-PROBE-NEXT: 7: 0
+; CHECK-PREINL-PROBE-NEXT: 8: 14 bar:14
+; CHECK-PREINL-PROBE-NEXT: 9: 0
+; CHECK-PREINL-PROBE-NEXT: !CFGChecksum: 563088904013236
+; CHECK-PREINL-PROBE-NEXT: !Attributes: 1
+; CHECK-PREINL-PROBE-NEXT:[foo:8 @ bar]:28:14
+; CHECK-PREINL-PROBE-NEXT: 1: 14
+; CHECK-PREINL-PROBE-NEXT: 4: 14
+; CHECK-PREINL-PROBE-NEXT: !CFGChecksum: 72617220756
+; CHECK-PREINL-PROBE-NEXT: !Attributes: 3

diff  --git a/llvm/tools/llvm-profgen/ProfileGenerator.cpp b/llvm/tools/llvm-profgen/ProfileGenerator.cpp
index a3366bb3ce6fa..c497dff752d17 100644
--- a/llvm/tools/llvm-profgen/ProfileGenerator.cpp
+++ b/llvm/tools/llvm-profgen/ProfileGenerator.cpp
@@ -7,12 +7,14 @@
 //===----------------------------------------------------------------------===//
 #include "ProfileGenerator.h"
 #include "ErrorHandling.h"
+#include "PerfReader.h"
 #include "ProfiledBinary.h"
 #include "llvm/DebugInfo/Symbolize/SymbolizableModule.h"
 #include "llvm/ProfileData/ProfileCommon.h"
 #include <algorithm>
 #include <float.h>
 #include <unordered_set>
+#include <utility>
 
 cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
                                     cl::Required,
@@ -109,7 +111,7 @@ bool ProfileGeneratorBase::UseFSDiscriminator = false;
 
 std::unique_ptr<ProfileGeneratorBase>
 ProfileGeneratorBase::create(ProfiledBinary *Binary,
-                             const ContextSampleCounterMap &SampleCounters,
+                             const ContextSampleCounterMap *SampleCounters,
                              bool ProfileIsCSFlat) {
   std::unique_ptr<ProfileGeneratorBase> Generator;
   if (ProfileIsCSFlat) {
@@ -125,6 +127,24 @@ ProfileGeneratorBase::create(ProfiledBinary *Binary,
   return Generator;
 }
 
+std::unique_ptr<ProfileGeneratorBase>
+ProfileGeneratorBase::create(ProfiledBinary *Binary,
+                             const SampleProfileMap &&Profiles,
+                             bool ProfileIsCSFlat) {
+  std::unique_ptr<ProfileGeneratorBase> Generator;
+  if (ProfileIsCSFlat) {
+    if (Binary->useFSDiscriminator())
+      exitWithError("FS discriminator is not supported in CS profile.");
+    Generator.reset(new CSProfileGenerator(Binary, std::move(Profiles)));
+  } else {
+    Generator.reset(new ProfileGenerator(Binary, std::move(Profiles)));
+  }
+  ProfileGeneratorBase::UseFSDiscriminator = Binary->useFSDiscriminator();
+  FunctionSamples::ProfileIsFS = Binary->useFSDiscriminator();
+
+  return Generator;
+}
+
 void ProfileGeneratorBase::write(std::unique_ptr<SampleProfileWriter> Writer,
                                  SampleProfileMap &ProfileMap) {
   // Populate profile symbol list if extended binary format is used.
@@ -372,31 +392,39 @@ void ProfileGeneratorBase::updateTotalSamples() {
 
 void ProfileGeneratorBase::collectProfiledFunctions() {
   std::unordered_set<const BinaryFunction *> ProfiledFunctions;
-  // Go through all the stacks, ranges and branches in sample counters, use the
-  // start of the range to look up the function it belongs and record the
-  // function.
-  for (const auto &CI : SampleCounters) {
-    if (const auto *CtxKey = dyn_cast<AddrBasedCtxKey>(CI.first.getPtr())) {
-      for (auto Addr : CtxKey->Context) {
-        if (FuncRange *FRange = Binary->findFuncRangeForOffset(
-                Binary->virtualAddrToOffset(Addr)))
+  if (SampleCounters) {
+    // Go through all the stacks, ranges and branches in sample counters, use
+    // the start of the range to look up the function it belongs and record the
+    // function.
+    for (const auto &CI : *SampleCounters) {
+      if (const auto *CtxKey = dyn_cast<AddrBasedCtxKey>(CI.first.getPtr())) {
+        for (auto Addr : CtxKey->Context) {
+          if (FuncRange *FRange = Binary->findFuncRangeForOffset(
+                  Binary->virtualAddrToOffset(Addr)))
+            ProfiledFunctions.insert(FRange->Func);
+        }
+      }
+
+      for (auto Item : CI.second.RangeCounter) {
+        uint64_t StartOffset = Item.first.first;
+        if (FuncRange *FRange = Binary->findFuncRangeForOffset(StartOffset))
           ProfiledFunctions.insert(FRange->Func);
       }
-    }
 
-    for (auto Item : CI.second.RangeCounter) {
-      uint64_t StartOffset = Item.first.first;
-      if (FuncRange *FRange = Binary->findFuncRangeForOffset(StartOffset))
-        ProfiledFunctions.insert(FRange->Func);
+      for (auto Item : CI.second.BranchCounter) {
+        uint64_t SourceOffset = Item.first.first;
+        uint64_t TargetOffset = Item.first.first;
+        if (FuncRange *FRange = Binary->findFuncRangeForOffset(SourceOffset))
+          ProfiledFunctions.insert(FRange->Func);
+        if (FuncRange *FRange = Binary->findFuncRangeForOffset(TargetOffset))
+          ProfiledFunctions.insert(FRange->Func);
+      }
     }
-
-    for (auto Item : CI.second.BranchCounter) {
-      uint64_t SourceOffset = Item.first.first;
-      uint64_t TargetOffset = Item.first.first;
-      if (FuncRange *FRange = Binary->findFuncRangeForOffset(SourceOffset))
-        ProfiledFunctions.insert(FRange->Func);
-      if (FuncRange *FRange = Binary->findFuncRangeForOffset(TargetOffset))
-        ProfiledFunctions.insert(FRange->Func);
+  } else {
+    // This is for the case the input is a llvm sample profile.
+    for (const auto &FS : ProfileMap) {
+      if (auto *Func = Binary->getBinaryFunction(FS.first.getName()))
+        ProfiledFunctions.insert(Func);
     }
   }
 
@@ -416,11 +444,18 @@ ProfileGenerator::getTopLevelFunctionProfile(StringRef FuncName) {
 
 void ProfileGenerator::generateProfile() {
   collectProfiledFunctions();
-  if (Binary->usePseudoProbes()) {
-    generateProbeBasedProfile();
-  } else {
-    generateLineNumBasedProfile();
+
+  if (Binary->usePseudoProbes())
+    Binary->decodePseudoProbe();
+
+  if (SampleCounters) {
+    if (Binary->usePseudoProbes()) {
+      generateProbeBasedProfile();
+    } else {
+      generateLineNumBasedProfile();
+    }
   }
+
   postProcessProfiles();
 }
 
@@ -448,9 +483,9 @@ void ProfileGenerator::trimColdProfiles(const SampleProfileMap &Profiles,
 }
 
 void ProfileGenerator::generateLineNumBasedProfile() {
-  assert(SampleCounters.size() == 1 &&
+  assert(SampleCounters->size() == 1 &&
          "Must have one entry for profile generation.");
-  const SampleCounter &SC = SampleCounters.begin()->second;
+  const SampleCounter &SC = SampleCounters->begin()->second;
   // Fill in function body samples
   populateBodySamplesForAllFunctions(SC.RangeCounter);
   // Fill in boundary sample counts as well as call site samples for calls
@@ -460,12 +495,11 @@ void ProfileGenerator::generateLineNumBasedProfile() {
 }
 
 void ProfileGenerator::generateProbeBasedProfile() {
-  assert(SampleCounters.size() == 1 &&
+  assert(SampleCounters->size() == 1 &&
          "Must have one entry for profile generation.");
-  Binary->decodePseudoProbe();
   // Enable pseudo probe functionalities in SampleProf
   FunctionSamples::ProfileIsProbeBased = true;
-  const SampleCounter &SC = SampleCounters.begin()->second;
+  const SampleCounter &SC = SampleCounters->begin()->second;
   // Fill in function body samples
   populateBodySamplesWithProbesForAllFunctions(SC.RangeCounter);
   // Fill in boundary sample counts as well as call site samples for calls
@@ -687,10 +721,15 @@ void CSProfileGenerator::generateProfile() {
 
   collectProfiledFunctions();
 
-  if (Binary->usePseudoProbes()) {
-    generateProbeBasedProfile();
-  } else {
-    generateLineNumBasedProfile();
+  if (Binary->usePseudoProbes())
+    Binary->decodePseudoProbe();
+
+  if (SampleCounters) {
+    if (Binary->usePseudoProbes()) {
+      generateProbeBasedProfile();
+    } else {
+      generateLineNumBasedProfile();
+    }
   }
 
   if (Binary->getTrackFuncContextSize())
@@ -709,7 +748,7 @@ void CSProfileGenerator::computeSizeForProfiledFunctions() {
 }
 
 void CSProfileGenerator::generateLineNumBasedProfile() {
-  for (const auto &CI : SampleCounters) {
+  for (const auto &CI : *SampleCounters) {
     const auto *CtxKey = cast<StringBasedCtxKey>(CI.first.getPtr());
 
     // Get or create function profile for the range
@@ -967,10 +1006,9 @@ extractPrefixContextStack(SampleContextFrameVector &ContextStack,
 }
 
 void CSProfileGenerator::generateProbeBasedProfile() {
-  Binary->decodePseudoProbe();
   // Enable pseudo probe functionalities in SampleProf
   FunctionSamples::ProfileIsProbeBased = true;
-  for (const auto &CI : SampleCounters) {
+  for (const auto &CI : *SampleCounters) {
     const AddrBasedCtxKey *CtxKey =
         dyn_cast<AddrBasedCtxKey>(CI.first.getPtr());
     SampleContextFrameVector ContextStack;

diff  --git a/llvm/tools/llvm-profgen/ProfileGenerator.h b/llvm/tools/llvm-profgen/ProfileGenerator.h
index 9660d8b40c956..956bed38e3000 100644
--- a/llvm/tools/llvm-profgen/ProfileGenerator.h
+++ b/llvm/tools/llvm-profgen/ProfileGenerator.h
@@ -33,11 +33,18 @@ class ProfileGeneratorBase {
 
 public:
   ProfileGeneratorBase(ProfiledBinary *Binary,
-                       const ContextSampleCounterMap &Counters)
+                       const ContextSampleCounterMap *Counters)
       : Binary(Binary), SampleCounters(Counters){};
+  ProfileGeneratorBase(ProfiledBinary *Binary,
+                       const SampleProfileMap &&Profiles)
+      : Binary(Binary), ProfileMap(std::move(Profiles)){};
+
   virtual ~ProfileGeneratorBase() = default;
   static std::unique_ptr<ProfileGeneratorBase>
-  create(ProfiledBinary *Binary, const ContextSampleCounterMap &SampleCounters,
+  create(ProfiledBinary *Binary, const ContextSampleCounterMap *Counters,
+         bool ProfileIsCSFlat);
+  static std::unique_ptr<ProfileGeneratorBase>
+  create(ProfiledBinary *Binary, const SampleProfileMap &&ProfileMap,
          bool ProfileIsCSFlat);
   virtual void generateProfile() = 0;
   void write();
@@ -113,20 +120,22 @@ class ProfileGeneratorBase {
 
   uint64_t ColdCountThreshold;
 
+  ProfiledBinary *Binary = nullptr;
+
   // Used by SampleProfileWriter
   SampleProfileMap ProfileMap;
 
-  ProfiledBinary *Binary = nullptr;
-
-  const ContextSampleCounterMap &SampleCounters;
+  const ContextSampleCounterMap *SampleCounters = nullptr;
 };
 
 class ProfileGenerator : public ProfileGeneratorBase {
 
 public:
   ProfileGenerator(ProfiledBinary *Binary,
-                   const ContextSampleCounterMap &Counters)
+                   const ContextSampleCounterMap *Counters)
       : ProfileGeneratorBase(Binary, Counters){};
+  ProfileGenerator(ProfiledBinary *Binary, const SampleProfileMap &&Profiles)
+      : ProfileGeneratorBase(Binary, std::move(Profiles)){};
   void generateProfile() override;
 
 private:
@@ -143,9 +152,10 @@ class ProfileGenerator : public ProfileGeneratorBase {
   void populateBodySamplesForAllFunctions(const RangeSample &RangeCounter);
   void
   populateBoundarySamplesForAllFunctions(const BranchSample &BranchCounters);
-  void populateBodySamplesWithProbesForAllFunctions(const RangeSample &RangeCounter);
   void
-  populateBoundarySamplesWithProbesForAllFunctions(const BranchSample &BranchCounters);
+  populateBodySamplesWithProbesForAllFunctions(const RangeSample &RangeCounter);
+  void populateBoundarySamplesWithProbesForAllFunctions(
+      const BranchSample &BranchCounters);
   void postProcessProfiles();
   void trimColdProfiles(const SampleProfileMap &Profiles,
                         uint64_t ColdCntThreshold);
@@ -154,9 +164,10 @@ class ProfileGenerator : public ProfileGeneratorBase {
 class CSProfileGenerator : public ProfileGeneratorBase {
 public:
   CSProfileGenerator(ProfiledBinary *Binary,
-                     const ContextSampleCounterMap &Counters)
+                     const ContextSampleCounterMap *Counters)
       : ProfileGeneratorBase(Binary, Counters){};
-
+  CSProfileGenerator(ProfiledBinary *Binary, const SampleProfileMap &&Profiles)
+      : ProfileGeneratorBase(Binary, std::move(Profiles)){};
   void generateProfile() override;
 
   // Trim the context stack at a given depth.

diff  --git a/llvm/tools/llvm-profgen/llvm-profgen.cpp b/llvm/tools/llvm-profgen/llvm-profgen.cpp
index e26b924e2ab0b..67444af5f232a 100644
--- a/llvm/tools/llvm-profgen/llvm-profgen.cpp
+++ b/llvm/tools/llvm-profgen/llvm-profgen.cpp
@@ -49,6 +49,12 @@ static cl::opt<std::string> UnsymbolizedProfFilename(
 static cl::alias UPA("up", cl::desc("Alias for --unsymbolized-profile"),
                      cl::aliasopt(UnsymbolizedProfFilename));
 
+static cl::opt<std::string>
+    SampleProfFilename("llvm-sample-profile",
+                       cl::value_desc("llvm sample profile"), cl::ZeroOrMore,
+                       cl::desc("Path of the LLVM sample profile"),
+                       cl::cat(ProfGenCategory));
+
 static cl::opt<std::string>
     BinaryPath("binary", cl::value_desc("binary"), cl::Required,
                cl::desc("Path of profiled executable binary."),
@@ -76,7 +82,9 @@ static void validateCommandLine() {
     uint16_t HasPerfScript = PerfScriptFilename.getNumOccurrences();
     uint16_t HasUnsymbolizedProfile =
         UnsymbolizedProfFilename.getNumOccurrences();
-    uint16_t S = HasPerfData + HasPerfScript + HasUnsymbolizedProfile;
+    uint16_t HasSampleProfile = SampleProfFilename.getNumOccurrences();
+    uint16_t S =
+        HasPerfData + HasPerfScript + HasUnsymbolizedProfile + HasSampleProfile;
     if (S != 1) {
       std::string Msg =
           S > 1
@@ -97,6 +105,7 @@ static void validateCommandLine() {
     CheckFileExists(HasPerfData, PerfDataFilename);
     CheckFileExists(HasPerfScript, PerfScriptFilename);
     CheckFileExists(HasUnsymbolizedProfile, UnsymbolizedProfFilename);
+    CheckFileExists(HasSampleProfile, SampleProfFilename);
   }
 
   if (!llvm::sys::fs::exists(BinaryPath)) {
@@ -146,20 +155,34 @@ int main(int argc, const char *argv[]) {
   if (ShowDisassemblyOnly)
     return EXIT_SUCCESS;
 
-  PerfInputFile PerfFile = getPerfInputFile();
-  std::unique_ptr<PerfReaderBase> Reader =
-      PerfReaderBase::create(Binary.get(), PerfFile);
-  // Parse perf events and samples
-  Reader->parsePerfTraces();
-
-  if (SkipSymbolization)
-    return EXIT_SUCCESS;
-
-  std::unique_ptr<ProfileGeneratorBase> Generator =
-      ProfileGeneratorBase::create(Binary.get(), Reader->getSampleCounters(),
-                                   Reader->profileIsCSFlat());
-  Generator->generateProfile();
-  Generator->write();
+  if (SampleProfFilename.getNumOccurrences()) {
+    LLVMContext Context;
+    auto ReaderOrErr = SampleProfileReader::create(SampleProfFilename, Context);
+    std::unique_ptr<sampleprof::SampleProfileReader> Reader =
+        std::move(ReaderOrErr.get());
+    Reader->read();
+    std::unique_ptr<ProfileGeneratorBase> Generator =
+        ProfileGeneratorBase::create(Binary.get(),
+                                     std::move(Reader->getProfiles()),
+                                     Reader->profileIsCSFlat());
+    Generator->generateProfile();
+    Generator->write();
+  } else {
+    PerfInputFile PerfFile = getPerfInputFile();
+    std::unique_ptr<PerfReaderBase> Reader =
+        PerfReaderBase::create(Binary.get(), PerfFile);
+    // Parse perf events and samples
+    Reader->parsePerfTraces();
+
+    if (SkipSymbolization)
+      return EXIT_SUCCESS;
+
+    std::unique_ptr<ProfileGeneratorBase> Generator =
+        ProfileGeneratorBase::create(Binary.get(), &Reader->getSampleCounters(),
+                                     Reader->profileIsCSFlat());
+    Generator->generateProfile();
+    Generator->write();
+  }
 
   return EXIT_SUCCESS;
 }


        


More information about the llvm-commits mailing list