From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9022 invoked by alias); 20 Aug 2010 10:21:17 -0000 Received: (qmail 8968 invoked by uid 22791); 20 Aug 2010 10:21:15 -0000 X-SWARE-Spam-Status: No, hits=-1.8 required=5.0 tests=AWL,BAYES_00,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from nikam-dmz.ms.mff.cuni.cz (HELO nikam.ms.mff.cuni.cz) (195.113.20.16) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 20 Aug 2010 10:21:09 +0000 Received: from localhost (occam.ms.mff.cuni.cz [195.113.18.121]) by nikam.ms.mff.cuni.cz (Postfix) with ESMTP id D611E9ACAAC; Fri, 20 Aug 2010 12:21:06 +0200 (CEST) Received: by localhost (Postfix, from userid 16202) id D098956419E; Fri, 20 Aug 2010 12:21:06 +0200 (CEST) Date: Fri, 20 Aug 2010 11:15:00 -0000 From: Jan Hubicka To: gcc-patches@gcc.gnu.org, tglek@mozilla.com Subject: Empty constructor removal Message-ID: <20100820102106.GF18841@kam.mff.cuni.cz> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.18 (2008-05-17) Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org X-SW-Source: 2010-08/txt/msg01547.txt.bz2 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" } } */