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:
parent
4a964ed01e
commit
561ebf7f17
61
test/tools/llvm-dwarfdump/X86/stats-multiple-cu-members.ll
Normal file
61
test/tools/llvm-dwarfdump/X86/stats-multiple-cu-members.ll
Normal 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)
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user