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]

Re: [PATCH][4.6] Properly inline all always-inline fns during early-inlining w/o iterating


> This makes iterating early inlining prettymuch useless apart
> from the lame testcase tree-ssa/inline-3.c which does some
> indirect inlining if the indirect function is passed directly
> as parameter (and thus constant propagation done for parameters
> during inlining resolves the indirect call).  Lame.  And
> pretty artificial.
Well, that testcase is derrived from libstdc bits used in tramp3d (and
also some of testcases in its benchmark suite) libstdc++ tends to
excercise these cases with small callbacks and also via virtual calls.
They are pretty common because libstdc tends to bring stuff off
templates this way.

Paolo was asking for implementing indirect inlining for a while.
Maritn implemented indirect inlining in main inliner that handles most
of cases but misses devirtualization (that should be fixed in next
release too) and also has the usual problem that missing early inlining
leads to worse inlining decisions in long run. Especially the last was
motivation for me to make early inlining handle this. Without this
inliner became touchy to tune for libstdc++ benchmark suite itself.
One can implement this via iteration or via jump functions.  I didn't
try the second case but I would guess it will be overall more expensive.
Except for patological case of testcase you was looking at we don't
spend that much time in the early inlining decisions and saving the
second pass at expense of building relatively involved IPA datastructure
does not seem good tradeoff.  It would be win only in testcases where we
do a lot of indirect inlning

What would be our strategy to deal with indirect calls to always
inlines?  Main inliner can handle those via indirect inlining bits, but
early inliner doesn't.

Otherwise the patch to topological ordering and idea of disabling
real inliner at -O0 seems good to me, so I will install it to
pretty-ipa unless you beat me.

Honza
> 
> The patch needs some adjustment (always run early inlining
> as now IPA inlining is disabled with -fno-inline, thus the
> combination -fno-early-inlining -fno-inline would no longer
> inline always-inline functions).  But otherwise it works.
> This should be a first step to disentangle and cleanup
> the early optimization phase.  It should also improve
> compile-time at -O0.
> 
> Bootstrap & regtest running on x86_64-unknown-linux-gnu
> (I'd really like to remove iterating completely).
> 
> Comments?
> 
> Thanks,
> Richard.
> 
> 2010-01-29  Richard Guenther  <rguenther@suse.de>
> 
> 	* ipa.c (cgraph_postorder): Adjust postorder to guarantee
> 	single-iteration always-inline inlining.
> 	* ipa-inline.c (cgraph_early_inlining): Do not iterate if
> 	not optimizing.
> 	(gate_cgraph_decide_inlining): New function.
> 	(pass_ipa_inline): Use it.  Do not run the IPA inliner if
> 	not inlining or optimizing.
> 
> 	* gcc.dg/torture/inline-2.c: New testcase.
> 
> Index: gcc/ipa.c
> ===================================================================
> *** gcc/ipa.c	(revision 156360)
> --- gcc/ipa.c	(working copy)
> *************** cgraph_postorder (struct cgraph_node **o
> *** 70,75 ****
> --- 70,81 ----
>   		    node2->aux = edge->next_caller;
>   		  else
>   		    node2->aux = &last;
> + 		  /* Break possible cycles involving always-inline
> + 		     functions by ignoring edges from always-inline
> + 		     functions to non-always-inline functions.  */
> + 		  if (edge->caller->local.disregard_inline_limits
> + 		      && !edge->callee->local.disregard_inline_limits)
> + 		    continue;
>   		  if (!edge->caller->aux)
>   		    {
>   		      if (!edge->caller->callers)
> Index: gcc/ipa-inline.c
> ===================================================================
> *** gcc/ipa-inline.c	(revision 156360)
> --- gcc/ipa-inline.c	(working copy)
> *************** cgraph_early_inlining (void)
> *** 1632,1637 ****
> --- 1632,1640 ----
>   
>     if (sorrycount || errorcount)
>       return 0;
> + 
> +   /* We iterate incremental inlining to get some pretty lame trivial
> +      cases of indirect inlining.  */
>     while (iterations < PARAM_VALUE (PARAM_EARLY_INLINER_MAX_ITERATIONS)
>            && cgraph_decide_inlining_incrementally (node,
>     					          iterations
> *************** cgraph_early_inlining (void)
> *** 1641,1646 ****
> --- 1644,1655 ----
>         todo |= optimize_inline_calls (current_function_decl);
>         iterations++;
>         timevar_pop (TV_INTEGRATION);
> + 
> +       /* Stop after one iteration if not optimizing.  */
> +       if (optimize < 2
> + 	  || optimize_function_for_size_p (cfun)
> + 	  || flag_no_inline)
> + 	break;
>       }
>     if (dump_file)
>       fprintf (dump_file, "Iterations: %i\n", iterations);
> *************** inline_write_summary (cgraph_node_set se
> *** 2044,2055 ****
>       ipa_prop_write_jump_functions (set);
>   }
>   
>   struct ipa_opt_pass_d pass_ipa_inline =
>   {
>    {
>     IPA_PASS,
>     "inline",				/* name */
> !   NULL,					/* gate */
>     cgraph_decide_inlining,		/* execute */
>     NULL,					/* sub */
>     NULL,					/* next */
> --- 2053,2073 ----
>       ipa_prop_write_jump_functions (set);
>   }
>   
> + /* When to run IPA inlining.  Inlining of always-inline functions
> +    happens during early inlining.  */
> + 
> + static bool
> + gate_cgraph_decide_inlining (void)
> + {
> +   return optimize && !flag_no_inline;
> + }
> + 
>   struct ipa_opt_pass_d pass_ipa_inline =
>   {
>    {
>     IPA_PASS,
>     "inline",				/* name */
> !   gate_cgraph_decide_inlining,		/* gate */
>     cgraph_decide_inlining,		/* execute */
>     NULL,					/* sub */
>     NULL,					/* next */
> Index: gcc/testsuite/gcc.dg/torture/inline-2.c
> ===================================================================
> *** gcc/testsuite/gcc.dg/torture/inline-2.c	(revision 0)
> --- gcc/testsuite/gcc.dg/torture/inline-2.c	(revision 0)
> ***************
> *** 0 ****
> --- 1,35 ----
> + /* { dg-do link } */
> + 
> + extern inline void foo2 (void) __attribute__((always_inline,gnu_inline));
> + extern inline void foo1 (void) __attribute__((always_inline,gnu_inline));
> + void bar1 (void);
> + void bar2 (void);
> + 
> + extern inline void __attribute__((always_inline,gnu_inline))
> + foo2 (void)
> + {
> +   bar2 ();
> + }
> + 
> + void
> + bar1 (void)
> + {
> +   foo2 ();
> + }
> + 
> + void
> + bar2 (void)
> + {
> +   foo1 ();
> + }
> + 
> + extern inline void __attribute__((always_inline,gnu_inline))
> + foo1 (void)
> + {
> +   bar1 ();
> + }
> + 
> + int main()
> + {
> +   return 0;
> + }


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