1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-26 12:43:36 +01:00

[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
This commit is contained in:
Kristina Bessonova 2020-01-14 20:39:04 +02:00
parent 4a964ed01e
commit 561ebf7f17
2 changed files with 96 additions and 33 deletions

View File

@ -0,0 +1,61 @@
; RUN: llc -O0 %s -o - -filetype=obj \
; RUN: | llvm-dwarfdump -statistics - | FileCheck %s
; This checks that if DW_TAG_structure_type duplicates in multiple CU,
; the number of total vars ("source variables") will include every copy,
; so the number of "variables with location" doesn't exceed the number of total vars.
; $ cat test.h
; struct s { static const int ss = 42; };
;
; $ cat test1.cpp
; #include "test.h"
; s S1;
;
; $ cat test2.cpp
; #include "test.h"
; s S2;
; CHECK: "source variables":4
; CHECK-SAME: "variables with location":4
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"
%struct.s = type { i8 }
%struct.s.1 = type { i8 }
@S1 = dso_local global %struct.s zeroinitializer, align 1, !dbg !0
@S2 = dso_local global %struct.s.1 zeroinitializer, align 1, !dbg !13
!llvm.dbg.cu = !{!2, !15}
!llvm.ident = !{!18, !18}
!llvm.module.flags = !{!19, !20, !21}
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
!1 = distinct !DIGlobalVariable(name: "S1", scope: !2, file: !3, line: 2, type: !6, isLocal: false, isDefinition: true)
!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)
!3 = !DIFile(filename: "test1.cpp", directory: "/")
!4 = !{}
!5 = !{!6}
!6 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s", file: !7, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !8, identifier: "_ZTS1s")
!7 = !DIFile(filename: "./test.h", directory: "/")
!8 = !{!9}
!9 = !DIDerivedType(tag: DW_TAG_member, name: "ss", scope: !6, file: !7, line: 1, baseType: !10, flags: DIFlagStaticMember, extraData: i32 42)
!10 = !DIDerivedType(tag: DW_TAG_const_type, baseType: !11)
!11 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
!12 = !{!0}
!13 = !DIGlobalVariableExpression(var: !14, expr: !DIExpression())
!14 = distinct !DIGlobalVariable(name: "S2", scope: !15, file: !16, line: 2, type: !6, isLocal: false, isDefinition: true)
!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)
!16 = !DIFile(filename: "test2.cpp", directory: "/")
!17 = !{!13}
!18 = !{!"clang version 10.0.0"}
!19 = !{i32 7, !"Dwarf Version", i32 4}
!20 = !{i32 2, !"Debug Info Version", i32 3}
!21 = !{i32 1, !"wchar_size", i32 4}
!22 = !{!23}
!23 = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "s", file: !7, line: 1, size: 8, flags: DIFlagTypePassByValue, elements: !24, identifier: "_ZTS1s")
!24 = !{!25}
!25 = !DIDerivedType(tag: DW_TAG_member, name: "ss", scope: !23, file: !7, line: 1, baseType: !10, flags: DIFlagStaticMember, extraData: i32 42)

View File

@ -31,6 +31,8 @@ struct PerFunctionStats {
unsigned TotalVarWithLoc = 0;
/// Number of constants with location across all inlined instances.
unsigned ConstantMembers = 0;
/// Number of arificial variables, parameters or members across all instances.
unsigned NumArtificial = 0;
/// List of all Variables and parameters in this function.
StringSet<> VarsInFunction;
/// 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,
bool HasLoc = false;
bool HasSrcLoc = false;
bool HasType = false;
bool IsArtificial = false;
uint64_t BytesCovered = 0;
uint64_t BytesEntryValuesCovered = 0;
auto &FnStats = FnStatMap[FnPrefix];
bool IsParam = Die.getTag() == dwarf::DW_TAG_formal_parameter;
bool IsVariable = Die.getTag() == dwarf::DW_TAG_variable;
bool IsConstantMember = Die.getTag() == dwarf::DW_TAG_member &&
Die.find(dwarf::DW_AT_const_value);
if (Die.getTag() == dwarf::DW_TAG_call_site ||
Die.getTag() == dwarf::DW_TAG_GNU_call_site) {
@ -215,7 +218,7 @@ static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
return;
}
if (!IsParam && !IsVariable && Die.getTag() != dwarf::DW_TAG_member) {
if (!IsParam && !IsVariable && !IsConstantMember) {
// Not a variable or constant member.
return;
}
@ -231,9 +234,6 @@ static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
if (Die.findRecursively(dwarf::DW_AT_type))
HasType = true;
if (Die.find(dwarf::DW_AT_artificial))
IsArtificial = true;
auto IsEntryValue = [&](ArrayRef<uint8_t> D) -> bool {
DWARFUnit *U = Die.getDwarfUnit();
DataExtractor Data(toStringRef(D),
@ -252,10 +252,6 @@ static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
HasLoc = true;
BytesCovered = BytesInScope;
} else {
if (Die.getTag() == dwarf::DW_TAG_member) {
// Non-const member.
return;
}
// Handle variables and function arguments.
Expected<std::vector<DWARFLocationExpression>> Loc =
Die.getLocations(dwarf::DW_AT_location);
@ -307,7 +303,6 @@ static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
FnStats.VarsInFunction.insert(VarID);
if (BytesInScope) {
FnStats.TotalVarWithLoc += (unsigned)HasLoc;
// Turns out we have a lot of ranges that extend past the lexical scope.
GlobalStats.ScopeBytesCovered += std::min(BytesInScope, BytesCovered);
GlobalStats.ScopeBytes += BytesInScope;
@ -323,29 +318,36 @@ static void collectStatsForDie(DWARFDie Die, std::string FnPrefix,
GlobalStats.VarScopeEntryValueBytesCovered += BytesEntryValuesCovered;
}
assert(GlobalStats.ScopeBytesCovered <= GlobalStats.ScopeBytes);
} else if (Die.getTag() == dwarf::DW_TAG_member) {
FnStats.ConstantMembers++;
} else {
FnStats.TotalVarWithLoc += (unsigned)HasLoc;
}
if (!IsArtificial) {
if (IsParam) {
FnStats.NumParams++;
if (HasType)
FnStats.NumParamTypes++;
if (HasSrcLoc)
FnStats.NumParamSourceLocations++;
if (HasLoc)
FnStats.NumParamLocations++;
} else if (IsVariable) {
FnStats.NumVars++;
if (HasType)
FnStats.NumVarTypes++;
if (HasSrcLoc)
FnStats.NumVarSourceLocations++;
if (HasLoc)
FnStats.NumVarLocations++;
}
if (IsConstantMember) {
FnStats.ConstantMembers++;
return;
}
FnStats.TotalVarWithLoc += (unsigned)HasLoc;
if (Die.find(dwarf::DW_AT_artificial)) {
FnStats.NumArtificial++;
return;
}
if (IsParam) {
FnStats.NumParams++;
if (HasType)
FnStats.NumParamTypes++;
if (HasSrcLoc)
FnStats.NumParamSourceLocations++;
if (HasLoc)
FnStats.NumParamLocations++;
} else if (IsVariable) {
FnStats.NumVars++;
if (HasType)
FnStats.NumVarTypes++;
if (HasSrcLoc)
FnStats.NumVarSourceLocations++;
if (HasLoc)
FnStats.NumVarLocations++;
}
}
@ -527,7 +529,7 @@ bool collectStatsForObjectFile(ObjectFile &Obj, DWARFContext &DICtx,
(Stats.NumFnInlined + Stats.NumFnOutOfLine);
// Count variables in global scope.
if (!Stats.IsFunction)
TotalVars += Stats.VarsInFunction.size();
TotalVars = Stats.NumVars + Stats.ConstantMembers + Stats.NumArtificial;
unsigned Constants = Stats.ConstantMembers;
VarParamWithLoc += Stats.TotalVarWithLoc + Constants;
VarParamTotal += TotalVars;