https://github.com/dwblaikie updated https://github.com/llvm/llvm-project/pull/87018
>From 6834c245205d1e38a615e97217dada3cd941ed03 Mon Sep 17 00:00:00 2001 From: David Blaikie <dblai...@gmail.com> Date: Fri, 2 Jun 2023 15:04:14 +0000 Subject: [PATCH 1/3] [DebugInfo] Add flag to only emit referenced member functions Complete C++ type information can be quite expensive - and there's limited value in representing every member function, even those that can't be called (we don't do similarly for every non-member function anyway). So add a flag to opt out of this behavior for experimenting with this more terse behavior. I think Sony already does this by default, so perhaps with a change to the defaults, Sony can migrate to this rather than a downstream patch. This breaks current debuggers in some expected ways - but those breakages are visible without this feature too. Consider member function template instantiations - they can't be consistently enumerated in every translation unit: a.h: ``` struct t1 { template <int i> static int f1() { return i; } }; namespace ns { template <int i> int f1() { return i; } } // namespace ns ``` a.cpp: ``` void f1() { t1::f1<0>(); ns::f1<0>(); } ``` b.cpp: ``` void f1(); int main() { f1(); t1::f1<1>(); ns::f1<1>(); } ``` ``` (gdb) p ns::f1<0>() $1 = 0 (gdb) p ns::f1<1>() $2 = 1 (gdb) p t1::f1<0>() Couldn't find method t1::f1<0> (gdb) p t1::f1<1>() $3 = 1 (gdb) s f1 () at a.cpp:3 3 t1::f1<0>(); (gdb) p t1::f1<0>() $4 = 0 (gdb) p t1::f1<1>() Couldn't find method t1::f1<1> (gdb) ``` (other similar non-canonical features are implicit special members (copy/move ctor/assignment operator, default ctor) and nested types (eg: pimpl idiom, where the nested type is declared-but-not-defined in one TU, and defined in another TU)) lldb can't parse the template expressions above, so I'm not sure how to test it there, but I'd guess it has similar problems. ( https://stackoverflow.com/questions/64602475/how-to-print-value-returned-by-template-member-function-in-gdb-lldb-debugging so... I guess that's just totally not supported in lldb, how unfortunate. And implicit special members are instantiated implicitly by lldb, so missing those doesn't tickle the same issue) Some very rudimentary numbers for a clang debug build: .debug_info section size: -g: 476MiB -g -fdebug-types-section: 357MiB -g -gomit-unreferenced-members: 340MiB Though it also means a major reduction in .debug_str size, -fdebug-types-section doesn't reduce string usage (so the first two examples have the same .debug_str size, 247MiB), down to 175MiB. So for total clang binary size (I don't have a quick "debug section size reduction" on-hand): 1.45 (no type units) GiB -> 1.34 -> 1.22, so it saves about 120MiB of binary size. Also open to any riffing on the flag name for sure. @probinson - would this be an accurate upstreaming of your internal handling/would you use this functionality? If it wouldn't be useful to you, it's maybe not worth adding upstream yet - not sure we'll use it at Google, but if it was useful to you folks and meant other folks could test with it it seemed maybe useful. Original Differential Revision: https://reviews.llvm.org/D152017 --- clang/include/clang/Basic/DebugOptions.def | 2 ++ clang/include/clang/Driver/Options.td | 7 +++++++ clang/lib/CodeGen/CGDebugInfo.cpp | 2 +- clang/lib/Driver/ToolChains/Clang.cpp | 6 ++++++ .../test/CodeGenCXX/debug-info-incomplete-types.cpp | 12 ++++++++++++ clang/test/Driver/debug-options.c | 6 ++++++ 6 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 clang/test/CodeGenCXX/debug-info-incomplete-types.cpp diff --git a/clang/include/clang/Basic/DebugOptions.def b/clang/include/clang/Basic/DebugOptions.def index 7cd3edf08a17e..fe2adaa20f4e3 100644 --- a/clang/include/clang/Basic/DebugOptions.def +++ b/clang/include/clang/Basic/DebugOptions.def @@ -68,6 +68,8 @@ BENIGN_DEBUGOPT(NoInlineLineTables, 1, 0) ///< Whether debug info should contain ///< inline line tables. DEBUGOPT(DebugStrictDwarf, 1, 1) ///< Whether or not to use strict DWARF info. +DEBUGOPT(DebugOmitUnreferencedMembers, 1, 0) ///< Omit unreferenced member + ///< functions in type debug info. /// Control the Assignment Tracking debug info feature. BENIGN_ENUM_DEBUGOPT(AssignmentTrackingMode, AssignmentTrackingOpts, 2, diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 29066ea14280c..4000403a1991d 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4260,6 +4260,13 @@ defm strict_dwarf : BoolOption<"g", "strict-dwarf", "the specified version, avoiding features from later versions.">, NegFlag<SetFalse>, BothFlags<[], [ClangOption, CLOption, DXCOption]>>, Group<g_flags_Group>; +defm omit_unreferenced_members : BoolOption<"g", "omit-unreferenced-members", + CodeGenOpts<"DebugOmitUnreferencedMembers">, DefaultFalse, + PosFlag<SetTrue, [], [ClangOption, CC1Option], + "Omit member function declarations from type descriptions if the " + "member is unreferenced.">, + NegFlag<SetFalse>, BothFlags<[], [ClangOption, CLOption, DXCOption]>>, + Group<g_flags_Group>; defm column_info : BoolOption<"g", "column-info", CodeGenOpts<"DebugColumnInfo">, DefaultTrue, NegFlag<SetFalse, [], [ClangOption, CC1Option]>, diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index 2a385d85aa2bc..b07da0c1309e4 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2755,7 +2755,7 @@ CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { // Collect data fields (including static variables and any initializers). CollectRecordFields(RD, DefUnit, EltTys, FwdDecl); - if (CXXDecl) + if (CXXDecl && !CGM.getCodeGenOpts().DebugOmitUnreferencedMembers) CollectCXXMemberFunctions(CXXDecl, DefUnit, EltTys, FwdDecl); LexicalBlockStack.pop_back(); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 3bcacff7724c7..5ceca0685afed 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4458,6 +4458,12 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T, DebuggerTuning != llvm::DebuggerKind::DBX))) CmdArgs.push_back("-gno-column-info"); + if (const Arg *A = Args.getLastArg(options::OPT_gomit_unreferenced_members)) + (void)checkDebugInfoOption(A, Args, D, TC); + if (Args.hasFlag(options::OPT_gomit_unreferenced_members, + options::OPT_gno_omit_unreferenced_members, false)) + CmdArgs.push_back("-gomit-unreferenced-members"); + // FIXME: Move backend command line options to the module. if (Args.hasFlag(options::OPT_gmodules, options::OPT_gno_modules, false)) { // If -gline-tables-only or -gline-directives-only is the last option it diff --git a/clang/test/CodeGenCXX/debug-info-incomplete-types.cpp b/clang/test/CodeGenCXX/debug-info-incomplete-types.cpp new file mode 100644 index 0000000000000..0138a82adbf3b --- /dev/null +++ b/clang/test/CodeGenCXX/debug-info-incomplete-types.cpp @@ -0,0 +1,12 @@ +// RUN: %clang_cc1 -debug-info-kind=limited -gomit-unreferenced-members %s -emit-llvm -o - | FileCheck %s + +struct t1 { + void f1(); + void f2(); +}; + +void t1::f1() { } + +// CHECK: distinct !DICompositeType(tag: DW_TAG_structure_type, name: "t1" +// CHECK-SAME: elements: [[ELEMENTS:![0-9]+]] +// CHECK: [[ELEMENTS]] = !{} diff --git a/clang/test/Driver/debug-options.c b/clang/test/Driver/debug-options.c index e4809511ac91a..45ff547666992 100644 --- a/clang/test/Driver/debug-options.c +++ b/clang/test/Driver/debug-options.c @@ -242,6 +242,9 @@ // RUN: %clang -### -c %s 2>&1 | FileCheck -check-prefix=NORNGBSE %s // RUN: %clang -### -c -fdebug-ranges-base-address -fno-debug-ranges-base-address %s 2>&1 | FileCheck -check-prefix=NORNGBSE %s // +// RUN: %clang -### -c -gomit-unreferenced-members %s 2>&1 | FileCheck -check-prefix=INCTYPES %s +// RUN: %clang -### -c %s 2>&1 | FileCheck -check-prefix=NOINCTYPES %s +// // RUN: %clang -### -c -glldb %s 2>&1 | FileCheck -check-prefix=NOPUB %s // RUN: %clang -### -c -glldb -gno-pubnames %s 2>&1 | FileCheck -check-prefix=NOPUB %s // @@ -381,6 +384,9 @@ // RNGBSE: -fdebug-ranges-base-address // NORNGBSE-NOT: -fdebug-ranges-base-address // +// INCTYPES: -gincomplete-types +// NOINCTYPES-NOT: -gincomplete-types +// // GARANGE-DAG: -generate-arange-section // // FDTS: "-mllvm" "-generate-type-units" >From 016d54485d6fed3ddf61f1b31d2fc56a432e1b35 Mon Sep 17 00:00:00 2001 From: David Blaikie <dblai...@gmail.com> Date: Thu, 23 May 2024 00:10:50 +0000 Subject: [PATCH 2/3] Addressing code review feedback * Rename to -gomit-unreferenced-methods * Use BoolGOption to simplify flag def --- clang/include/clang/Basic/DebugOptions.def | 2 +- clang/include/clang/Driver/Options.td | 11 ++++------- clang/lib/CodeGen/CGDebugInfo.cpp | 2 +- clang/lib/Driver/ToolChains/Clang.cpp | 9 +++++---- clang/test/CodeGenCXX/debug-info-incomplete-types.cpp | 2 +- clang/test/Driver/debug-options.c | 6 +++--- 6 files changed, 15 insertions(+), 17 deletions(-) diff --git a/clang/include/clang/Basic/DebugOptions.def b/clang/include/clang/Basic/DebugOptions.def index fe2adaa20f4e3..6ad8fb81f90a9 100644 --- a/clang/include/clang/Basic/DebugOptions.def +++ b/clang/include/clang/Basic/DebugOptions.def @@ -68,7 +68,7 @@ BENIGN_DEBUGOPT(NoInlineLineTables, 1, 0) ///< Whether debug info should contain ///< inline line tables. DEBUGOPT(DebugStrictDwarf, 1, 1) ///< Whether or not to use strict DWARF info. -DEBUGOPT(DebugOmitUnreferencedMembers, 1, 0) ///< Omit unreferenced member +DEBUGOPT(DebugOmitUnreferencedMethods, 1, 0) ///< Omit unreferenced member ///< functions in type debug info. /// Control the Assignment Tracking debug info feature. diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 4000403a1991d..8b737c8992ff0 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -4260,13 +4260,10 @@ defm strict_dwarf : BoolOption<"g", "strict-dwarf", "the specified version, avoiding features from later versions.">, NegFlag<SetFalse>, BothFlags<[], [ClangOption, CLOption, DXCOption]>>, Group<g_flags_Group>; -defm omit_unreferenced_members : BoolOption<"g", "omit-unreferenced-members", - CodeGenOpts<"DebugOmitUnreferencedMembers">, DefaultFalse, - PosFlag<SetTrue, [], [ClangOption, CC1Option], - "Omit member function declarations from type descriptions if the " - "member is unreferenced.">, - NegFlag<SetFalse>, BothFlags<[], [ClangOption, CLOption, DXCOption]>>, - Group<g_flags_Group>; +defm omit_unreferenced_methods : BoolGOption<"omit-unreferenced-methods", + CodeGenOpts<"DebugOmitUnreferencedMethods">, DefaultFalse, + NegFlag<SetFalse>, + PosFlag<SetTrue, [], [CC1Option]>, BothFlags<[], [ClangOption, CLOption, DXCOption]>>; defm column_info : BoolOption<"g", "column-info", CodeGenOpts<"DebugColumnInfo">, DefaultTrue, NegFlag<SetFalse, [], [ClangOption, CC1Option]>, diff --git a/clang/lib/CodeGen/CGDebugInfo.cpp b/clang/lib/CodeGen/CGDebugInfo.cpp index b07da0c1309e4..a368f6c54e21d 100644 --- a/clang/lib/CodeGen/CGDebugInfo.cpp +++ b/clang/lib/CodeGen/CGDebugInfo.cpp @@ -2755,7 +2755,7 @@ CGDebugInfo::CreateTypeDefinition(const RecordType *Ty) { // Collect data fields (including static variables and any initializers). CollectRecordFields(RD, DefUnit, EltTys, FwdDecl); - if (CXXDecl && !CGM.getCodeGenOpts().DebugOmitUnreferencedMembers) + if (CXXDecl && !CGM.getCodeGenOpts().DebugOmitUnreferencedMethods) CollectCXXMemberFunctions(CXXDecl, DefUnit, EltTys, FwdDecl); LexicalBlockStack.pop_back(); diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 5ceca0685afed..9ae8bb52bfc40 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4458,11 +4458,12 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T, DebuggerTuning != llvm::DebuggerKind::DBX))) CmdArgs.push_back("-gno-column-info"); - if (const Arg *A = Args.getLastArg(options::OPT_gomit_unreferenced_members)) + if (const Arg *A = + Args.getLastArg(options::OPT_gomit_unreferenced_methods, + options::OPT_gno_omit_unreferenced_methods)) (void)checkDebugInfoOption(A, Args, D, TC); - if (Args.hasFlag(options::OPT_gomit_unreferenced_members, - options::OPT_gno_omit_unreferenced_members, false)) - CmdArgs.push_back("-gomit-unreferenced-members"); + Args.addOptInFlag(CmdArgs, options::OPT_gomit_unreferenced_methods, + options::OPT_gno_omit_unreferenced_methods); // FIXME: Move backend command line options to the module. if (Args.hasFlag(options::OPT_gmodules, options::OPT_gno_modules, false)) { diff --git a/clang/test/CodeGenCXX/debug-info-incomplete-types.cpp b/clang/test/CodeGenCXX/debug-info-incomplete-types.cpp index 0138a82adbf3b..0bf59233b4e2e 100644 --- a/clang/test/CodeGenCXX/debug-info-incomplete-types.cpp +++ b/clang/test/CodeGenCXX/debug-info-incomplete-types.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -debug-info-kind=limited -gomit-unreferenced-members %s -emit-llvm -o - | FileCheck %s +// RUN: %clang_cc1 -debug-info-kind=limited -gomit-unreferenced-methods %s -emit-llvm -o - | FileCheck %s struct t1 { void f1(); diff --git a/clang/test/Driver/debug-options.c b/clang/test/Driver/debug-options.c index 45ff547666992..d0c224bac434d 100644 --- a/clang/test/Driver/debug-options.c +++ b/clang/test/Driver/debug-options.c @@ -242,7 +242,7 @@ // RUN: %clang -### -c %s 2>&1 | FileCheck -check-prefix=NORNGBSE %s // RUN: %clang -### -c -fdebug-ranges-base-address -fno-debug-ranges-base-address %s 2>&1 | FileCheck -check-prefix=NORNGBSE %s // -// RUN: %clang -### -c -gomit-unreferenced-members %s 2>&1 | FileCheck -check-prefix=INCTYPES %s +// RUN: %clang -### -c -gomit-unreferenced-methods %s 2>&1 | FileCheck -check-prefix=INCTYPES %s // RUN: %clang -### -c %s 2>&1 | FileCheck -check-prefix=NOINCTYPES %s // // RUN: %clang -### -c -glldb %s 2>&1 | FileCheck -check-prefix=NOPUB %s @@ -384,8 +384,8 @@ // RNGBSE: -fdebug-ranges-base-address // NORNGBSE-NOT: -fdebug-ranges-base-address // -// INCTYPES: -gincomplete-types -// NOINCTYPES-NOT: -gincomplete-types +// INCTYPES: -gomit-unreferenced-methods +// NOINCTYPES-NOT: -gomit-unreferenced-methods // // GARANGE-DAG: -generate-arange-section // >From 19cf317193817a399cbe6e66ee8efbc8f406784c Mon Sep 17 00:00:00 2001 From: David Blaikie <dblai...@gmail.com> Date: Fri, 24 May 2024 15:08:39 +0000 Subject: [PATCH 3/3] disable -gomit-unreferenced-methods when using -fstandalone-debug or -fdebug-types-section --- clang/lib/Driver/ToolChains/Clang.cpp | 22 +++++++++++++++------- clang/test/Driver/debug-options.c | 2 ++ 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index 9ae8bb52bfc40..a504a0948ba5c 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -45,6 +45,7 @@ #include "llvm/ADT/StringExtras.h" #include "llvm/BinaryFormat/Magic.h" #include "llvm/Config/llvm-config.h" +#include "llvm/Frontend/Debug/Options.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Option/ArgList.h" #include "llvm/Support/CodeGen.h" @@ -4458,13 +4459,6 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T, DebuggerTuning != llvm::DebuggerKind::DBX))) CmdArgs.push_back("-gno-column-info"); - if (const Arg *A = - Args.getLastArg(options::OPT_gomit_unreferenced_methods, - options::OPT_gno_omit_unreferenced_methods)) - (void)checkDebugInfoOption(A, Args, D, TC); - Args.addOptInFlag(CmdArgs, options::OPT_gomit_unreferenced_methods, - options::OPT_gno_omit_unreferenced_methods); - // FIXME: Move backend command line options to the module. if (Args.hasFlag(options::OPT_gmodules, options::OPT_gno_modules, false)) { // If -gline-tables-only or -gline-directives-only is the last option it @@ -4613,6 +4607,7 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T, Args.addOptInFlag(CmdArgs, options::OPT_fforce_dwarf_frame, options::OPT_fno_force_dwarf_frame); + bool EnableTypeUnits = false; if (Args.hasFlag(options::OPT_fdebug_types_section, options::OPT_fno_debug_types_section, false)) { if (!(T.isOSBinFormatELF() || T.isOSBinFormatWasm())) { @@ -4623,11 +4618,24 @@ renderDebugOptions(const ToolChain &TC, const Driver &D, const llvm::Triple &T, } else if (checkDebugInfoOption( Args.getLastArg(options::OPT_fdebug_types_section), Args, D, TC)) { + EnableTypeUnits = true; CmdArgs.push_back("-mllvm"); CmdArgs.push_back("-generate-type-units"); } } + if (const Arg *A = + Args.getLastArg(options::OPT_gomit_unreferenced_methods, + options::OPT_gno_omit_unreferenced_methods)) + (void)checkDebugInfoOption(A, Args, D, TC); + if (Args.hasFlag(options::OPT_gomit_unreferenced_methods, + options::OPT_gno_omit_unreferenced_methods, false) && + (DebugInfoKind == llvm::codegenoptions::DebugInfoConstructor || + DebugInfoKind == llvm::codegenoptions::LimitedDebugInfo) && + !EnableTypeUnits) { + CmdArgs.push_back("-gomit-unreferenced-methods"); + } + // To avoid join/split of directory+filename, the integrated assembler prefers // the directory form of .file on all DWARF versions. GNU as doesn't allow the // form before DWARF v5. diff --git a/clang/test/Driver/debug-options.c b/clang/test/Driver/debug-options.c index d0c224bac434d..f46a418733c88 100644 --- a/clang/test/Driver/debug-options.c +++ b/clang/test/Driver/debug-options.c @@ -244,6 +244,8 @@ // // RUN: %clang -### -c -gomit-unreferenced-methods %s 2>&1 | FileCheck -check-prefix=INCTYPES %s // RUN: %clang -### -c %s 2>&1 | FileCheck -check-prefix=NOINCTYPES %s +// RUN: %clang -### -c -gomit-unreferenced-methods -fdebug-types-section %s 2>&1 | FileCheck -check-prefix=NOINCTYPES %s +// RUN: %clang -### -c -gomit-unreferenced-methods -fstandalone-debug %s 2>&1 | FileCheck -check-prefix=NOINCTYPES %s // // RUN: %clang -### -c -glldb %s 2>&1 | FileCheck -check-prefix=NOPUB %s // RUN: %clang -### -c -glldb -gno-pubnames %s 2>&1 | FileCheck -check-prefix=NOPUB %s _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits