From f9521b0bb7fa9a502170f1dd4dd16a1dab75cdfc Mon Sep 17 00:00:00 2001 From: "Duncan P. N. Exon Smith" Date: Sun, 17 Apr 2016 07:45:08 +0000 Subject: [PATCH] DebugInfo: Make DICompositeTypes distinct most of the time Since elements of most kinds of DICompositeType have back references, most are involved in uniquing cycles. Except via the ODR 'identifier:' field, which doesn't care about the storage type (see r266549), they have no hope of being uniqued. Distinct nodes are far more efficient, so use them for most kinds of DICompositeType definitions (i.e., when DIType::isForwardDecl is false). The exceptions: - DW_TAG_array_type, since their elements never have back-references and they never have ODR 'identifier:' fields; - DW_TAG_enumeration_type when there is no ODR 'identifier:' field, since their elements usually don't have back-references. This breaks the last major uniquing cycle I'm aware of in the debug info graph. The impact won't be enormous for C++ because references to ODR-uniqued nodes still use string-based DITypeRefs; but this should prevent a regression in C++ when we drop the string-based references. This wouldn't have been reasonable until r266549, when composite types stopped relying on being uniqued by structural equivalence to prevent blow-ups at LTO time. llvm-svn: 266556 --- clang/lib/CodeGen/CGDebugInfo.cpp | 24 ++++++++++++++++++++++ .../test/CodeGenCXX/debug-info-anon-union-vars.cpp | 2 +- .../test/CodeGenCXX/debug-info-artificial-arg.cpp | 2 +- clang/test/CodeGenCXX/debug-info-class.cpp | 2 +- .../test/CodeGenCXX/debug-info-template-limit.cpp | 2 +- .../test/CodeGenCXX/debug-info-template-member.cpp | 6 +++--- .../test/CodeGenCXX/debug-info-template-quals.cpp | 2 +- clang/test/CodeGenCXX/debug-info-template.cpp | 4 ++-- clang/test/CodeGenCXX/debug-lambda-expressions.cpp | 12 +++++------ clang/test/Modules/ExtDebugInfo.cpp | 4 ++-- clang/test/Modules/ExtDebugInfo.m | 4 ++-- clang/test/Modules/ModuleDebugInfo.m | 4 ++-- 12 files changed, 46 insertions(+), 22 deletions(-) diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 6fd0032..ae95dd8 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2374,6 +2374,30 @@ llvm::DICompositeType *CGDebugInfo::CreateLimitedType(const RecordType *Ty) { getTagForRecord(RD), RDName, RDContext, DefUnit, Line, 0, Size, Align, 0, FullName); + // Elements of composite types usually have back to the type, creating + // uniquing cycles. Distinct nodes are more efficient. + switch (RealDecl->getTag()) { + default: + llvm_unreachable("invalid composite type tag"); + + case llvm::dwarf::DW_TAG_array_type: + case llvm::dwarf::DW_TAG_enumeration_type: + // Array elements and most enumeration elements don't have back references, + // so they don't tend to be involved in uniquing cycles and there is some + // chance of merging them when linking together two modules. Only make + // them distinct if they are ODR-uniqued. + if (FullName.empty()) + break; + + case llvm::dwarf::DW_TAG_structure_type: + case llvm::dwarf::DW_TAG_union_type: + case llvm::dwarf::DW_TAG_class_type: + // Immediatley resolve to a distinct node. + RealDecl = + llvm::MDNode::replaceWithDistinct(llvm::TempDICompositeType(RealDecl)); + break; + } + RegionMap[Ty->getDecl()].reset(RealDecl); TypeCache[QualType(Ty, 0).getAsOpaquePtr()].reset(RealDecl); diff --git a/clang/test/CodeGenCXX/debug-info-anon-union-vars.cpp b/clang/test/CodeGenCXX/debug-info-anon-union-vars.cpp index 8074225..b844d42 100644 --- a/clang/test/CodeGenCXX/debug-info-anon-union-vars.cpp +++ b/clang/test/CodeGenCXX/debug-info-anon-union-vars.cpp @@ -56,7 +56,7 @@ void instantiate(int x) { // CHECK: !DILocalVariable( // CHECK-NOT: name: // CHECK: type: ![[UNION:[0-9]+]] -// CHECK: ![[UNION]] = !DICompositeType(tag: DW_TAG_union_type, +// CHECK: ![[UNION]] = distinct !DICompositeType(tag: DW_TAG_union_type, // CHECK-NOT: name: // CHECK: elements // CHECK: !DIDerivedType(tag: DW_TAG_member, name: "i", scope: ![[UNION]], diff --git a/clang/test/CodeGenCXX/debug-info-artificial-arg.cpp b/clang/test/CodeGenCXX/debug-info-artificial-arg.cpp index c840df6..e927dc5 100644 --- a/clang/test/CodeGenCXX/debug-info-artificial-arg.cpp +++ b/clang/test/CodeGenCXX/debug-info-artificial-arg.cpp @@ -22,7 +22,7 @@ int main(int argc, char **argv) { A reallyA (500); } -// CHECK: ![[CLASSTYPE:.*]] = !DICompositeType(tag: DW_TAG_class_type, name: "A", +// CHECK: ![[CLASSTYPE:.*]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "A", // CHECK-SAME: identifier: "_ZTS1A" // CHECK: ![[ARTARG:.*]] = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !"_ZTS1A", // CHECK-SAME: DIFlagArtificial diff --git a/clang/test/CodeGenCXX/debug-info-class.cpp b/clang/test/CodeGenCXX/debug-info-class.cpp index ed52fd0..ece5c94 100644 --- a/clang/test/CodeGenCXX/debug-info-class.cpp +++ b/clang/test/CodeGenCXX/debug-info-class.cpp @@ -101,7 +101,7 @@ int main(int argc, char **argv) { // CHECK: ![[INT:[0-9]+]] = !DIBasicType(name: "int" -// CHECK: [[C:![0-9]*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "C", +// CHECK: [[C:![0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "C", // CHECK-NOT: DIFlagFwdDecl // CHECK-SAME: elements: [[C_MEM:![0-9]*]] // CHECK-SAME: vtableHolder: !"_ZTS1C" diff --git a/clang/test/CodeGenCXX/debug-info-template-limit.cpp b/clang/test/CodeGenCXX/debug-info-template-limit.cpp index 5c4ac0c..7e3a4a6 100644 --- a/clang/test/CodeGenCXX/debug-info-template-limit.cpp +++ b/clang/test/CodeGenCXX/debug-info-template-limit.cpp @@ -1,7 +1,7 @@ // RUN: %clang_cc1 -emit-llvm -debug-info-kind=limited -triple %itanium_abi_triple %s -o - | FileCheck %s // Check that this pointer type is TC -// CHECK: ![[LINE:[0-9]+]] = !DICompositeType(tag: DW_TAG_class_type, name: "TC"{{.*}}, identifier: "_ZTS2TCIiE") +// CHECK: ![[LINE:[0-9]+]] = distinct !DICompositeType(tag: DW_TAG_class_type, name: "TC"{{.*}}, identifier: "_ZTS2TCIiE") // CHECK: !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !"_ZTS2TCIiE" template diff --git a/clang/test/CodeGenCXX/debug-info-template-member.cpp b/clang/test/CodeGenCXX/debug-info-template-member.cpp index a6ba82a..dcc4646 100644 --- a/clang/test/CodeGenCXX/debug-info-template-member.cpp +++ b/clang/test/CodeGenCXX/debug-info-template-member.cpp @@ -24,7 +24,7 @@ inline int add3(int x) { // CHECK-SAME: type: [[FOO_FUNC_TYPE:![0-9]*]] // CHECK: [[FOO_FUNC_TYPE]] = !DISubroutineType(types: [[FOO_FUNC_PARAMS:![0-9]*]]) // CHECK: [[FOO_FUNC_PARAMS]] = !{null, !{{[0-9]*}}, !"[[OUTER_FOO_INNER_ID:.*]]"} -// CHECK: !{{[0-9]*}} = !DICompositeType(tag: DW_TAG_structure_type, name: "inner"{{.*}}, identifier: "[[OUTER_FOO_INNER_ID]]") +// CHECK: !{{[0-9]*}} = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "inner"{{.*}}, identifier: "[[OUTER_FOO_INNER_ID]]") // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "virt" // CHECK-SAME: elements: [[VIRT_MEM:![0-9]*]] @@ -34,7 +34,7 @@ inline int add3(int x) { // CHECK: [[VIRT_TEMP_PARAM]] = !{[[VIRT_T:![0-9]*]]} // CHECK: [[VIRT_T]] = !DITemplateTypeParameter(name: "T", type: !"_ZTS4elem") -// CHECK: [[C:![0-9]*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "MyClass" +// CHECK: [[C:![0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "MyClass" // CHECK-SAME: elements: [[C_MEM:![0-9]*]] // CHECK-SAME: vtableHolder: !"_ZTS7MyClass" // CHECK-SAME: identifier: "_ZTS7MyClass") @@ -43,7 +43,7 @@ inline int add3(int x) { // CHECK: [[C_FUNC]] = !DISubprogram(name: "func",{{.*}} line: 7, -// CHECK: [[ELEM:![0-9]*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "elem" +// CHECK: [[ELEM:![0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "elem" // CHECK-SAME: elements: [[ELEM_MEM:![0-9]*]] // CHECK-SAME: identifier: "_ZTS4elem" // CHECK: [[ELEM_MEM]] = !{[[ELEM_X:![0-9]*]]} diff --git a/clang/test/CodeGenCXX/debug-info-template-quals.cpp b/clang/test/CodeGenCXX/debug-info-template-quals.cpp index 1e8bdb1..881bb0e 100644 --- a/clang/test/CodeGenCXX/debug-info-template-quals.cpp +++ b/clang/test/CodeGenCXX/debug-info-template-quals.cpp @@ -15,7 +15,7 @@ void foo (const char *c) { str.assign(c, str); } -// CHECK: [[BS:.*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "basic_string" +// CHECK: [[BS:.*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "basic_string" // CHECK-SAME: line: 4 // CHECK-SAME: size: 8, align: 8 // CHECK: [[TYPE:![0-9]*]] = !DISubroutineType(types: [[ARGS:.*]]) diff --git a/clang/test/CodeGenCXX/debug-info-template.cpp b/clang/test/CodeGenCXX/debug-info-template.cpp index 74adef9..569357c 100644 --- a/clang/test/CodeGenCXX/debug-info-template.cpp +++ b/clang/test/CodeGenCXX/debug-info-template.cpp @@ -6,7 +6,7 @@ // CHECK: [[RETAIN]] = !{!{{[0-9]]*}}, [[FOO:![0-9]*]], -// CHECK: [[TC:![0-9]*]] = !DICompositeType(tag: DW_TAG_structure_type, name: "TC" +// CHECK: [[TC:![0-9]*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "TC" // CHECK-SAME: templateParams: [[TCARGS:![0-9]*]] // CHECK: [[TCARGS]] = !{[[TCARG1:![0-9]*]], [[TCARG2:![0-9]*]], [[TCARG3:![0-9]*]], [[TCARG4:![0-9]*]], [[TCARG5:![0-9]*]], [[TCARG6:![0-9]*]], [[TCARG7:![0-9]*]]} // @@ -48,7 +48,7 @@ // We could just emit a declaration of 'foo' here, rather than the entire // definition (same goes for any time we emit a member (function or data) // pointer type) -// CHECK: [[FOO]] = !DICompositeType(tag: DW_TAG_structure_type, name: "foo", {{.*}}identifier: "_ZTS3foo") +// CHECK: [[FOO]] = distinct !DICompositeType(tag: DW_TAG_structure_type, name: "foo", {{.*}}identifier: "_ZTS3foo") // CHECK: !DISubprogram(name: "f", linkageName: "_ZN3foo1fEv", {{.*}}type: [[FTYPE:![0-9]*]] // diff --git a/clang/test/CodeGenCXX/debug-lambda-expressions.cpp b/clang/test/CodeGenCXX/debug-lambda-expressions.cpp index 3efdee5..985234f 100644 --- a/clang/test/CodeGenCXX/debug-lambda-expressions.cpp +++ b/clang/test/CodeGenCXX/debug-lambda-expressions.cpp @@ -23,7 +23,7 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK: !DIGlobalVariable(name: "cvar" // CHECK-SAME: line: [[CVAR_LINE:[0-9]+]] // CHECK-SAME: type: ![[CVAR_T:[0-9]+]] -// CHECK: ![[CVAR_T]] = !DICompositeType(tag: DW_TAG_class_type +// CHECK: ![[CVAR_T]] = distinct !DICompositeType(tag: DW_TAG_class_type // CHECK-SAME: line: [[CVAR_LINE]], // CHECK-SAME: elements: ![[CVAR_ARGS:[0-9]+]] // CHECK: ![[CVAR_ARGS]] = !{!{{[0-9]+}}} @@ -32,7 +32,7 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK: !DIGlobalVariable(name: "var" // CHECK-SAME: line: [[VAR_LINE:[0-9]+]] // CHECK-SAME: type: ![[VAR_T:[0-9]+]] -// CHECK: ![[VAR_T]] = !DICompositeType(tag: DW_TAG_class_type +// CHECK: ![[VAR_T]] = distinct !DICompositeType(tag: DW_TAG_class_type // CHECK-SAME: line: [[VAR_LINE]], // CHECK-SAME: elements: ![[VAR_ARGS:[0-9]+]] // CHECK: ![[VAR_ARGS]] = !{!{{[0-9]+}}} @@ -41,7 +41,7 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK: ![[A_FUNC:.*]] = distinct !DISubprogram(name: "a"{{.*}}, line: [[A_LINE:[0-9]+]]{{.*}}, isDefinition: true // Back to A. -- 78 -// CHECK: ![[LAM_A:.*]] = !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[A_FUNC]]{{.*}}, line: [[A_LINE]], +// CHECK: ![[LAM_A:.*]] = distinct !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[A_FUNC]]{{.*}}, line: [[A_LINE]], // CHECK-SAME: elements: ![[LAM_A_ARGS:[0-9]+]] // CHECK: ![[LAM_A_ARGS]] = !{![[CON_LAM_A:[0-9]+]]} // CHECK: ![[CON_LAM_A]] = !DISubprogram(name: "operator()" @@ -53,7 +53,7 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK: ![[B_FUNC:.*]] = distinct !DISubprogram(name: "b"{{.*}}, line: [[B_LINE:[0-9]+]]{{.*}}, isDefinition: true // Back to B. -- 67 -// CHECK: ![[LAM_B:.*]] = !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[B_FUNC]]{{.*}}, line: [[B_LINE]], +// CHECK: ![[LAM_B:.*]] = distinct !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[B_FUNC]]{{.*}}, line: [[B_LINE]], // CHECK-SAME: elements: ![[LAM_B_ARGS:[0-9]+]] // CHECK: ![[LAM_B_ARGS]] = !{![[CAP_B:[0-9]+]], ![[CON_LAM_B:[0-9]+]]} // CHECK: ![[CAP_B]] = !DIDerivedType(tag: DW_TAG_member, name: "x" @@ -69,7 +69,7 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK: ![[C_FUNC:.*]] = distinct !DISubprogram(name: "c"{{.*}}, line: [[C_LINE:[0-9]+]]{{.*}}, isDefinition: true // Back to C. -- 55 -// CHECK: ![[LAM_C:.*]] = !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[C_FUNC]]{{.*}}, line: [[C_LINE]], +// CHECK: ![[LAM_C:.*]] = distinct !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[C_FUNC]]{{.*}}, line: [[C_LINE]], // CHECK-SAME: elements: ![[LAM_C_ARGS:[0-9]+]] // CHECK: ![[LAM_C_ARGS]] = !{![[CAP_C:[0-9]+]], ![[CON_LAM_C:[0-9]+]]} // CHECK: ![[CAP_C]] = !DIDerivedType(tag: DW_TAG_member, name: "x" @@ -86,7 +86,7 @@ int d(int x) { D y[10]; return [x,y] { return y[x].x; }(); } // CHECK: ![[D_FUNC:.*]] = distinct !DISubprogram(name: "d"{{.*}}, line: [[D_LINE:[0-9]+]]{{.*}}, isDefinition: true // Back to D. -- 24 -// CHECK: ![[LAM_D:.*]] = !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[D_FUNC]]{{.*}}, line: [[D_LINE]], +// CHECK: ![[LAM_D:.*]] = distinct !DICompositeType(tag: DW_TAG_class_type{{.*}}, scope: ![[D_FUNC]]{{.*}}, line: [[D_LINE]], // CHECK-SAME: elements: ![[LAM_D_ARGS:[0-9]+]] // CHECK: ![[LAM_D_ARGS]] = !{![[CAP_D_X:[0-9]+]], ![[CAP_D_Y:[0-9]+]], ![[CON_LAM_D:[0-9]+]]} // CHECK: ![[CAP_D_X]] = !DIDerivedType(tag: DW_TAG_member, name: "x" diff --git a/clang/test/Modules/ExtDebugInfo.cpp b/clang/test/Modules/ExtDebugInfo.cpp index 3b4547a8..6c38e7f 100644 --- a/clang/test/Modules/ExtDebugInfo.cpp +++ b/clang/test/Modules/ExtDebugInfo.cpp @@ -91,11 +91,11 @@ void foo() { // CHECK: !DIGlobalVariable(name: "GlobalUnion", // CHECK-SAME: type: ![[GLOBAL_UNION:[0-9]+]] -// CHECK: ![[GLOBAL_UNION]] = !DICompositeType(tag: DW_TAG_union_type, +// CHECK: ![[GLOBAL_UNION]] = distinct !DICompositeType(tag: DW_TAG_union_type, // CHECK-SAME: elements: !{{[0-9]+}}) // CHECK: !DIGlobalVariable(name: "GlobalStruct", // CHECK-SAME: type: ![[GLOBAL_STRUCT:[0-9]+]] -// CHECK: ![[GLOBAL_STRUCT]] = !DICompositeType(tag: DW_TAG_structure_type, +// CHECK: ![[GLOBAL_STRUCT]] = distinct !DICompositeType(tag: DW_TAG_structure_type, // CHECK-SAME: elements: !{{[0-9]+}}) // CHECK: !DIGlobalVariable(name: "anon", diff --git a/clang/test/Modules/ExtDebugInfo.m b/clang/test/Modules/ExtDebugInfo.m index d758bfd..3b907ac 100644 --- a/clang/test/Modules/ExtDebugInfo.m +++ b/clang/test/Modules/ExtDebugInfo.m @@ -32,12 +32,12 @@ int foo(ObjCClass *c) { // CHECK: !DIGlobalVariable(name: "GlobalUnion", // CHECK-SAME: type: ![[GLOBAL_UNION:[0-9]+]] // CHECK: ![[MOD:.*]] = !DIModule(scope: null, name: "DebugObjC -// CHECK: ![[GLOBAL_UNION]] = !DICompositeType(tag: DW_TAG_union_type, +// CHECK: ![[GLOBAL_UNION]] = distinct !DICompositeType(tag: DW_TAG_union_type, // CHECK-SAME: elements: !{{[0-9]+}}) // CHECK: !DIGlobalVariable(name: "GlobalStruct", // CHECK-SAME: type: ![[GLOBAL_STRUCT:[0-9]+]] -// CHECK: ![[GLOBAL_STRUCT]] = !DICompositeType(tag: DW_TAG_structure_type, +// CHECK: ![[GLOBAL_STRUCT]] = distinct !DICompositeType(tag: DW_TAG_structure_type, // CHECK-SAME: elements: !{{[0-9]+}}) // CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "TypedefUnion", diff --git a/clang/test/Modules/ModuleDebugInfo.m b/clang/test/Modules/ModuleDebugInfo.m index 02ae93f..360db91 100644 --- a/clang/test/Modules/ModuleDebugInfo.m +++ b/clang/test/Modules/ModuleDebugInfo.m @@ -50,7 +50,7 @@ // CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "FwdDeclared" // CHECK-SAME: elements: -// CHECK: ![[TD_UNION:.*]] = !DICompositeType(tag: DW_TAG_union_type, +// CHECK: ![[TD_UNION:.*]] = distinct !DICompositeType(tag: DW_TAG_union_type, // CHECK-NOT: name: // CHECK-SAME: elements: // CHECK-SAME: ) @@ -61,7 +61,7 @@ // CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "TypedefEnum", // CHECK-SAME: baseType: ![[TD_ENUM:.*]]) -// CHECK: ![[TD_STRUCT:.*]] = !DICompositeType(tag: DW_TAG_structure_type, +// CHECK: ![[TD_STRUCT:.*]] = distinct !DICompositeType(tag: DW_TAG_structure_type, // CHECK-NOT: name: // CHECK-SAME: elements: // CHECK: !DIDerivedType(tag: DW_TAG_typedef, name: "TypedefStruct", -- 2.7.4