[PATCH] Drop callee function size limits for IPA inlining

Richard Guenther rguenther@suse.de
Tue Feb 15 16:57:00 GMT 2011


IPA inlining imposes IMHO artificial limits on sizes of callees it
wants to inline regardless of working with an edge badness approach
that factors in things like call frequencies from profile-feedback.
This results in strange missed inlinings even when using -O3
(and thus -finline-functions).  The patch below makes the IPA inliner
rely solely on the unit- and function-growth limits (which would
it also make possible to re-define -finline-limit to simply map
to the unit-growth limit).  For this to work reasonably well I
have to drop the large-unit-insns limit (where the unit-growth
kicks in) to 100 (or get rid of it entirely), otherwise we happily
grow small units up to the current default of 10000.

This patch is a RFC, it closely interacts with the current badness
function and fibheap updating (ISTR running into an assert during
bootstrap, a bootstrap w/o that assert finished).  Very likely
the default function-growth and unit-growth limits need tuning
over a larger codebase - I sofar tested the Phoronix C-Ray benchmark
where we now get the desired inlining at -O3 and compared cc1 size
which decreases slightly with this patch (ontop of the SCC patch).

Comments welcome.

Thanks,
Richard.

2011-02-15  Richard Guenther  <rguenther@suse.de>

	* ipa-inline.c (update_caller_keys): Do not prune edges.
	(update_callee_keys): Likewise.
	(add_new_edges_to_heap): Add a fixme.
	(cgraph_decide_inlining_of_small_functions): Do not consider
	callee function size limits for IPA inlining.
	* params.def (PARAM_LARGE_UNIT_INSNS): Drop to 100.

Index: gcc/ipa-inline.c
===================================================================
*** gcc/ipa-inline.c.orig	2011-02-15 17:04:48.000000000 +0100
--- gcc/ipa-inline.c	2011-02-15 17:15:52.000000000 +0100
*************** update_caller_keys (fibheap_t heap, stru
*** 671,677 ****
  		    bitmap updated_nodes)
  {
    struct cgraph_edge *edge;
-   cgraph_inline_failed_t failed_reason;
  
    if (!node->local.inlinable
        || cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE
--- 671,676 ----
*************** update_caller_keys (fibheap_t heap, stru
*** 687,705 ****
        break;
    if (!edge)
      return;
-   /* Prune out edges we won't inline into anymore.  */
-   if (!cgraph_default_inline_p (node, &failed_reason))
-     {
-       for (; edge; edge = edge->next_caller)
- 	if (edge->aux)
- 	  {
- 	    fibheap_delete_node (heap, (fibnode_t) edge->aux);
- 	    edge->aux = NULL;
- 	    if (edge->inline_failed)
- 	      edge->inline_failed = failed_reason;
- 	  }
-       return;
-     }
  
    for (; edge; edge = edge->next_caller)
      if (edge->inline_failed)
--- 686,691 ----
*************** update_callee_keys (fibheap_t heap, stru
*** 731,742 ****
  	    && !bitmap_bit_p (updated_nodes, e->callee->uid))
  	  {
  	    node->global.estimated_growth = INT_MIN;
! 	    /* If function becomes uninlinable, we need to remove it from the heap.  */
! 	    if (!cgraph_default_inline_p (e->callee, &e->inline_failed))
! 	      update_caller_keys (heap, e->callee, updated_nodes);
! 	    else
! 	    /* Otherwise update just edge E.  */
! 	      update_edge_key (heap, e);
  	  }
  	if (e->next_callee)
  	  e = e->next_callee;
--- 717,723 ----
  	    && !bitmap_bit_p (updated_nodes, e->callee->uid))
  	  {
  	    node->global.estimated_growth = INT_MIN;
! 	    update_edge_key (heap, e);
  	  }
  	if (e->next_callee)
  	  e = e->next_callee;
*************** add_new_edges_to_heap (fibheap_t heap, V
*** 996,1001 ****
--- 977,983 ----
        gcc_assert (!edge->aux);
        if (edge->callee->local.inlinable
  	  && edge->inline_failed
+ 	  /* ???  This is overly restrictive now.  */
  	  && cgraph_default_inline_p (edge->callee, &edge->inline_failed))
          edge->aux = fibheap_insert (heap, cgraph_edge_badness (edge, false), edge);
      }
*************** cgraph_decide_inlining_of_small_function
*** 1014,1020 ****
  {
    struct cgraph_node *node;
    struct cgraph_edge *edge;
-   cgraph_inline_failed_t failed_reason;
    fibheap_t heap = fibheap_new ();
    bitmap updated_nodes = BITMAP_ALLOC (NULL);
    int min_size, max_size;
--- 996,1001 ----
*************** cgraph_decide_inlining_of_small_function
*** 1032,1052 ****
      {
        if (!node->local.inlinable || !node->callers)
  	continue;
-       if (dump_file)
- 	fprintf (dump_file, "Considering inline candidate %s.\n", cgraph_node_name (node));
  
        node->global.estimated_growth = INT_MIN;
!       if (!cgraph_default_inline_p (node, &failed_reason))
  	{
! 	  cgraph_set_inline_failed (node, failed_reason);
  	  continue;
  	}
  
        for (edge = node->callers; edge; edge = edge->next_caller)
  	if (edge->inline_failed)
  	  {
  	    gcc_assert (!edge->aux);
! 	    edge->aux = fibheap_insert (heap, cgraph_edge_badness (edge, false), edge);
  	  }
      }
  
--- 1013,1050 ----
      {
        if (!node->local.inlinable || !node->callers)
  	continue;
  
        node->global.estimated_growth = INT_MIN;
! 
!       /* The following are checks split out from cgraph_default_inline_p
!          that do not change during the inlining.  */
!       if (!node->analyzed)
  	{
! 	  cgraph_set_inline_failed (node, CIF_BODY_NOT_AVAILABLE);
! 	  continue;
! 	}
!       if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
! 	{
! 	  cgraph_set_inline_failed (node, CIF_OVERWRITABLE);
! 	  continue;
! 	}
! 
!       /* We do not want to inline functions that are not declared inline
!          if neither -finline-small-functions nor -finline-functions is set.  */
!       if (!DECL_DECLARED_INLINE_P (node->decl)
! 	  && !flag_inline_small_functions
! 	  && !flag_inline_functions)
! 	{
! 	  cgraph_set_inline_failed (node, CIF_FUNCTION_NOT_INLINE_CANDIDATE);
  	  continue;
  	}
  
        for (edge = node->callers; edge; edge = edge->next_caller)
  	if (edge->inline_failed)
  	  {
+ 	    int badness = cgraph_edge_badness (edge, false);
  	    gcc_assert (!edge->aux);
! 	    edge->aux = fibheap_insert (heap, badness, edge);
  	  }
      }
  
*************** cgraph_decide_inlining_of_small_function
*** 1160,1176 ****
  	      if (dump_file)
  		fprintf (dump_file, " inline_failed:%s.\n",
  			 cgraph_inline_failed_string (edge->inline_failed));
- 	    }
- 	  continue;
- 	}
-       if (!cgraph_default_inline_p (edge->callee, &edge->inline_failed))
- 	{
-           if (!cgraph_recursive_inlining_p (edge->caller, edge->callee,
- 				            &edge->inline_failed))
- 	    {
- 	      if (dump_file)
- 		fprintf (dump_file, " inline_failed:%s.\n",
- 			 cgraph_inline_failed_string (edge->inline_failed));
  	    }
  	  continue;
  	}
--- 1158,1163 ----
Index: gcc/params.def
===================================================================
*** gcc/params.def.orig	2011-02-15 17:04:48.000000000 +0100
--- gcc/params.def	2011-02-15 17:06:42.000000000 +0100
*************** DEFPARAM(PARAM_LARGE_FUNCTION_GROWTH,
*** 186,192 ****
  DEFPARAM(PARAM_LARGE_UNIT_INSNS,
  	 "large-unit-insns",
  	 "The size of translation unit to be considered large",
! 	 10000, 0, 0)
  DEFPARAM(PARAM_INLINE_UNIT_GROWTH,
  	 "inline-unit-growth",
  	 "How much can given compilation unit grow because of the inlining (in percent)",
--- 186,192 ----
  DEFPARAM(PARAM_LARGE_UNIT_INSNS,
  	 "large-unit-insns",
  	 "The size of translation unit to be considered large",
! 	 100, 0, 0)
  DEFPARAM(PARAM_INLINE_UNIT_GROWTH,
  	 "inline-unit-growth",
  	 "How much can given compilation unit grow because of the inlining (in percent)",



More information about the Gcc-patches mailing list