[PATCH] Fix PR37448 (and dups?)

Richard Biener rguenther@suse.de
Thu Feb 18 15:26:00 GMT 2016


On Thu, 18 Feb 2016, Jan Hubicka wrote:

> > 
> > This fixes the IPA inline analysis quadraticness that arises when we
> > inline functions into the same function many times via
> > inline_to_all_callers as we do in the testcase for PR37448.  In that
> > case updating the overall summary of the caller is done for each
> > inlined call instead of just once.
> > 
> > The solution is to keep track of which nodes we inlined to and
> > delay the summary update.
> > 
> > Honza, I believe this is safe as the callers summary should only
> > matter for further inline decisions and not this one (inlining
> > into all callers).  Double-checking is appreciated - there should
> > be no code changes by this patch (I verified this on the PR37448
> > testcase).
> 
> I think it is not the case if one function contains multiple calls
> and eventually hits large function growth.  In that case we inline
> just some callers and not the others.

Are you sure?  I thought we compute that up-front ... at least
we make sure we can_inline_edge_p all calls before even trying
to inline all calls - that looks somewhat redundant then if it
can happen that we give up anyway.  Ah, so can_inline_edge_p has

  /* Check if caller growth allows the inlining.  */
  else if (!DECL_DISREGARD_INLINE_LIMITS (callee->decl)
           && !disregard_limits
           && !lookup_attribute ("flatten",
                                 DECL_ATTRIBUTES (caller->decl))
           && !caller_growth_limits (e))
    inlinable = false;

and we check that from when we do the inlining and upfront from
want_inline_function_to_all_callers_p ... we also give up
if we inline a recursive function it seems.

> For next stage1 I plan to finish the overahaul to sreals that will let
> me to make update_overall_summary incremental (i.e. O(size_of_inlined_function)
> and not O(size_of_inlined_function+size_of_function_inlined_to)) that will
> also solve these issues.

Hopefully.

> One can probably do a pesimistic estimate on code size of the function 
> (i.e. add the size of inlined function) and only if that hits the large 
> function growth do the exact calculation. Or we can just decide that it 
> is OK to ignore large function growht in this partiuclar case.

Ignoring it is probably not a good idea and will just lead to a different
degenerate case.  As we update the summary afterwards it's probably
ok to do incremental (pessimistic) updates on the size anyway?  In
inline_merge_summary I mean?  Or should I open-code that into
inline_call if ! update_overall_summary?

Richard.

> Honza
> > 
> > This brings down compile-time of ipa inlining heuristics from
> > 
> >  ipa inlining heuristics : 260.14 (84%) usr   0.50 (23%) sys 260.91 (84%) 
> > wall  102217 kB (10%) ggc
> > 
> > (that's an optimized non-checking compiler) to
> > 
> >  ipa inlining heuristics :   3.52 ( 3%) usr   0.55 (12%) sys   4.21 ( 3%) 
> > wall  102216 kB (12%) ggc
> > 
> > (that's an unoptimized, checking enabled compiler, "before" on that
> > unoptimized compiler is  ipa inlining heuristics : 935.06 (89%)).
> > 
> > We still do a lot of inlining here so we see
> > 
> >  integration             :  21.22 (17%) usr   0.45 (10%) sys  21.68 (17%) 
> > wall  142979 kB (17%) ggc
> > 
> > which is supposedly expected (same unoptimized, checking enabled 
> > compiler).
> > 
> > Bootstrap & regtest is running on x86_64-unknown-linux-gnu, ok for trunk
> > and branch(es)?
> > 
> > Thanks,
> > Richard.
> > 
> > 2016-02-18  Richard Biener  <rguenther@suse.de>
> > 
> > 	PR ipa/37448
> > 	* ipa-inline.c (inline_to_all_callers_1): Add to the callers
> > 	hash-set, do not update overall summaries here.  Renamed from ...
> > 	(inline_to_all_callers): ... this which is now wrapping the
> > 	above and performing delayed overall summary update.
> > 
> > Index: gcc/ipa-inline.c
> > ===================================================================
> > *** gcc/ipa-inline.c	(revision 233498)
> > --- gcc/ipa-inline.c	(working copy)
> > *************** flatten_function (struct cgraph_node *no
> > *** 2163,2169 ****
> >      recursion.  */
> >   
> >   static bool
> > ! inline_to_all_callers (struct cgraph_node *node, void *data)
> >   {
> >     int *num_calls = (int *)data;
> >     bool callee_removed = false;
> > --- 2163,2170 ----
> >      recursion.  */
> >   
> >   static bool
> > ! inline_to_all_callers_1 (struct cgraph_node *node, void *data,
> > ! 			 hash_set<cgraph_node *> *callers)
> >   {
> >     int *num_calls = (int *)data;
> >     bool callee_removed = false;
> > *************** inline_to_all_callers (struct cgraph_nod
> > *** 2193,2199 ****
> >   		   inline_summaries->get (node->callers->caller)->size);
> >   	}
> >   
> > !       inline_call (node->callers, true, NULL, NULL, true, &callee_removed);
> >         if (dump_file)
> >   	fprintf (dump_file,
> >   		 " Inlined into %s which now has %i size\n",
> > --- 2194,2203 ----
> >   		   inline_summaries->get (node->callers->caller)->size);
> >   	}
> >   
> > !       /* Remember which callers we inlined to, delaying updating the
> > ! 	 overall summary.  */
> > !       callers->add (node->callers->caller);
> > !       inline_call (node->callers, true, NULL, NULL, false, &callee_removed);
> >         if (dump_file)
> >   	fprintf (dump_file,
> >   		 " Inlined into %s which now has %i size\n",
> > *************** inline_to_all_callers (struct cgraph_nod
> > *** 2211,2216 ****
> > --- 2215,2237 ----
> >     return false;
> >   }
> >   
> > + /* Wrapper around inline_to_all_callers_1 doing delayed overall summary
> > +    update.  */
> > + 
> > + static bool
> > + inline_to_all_callers (struct cgraph_node *node, void *data)
> > + {
> > +   hash_set<cgraph_node *> callers;
> > +   bool res = inline_to_all_callers_1 (node, data, &callers);
> > +   /* Perform the delayed update of the overall summary of all callers
> > +      processed.  This avoids quadratic behavior in the cases where
> > +      we have a lot of calls to the same function.  */
> > +   for (hash_set<cgraph_node *>::iterator i = callers.begin ();
> > +        i != callers.end (); ++i)
> > +     inline_update_overall_summary (*i);
> > +   return res;
> > + }
> > + 
> >   /* Output overall time estimate.  */
> >   static void
> >   dump_overall_stats (void)
> 
> 

-- 
Richard Biener <rguenther@suse.de>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 21284 (AG Nuernberg)



More information about the Gcc-patches mailing list