[llvm] 9806b39 - [llvm-dwarfdump][Statistics] Distinguish functions/variables with same name across different CUs

Kristina Bessonova via llvm-commits llvm-commits at lists.llvm.org
Tue Jan 28 09:51:11 PST 2020


Author: Kristina Bessonova
Date: 2020-01-28T19:50:46+02:00
New Revision: 9806b39dae18982864dc3d9cdb2871d9590e5408

URL: https://github.com/llvm/llvm-project/commit/9806b39dae18982864dc3d9cdb2871d9590e5408
DIFF: https://github.com/llvm/llvm-project/commit/9806b39dae18982864dc3d9cdb2871d9590e5408.diff

LOG: [llvm-dwarfdump][Statistics] Distinguish functions/variables with same name across different CUs

Different variables and functions might have the same name in different CU.
To calculate 'Availability' metric more accurate (i.e. to avoid getting
availability above 100%), we need to have some additional logic to
distinguish between them.

The patch introduces a DIE identifier that consists of a function/variable name
and declaration information: a filename and a line number. This allows
distinguishing different functions/variables (different means declared in
different files/lines) with the same name, keeping duplicates counted
as duplicates.

Reviewed by: aprantl, djtodoro

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

Added: 
    llvm/test/tools/llvm-dwarfdump/X86/stats-multiple-cu-same-name.ll

Modified: 
    llvm/tools/llvm-dwarfdump/Statistics.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-dwarfdump/X86/stats-multiple-cu-same-name.ll b/llvm/test/tools/llvm-dwarfdump/X86/stats-multiple-cu-same-name.ll
new file mode 100644
index 000000000000..bfcc1b8bdfe7
--- /dev/null
+++ b/llvm/test/tools/llvm-dwarfdump/X86/stats-multiple-cu-same-name.ll
@@ -0,0 +1,89 @@
+; RUN: llc -O0 %s -o - -filetype=obj \
+; RUN:   | llvm-dwarfdump -statistics - | FileCheck %s
+
+; Test that statistics distinguish functions with the same name.
+
+; CHECK:      "source functions":4,
+; CHECK-SAME: "unique source variables":2
+; CHECK-SAME: "source variables":2
+
+; $ cat test1.cpp
+; static int foo(int a) {
+;   return a;
+; }
+; int boo() { return foo(42); }
+;
+; $ cat test2.cpp
+; static int foo(int a) {
+;   return a;
+; }
+; int bar() { return foo(42); }
+
+source_filename = "llvm-link"
+target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-unknown-linux-gnu"
+
+; Function Attrs: noinline optnone uwtable
+define dso_local i32 @_Z3boov() !dbg !9 {
+entry:
+  %call = call i32 @_ZL3fooi(i32 42), !dbg !13
+  ret i32 %call
+}
+; Function Attrs: noinline nounwind optnone uwtable
+define internal i32 @_ZL3fooi(i32 %a) !dbg !15 {
+entry:
+  %a.addr = alloca i32, align 4
+  store i32 %a, i32* %a.addr, align 4
+  call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !18, metadata !DIExpression()), !dbg !19
+  %0 = load i32, i32* %a.addr, align 4, !dbg !20
+  ret i32 %0
+}
+; Function Attrs: nounwind readnone speculatable willreturn
+declare void @llvm.dbg.declare(metadata, metadata, metadata)
+; Function Attrs: noinline optnone uwtable
+define dso_local i32 @_Z3barv() !dbg !22 {
+entry:
+  %call = call i32 @_ZL3fooi.1(i32 442), !dbg !23
+  ret i32 %call
+}
+; Function Attrs: noinline nounwind optnone uwtable
+define internal i32 @_ZL3fooi.1(i32 %a) !dbg !25 {
+entry:
+  %a.addr = alloca i32, align 4
+  store i32 %a, i32* %a.addr, align 4
+  call void @llvm.dbg.declare(metadata i32* %a.addr, metadata !26, metadata !DIExpression()), !dbg !27
+  %0 = load i32, i32* %a.addr, align 4, !dbg !28
+  %mul = mul nsw i32 %0, 2
+  ret i32 %mul
+}
+
+!llvm.dbg.cu = !{!0, !3}
+!llvm.ident = !{!5, !5}
+!llvm.module.flags = !{!6, !7, !8}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 10.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
+!1 = !DIFile(filename: "test1.cpp", directory: "/")
+!2 = !{}
+!3 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !4, producer: "clang version 10.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, splitDebugInlining: false, nameTableKind: None)
+!4 = !DIFile(filename: "test2.cpp", directory: "/")
+!5 = !{!"clang version 10.0.0"}
+!6 = !{i32 7, !"Dwarf Version", i32 4}
+!7 = !{i32 2, !"Debug Info Version", i32 3}
+!8 = !{i32 1, !"wchar_size", i32 4}
+!9 = distinct !DISubprogram(name: "boo", linkageName: "_Z3boov", scope: !1, file: !1, line: 5, type: !10, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!10 = !DISubroutineType(types: !11)
+!11 = !{!12}
+!12 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
+!13 = !DILocation(line: 6, column: 10, scope: !9)
+!15 = distinct !DISubprogram(name: "foo", linkageName: "_ZL3fooi", scope: !1, file: !1, line: 1, type: !16, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !0, retainedNodes: !2)
+!16 = !DISubroutineType(types: !17)
+!17 = !{!12, !12}
+!18 = !DILocalVariable(name: "a", arg: 1, scope: !15, file: !1, line: 1, type: !12)
+!19 = !DILocation(line: 1, column: 20, scope: !15)
+!20 = !DILocation(line: 2, column: 10, scope: !15)
+!22 = distinct !DISubprogram(name: "bar", linkageName: "_Z3barv", scope: !4, file: !4, line: 5, type: !10, scopeLine: 5, flags: DIFlagPrototyped, spFlags: DISPFlagDefinition, unit: !3, retainedNodes: !2)
+!23 = !DILocation(line: 6, column: 10, scope: !22)
+!25 = distinct !DISubprogram(name: "foo", linkageName: "_ZL3fooi", scope: !4, file: !4, line: 1, type: !16, scopeLine: 1, flags: DIFlagPrototyped, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !3, retainedNodes: !2)
+!26 = !DILocalVariable(name: "a", arg: 1, scope: !25, file: !4, line: 1, type: !12)
+!27 = !DILocation(line: 1, column: 20, scope: !25)
+!28 = !DILocation(line: 2, column: 10, scope: !25)

diff  --git a/llvm/tools/llvm-dwarfdump/Statistics.cpp b/llvm/tools/llvm-dwarfdump/Statistics.cpp
index a183501afef7..c77e9e40193a 100644
--- a/llvm/tools/llvm-dwarfdump/Statistics.cpp
+++ b/llvm/tools/llvm-dwarfdump/Statistics.cpp
@@ -157,6 +157,35 @@ static void collectLocStats(uint64_t BytesCovered, uint64_t BytesInScope,
   else if (IsLocalVar)
     VarLocStats[CoverageBucket]++;
 }
+/// Construct an identifier for a given DIE from its Prefix, Name, DeclFileName
+/// and DeclLine. The identifier aims to be unique for any unique entities,
+/// but keeping the same among 
diff erent instances of the same entity.
+static std::string constructDieID(DWARFDie Die,
+                                  StringRef Prefix = StringRef()) {
+  std::string IDStr;
+  llvm::raw_string_ostream ID(IDStr);
+  ID << Prefix
+     << Die.getName(DINameKind::LinkageName);
+
+  // Prefix + Name is enough for local variables and parameters.
+  if (!Prefix.empty() && !Prefix.equals("g"))
+    return ID.str();
+
+  auto DeclFile = Die.findRecursively(dwarf::DW_AT_decl_file);
+  std::string File;
+  if (DeclFile) {
+    DWARFUnit *U = Die.getDwarfUnit();
+    if (const auto *LT = U->getContext().getLineTableForUnit(U))
+      if (LT->getFileNameByIndex(
+              dwarf::toUnsigned(DeclFile, 0), U->getCompilationDir(),
+              DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, File))
+        File = sys::path::filename(File);
+  }
+  ID << ":" << (File.empty() ? "/" : File);
+  ID << ":"
+     << dwarf::toUnsigned(Die.findRecursively(dwarf::DW_AT_decl_line), 0);
+  return ID.str();
+}
 
 /// Collect debug info quality metrics for one DIE.
 static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
@@ -270,10 +299,10 @@ static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
   if (DWARFDie D =
           Die.getAttributeValueAsReferencedDie(dwarf::DW_AT_abstract_origin))
     Die = D;
-  // By using the variable name + the path through the lexical block tree, the
-  // keys are consistent across duplicate abstract origins in 
diff erent CUs.
-  std::string VarName = StringRef(Die.getName(DINameKind::ShortName));
-  FnStats.VarsInFunction.insert(VarPrefix + VarName);
+
+  std::string VarID = constructDieID(Die, VarPrefix);
+  FnStats.VarsInFunction.insert(VarID);
+
   if (BytesInScope) {
     FnStats.TotalVarWithLoc += (unsigned)HasLoc;
     // Turns out we have a lot of ranges that extend past the lexical scope.
@@ -358,27 +387,25 @@ static void collectStatsRecursive(DWARFDie Die, std::string FnPrefix,
 
     // Count the function.
     if (!IsBlock) {
-      StringRef Name = Die.getName(DINameKind::LinkageName);
-      if (Name.empty())
-        Name = Die.getName(DINameKind::ShortName);
-      FnPrefix = Name;
       // Skip over abstract origins.
       if (Die.find(dwarf::DW_AT_inline))
         return;
+      std::string FnID = constructDieID(Die);
       // We've seen an (inlined) instance of this function.
-      auto &FnStats = FnStatMap[Name];
+      auto &FnStats = FnStatMap[FnID];
+      FnStats.IsFunction = true;
       if (IsInlinedFunction) {
         FnStats.NumFnInlined++;
         if (Die.findRecursively(dwarf::DW_AT_abstract_origin))
           FnStats.NumAbstractOrigins++;
       }
-      FnStats.IsFunction = true;
       if (BytesInThisScope && !IsInlinedFunction)
         FnStats.HasPCAddresses = true;
-      std::string FnName = StringRef(Die.getName(DINameKind::ShortName));
       if (Die.findRecursively(dwarf::DW_AT_decl_file) &&
           Die.findRecursively(dwarf::DW_AT_decl_line))
         FnStats.HasSourceLocation = true;
+      // Update function prefix.
+      FnPrefix = FnID;
     }
 
     if (BytesInThisScope) {


        


More information about the llvm-commits mailing list