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]

[PATCH] Also optimize DECL_ONE_ONLY cdtors (PR c++/3187, take 2)


Hi!

On Fri, Nov 13, 2009 at 07:07:08PM +0100, Jakub Jelinek wrote:
> This patch on top of the patch I've just sent also optimizes comdat
> cdtors if HAVE_COMDAT_GROUP and the symbols are weak.
> If the cdtors have the same body, we always force both the function and
> alias to be created whenever one of them is needed, and use a different
> comdat group name *C.* instead of *C1* and *C2* (and similarly for D[.12]).
> When not mixing object files from different compilers we save space, if we
> mix files from different compilers we risk that both this *C.* comdat group
> will stay and also both the *C1* and *C2* from other compiler.
> To avoid that we'd need to invent a linker extension.
> 
> I'm posting this separately from the patch because Jason wanted to discuss
> this on the ABI list first.

Here is an updated patch on top of the patch I've just sent,
bootstrapped/regtested on x86_64-linux and i686-linux.
The same caveats apply (libstdc++ exports need small tweaking to avoid
abi_check FAIL).

2009-11-16  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.

	* g++.dg/abi/mangle1.C: Allow _ZN1AC2Ev and _ZN1BC2Ev to be
	emitted as aliases to _ZN1AC1Ev resp. _ZN1BC2Ev.

--- gcc/cp/optimize.c.jj	2009-11-16 11:38:00.000000000 +0100
+++ gcc/cp/optimize.c	2009-11-16 13:43:40.000000000 +0100
@@ -142,6 +142,45 @@ build_delete_destructor_body (tree delet
     }
 }
 
+/* Return name of comdat group for complete and base ctor (or dtor)
+   that have the same body.  */
+
+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] = '.';
+	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.  */
@@ -248,9 +287,18 @@ maybe_clone_body (tree fn)
 	  && idx == 1
 	  && !flag_use_repository
 	  && DECL_INTERFACE_KNOWN (fns[0])
-	  && !DECL_ONE_ONLY (fns[0])
 	  && cgraph_same_body_alias (clone, fns[0]))
-	alias = true;
+	{
+	  alias = true;
+	  if (DECL_ONE_ONLY (fns[0])
+	      && DECL_WEAK (fns[0])
+	      && HAVE_COMDAT_GROUP)
+	    {
+	      DECL_COMDAT_GROUP (fns[0])
+		= cdtor_comdat_group (fns[0], fns[1]);
+	      DECL_COMDAT_GROUP (fns[1]) = DECL_COMDAT_GROUP (fns[0]);
+	    }
+	}
 
       /* Build the delete destructor by calling complete destructor
          and delete function.  */
--- gcc/testsuite/g++.dg/abi/mangle1.C.jj	2008-09-30 16:55:21.000000000 +0200
+++ gcc/testsuite/g++.dg/abi/mangle1.C	2009-11-16 15:34:22.000000000 +0100
@@ -13,8 +13,8 @@ struct C: public B { };
 C c;
 
 // { dg-final { scan-assembler "\n_?_ZN1A1fEv\[: \t\n\]" } }
-// { dg-final { scan-assembler "\n_?_ZN1AC2Ev\[: \t\n\]" } }
-// { dg-final { scan-assembler "\n_?_ZN1BC2Ev\[: \t\n\]" } }
+// { dg-final { scan-assembler "\n_?_ZN1AC\[12\]Ev\[: \t\n\]" } }
+// { dg-final { scan-assembler "\n_?_ZN1BC\[12\]Ev\[: \t\n\]" } }
 // { dg-final { scan-assembler "\n_?_ZN1CC1Ev\[: \t\n\]" } }
 // { dg-final { scan-assembler "\n_?_ZTC1C0_1B\[: \t\n\]" } }
 // { dg-final { scan-assembler "\n_?_ZTI1A\[: \t\n\]" } }


	Jakub


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