This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Empty constructor removal
- From: Jan Hubicka <hubicka at ucw dot cz>
- To: gcc-patches at gcc dot gnu dot org, tglek at mozilla dot com
- Date: Fri, 20 Aug 2010 12:21:06 +0200
- Subject: Empty constructor removal
Hi,
this patch implements removal of pure static constructors and destructors as
discussed in PR45307.
The main part of patch makes DECL_STATIC_CONSTRUCTOR/DECL_STATIC_DESTRUCTOR to
no longer imply needed flag that makes it neccesary to handle them correctly at
few places. Motivation for this change was not the empty constructor removal
idea, but I need it to implement constructor merging pass that is intended to
speedup mozilla (and other large C++ projects) startup times with LTO.
Bootstrapped/regtested x86_64-linux, will commit it tonight if there are no
complains.
PR c++/45307
* cgraph.h (cgraph_only_called_directly_p,
cgraph_can_remove_if_no_direct_calls_and_refs_p): Handle
static cdtors.
* cgraphunit.c (cgraph_decide_is_function_needed): Static cdtors
are not needed.
(cgraph_finalize_function): Static cdtors are reachable.
(cgraph_mark_functions_to_output): Use cgraph_only_called_directly_p.
* gcc.dg/ipa/ctor-empty-1.c: Add testcase.
Index: cgraph.h
===================================================================
*** cgraph.h (revision 163398)
--- cgraph.h (working copy)
*************** varpool_node_set_nonempty_p (varpool_nod
*** 903,909 ****
static inline bool
cgraph_only_called_directly_p (struct cgraph_node *node)
{
! return !node->needed && !node->address_taken && !node->local.externally_visible;
}
/* Return true when function NODE can be removed from callgraph
--- 903,912 ----
static inline bool
cgraph_only_called_directly_p (struct cgraph_node *node)
{
! return (!node->needed && !node->address_taken
! && !DECL_STATIC_CONSTRUCTOR (node->decl)
! && !DECL_STATIC_DESTRUCTOR (node->decl)
! && !node->local.externally_visible);
}
/* Return true when function NODE can be removed from callgraph
*************** cgraph_only_called_directly_p (struct cg
*** 912,919 ****
static inline bool
cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node)
{
! return (!node->needed && !node->reachable_from_other_partition
! && (DECL_COMDAT (node->decl) || !node->local.externally_visible));
}
/* Return true when function NODE can be removed from callgraph
--- 915,938 ----
static inline bool
cgraph_can_remove_if_no_direct_calls_and_refs_p (struct cgraph_node *node)
{
! /* When function is needed, we can not remove it. */
! if (node->needed || node->reachable_from_other_partition)
! return false;
! /* Only COMDAT functions can be removed if externally visible. */
! if (node->local.externally_visible
! && (!DECL_COMDAT (node->decl) || node->local.used_from_object_file))
! return false;
! /* Constructors and destructors are executed by the runtime, however
! we can get rid of all pure constructors and destructors. */
! if (DECL_STATIC_CONSTRUCTOR (node->decl)
! || DECL_STATIC_DESTRUCTOR (node->decl))
! {
! int flags = flags_from_decl_or_type (node->decl);
! if (!(flags & (ECF_CONST | ECF_PURE))
! || (flags & ECF_LOOPING_CONST_OR_PURE))
! return false;
! }
! return true;
}
/* Return true when function NODE can be removed from callgraph
Index: cgraphunit.c
===================================================================
*** cgraphunit.c (revision 163398)
--- cgraphunit.c (working copy)
*************** cgraph_decide_is_function_needed (struct
*** 367,377 ****
&& !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
return true;
- /* Constructors and destructors are reachable from the runtime by
- some mechanism. */
- if (DECL_STATIC_CONSTRUCTOR (decl) || DECL_STATIC_DESTRUCTOR (decl))
- return true;
-
return false;
}
--- 367,372 ----
*************** cgraph_finalize_function (tree decl, boo
*** 532,538 ****
/* Since we reclaim unreachable nodes at the end of every language
level unit, we need to be conservative about possible entry points
there. */
! if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)))
cgraph_mark_reachable_node (node);
/* If we've not yet emitted decl, tell the debug info about it. */
--- 527,535 ----
/* Since we reclaim unreachable nodes at the end of every language
level unit, we need to be conservative about possible entry points
there. */
! if ((TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
! || DECL_STATIC_CONSTRUCTOR (decl)
! || DECL_STATIC_DESTRUCTOR (decl))
cgraph_mark_reachable_node (node);
/* If we've not yet emitted decl, tell the debug info about it. */
*************** cgraph_mark_functions_to_output (void)
*** 1219,1226 ****
outside the current compilation unit. */
if (node->analyzed
&& !node->global.inlined_to
! && (node->needed || node->reachable_from_other_partition
! || node->address_taken
|| (e && node->reachable))
&& !TREE_ASM_WRITTEN (decl)
&& !DECL_EXTERNAL (decl))
--- 1216,1222 ----
outside the current compilation unit. */
if (node->analyzed
&& !node->global.inlined_to
! && (!cgraph_only_called_directly_p (node)
|| (e && node->reachable))
&& !TREE_ASM_WRITTEN (decl)
&& !DECL_EXTERNAL (decl))
Index: testsuite/gcc.dg/ipa/ctor-empty-1.c
===================================================================
*** testsuite/gcc.dg/ipa/ctor-empty-1.c (revision 0)
--- testsuite/gcc.dg/ipa/ctor-empty-1.c (revision 0)
***************
*** 0 ****
--- 1,8 ----
+ /* { dg-do compile } */
+ /* { dg-options "-O3 -c -fdump-ipa-inline" } */
+ __attribute__((constructor))
+ void empty_constructor()
+ {
+ }
+ /* { dg-final { scan-ipa-dump-not "empty_constructor" "inline" } } */
+ /* { dg-final { cleanup-ipa-dump "inline" } } */