Skip to content

Commit 4b0a7fe

Browse files
committed
[llvm-dwarfdump][Statistics] Make calculations of vars in global scope more accurate
It isn't known how many times we've seen the same variable or member in the global scope (unlike in functions), but there still can be some duplicates among different CUs. So, this patch proposes to count variables in the global scope just as a sum of the number of vars, constant members and artificial entities. Reviewed by: aprantl Differential Revision: https://reviews.llvm.org/D73004
1 parent 5499e2f commit 4b0a7fe

File tree

2 files changed

+95
-32
lines changed

2 files changed

+95
-32
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
; RUN: llc -O0 %s -o - -filetype=obj \
2+
; RUN: | llvm-dwarfdump -statistics - | FileCheck %s
3+
4+
; This checks that if DW_TAG_structure_type duplicates in multiple CU,
5+
; the number of total vars ("source variables") will include every copy,
6+
; so the number of "variables with location" doesn't exceed the number of total vars.
7+
8+
; $ cat test.h
9+
; struct s { static const int ss = 42; };
10+
;
11+
; $ cat test1.cpp
12+
; #include "test.h"
13+
; s S1;
14+
;
15+
; $ cat test2.cpp
16+
; #include "test.h"
17+
; s S2;
18+
19+
; CHECK: "source variables":4
20+
; CHECK-SAME: "variables with location":4
21+
22+
source_filename = "llvm-link"
23+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
24+
target triple = "x86_64-unknown-linux-gnu"
25+
26+
%struct.s = type { i8 }
27+
%struct.s.1 = type { i8 }
28+
29+
@S1 = dso_local global %struct.s zeroinitializer, align 1, !dbg !0
30+
@S2 = dso_local global %struct.s.1 zeroinitializer, align 1, !dbg !13
31+
32+
!llvm.dbg.cu = !{!2, !15}
33+
!llvm.ident = !{!18, !18}
34+
!llvm.module.flags = !{!19, !20, !21}
35+
36+
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
37+
!1 = distinct !DIGlobalVariable(name: "S1", scope: !2, file: !3, line: 2, type: !6, isLocal: false, isDefinition: true)
38+
!2 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !3, producer: "clang version 10.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !12, splitDebugInlining: false, nameTableKind: None)
39+
!3 = !DIFile(filename: "test1.cpp", directory: "/")
40+
!4 = !{}
41+
!5 = !{!6}
42+
!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s", file: !7, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !8, identifier: "_ZTS1s")
43+
!7 = !DIFile(filename: "./test.h", directory: "/")
44+
!8 = !{!9}
45+
!9 = !DIDerivedType(tag: DW_TAG_member, name: "ss", scope: !6, file: !7, line: 1, baseType: !10, flags: DIFlagStaticMember, extraData: i32 42)
46+
!10 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !11)
47+
!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
48+
!12 = !{!0}
49+
!13 = !DIGlobalVariableExpression(var: !14, expr: !DIExpression())
50+
!14 = distinct !DIGlobalVariable(name: "S2", scope: !15, file: !16, line: 2, type: !6, isLocal: false, isDefinition: true)
51+
!15 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !16, producer: "clang version 10.0.0", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !22, globals: !17, splitDebugInlining: false, nameTableKind: None)
52+
!16 = !DIFile(filename: "test2.cpp", directory: "/")
53+
!17 = !{!13}
54+
!18 = !{!"clang version 10.0.0"}
55+
!19 = !{i32 7, !"Dwarf Version", i32 4}
56+
!20 = !{i32 2, !"Debug Info Version", i32 3}
57+
!21 = !{i32 1, !"wchar_size", i32 4}
58+
!22 = !{!23}
59+
!23 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s", file: !7, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !24, identifier: "_ZTS1s")
60+
!24 = !{!25}
61+
!25 = !DIDerivedType(tag: DW_TAG_member, name: "ss", scope: !23, file: !7, line: 1, baseType: !10, flags: DIFlagStaticMember, extraData: i32 42)

llvm/tools/llvm-dwarfdump/Statistics.cpp

Lines changed: 34 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ struct PerFunctionStats {
3131
unsigned TotalVarWithLoc = 0;
3232
/// Number of constants with location across all inlined instances.
3333
unsigned ConstantMembers = 0;
34+
/// Number of arificial variables, parameters or members across all instances.
35+
unsigned NumArtificial = 0;
3436
/// List of all Variables and parameters in this function.
3537
StringSet<> VarsInFunction;
3638
/// Compile units also cover a PC range, but have this flag set to false.
@@ -196,12 +198,13 @@ static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
196198
bool HasLoc = false;
197199
bool HasSrcLoc = false;
198200
bool HasType = false;
199-
bool IsArtificial = false;
200201
uint64_t BytesCovered = 0;
201202
uint64_t BytesEntryValuesCovered = 0;
202203
auto &FnStats = FnStatMap[FnPrefix];
203204
bool IsParam = Die.getTag() == dwarf::DW_TAG_formal_parameter;
204205
bool IsVariable = Die.getTag() == dwarf::DW_TAG_variable;
206+
bool IsConstantMember = Die.getTag() == dwarf::DW_TAG_member &&
207+
Die.find(dwarf::DW_AT_const_value);
205208

206209
if (Die.getTag() == dwarf::DW_TAG_call_site ||
207210
Die.getTag() == dwarf::DW_TAG_GNU_call_site) {
@@ -215,7 +218,7 @@ static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
215218
return;
216219
}
217220

218-
if (!IsParam && !IsVariable && Die.getTag() != dwarf::DW_TAG_member) {
221+
if (!IsParam && !IsVariable && !IsConstantMember) {
219222
// Not a variable or constant member.
220223
return;
221224
}
@@ -231,9 +234,6 @@ static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
231234
if (Die.findRecursively(dwarf::DW_AT_type))
232235
HasType = true;
233236

234-
if (Die.find(dwarf::DW_AT_artificial))
235-
IsArtificial = true;
236-
237237
auto IsEntryValue = [&](ArrayRef<uint8_t> D) -> bool {
238238
DWARFUnit *U = Die.getDwarfUnit();
239239
DataExtractor Data(toStringRef(D),
@@ -252,10 +252,6 @@ static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
252252
HasLoc = true;
253253
BytesCovered = BytesInScope;
254254
} else {
255-
if (Die.getTag() == dwarf::DW_TAG_member) {
256-
// Non-const member.
257-
return;
258-
}
259255
// Handle variables and function arguments.
260256
Expected<std::vector<DWARFLocationExpression>> Loc =
261257
Die.getLocations(dwarf::DW_AT_location);
@@ -307,7 +303,6 @@ static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
307303
FnStats.VarsInFunction.insert(VarID);
308304

309305
if (BytesInScope) {
310-
FnStats.TotalVarWithLoc += (unsigned)HasLoc;
311306
// Turns out we have a lot of ranges that extend past the lexical scope.
312307
GlobalStats.ScopeBytesCovered += std::min(BytesInScope, BytesCovered);
313308
GlobalStats.ScopeBytes += BytesInScope;
@@ -323,29 +318,36 @@ static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
323318
GlobalStats.VarScopeEntryValueBytesCovered += BytesEntryValuesCovered;
324319
}
325320
assert(GlobalStats.ScopeBytesCovered <= GlobalStats.ScopeBytes);
326-
} else if (Die.getTag() == dwarf::DW_TAG_member) {
321+
}
322+
323+
if (IsConstantMember) {
327324
FnStats.ConstantMembers++;
328-
} else {
329-
FnStats.TotalVarWithLoc += (unsigned)HasLoc;
325+
return;
330326
}
331-
if (!IsArtificial) {
332-
if (IsParam) {
333-
FnStats.NumParams++;
334-
if (HasType)
335-
FnStats.NumParamTypes++;
336-
if (HasSrcLoc)
337-
FnStats.NumParamSourceLocations++;
338-
if (HasLoc)
339-
FnStats.NumParamLocations++;
340-
} else if (IsVariable) {
341-
FnStats.NumVars++;
342-
if (HasType)
343-
FnStats.NumVarTypes++;
344-
if (HasSrcLoc)
345-
FnStats.NumVarSourceLocations++;
346-
if (HasLoc)
347-
FnStats.NumVarLocations++;
348-
}
327+
328+
FnStats.TotalVarWithLoc += (unsigned)HasLoc;
329+
330+
if (Die.find(dwarf::DW_AT_artificial)) {
331+
FnStats.NumArtificial++;
332+
return;
333+
}
334+
335+
if (IsParam) {
336+
FnStats.NumParams++;
337+
if (HasType)
338+
FnStats.NumParamTypes++;
339+
if (HasSrcLoc)
340+
FnStats.NumParamSourceLocations++;
341+
if (HasLoc)
342+
FnStats.NumParamLocations++;
343+
} else if (IsVariable) {
344+
FnStats.NumVars++;
345+
if (HasType)
346+
FnStats.NumVarTypes++;
347+
if (HasSrcLoc)
348+
FnStats.NumVarSourceLocations++;
349+
if (HasLoc)
350+
FnStats.NumVarLocations++;
349351
}
350352
}
351353

@@ -527,7 +529,7 @@ bool collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
527529
(Stats.NumFnInlined + Stats.NumFnOutOfLine);
528530
// Count variables in global scope.
529531
if (!Stats.IsFunction)
530-
TotalVars += Stats.VarsInFunction.size();
532+
TotalVars = Stats.NumVars + Stats.ConstantMembers + Stats.NumArtificial;
531533
unsigned Constants = Stats.ConstantMembers;
532534
VarParamWithLoc += Stats.TotalVarWithLoc + Constants;
533535
VarParamTotal += TotalVars;

0 commit comments

Comments
 (0)