[InstrProf][llvm-profdata] Dump profile correlation data as YAML
authorEllis Hoag <ellis.sparky.hoag@gmail.com>
Fri, 7 Oct 2022 16:27:40 +0000 (09:27 -0700)
committerEllis Hoag <ellis.sparky.hoag@gmail.com>
Fri, 7 Oct 2022 16:47:25 +0000 (09:47 -0700)
Change the behavior of the `llvm-profdata show --debug-info=` command to dump a YAML file when using debug info correlation since it provides more information in a parseable format.

Reviewed By: yozhu, phosek

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

compiler-rt/test/profile/Linux/instrprof-show-debug-info-correlation.c
llvm/include/llvm/ProfileData/InstrProfCorrelator.h
llvm/lib/ProfileData/InstrProfCorrelator.cpp
llvm/tools/llvm-profdata/llvm-profdata.cpp

index d0ab3ac..a7ea54f 100644 (file)
@@ -1,16 +1,41 @@
 // RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %s
 // RUN: llvm-profdata show --debug-info=%t --detailed-summary --show-prof-sym-list | FileCheck %s
+// RUN: llvm-profdata show --debug-info=%t --output-format=yaml | FileCheck %s --match-full-lines --check-prefix YAML
 
 // RUN: %clang_pgogen -o %t.no.dbg -mllvm --debug-info-correlate -mllvm --disable-vp=true %s
 // RUN: not llvm-profdata show --debug-info=%t.no.dbg 2>&1 | FileCheck %s --check-prefix NO-DBG
 // NO-DBG: unable to correlate profile: could not find any profile metadata in debug info
 
+// CHECK: a
+// YAML: Probes:
+// YAML:   - Function Name:   a
+// YAML:     Linkage Name:    a
+// YAML:     CFG Hash:        0x[[#%.1X,HASH:]]
+// YAML:     Counter Offset:  0x0
+// YAML:     Num Counters:    1
+// YAML:     File:            [[FILE:'.*']]
+// YAML:     Line:            [[@LINE+1]]
 void a() {}
-void b() {}
-int main() { return 0; }
 
-// CHECK: a
 // CHECK: b
+// YAML:   - Function Name:   b
+// YAML:     Linkage Name:    b
+// YAML:     CFG Hash:        0x[[#%.1X,HASH:]]
+// YAML:     Counter Offset:  0x8
+// YAML:     Num Counters:    1
+// YAML:     File:            [[FILE:'.*']]
+// YAML:     Line:            [[@LINE+1]]
+void b() {}
+
 // CHECK: main
+// YAML:   - Function Name:   main
+// YAML:     Linkage Name:    main
+// YAML:     CFG Hash:        0x[[#%.1X,HASH:]]
+// YAML:     Counter Offset:  0x10
+// YAML:     Num Counters:    1
+// YAML:     File:            [[FILE]]
+// YAML:     Line:            [[@LINE+1]]
+int main() { return 0; }
+
 // CHECK: Counters section size: 0x18 bytes
 // CHECK: Found 3 functions
index 79995c8..0efd4ea 100644 (file)
@@ -16,6 +16,7 @@
 #include "llvm/ProfileData/InstrProf.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/YAMLTraits.h"
 #include <vector>
 
 namespace llvm {
@@ -36,6 +37,9 @@ public:
   /// to their functions.
   virtual Error correlateProfileData() = 0;
 
+  /// Process debug info and dump the correlation data.
+  virtual Error dumpYaml(raw_ostream &OS) = 0;
+
   /// Return the number of ProfileData elements.
   llvm::Optional<size_t> getDataSize() const;
 
@@ -69,7 +73,7 @@ protected:
     /// True if target and host have different endian orders.
     bool ShouldSwapBytes;
   };
-  const std::unique_ptr<InstrProfCorrelator::Context> Ctx;
+  const std::unique_ptr<Context> Ctx;
 
   InstrProfCorrelator(InstrProfCorrelatorKind K, std::unique_ptr<Context> Ctx)
       : Ctx(std::move(Ctx)), Kind(K) {}
@@ -77,6 +81,24 @@ protected:
   std::string Names;
   std::vector<std::string> NamesVec;
 
+  struct Probe {
+    std::string FunctionName;
+    Optional<std::string> LinkageName;
+    yaml::Hex64 CFGHash;
+    yaml::Hex64 CounterOffset;
+    uint32_t NumCounters;
+    Optional<std::string> FilePath;
+    Optional<int> LineNumber;
+  };
+
+  struct CorrelationData {
+    std::vector<Probe> Probes;
+  };
+
+  friend struct yaml::MappingTraits<Probe>;
+  friend struct yaml::SequenceElementTraits<Probe>;
+  friend struct yaml::MappingTraits<CorrelationData>;
+
 private:
   static llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
   get(std::unique_ptr<MemoryBuffer> Buffer);
@@ -109,7 +131,10 @@ protected:
   std::vector<RawInstrProf::ProfileData<IntPtrT>> Data;
 
   Error correlateProfileData() override;
-  virtual void correlateProfileDataImpl() = 0;
+  virtual void correlateProfileDataImpl(
+      InstrProfCorrelator::CorrelationData *Data = nullptr) = 0;
+
+  Error dumpYaml(raw_ostream &OS) override;
 
   void addProbe(StringRef FunctionName, uint64_t CFGHash, IntPtrT CounterOffset,
                 IntPtrT FunctionPtr, uint32_t NumCounters);
@@ -171,7 +196,8 @@ private:
   ///       NULL
   ///     NULL
   /// \endcode
-  void correlateProfileDataImpl() override;
+  void correlateProfileDataImpl(
+      InstrProfCorrelator::CorrelationData *Data = nullptr) override;
 };
 
 } // end namespace llvm
index 4b8212c..6c460a5 100644 (file)
@@ -155,6 +155,42 @@ Error InstrProfCorrelatorImpl<IntPtrT>::correlateProfileData() {
   return Result;
 }
 
+template <> struct yaml::MappingTraits<InstrProfCorrelator::CorrelationData> {
+  static void mapping(yaml::IO &io,
+                      InstrProfCorrelator::CorrelationData &Data) {
+    io.mapRequired("Probes", Data.Probes);
+  }
+};
+
+template <> struct yaml::MappingTraits<InstrProfCorrelator::Probe> {
+  static void mapping(yaml::IO &io, InstrProfCorrelator::Probe &P) {
+    io.mapRequired("Function Name", P.FunctionName);
+    io.mapOptional("Linkage Name", P.LinkageName);
+    io.mapRequired("CFG Hash", P.CFGHash);
+    io.mapRequired("Counter Offset", P.CounterOffset);
+    io.mapRequired("Num Counters", P.NumCounters);
+    io.mapOptional("File", P.FilePath);
+    io.mapOptional("Line", P.LineNumber);
+  }
+};
+
+template <> struct yaml::SequenceElementTraits<InstrProfCorrelator::Probe> {
+  static const bool flow = false;
+};
+
+template <class IntPtrT>
+Error InstrProfCorrelatorImpl<IntPtrT>::dumpYaml(raw_ostream &OS) {
+  InstrProfCorrelator::CorrelationData Data;
+  correlateProfileDataImpl(&Data);
+  if (Data.Probes.empty())
+    return make_error<InstrProfError>(
+        instrprof_error::unable_to_correlate_profile,
+        "could not find any profile metadata in debug info");
+  yaml::Output YamlOS(OS);
+  YamlOS << Data;
+  return Error::success();
+}
+
 template <class IntPtrT>
 void InstrProfCorrelatorImpl<IntPtrT>::addProbe(StringRef FunctionName,
                                                 uint64_t CFGHash,
@@ -222,15 +258,16 @@ bool DwarfInstrProfCorrelator<IntPtrT>::isDIEOfProbe(const DWARFDie &Die) {
 }
 
 template <class IntPtrT>
-void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl() {
+void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
+    InstrProfCorrelator::CorrelationData *Data) {
   auto maybeAddProbe = [&](DWARFDie Die) {
     if (!isDIEOfProbe(Die))
       return;
     Optional<const char *> FunctionName;
     Optional<uint64_t> CFGHash;
     Optional<uint64_t> CounterPtr = getLocation(Die);
-    auto FunctionPtr =
-        dwarf::toAddress(Die.getParent().find(dwarf::DW_AT_low_pc));
+    auto FnDie = Die.getParent();
+    auto FunctionPtr = dwarf::toAddress(FnDie.find(dwarf::DW_AT_low_pc));
     Optional<uint64_t> NumCounters;
     for (const DWARFDie &Child : Die.children()) {
       if (Child.getTag() != dwarf::DW_TAG_LLVM_annotation)
@@ -283,8 +320,26 @@ void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl() {
                         << "\n");
       LLVM_DEBUG(Die.dump(dbgs()));
     }
-    this->addProbe(*FunctionName, *CFGHash, *CounterPtr - CountersStart,
-                   FunctionPtr.value_or(0), *NumCounters);
+    IntPtrT CounterOffset = *CounterPtr - CountersStart;
+    if (Data) {
+      InstrProfCorrelator::Probe P;
+      P.FunctionName = *FunctionName;
+      if (auto Name = FnDie.getName(DINameKind::LinkageName))
+        P.LinkageName = Name;
+      P.CFGHash = *CFGHash;
+      P.CounterOffset = CounterOffset;
+      P.NumCounters = *NumCounters;
+      auto FilePath = FnDie.getDeclFile(
+          DILineInfoSpecifier::FileLineInfoKind::RelativeFilePath);
+      if (!FilePath.empty())
+        P.FilePath = FilePath;
+      if (auto LineNumber = FnDie.getDeclLine())
+        P.LineNumber = LineNumber;
+      Data->Probes.push_back(P);
+    } else {
+      this->addProbe(*FunctionName, *CFGHash, CounterOffset,
+                     FunctionPtr.value_or(0), *NumCounters);
+    }
   };
   for (auto &CU : DICtx->normal_units())
     for (const auto &Entry : CU->dies())
index 3fe91f4..95019c9 100644 (file)
@@ -2703,11 +2703,14 @@ static int showDebugInfoCorrelation(const std::string &Filename,
                                     OutputFormat OFormat, raw_fd_ostream &OS) {
   if (OFormat == OutputFormat::Json)
     exitWithError("JSON output is not supported for debug info correlation");
-  if (OFormat == OutputFormat::Yaml)
-    exitWithError("YAML output is not supported for debug info correlation");
   std::unique_ptr<InstrProfCorrelator> Correlator;
   if (auto Err = InstrProfCorrelator::get(Filename).moveInto(Correlator))
     exitWithError(std::move(Err), Filename);
+  if (OFormat == OutputFormat::Yaml) {
+    if (auto Err = Correlator->dumpYaml(OS))
+      exitWithError(std::move(Err), Filename);
+    return 0;
+  }
 
   if (auto Err = Correlator->correlateProfileData())
     exitWithError(std::move(Err), Filename);