This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

At linktime, consider linkonces as ones that will go away


Hi,
this patch makes us more aggressive at optimizing COMDAT functions in LTO and
whole program mode.  Unlike in local compilation, we do not need to worry that
linking many units together will duplicate function very many times as we are
going to have duplication at most in between program and library that is not
too bad or in between DSOs that is even less problem since dynamic linking
does not discard linkonces anyway and we save relocations this way.

In addition to hidden symbol patch this has just small effect on Mozilla (0.2%)
but should help for programs that do not play with visibilities.

The patch probaby has longest function name I ever invented, but I can't think
of something shorter that would not be unreadable.

Bootstrapped/regtested x86_64-linux, will commit it later today.
Honza

	* cgraph.c (cgraph_will_be_removed_from_program_if_no_direct_calls):
	New function.
	* cgraph.h (cgraph_will_be_removed_from_program_if_no_direct_calls):
	Declare.
	* ipa-cp.c (ipcp_estimate_growth): Use it.
	* ipa-inline.c (cgraph_estimate_growth, cgraph_decide_inlining):
	Likewise.
	
Index: cgraph.c
===================================================================
*** cgraph.c	(revision 161905)
--- cgraph.c	(working copy)
*************** cgraph_edge_cannot_lead_to_return (struc
*** 2650,2653 ****
--- 2651,2679 ----
      return cgraph_node_cannot_return (e->callee);
  }
  
+ /* Return true when function NODE can be excpected to be removed
+    from program when direct calls in this compilation unit are removed.
+ 
+    As a special case COMDAT functions are
+    cgraph_can_remove_if_no_direct_calls_p while the are not
+    cgraph_only_called_directly_p (it is possible they are called from other
+    unit)
+ 
+    This function behaves as cgraph_only_called_directly_p because eliminating
+    all uses of COMDAT function does not make it neccesarily disappear from
+    the program unless we are compiling whole program or we do LTO.  In this
+    case we know we win since dynamic linking will not really discard the
+    linkonce section.  */
+ 
+ bool
+ cgraph_will_be_removed_from_program_if_no_direct_calls (struct cgraph_node *node)
+ {
+   if (node->local.used_from_object_file)
+     return false;
+   if (!in_lto_p && !flag_whole_program)
+     return cgraph_only_called_directly_p (node);
+   else
+     return cgraph_can_remove_if_no_direct_calls_p (node);
+ }
+ 
  #include "gt-cgraph.h"
Index: cgraph.h
===================================================================
*** cgraph.h	(revision 161905)
--- cgraph.h	(working copy)
*************** void cgraph_remove_node_duplication_hook
*** 664,669 ****
--- 664,671 ----
  void cgraph_materialize_all_clones (void);
  gimple cgraph_redirect_edge_call_stmt_to_callee (struct cgraph_edge *);
  bool cgraph_propagate_frequency (struct cgraph_node *node);
+ bool cgraph_will_be_removed_from_program_if_no_direct_calls
+   (struct cgraph_node *node);
  /* In cgraphbuild.c  */
  unsigned int rebuild_cgraph_edges (void);
  void cgraph_rebuild_references (void);
Index: ipa-cp.c
===================================================================
*** ipa-cp.c	(revision 161905)
--- ipa-cp.c	(working copy)
*************** ipcp_estimate_growth (struct cgraph_node
*** 951,957 ****
    struct cgraph_edge *cs;
    int redirectable_node_callers = 0;
    int removable_args = 0;
!   bool need_original = !cgraph_only_called_directly_p (node);
    struct ipa_node_params *info;
    int i, count;
    int growth;
--- 951,958 ----
    struct cgraph_edge *cs;
    int redirectable_node_callers = 0;
    int removable_args = 0;
!   bool need_original
!      = !cgraph_will_be_removed_from_program_if_no_direct_calls (node);
    struct ipa_node_params *info;
    int i, count;
    int growth;
*************** ipcp_insert_stage (void)
*** 1134,1140 ****
        for (cs = node->callers; cs != NULL; cs = cs->next_caller)
  	if (cs->caller == node || ipcp_need_redirect_p (cs))
  	  break;
!       if (!cs && cgraph_only_called_directly_p (node))
  	bitmap_set_bit (dead_nodes, node->uid);
  
        info = IPA_NODE_REF (node);
--- 1135,1141 ----
        for (cs = node->callers; cs != NULL; cs = cs->next_caller)
  	if (cs->caller == node || ipcp_need_redirect_p (cs))
  	  break;
!       if (!cs && cgraph_will_be_removed_from_program_if_no_direct_calls (node))
  	bitmap_set_bit (dead_nodes, node->uid);
  
        info = IPA_NODE_REF (node);
Index: ipa-inline.c
===================================================================
*** ipa-inline.c	(revision 161905)
--- ipa-inline.c	(working copy)
*************** cgraph_estimate_growth (struct cgraph_no
*** 389,395 ****
       we decide to not inline for different reasons, but it is not big deal
       as in that case we will keep the body around, but we will also avoid
       some inlining.  */
!   if (cgraph_only_called_directly_p (node)
        && !DECL_EXTERNAL (node->decl) && !self_recursive)
      growth -= node->global.size;
  
--- 389,395 ----
       we decide to not inline for different reasons, but it is not big deal
       as in that case we will keep the body around, but we will also avoid
       some inlining.  */
!   if (cgraph_will_be_removed_from_program_if_no_direct_calls (node)
        && !DECL_EXTERNAL (node->decl) && !self_recursive)
      growth -= node->global.size;
  
*************** cgraph_decide_inlining (void)
*** 1496,1509 ****
  
  	  if (node->callers
  	      && !node->callers->next_caller
! 	      && cgraph_only_called_directly_p (node)
  	      && node->local.inlinable
  	      && node->callers->inline_failed
  	      && node->callers->caller != node
  	      && node->callers->caller->global.inlined_to != node
  	      && !node->callers->call_stmt_cannot_inline_p
! 	      && !DECL_EXTERNAL (node->decl)
! 	      && !DECL_COMDAT (node->decl))
  	    {
  	      cgraph_inline_failed_t reason;
  	      old_size = overall_size;
--- 1496,1508 ----
  
  	  if (node->callers
  	      && !node->callers->next_caller
! 	      && cgraph_will_be_removed_from_program_if_no_direct_calls (node)
  	      && node->local.inlinable
  	      && node->callers->inline_failed
  	      && node->callers->caller != node
  	      && node->callers->caller->global.inlined_to != node
  	      && !node->callers->call_stmt_cannot_inline_p
! 	      && !DECL_EXTERNAL (node->decl))
  	    {
  	      cgraph_inline_failed_t reason;
  	      old_size = overall_size;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]