[llvm] 451f3fc - [DwarfDump] Add new set of line-table-related statistics to llvm-dwarfdump (#93289)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 13 09:15:36 PDT 2024


Author: Stephen Tozer
Date: 2024-06-13T17:15:31+01:00
New Revision: 451f3fcffdeb95db8a42b1403bdf9d95dda0e6d0

URL: https://github.com/llvm/llvm-project/commit/451f3fcffdeb95db8a42b1403bdf9d95dda0e6d0
DIFF: https://github.com/llvm/llvm-project/commit/451f3fcffdeb95db8a42b1403bdf9d95dda0e6d0.diff

LOG: [DwarfDump] Add new set of line-table-related statistics to llvm-dwarfdump (#93289)

This patch adds a new set of statistics to llvm-dwarfdump that provide
additional information about .debug_line regarding the number of bytes
covered by the line table (and how many of those are covered by line 0
entries), and the number of entries within the table and how many of
those are is_stmt, unique, or unique and non-line-0 (where "uniqueness"
is based on file, line, and column only).

Collectively these give a little more insight into the state of debug
line information, rather than variables (as most of the dwarfdump
statistics are currently oriented towards). I've added all of the stats
that were useful to some degree, but I think the most generally useful
stat is "unique line entries", since it gives the most straightforward
indication of regressions, i.e. when the number goes down it means that
fewer source lines are reachable in the program.

Added: 
    

Modified: 
    llvm/test/tools/llvm-dwarfdump/X86/locstats.ll
    llvm/tools/llvm-dwarfdump/Statistics.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-dwarfdump/X86/locstats.ll b/llvm/test/tools/llvm-dwarfdump/X86/locstats.ll
index f850119acb000..cb5908976fb6c 100644
--- a/llvm/test/tools/llvm-dwarfdump/X86/locstats.ll
+++ b/llvm/test/tools/llvm-dwarfdump/X86/locstats.ll
@@ -1,5 +1,11 @@
 ; RUN: llc -debug-entry-values %s -o - -filetype=obj \
 ; RUN:   | llvm-dwarfdump -statistics - | FileCheck %s
+; RUN: llc -debug-entry-values --dwarf-version=4 %s -o - -filetype=obj \
+; RUN:   | llvm-dwarfdump -statistics - | FileCheck %s
+; RUN: llc -debug-entry-values --dwarf-version=3 %s -o - -filetype=obj \
+; RUN:   | llvm-dwarfdump -statistics - | FileCheck %s
+; RUN: llc -debug-entry-values --dwarf-version=2 %s -o - -filetype=obj \
+; RUN:   | llvm-dwarfdump -statistics - | FileCheck %s
 
 ; CHECK:      "sum_all_variables(#bytes in parent scope covered by DW_OP_entry_value)": 5,
 ; CHECK-NEXT: "sum_all_params(#bytes in parent scope)": 20,
@@ -89,6 +95,12 @@
 ; CHECK-NEXT: "#local vars - entry values with [80%,90%) of parent scope covered by DW_AT_location": 1,
 ; CHECK-NEXT: "#local vars - entry values with [90%,100%) of parent scope covered by DW_AT_location": 0,
 ; CHECK-NEXT: "#local vars - entry values with 100% of parent scope covered by DW_AT_location": 1
+; CHECK-NEXT: "#bytes with line information": 51,
+; CHECK-NEXT: "#bytes with line-0 locations": 3,
+; CHECK-NEXT: "#line entries": 7,
+; CHECK-NEXT: "#line entries (is_stmt)": 5,
+; CHECK-NEXT: "#line entries (unique)": 6,
+; CHECK-NEXT: "#line entries (unique non-0)": 5
 
 ; The source code of the test case:
 ; extern void fn3(int *);

diff  --git a/llvm/tools/llvm-dwarfdump/Statistics.cpp b/llvm/tools/llvm-dwarfdump/Statistics.cpp
index 1846f9265c755..8d6dd17ceae90 100644
--- a/llvm/tools/llvm-dwarfdump/Statistics.cpp
+++ b/llvm/tools/llvm-dwarfdump/Statistics.cpp
@@ -8,6 +8,7 @@
 
 #include "llvm-dwarfdump.h"
 #include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseSet.h"
 #include "llvm/ADT/StringSet.h"
 #include "llvm/DebugInfo/DWARF/DWARFContext.h"
 #include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
@@ -188,6 +189,16 @@ struct LocationStats {
   /// Total number of local variables processed.
   SaturatingUINT64 NumVar = 0;
 };
+
+/// Holds accumulated debug line statistics across all CUs.
+struct LineStats {
+  SaturatingUINT64 NumBytes = 0;
+  SaturatingUINT64 NumLineZeroBytes = 0;
+  SaturatingUINT64 NumEntries = 0;
+  SaturatingUINT64 NumIsStmtEntries = 0;
+  SaturatingUINT64 NumUniqueEntries = 0;
+  SaturatingUINT64 NumUniqueNonZeroEntries = 0;
+};
 } // namespace
 
 /// Collect debug location statistics for one DIE.
@@ -848,6 +859,7 @@ bool dwarfdump::collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
   StringRef FormatName = Obj.getFileFormatName();
   GlobalStats GlobalStats;
   LocationStats LocStats;
+  LineStats LnStats;
   StringMap<PerFunctionStats> Statistics;
   // This variable holds variable information for functions with
   // abstract_origin globally, across all CUs.
@@ -856,6 +868,14 @@ bool dwarfdump::collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
   // abstract_origin.
   FunctionDIECUTyMap AbstractOriginFnCUs;
   CrossCUReferencingDIELocationTy CrossCUReferencesToBeResolved;
+  // Tuple representing a single source code position in the line table. Fields
+  // are respectively: Line, Col, File, where 'File' is an index into the Files
+  // vector below.
+  using LineTuple = std::tuple<uint32_t, uint16_t, uint16_t>;
+  SmallVector<std::string> Files;
+  DenseSet<LineTuple> UniqueLines;
+  DenseSet<LineTuple> UniqueNonZeroLines;
+
   for (const auto &CU : static_cast<DWARFContext *>(&DICtx)->compile_units()) {
     if (DWARFDie CUDie = CU->getNonSkeletonUnitDIE(false)) {
       // This variable holds variable information for functions with
@@ -882,8 +902,58 @@ bool dwarfdump::collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
         CrossCUReferencesToBeResolved.push_back(
             DIELocation(CUDie.getDwarfUnit(), CrossCUReferencingDIEOffset));
     }
+    const auto *LineTable = DICtx.getLineTableForUnit(CU.get());
+    std::optional<uint64_t> LastFileIdxOpt;
+    if (LineTable)
+      LastFileIdxOpt = LineTable->getLastValidFileIndex();
+    if (LastFileIdxOpt) {
+      // Each CU has its own file index; in order to track unique line entries
+      // across CUs, we therefore need to map each CU file index to a global
+      // file index, which we store here.
+      DenseMap<uint64_t, uint16_t> CUFileMapping;
+      for (uint64_t FileIdx = 0; FileIdx <= *LastFileIdxOpt; ++FileIdx) {
+        std::string File;
+        if (LineTable->getFileNameByIndex(
+                FileIdx, CU->getCompilationDir(),
+                DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
+                File)) {
+          auto ExistingFile = llvm::find(Files, File);
+          if (ExistingFile != Files.end()) {
+            CUFileMapping[FileIdx] = std::distance(Files.begin(), ExistingFile);
+          } else {
+            CUFileMapping[FileIdx] = Files.size();
+            Files.push_back(File);
+          }
+        }
+      }
+      for (const auto &Seq : LineTable->Sequences) {
+        LnStats.NumBytes += Seq.HighPC - Seq.LowPC;
+        // Ignore the `end_sequence` entry, since it's not interesting for us.
+        LnStats.NumEntries += Seq.LastRowIndex - Seq.FirstRowIndex - 1;
+        for (size_t RowIdx = Seq.FirstRowIndex; RowIdx < Seq.LastRowIndex - 1;
+             ++RowIdx) {
+          auto Entry = LineTable->Rows[RowIdx];
+          if (Entry.IsStmt)
+            LnStats.NumIsStmtEntries += 1;
+          assert(CUFileMapping.contains(Entry.File) &&
+                 "Should have been collected earlier!");
+          uint16_t MappedFile = CUFileMapping[Entry.File];
+          UniqueLines.insert({Entry.Line, Entry.Column, MappedFile});
+          if (Entry.Line != 0) {
+            UniqueNonZeroLines.insert({Entry.Line, Entry.Column, MappedFile});
+          } else {
+            auto EntryStartAddress = Entry.Address.Address;
+            auto EntryEndAddress = LineTable->Rows[RowIdx + 1].Address.Address;
+            LnStats.NumLineZeroBytes += EntryEndAddress - EntryStartAddress;
+          }
+        }
+      }
+    }
   }
 
+  LnStats.NumUniqueEntries = UniqueLines.size();
+  LnStats.NumUniqueNonZeroEntries = UniqueNonZeroLines.size();
+
   /// Resolve CrossCU references.
   collectZeroLocCovForVarsWithCrossCUReferencingAbstractOrigin(
       LocStats, AbstractOriginFnCUs, GlobalAbstractOriginFnInfo,
@@ -1043,6 +1113,16 @@ bool dwarfdump::collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
   printLocationStats(J, "#local vars", LocStats.LocalVarLocStats);
   printLocationStats(J, "#local vars - entry values",
                      LocStats.LocalVarNonEntryValLocStats);
+
+  // Print line statistics for the object file.
+  printDatum(J, "#bytes with line information", LnStats.NumBytes.Value);
+  printDatum(J, "#bytes with line-0 locations", LnStats.NumLineZeroBytes.Value);
+  printDatum(J, "#line entries", LnStats.NumEntries.Value);
+  printDatum(J, "#line entries (is_stmt)", LnStats.NumIsStmtEntries.Value);
+  printDatum(J, "#line entries (unique)", LnStats.NumUniqueEntries.Value);
+  printDatum(J, "#line entries (unique non-0)",
+             LnStats.NumUniqueNonZeroEntries.Value);
+
   J.objectEnd();
   OS << '\n';
   LLVM_DEBUG(


        


More information about the llvm-commits mailing list