This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++ PATCH] Optimize C++ comdat ctors/dtors in classes without virtual bases (PR c++/3187, take 3)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Jason Merrill <jason at redhat dot com>
- Cc: gcc-patches at gcc dot gnu dot org
- Date: Mon, 30 Nov 2009 17:36:53 -0500
- Subject: [C++ PATCH] Optimize C++ comdat ctors/dtors in classes without virtual bases (PR c++/3187, take 3)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
Here is the latest version of the cdtor optimization patch.
The comdat group name is *[CD]5* and if the dtor is virtual, deleting dtor
is emitted into that comdat group as well.
libstdc++ symbol version script has been adjusted, so that it exports
exactly what it used to export before this patch.
On x86_64-linux this patch saves 21KB of libstdc++.so's .text.
Bootstrapped/regtested on x86_64-linux, ok for trunk?
2009-11-30 Jakub Jelinek <jakub@redhat.com>
PR c++/3187
* optimize.c (cdtor_comdat_group): New function.
(maybe_clone_body): Also optimize DECL_COMDAT base/complete cdtors
and in that case put also the deleting dtor in the same comdat group
as base and complete dtor if dtor is virtual.
* config/abi/pre/gnu.ver: Don't export certain base dtors that
weren't previously exported.
--- gcc/cp/optimize.c.jj 2009-11-30 15:53:13.000000000 +0100
+++ gcc/cp/optimize.c 2009-11-30 19:18:51.000000000 +0100
@@ -142,6 +142,46 @@ build_delete_destructor_body (tree delet
}
}
+/* Return name of comdat group for complete and base ctor (or dtor)
+ that have the same body. If dtor is virtual, deleting dtor goes
+ into this comdat group as well. */
+
+static tree
+cdtor_comdat_group (tree complete, tree base)
+{
+ tree complete_name = DECL_COMDAT_GROUP (complete);
+ tree base_name = DECL_COMDAT_GROUP (base);
+ char *grp_name;
+ const char *p, *q;
+ bool diff_seen = false;
+ size_t idx;
+ if (complete_name == NULL)
+ complete_name = cxx_comdat_group (complete);
+ if (base_name == NULL)
+ base_name = cxx_comdat_group (base);
+ gcc_assert (IDENTIFIER_LENGTH (complete_name)
+ == IDENTIFIER_LENGTH (base_name));
+ grp_name = XALLOCAVEC (char, IDENTIFIER_LENGTH (complete_name) + 1);
+ p = IDENTIFIER_POINTER (complete_name);
+ q = IDENTIFIER_POINTER (base_name);
+ for (idx = 0; idx < IDENTIFIER_LENGTH (complete_name); idx++)
+ if (p[idx] == q[idx])
+ grp_name[idx] = p[idx];
+ else
+ {
+ gcc_assert (!diff_seen
+ && idx > 0
+ && (p[idx - 1] == 'C' || p[idx - 1] == 'D')
+ && p[idx] == '1'
+ && q[idx] == '2');
+ grp_name[idx] = '5';
+ diff_seen = true;
+ }
+ grp_name[idx] = '\0';
+ gcc_assert (diff_seen);
+ return get_identifier (grp_name);
+}
+
/* FN is a function that has a complete body. Clone the body as
necessary. Returns nonzero if there's no longer any need to
process the main body. */
@@ -149,6 +189,7 @@ build_delete_destructor_body (tree delet
bool
maybe_clone_body (tree fn)
{
+ tree comdat_group = NULL_TREE;
tree clone;
tree fns[3];
bool first = true;
@@ -248,12 +289,28 @@ maybe_clone_body (tree fn)
&& idx == 1
&& !flag_use_repository
&& DECL_INTERFACE_KNOWN (fns[0])
- && !DECL_ONE_ONLY (fns[0])
+ && (SUPPORTS_ONE_ONLY || !DECL_WEAK (fns[0]))
+ && (!DECL_ONE_ONLY (fns[0])
+ || (HAVE_COMDAT_GROUP && DECL_WEAK (fns[0])))
&& cgraph_same_body_alias (clone, fns[0]))
{
alias = true;
+ if (DECL_ONE_ONLY (fns[0]))
+ {
+ /* For comdat base and complete cdtors put them
+ into the same, *[CD]5* comdat group instead of
+ *[CD][12]*. */
+ comdat_group = cdtor_comdat_group (fns[1], fns[0]);
+ DECL_COMDAT_GROUP (fns[0]) = comdat_group;
+ DECL_COMDAT_GROUP (fns[1]) = comdat_group;
+ }
emit_associated_thunks (clone);
}
+ else if (idx == 2 && comdat_group)
+ /* If *[CD][12]* dtors go into the *[CD]5* comdat group
+ and dtor is virtual, it goes into the same comdat group
+ as well. */
+ DECL_COMDAT_GROUP (fns[2]) = comdat_group;
/* Build the delete destructor by calling complete destructor
and delete function. */
--- libstdc++-v3/config/abi/pre/gnu.ver.jj 2009-11-12 14:14:03.000000000 +0100
+++ libstdc++-v3/config/abi/pre/gnu.ver 2009-11-30 20:47:34.000000000 +0100
@@ -72,13 +72,18 @@ GLIBCXX_3.4 {
std::c[v-z]*;
# std::[d-g]*;
std::d[a-d]*;
- std::d[f-z]*;
+ std::d[f-n]*;
+ std::domain_error::d*;
+# std::domain_error::~d*;
+ std::d[p-z]*;
std::e[a-q]*;
std::error[^_]*;
std::e[s-z]*;
std::gslice*;
std::h[^a]*;
- std::i[a-n]*;
+ std::i[a-m]*;
+ std::invalid_argument::i*;
+# std::invalid_argument::~i*;
# std::ios_base::[A-Ha-z]*;
std::ios_base::[A-Ha-f]*;
std::ios_base::goodbit;
@@ -94,7 +99,8 @@ GLIBCXX_3.4 {
std::istrstream*;
std::i[t-z]*;
std::[A-Zj-k]*;
- std::length_error*;
+ std::length_error::l*;
+# std::length_error::~l*;
std::logic_error*;
std::locale::[A-Za-e]*;
std::locale::facet::[A-Za-z]*;
@@ -122,10 +128,14 @@ GLIBCXX_3.4 {
std::nu[^m]*;
std::num[^e]*;
std::ostrstream*;
- std::out_of_range*;
- std::overflow_error*;
+ std::out_of_range::o*;
+# std::out_of_range::~o*;
+ std::overflow_error::o*;
+# std::overflow_error::~o*;
# std::[p-q]*;
- std::r[^e]*;
+ std::r[^ae]*;
+ std::range_error::r*;
+# std::range_error::~r*;
std::re[^t]*;
# std::rethrow_exception
std::set_new_handler*;
@@ -143,7 +153,8 @@ GLIBCXX_3.4 {
std::tr1::h[^a]*;
std::t[s-z]*;
# std::[A-Zu-z]*;
- std::underflow_error*;
+ std::underflow_error::u*;
+# std::underflow_error::~u*;
std::uncaught_exception*;
std::unexpected*;
std::[A-Zv-z]*;
@@ -284,7 +295,8 @@ GLIBCXX_3.4 {
_ZNSt15basic_streambufI[cw]St11char_traitsI[cw]EEaSERKS2_;
# std::basic_stringbuf
- _ZNSt15basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EE[CD]*;
+ _ZNSt15basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EEC*;
+ _ZNSt15basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EED[^2]*;
_ZNSt15basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EE[0-9][a-r]*;
_ZNSt15basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EE[0-9]seek*;
_ZNSt15basic_stringbufI[cw]St11char_traitsI[cw]ESaI[cw]EE[0-9]set*;
@@ -639,6 +651,16 @@ GLIBCXX_3.4 {
_ZGVNSt[^1]*;
_ZGVNSt1[^7]*;
+ # complete and deleting destructors where base destructors should not
+ # be exported.
+ _ZNSt11range_errorD[01]Ev;
+ _ZNSt12domain_errorD[01]Ev;
+ _ZNSt12length_errorD[01]Ev;
+ _ZNSt12out_of_rangeD[01]Ev;
+ _ZNSt14overflow_errorD[01]Ev;
+ _ZNSt15underflow_errorD[01]Ev;
+ _ZNSt16invalid_argumentD[01]Ev;
+
# virtual function thunks
_ZThn8_NS*;
_ZThn16_NS*;
@@ -891,7 +913,8 @@ GLIBCXX_3.4.10 {
_ZNSt15basic_streambufI[cw]St11char_traitsI[cw]EE6stosscEv;
_ZN9__gnu_cxx18stdio_sync_filebufI[cw]St11char_traitsI[cw]EE4syncEv;
- _ZN9__gnu_cxx18stdio_sync_filebufI[cw]St11char_traitsI[cw]EE[5-9CD]*;
+ _ZN9__gnu_cxx18stdio_sync_filebufI[cw]St11char_traitsI[cw]EE[5-9C]*;
+ _ZN9__gnu_cxx18stdio_sync_filebufI[cw]St11char_traitsI[cw]EED[^2]*;
} GLIBCXX_3.4.9;
Jakub