public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
* question about inlining long call sequence
@ 2019-02-12  9:46 Bin.Cheng
  2019-02-12 10:16 ` Martin Jambor
  0 siblings, 1 reply; 3+ messages in thread
From: Bin.Cheng @ 2019-02-12  9:46 UTC (permalink / raw)
  To: GCC Development

Hi,
When reading inlining code in GCC, I wonder if we have size heuristics
to limit inlining long call sequence?  For example, for call sequence
A -> B -> C -> D -> ... -> X -> Y -> Z
if each function call grows size by a very small amount, inlining Z
all the way up to the outermost function could result in a big
function which may hurt icache.  Is this case handled in inliner? if
yes, which code handles this?  Thanks in advance.

BTW, I am using GCC 6, not sure if trunk has different behavior.

Thanks,
bin

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: question about inlining long call sequence
  2019-02-12  9:46 question about inlining long call sequence Bin.Cheng
@ 2019-02-12 10:16 ` Martin Jambor
  2019-02-13 10:09   ` Bin.Cheng
  0 siblings, 1 reply; 3+ messages in thread
From: Martin Jambor @ 2019-02-12 10:16 UTC (permalink / raw)
  To: Bin.Cheng, GCC Development; +Cc: Jan Hubicka

On Tue, Feb 12 2019, Bin.Cheng wrote:
> Hi,
> When reading inlining code in GCC, I wonder if we have size heuristics
> to limit inlining long call sequence?  For example, for call sequence
> A -> B -> C -> D -> ... -> X -> Y -> Z
> if each function call grows size by a very small amount, inlining Z
> all the way up to the outermost function could result in a big
> function which may hurt icache.  Is this case handled in inliner? if
> yes, which code handles this?  Thanks in advance.
>
> BTW, I am using GCC 6, not sure if trunk has different behavior.

I believe it is done in caller_growth_limits() in ipa-inline.c in both
trunk and GCC 6.  The following comment in the function might shed a bit
more light on the behavior regarding big functions:

  /* Look for function e->caller is inlined to.  While doing
     so work out the largest function body on the way.  As
     described above, we want to base our function growth
     limits based on that.  Not on the self size of the
     outer function, not on the self size of inline code
     we immediately inline to.  This is the most relaxed
     interpretation of the rule "do not grow large functions
     too much in order to prevent compiler from exploding".  */

HTH

Martin

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: question about inlining long call sequence
  2019-02-12 10:16 ` Martin Jambor
@ 2019-02-13 10:09   ` Bin.Cheng
  0 siblings, 0 replies; 3+ messages in thread
From: Bin.Cheng @ 2019-02-13 10:09 UTC (permalink / raw)
  To: Martin Jambor; +Cc: GCC Development, Jan Hubicka

On Tue, Feb 12, 2019 at 6:16 PM Martin Jambor <mjambor@suse.cz> wrote:
>
> On Tue, Feb 12 2019, Bin.Cheng wrote:
> > Hi,
> > When reading inlining code in GCC, I wonder if we have size heuristics
> > to limit inlining long call sequence?  For example, for call sequence
> > A -> B -> C -> D -> ... -> X -> Y -> Z
> > if each function call grows size by a very small amount, inlining Z
> > all the way up to the outermost function could result in a big
> > function which may hurt icache.  Is this case handled in inliner? if
> > yes, which code handles this?  Thanks in advance.
> >
> > BTW, I am using GCC 6, not sure if trunk has different behavior.
>
> I believe it is done in caller_growth_limits() in ipa-inline.c in both
> trunk and GCC 6.  The following comment in the function might shed a bit
> more light on the behavior regarding big functions:
>
>   /* Look for function e->caller is inlined to.  While doing
>      so work out the largest function body on the way.  As
>      described above, we want to base our function growth
>      limits based on that.  Not on the self size of the
>      outer function, not on the self size of inline code
>      we immediately inline to.  This is the most relaxed
>      interpretation of the rule "do not grow large functions
>      too much in order to prevent compiler from exploding".  */
Thanks, assume it's below code collecting maximum code size limit
along call stack:

  while (true)
    {
      info = inline_summaries->get (to);
      if (limit < info->self_size)
        limit = info->self_size;
      if (stack_size_limit < info->estimated_self_stack_size)
        stack_size_limit = info->estimated_self_stack_size;
      if (to->global.inlined_to)
        to = to->callers->caller;

Question is it only collects the maximum self_size of outer callers,
since we are inlining from outer function to inner, only check
self_size of caller means we can still get bloated size for some
cases? Or what piece of code I have missed?

Another question is in want_inline_small_function_p:

      /* Apply MAX_INLINE_INSNS_AUTO limit for functions not declared inline
         Upgrade it to MAX_INLINE_INSNS_SINGLE when hints suggests that
         inlining given function is very profitable.  */
      else if (!DECL_DECLARED_INLINE_P (callee->decl)
               && !big_speedup
               && !(hints & INLINE_HINT_known_hot)
               && growth >= ((hints & (INLINE_HINT_indirect_call
                                       | INLINE_HINT_loop_iterations
                                       | INLINE_HINT_array_index
                                       | INLINE_HINT_loop_stride))
                             ? MAX (MAX_INLINE_INSNS_AUTO,
                                    MAX_INLINE_INSNS_SINGLE)
                             : MAX_INLINE_INSNS_AUTO))
So for function not declared as inline, if it's considered as
known_hot, there will be no size restriction at all.  This looks like
an issue to me, given we do restrict size even for know_hot function
which is declared as inline:

      /* Apply MAX_INLINE_INSNS_SINGLE limit.  Do not do so when
         hints suggests that inlining given function is very profitable.  */
      else if (DECL_DECLARED_INLINE_P (callee->decl)
               && growth >= MAX_INLINE_INSNS_SINGLE
               && ((!big_speedup
                    && !(hints & (INLINE_HINT_indirect_call
                                  | INLINE_HINT_known_hot
                                  | INLINE_HINT_loop_iterations
                                  | INLINE_HINT_array_index
                                  | INLINE_HINT_loop_stride)))
                   || growth >= MAX_INLINE_INSNS_SINGLE * 16))

Again, this is on GCC6.

Thanks,
bin
>
> HTH
>
> Martin

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2019-02-13 10:09 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-02-12  9:46 question about inlining long call sequence Bin.Cheng
2019-02-12 10:16 ` Martin Jambor
2019-02-13 10:09   ` Bin.Cheng

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).