From patchwork Tue Nov 16 16:49:22 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Hubicka X-Patchwork-Id: 71432 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 729B1B713D for ; Wed, 17 Nov 2010 03:49:44 +1100 (EST) Received: (qmail 12413 invoked by alias); 16 Nov 2010 16:49:36 -0000 Received: (qmail 12400 invoked by uid 22791); 16 Nov 2010 16:49:33 -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; Tue, 16 Nov 2010 16:49:24 +0000 Received: by nikam.ms.mff.cuni.cz (Postfix, from userid 16202) id 5FED49ACA9B; Tue, 16 Nov 2010 17:49:22 +0100 (CET) Date: Tue, 16 Nov 2010 17:49:22 +0100 From: Jan Hubicka To: gcc-patches@gcc.gnu.org Subject: Fix varpool confussion about what to remove and what not Message-ID: <20101116164922.GB6660@kam.mff.cuni.cz> MIME-Version: 1.0 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-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Hi, this patch makes varpool less confused about removal of unreferenced variables. This is done twice. First as part of cgraph_remove_unreachable_nodes that currently contains a bug that makes it to remove unused vars even with -fno-toplevel-reorder and at varpool_remove_unreferenced_decls (after function bodies has been assembled) that gets -fno-toplevel-reorder but uses decide_is_variable_needed that is intended for varpool_finalize_node use only and is completely confused about whole program and LTO and consequently makes wore decisions with -fuse-linker-plugin than with -fwhole-program. I noticed another bug; we used to mark all variables referenced after late GIMPLE optimization but we don't do this anymore. This makes the dubious DECL_RTL_SET_P neccesary. This check was introduced to work around dwarf2out referencing unreferenced vars. This problem was solved at dwarf2out side some time ago. I will look into this problem incrementally. Boostrapped/regtested x86_64-linux, will commit it later today. * cgraph.h (varpool_can_remove_if_no_refs): Move here from ...; when !flag_toplevel_reorder do not remove unless variable is COMDAT or ARTIFICIAL. * ipa.c (varpool_can_remove_if_no_refs): ... here. (cgraph_remove_unreachable_nodes): Only analyzed nodes needs to stay. * cgraphunit.c (cgraph_analyze_functions): Dump varpool, too. * varpool.c (decide_is_variable_needed): Do not handle visibility issues. (varpool_finalize_decl): Likewise. (varpool_remove_unreferenced_decls): Use varpool_mark_needed_node; update outdated comment on DECL_RTL_SET_P check. Index: cgraph.h =================================================================== --- cgraph.h (revision 166777) +++ cgraph.h (working copy) @@ -928,6 +928,18 @@ cgraph_can_remove_if_no_direct_calls_p ( return !node->address_taken && cgraph_can_remove_if_no_direct_calls_and_refs_p (node); } +/* Return true when function NODE can be removed from callgraph + if all direct calls are eliminated. */ + +static inline bool +varpool_can_remove_if_no_refs (struct varpool_node *node) +{ + return (!node->force_output && !node->used_from_other_partition + && (flag_toplevel_reorder || DECL_COMDAT (node->decl) + || DECL_ARTIFICIAL (node->decl)) + && (DECL_COMDAT (node->decl) || !node->externally_visible)); +} + /* Return true when all references to VNODE must be visible in ipa_ref_list. i.e. if the variable is not externally visible or not used in some magic way (asm statement or such). Index: cgraphunit.c =================================================================== --- cgraphunit.c (revision 166777) +++ cgraphunit.c (working copy) @@ -943,6 +943,7 @@ cgraph_analyze_functions (void) fprintf (cgraph_dump_file, " %s", cgraph_node_name (node)); fprintf (cgraph_dump_file, "\n\nInitial "); dump_cgraph (cgraph_dump_file); + dump_varpool (cgraph_dump_file); } if (cgraph_dump_file) @@ -972,6 +973,7 @@ cgraph_analyze_functions (void) { fprintf (cgraph_dump_file, "\n\nReclaimed "); dump_cgraph (cgraph_dump_file); + dump_varpool (cgraph_dump_file); } bitmap_obstack_release (NULL); first_analyzed = cgraph_nodes; @@ -1816,6 +1818,7 @@ cgraph_optimize (void) { fprintf (cgraph_dump_file, "\nFinal "); dump_cgraph (cgraph_dump_file); + dump_varpool (cgraph_dump_file); } #ifdef ENABLE_CHECKING verify_cgraph (); Index: ipa.c =================================================================== --- ipa.c (revision 166777) +++ ipa.c (working copy) @@ -188,16 +188,6 @@ process_references (struct ipa_ref_list } } -/* Return true when function NODE can be removed from callgraph - if all direct calls are eliminated. */ - -static inline bool -varpool_can_remove_if_no_refs (struct varpool_node *node) -{ - return (!node->force_output && !node->used_from_other_partition - && (DECL_COMDAT (node->decl) || !node->externally_visible)); -} - /* Return true when function can be marked local. */ static bool @@ -269,7 +259,8 @@ cgraph_remove_unreachable_nodes (bool be { vnode->next_needed = NULL; vnode->prev_needed = NULL; - if (!varpool_can_remove_if_no_refs (vnode)) + if (vnode->analyzed + && !varpool_can_remove_if_no_refs (vnode)) { vnode->needed = false; varpool_mark_needed_node (vnode); Index: varpool.c =================================================================== --- varpool.c (revision 166777) +++ varpool.c (working copy) @@ -331,31 +331,24 @@ varpool_reset_queue (void) bool decide_is_variable_needed (struct varpool_node *node, tree decl) { - if (node->used_from_other_partition) - return true; /* If the user told us it is used, then it must be so. */ - if ((node->externally_visible && !DECL_COMDAT (decl)) - || node->force_output) + if (node->force_output) return true; + gcc_assert (!DECL_EXTERNAL (decl)); + /* Externally visible variables must be output. The exception is COMDAT variables that must be output only when they are needed. */ if (TREE_PUBLIC (decl) - && !flag_whole_program - && !flag_lto && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) return true; /* When not reordering top level variables, we have to assume that we are going to keep everything. */ - if (flag_toplevel_reorder) - return false; - - /* We want to emit COMDAT variables only when absolutely necessary. */ - if (DECL_COMDAT (decl)) - return false; - return true; + if (!flag_toplevel_reorder) + return true; + return false; } /* Return if DECL is constant and its initial value is known (so we can do @@ -427,11 +420,6 @@ varpool_finalize_decl (tree decl) if (decide_is_variable_needed (node, decl)) varpool_mark_needed_node (node); - /* Since we reclaim unreachable nodes at the end of every language - level unit, we need to be conservative about possible entry points - there. */ - else if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) - varpool_mark_needed_node (node); if (cgraph_global_info_ready) varpool_assemble_pending_decls (); } @@ -557,18 +545,14 @@ varpool_remove_unreferenced_decls (void) while (node) { - tree decl = node->decl; next = node->next_needed; node->needed = 0; - if (node->finalized - && (decide_is_variable_needed (node, decl) - /* ??? Cgraph does not yet rule the world with an iron hand, - and does not control the emission of debug information. - After a variable has its DECL_RTL set, we must assume that - it may be referenced by the debug information, and we can - no longer elide it. */ - || DECL_RTL_SET_P (decl))) + if (node->analyzed + && (!varpool_can_remove_if_no_refs (node) + /* We just expanded all function bodies. See if any of + them needed the variable. */ + || DECL_RTL_SET_P (node->decl))) varpool_mark_needed_node (node); node = next;