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 5)
- 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: Tue, 1 Dec 2009 14:22:47 -0500
- Subject: [C++ PATCH] Optimize C++ comdat ctors/dtors in classes without virtual bases (PR c++/3187, take 5)
- References: <20091130223653.GO22813@hs20-bc2-1.build.redhat.com> <20091201094652.GQ22813@hs20-bc2-1.build.redhat.com>
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
Hi!
After discussions on IRC, here is the latest version of the patch.
For now the problematic implicitly defined virtual comdat destructors aren't
optimized, even when the base and complete dtor have the same body, as the
deleting dtor isn't necessarily emitted iff the base/complete dtors are
emitted.
The nice effect of that patch is that the libstdc++ symbol version script
changes aren't needed.
Bootstrapped/regtested on x86_64-linux (with the checking patch on top of
it), ok for trunk?
2009-12-01 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.
--- 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,10 +289,26 @@ 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])
+ /* Don't optimize synthetized virtual dtors, because then
+ the deleting and other dtors are emitted when needed
+ and so it is not certain we would emit both
+ deleting and complete/base dtors in the comdat group. */
+ && (fns[2] == NULL || !DECL_ARTIFICIAL (fn))))
&& 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;
+ }
emit_associated_thunks (clone);
}
@@ -333,6 +390,15 @@ maybe_clone_body (tree fn)
}
pop_from_top_level ();
+ if (comdat_group)
+ {
+ DECL_COMDAT_GROUP (fns[1]) = comdat_group;
+ if (fns[2])
+ /* 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;
+ }
+
/* We don't need to process the original function any further. */
return 1;
}
Jakub