This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++ PATCH] Optimize C++ comdat ctors/dtors in classes without virtual bases (PR c++/3187, take 3)


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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]