This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Also optimize DECL_ONE_ONLY cdtors (PR c++/3187, take 2)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Jason Merrill <jason at redhat dot com>
- Cc: Benjamin Kosnik <bkoz at redhat dot com>, gcc-patches at gcc dot gnu dot org
- Date: Mon, 16 Nov 2009 18:43:56 +0100
- Subject: [PATCH] Also optimize DECL_ONE_ONLY cdtors (PR c++/3187, take 2)
- References: <20091113180708.GX14664@tyan-ft48-01.lab.bos.redhat.com>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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