diff mbox series

Convert inliner to new param infrastructure

Message ID 20191123131220.ivtblcgtwstd6gyr@kam.mff.cuni.cz
State New
Headers show
Series Convert inliner to new param infrastructure | expand

Commit Message

Jan Hubicka Nov. 23, 2019, 1:12 p.m. UTC
Hi,
This patch adds opt_for_fn for all cross module params used by inliner
so they can be modified at function granuality.  With inlining almost always
there are three functions to consider (callee and caller of the inlined edge
and the outer function caller is inlined to).

I always use the outer function params since that is how local parameters
behave.  I hope it is kind of what is also expected in most case: it is better
to inline agressively into -O3 compiled code rather than inline agressively -O3
functions into their callers.

New params infrastructure is nice.  One drawback is that is very hard to
search for individual param uses since they all occupy global namespace.
With C++ world we had chance to do something like params.param_flag_name
or params::param_flag_name instead...

Bootstrapped/regtested x86_64-linux, comitted.

	* cif-code.def (MAX_INLINE_INSNS_SINGLE_O2_LIMIT): Remove.
	* doc/invoke.texi (max-inline-insns-single-O2,
	inline-heuristics-hint-percent-O2, inline-min-speedup-O2,
	early-inlining-insns-O2): Remove documentation.
	* ipa-fnsummary.c (analyze_function_body,
	compute_fn_summary): Use opt_for_fn when accessing parameters.
	* ipa-inline.c (caller_growth_limits, can_inline_edge_p,
	inline_insns_auto, can_inline_edge_by_limits_p,
	want_early_inline_function_p, big_speedup_p,
	want_inline_small_function_p, want_inline_self_recursive_call_p,
	recursive_inlining, compute_max_insns, inline_small_functions):
	Likewise.
	* opts.c (default_options): Add -O3 defaults for
	OPT__param_early_inlining_insns_,
	OPT__param_inline_heuristics_hint_percent_,
	OPT__param_inline_min_speedup_, OPT__param_max_inline_insns_single_.
	* params.opt (-param=early-inlining-insns-O2=,
	-param=inline-heuristics-hint-percent-O2=,
	-param=inline-min-speedup-O2=, -param=max-inline-insns-single-O2=
	-param=early-inlining-insns=, -param=inline-heuristics-hint-percent=,
	-param=inline-min-speedup=, -param=inline-unit-growth=,
	-param=large-function-growth=, -param=large-stack-frame=,
	-param=large-stack-frame-growth=, -param=large-unit-insns=,
	-param=max-inline-insns-recursive=,
	-param=max-inline-insns-recursive-auto=,
	-param=max-inline-insns-single=,
	-param=max-inline-insns-size=, -param=max-inline-insns-small=,
	-param=max-inline-recursive-depth=,
	-param=max-inline-recursive-depth-auto=,
	-param=min-inline-recursive-probability=,
	-param=partial-inlining-entry-probability=,
	-param=uninlined-function-insns=, -param=uninlined-function-time=,
	-param=uninlined-thunk-insns=, -param=uninlined-thunk-time=): Add
	Optimization.

	* g++.dg/tree-ssa/pr53844.C: Drop -O2 from param name.
	* g++.dg/tree-ssa/pr61034.C: Likewise.
	* g++.dg/tree-ssa/pr8781.C: Likewise.
	* g++.dg/warn/Wstringop-truncation-1.C: Likewise.
	* gcc.dg/ipa/pr63416.c: Likewise.
	* gcc.dg/tree-ssa/ssa-thread-12.c: Likewise.
	* gcc.dg/vect/pr66142.c: Likewise.
	* gcc.dg/winline-3.c: Likewise.
	* gcc.target/powerpc/pr72804.c: Likewise.

Comments

Rainer Orth Nov. 24, 2019, 4:37 p.m. UTC | #1
Hi Jan,

> This patch adds opt_for_fn for all cross module params used by inliner
> so they can be modified at function granuality.  With inlining almost always
> there are three functions to consider (callee and caller of the inlined edge
> and the outer function caller is inlined to).
>
> I always use the outer function params since that is how local parameters
> behave.  I hope it is kind of what is also expected in most case: it is better
> to inline agressively into -O3 compiled code rather than inline agressively -O3
> functions into their callers.
>
> New params infrastructure is nice.  One drawback is that is very hard to
> search for individual param uses since they all occupy global namespace.
> With C++ world we had chance to do something like params.param_flag_name
> or params::param_flag_name instead...
>
> Bootstrapped/regtested x86_64-linux, comitted.

this patch introduced a regression (everywhere, it seems):

+FAIL: gcc.dg/winline-3.c  (test for warnings, line 5)
+FAIL: gcc.dg/winline-3.c (test for excess errors)

Excess errors:
/vol/gcc/src/hg/trunk/local/gcc/testsuite/gcc.dg/winline-3.c:5:12: warning: inlining failed in call to 'q': --param max-inline-insns-auto limit reached [-Winline]

I suspect you just forgot to adapt the expected warning message
((...-single -> ...-auto)?

	Rainer
Martin Liška Nov. 25, 2019, 8:31 a.m. UTC | #2
On 11/23/19 2:12 PM, Jan Hubicka wrote:
> I always use the outer function params since that is how local parameters
> behave.  I hope it is kind of what is also expected in most case: it is better
> to inline agressively into -O3 compiled code rather than inline agressively -O3
> functions into their callers.

Hello.

Great that you converted the inliner parameters so quickly!

> 
> New params infrastructure is nice.  One drawback is that is very hard to
> search for individual param uses since they all occupy global namespace.
> With C++ world we had chance to do something like params.param_flag_name
> or params::param_flag_name instead...


Why is it difficult to search for all usages? Now, we don't use any PARAM_XYZ macros
and one can easily find all usages with something like:
$ git grep param_stack_frame_growth

Martin
Jan Hubicka Nov. 25, 2019, 9:27 a.m. UTC | #3
> On 11/23/19 2:12 PM, Jan Hubicka wrote:
> > I always use the outer function params since that is how local parameters
> > behave.  I hope it is kind of what is also expected in most case: it is better
> > to inline agressively into -O3 compiled code rather than inline agressively -O3
> > functions into their callers.
> 
> Hello.
> 
> Great that you converted the inliner parameters so quickly!

It is easy to do - i did the same with all command line options some
time ago.  I will look into the other options that are set by maybe_*
infrastrcture.
> 
> > 
> > New params infrastructure is nice.  One drawback is that is very hard to
> > search for individual param uses since they all occupy global namespace.
> > With C++ world we had chance to do something like params.param_flag_name
> > or params::param_flag_name instead...
> 
> 
> Why is it difficult to search for all usages? Now, we don't use any PARAM_XYZ macros
> and one can easily find all usages with something like:
> $ git grep param_stack_frame_growth

It is not that hard, but I was in task of replacing all param_xyz by
opt_for_fn (some meaningful decl, param_xyz). Problem is taht
param_<something> is common in ipa-prop code so I could not simply
search for that.

Just it seemed to me that c++ way would be to give those a namespace.

Honza
> 
> Martin
Martin Liška Nov. 25, 2019, 9:32 a.m. UTC | #4
On 11/25/19 10:27 AM, Jan Hubicka wrote:
>> On 11/23/19 2:12 PM, Jan Hubicka wrote:
>>> I always use the outer function params since that is how local parameters
>>> behave.  I hope it is kind of what is also expected in most case: it is better
>>> to inline agressively into -O3 compiled code rather than inline agressively -O3
>>> functions into their callers.
>>
>> Hello.
>>
>> Great that you converted the inliner parameters so quickly!
> 
> It is easy to do - i did the same with all command line options some
> time ago.  I will look into the other options that are set by maybe_*
> infrastrcture.
>>
>>>
>>> New params infrastructure is nice.  One drawback is that is very hard to
>>> search for individual param uses since they all occupy global namespace.
>>> With C++ world we had chance to do something like params.param_flag_name
>>> or params::param_flag_name instead...

Makes sense to me, feel free to send a patch for that. Note that one would
expect the same of options as well.

Martin

>>
>>
>> Why is it difficult to search for all usages? Now, we don't use any PARAM_XYZ macros
>> and one can easily find all usages with something like:
>> $ git grep param_stack_frame_growth
> 
> It is not that hard, but I was in task of replacing all param_xyz by
> opt_for_fn (some meaningful decl, param_xyz). Problem is taht
> param_<something> is common in ipa-prop code so I could not simply
> search for that.
> 
> Just it seemed to me that c++ way would be to give those a namespace.
> 
> Honza
>>
>> Martin
diff mbox series

Patch

Index: cif-code.def
===================================================================
--- cif-code.def	(revision 278629)
+++ cif-code.def	(working copy)
@@ -70,8 +70,6 @@  DEFCIFCODE(LARGE_STACK_FRAME_GROWTH_LIMI
 	   N_("--param large-stack-frame-growth limit reached"))
 DEFCIFCODE(MAX_INLINE_INSNS_SINGLE_LIMIT, CIF_FINAL_NORMAL,
 	   N_("--param max-inline-insns-single limit reached"))
-DEFCIFCODE(MAX_INLINE_INSNS_SINGLE_O2_LIMIT, CIF_FINAL_NORMAL,
-	   N_("--param max-inline-insns-single-O2 limit reached"))
 DEFCIFCODE(MAX_INLINE_INSNS_AUTO_LIMIT, CIF_FINAL_NORMAL,
 	   N_("--param max-inline-insns-auto limit reached"))
 DEFCIFCODE(INLINE_UNIT_GROWTH_LIMIT, CIF_FINAL_NORMAL,
Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 278629)
+++ doc/invoke.texi	(working copy)
@@ -11281,17 +11281,12 @@  when modulo scheduling a loop.  Larger v
 compilation time.
 
 @item max-inline-insns-single
-@item max-inline-insns-single-O2
 Several parameters control the tree inliner used in GCC@.  This number sets the
 maximum number of instructions (counted in GCC's internal representation) in a
 single function that the tree inliner considers for inlining.  This only
 affects functions declared inline and methods implemented in a class
 declaration (C++). 
 
-For functions compiled with optimization levels
-@option{-O3} and @option{-Ofast} parameter @option{max-inline-insns-single} is
-applied. In other cases @option{max-inline-insns-single-O2} is applied.
-
 
 @item max-inline-insns-auto
 When you use @option{-finline-functions} (included in @option{-O3}),
@@ -11317,33 +11312,22 @@  Extra time accounted by inliner for func
 execute function prologue and epilogue
 
 @item inline-heuristics-hint-percent
-@item inline-heuristics-hint-percent-O2
 The scale (in percents) applied to @option{inline-insns-single},
 @option{inline-insns-single-O2}, @option{inline-insns-auto}
 when inline heuristics hints that inlining is
 very profitable (will enable later optimizations).
 
-For functions compiled with optimization levels
-@option{-O3} and @option{-Ofast} parameter
-@option{inline-heuristics-hint-percent} is applied. In other cases
-@option{inline-heuristics-hint-percent-O2} is applied.
-
 @item uninlined-thunk-insns
 @item uninlined-thunk-time
 Same as @option{--param uninlined-function-insns} and
 @option{--param uninlined-function-time} but applied to function thunks
 
 @item inline-min-speedup
-@item inline-min-speedup-O2
 When estimated performance improvement of caller + callee runtime exceeds this
 threshold (in percent), the function can be inlined regardless of the limit on
 @option{--param max-inline-insns-single} and @option{--param
 max-inline-insns-auto}.
 
-For functions compiled with optimization levels
-@option{-O3} and @option{-Ofast} parameter @option{inline-min-speedup} is
-applied. In other cases @option{inline-min-speedup-O2} is applied.
-
 @item large-function-insns
 The limit specifying really large functions.  For functions larger than this
 limit after inlining, inlining is constrained by
@@ -11421,14 +11405,9 @@  via a given call expression.  This param
 expressions whose probability exceeds the given threshold (in percents).
 
 @item early-inlining-insns
-@item early-inlining-insns-O2
 Specify growth that the early inliner can make.  In effect it increases
 the amount of inlining for code having a large abstraction penalty.
 
-For functions compiled with optimization levels
-@option{-O3} and @option{-Ofast} parameter @option{early-inlining-insns} is
-applied. In other cases @option{early-inlining-insns-O2} is applied.
-
 @item max-early-inliner-iterations
 Limit of iterations of the early inliner.  This basically bounds
 the number of nested indirect calls the early inliner can resolve.
Index: ipa-fnsummary.c
===================================================================
--- ipa-fnsummary.c	(revision 278629)
+++ ipa-fnsummary.c	(working copy)
@@ -2397,9 +2397,9 @@  fp_expression_p (gimple *stmt)
 static void
 analyze_function_body (struct cgraph_node *node, bool early)
 {
-  sreal time = param_uninlined_function_time;
+  sreal time = opt_for_fn (node->decl, param_uninlined_function_time);
   /* Estimate static overhead for function prologue/epilogue and alignment. */
-  int size = param_uninlined_function_insns;
+  int size = opt_for_fn (node->decl, param_uninlined_function_insns);
   /* Benefits are scaled by probability of elimination that is in range
      <0,2>.  */
   basic_block bb;
@@ -2465,9 +2465,11 @@  analyze_function_body (struct cgraph_nod
   info->account_size_time (0, 0, bb_predicate, bb_predicate);
 
   bb_predicate = predicate::not_inlined ();
-  info->account_size_time (param_uninlined_function_insns
+  info->account_size_time (opt_for_fn (node->decl,
+				param_uninlined_function_insns)
 			   * ipa_fn_summary::size_scale,
-			   param_uninlined_function_time,
+			   opt_for_fn (node->decl,
+				param_uninlined_function_time),
 			   bb_predicate,
 		           bb_predicate);
 
@@ -2865,8 +2867,10 @@  compute_fn_summary (struct cgraph_node *
       es->call_stmt_size = eni_size_weights.call_cost;
       es->call_stmt_time = eni_time_weights.call_cost;
       info->account_size_time (ipa_fn_summary::size_scale
-			       * param_uninlined_function_thunk_insns,
-			       param_uninlined_function_thunk_time, t, t);
+			       * opt_for_fn (node->decl,
+				 param_uninlined_function_thunk_insns),
+			       opt_for_fn (node->decl,
+				 param_uninlined_function_thunk_time), t, t);
       t = predicate::not_inlined ();
       info->account_size_time (2 * ipa_fn_summary::size_scale, 0, t, t);
       ipa_update_overall_fn_summary (node);
Index: ipa-inline.c
===================================================================
--- ipa-inline.c	(revision 278629)
+++ ipa-inline.c	(working copy)
@@ -178,13 +178,13 @@  caller_growth_limits (struct cgraph_edge
   if (limit < what_size_info->self_size)
     limit = what_size_info->self_size;
 
-  limit += limit * param_large_function_growth / 100;
+  limit += limit * opt_for_fn (to->decl, param_large_function_growth) / 100;
 
   /* Check the size after inlining against the function limits.  But allow
      the function to shrink if it went over the limits by forced inlining.  */
   newsize = estimate_size_after_inlining (to, e);
   if (newsize >= ipa_size_summaries->get (what)->size
-      && newsize > param_large_function_insns
+      && newsize > opt_for_fn (to->decl, param_large_function_insns)
       && newsize > limit)
     {
       e->inline_failed = CIF_LARGE_FUNCTION_GROWTH_LIMIT;
@@ -200,7 +200,8 @@  caller_growth_limits (struct cgraph_edge
      on every invocation of the caller (i.e. its call statement dominates
      exit block).  We do not track this information, yet.  */
   stack_size_limit += ((gcov_type)stack_size_limit
-		       * param_stack_frame_growth / 100);
+		       * opt_for_fn (to->decl, param_stack_frame_growth)
+		       / 100);
 
   inlined_stack = (ipa_get_stack_frame_offset (to)
 		   + outer_info->estimated_self_stack_size
@@ -213,7 +214,7 @@  caller_growth_limits (struct cgraph_edge
 	 This bit overoptimistically assume that we are good at stack
 	 packing.  */
       && inlined_stack > ipa_fn_summaries->get (to)->estimated_stack_size
-      && inlined_stack > param_large_stack_frame)
+      && inlined_stack > opt_for_fn (to->decl, param_large_stack_frame))
     {
       e->inline_failed = CIF_LARGE_STACK_FRAME_GROWTH_LIMIT;
       return false;
@@ -395,20 +396,10 @@  can_inline_edge_p (struct cgraph_edge *e
 static int
 inline_insns_single (cgraph_node *n, bool hint)
 {
-  if (opt_for_fn (n->decl, optimize) >= 3)
-    {
-      if (hint)
-	return param_max_inline_insns_single
-	       * param_inline_heuristics_hint_percent / 100;
-      return param_max_inline_insns_single;
-    }
-  else
-    {
-      if (hint)
-	return param_max_inline_insns_single_o2
-	       * param_inline_heuristics_hint_percent_o2 / 100;
-      return param_max_inline_insns_single_o2;
-    }
+  if (hint)
+    return opt_for_fn (n->decl, param_max_inline_insns_single)
+	   * opt_for_fn (n->decl, param_inline_heuristics_hint_percent) / 100;
+  return opt_for_fn (n->decl, param_max_inline_insns_single);
 }
 
 /* Return inlining_insns_auto limit for function N. If HINT is true
@@ -419,7 +410,8 @@  inline_insns_auto (cgraph_node *n, bool
 {
   int max_inline_insns_auto = opt_for_fn (n->decl, param_max_inline_insns_auto);
   if (hint)
-    return max_inline_insns_auto * param_inline_heuristics_hint_percent / 100;
+    return max_inline_insns_auto
+	   * opt_for_fn (n->decl, param_inline_heuristics_hint_percent) / 100;
   return max_inline_insns_auto;
 }
 
@@ -563,7 +555,7 @@  can_inline_edge_by_limits_p (struct cgra
 	       > opt_for_fn (caller->decl, optimize_size))
 	{
 	  int growth = estimate_edge_growth (e);
-	  if (growth > param_max_inline_insns_size
+	  if (growth > opt_for_fn (caller->decl, param_max_inline_insns_size)
 	      && (!DECL_DECLARED_INLINE_P (callee->decl)
 		  && growth >= MAX (inline_insns_single (caller, false),
 				    inline_insns_auto (caller, false))))
@@ -675,9 +667,7 @@  want_early_inline_function_p (struct cgr
       /* First take care of very large functions.  */
       int min_growth = estimate_min_edge_growth (e), growth = 0;
       int n;
-      int early_inlining_insns = opt_for_fn (e->caller->decl, optimize) >= 3
-				 ? param_early_inlining_insns
-				 : param_early_inlining_insns_o2;
+      int early_inlining_insns = param_early_inlining_insns;
 
       if (min_growth > early_inlining_insns)
 	{
@@ -824,9 +814,7 @@  big_speedup_p (struct cgraph_edge *e)
   cgraph_node *caller = (e->caller->inlined_to
 			 ? e->caller->inlined_to
 			 : e->caller);
-  int limit = opt_for_fn (caller->decl, optimize) >= 3
-	      ? param_inline_min_speedup
-	      : param_inline_min_speedup_o2;
+  int limit = opt_for_fn (caller->decl, param_inline_min_speedup);
 
   if ((time - inlined_time) * 100 > time * limit)
     return true;
@@ -841,6 +829,8 @@  want_inline_small_function_p (struct cgr
 {
   bool want_inline = true;
   struct cgraph_node *callee = e->callee->ultimate_alias_target ();
+  cgraph_node *to  = (e->caller->inlined_to
+		      ? e->caller->inlined_to : e->caller);
 
   /* Allow this function to be called before can_inline_edge_p,
      since it's usually cheaper.  */
@@ -876,9 +866,7 @@  want_inline_small_function_p (struct cgr
 			    ? CIF_MAX_INLINE_INSNS_SINGLE_LIMIT
 			    : CIF_MAX_INLINE_INSNS_AUTO_LIMIT);
       else
-	e->inline_failed = (DECL_DECLARED_INLINE_P (callee->decl)
-			      ? CIF_MAX_INLINE_INSNS_SINGLE_O2_LIMIT
-			      : CIF_MAX_INLINE_INSNS_AUTO_LIMIT);
+	e->inline_failed = CIF_MAX_INLINE_INSNS_AUTO_LIMIT;
       want_inline = false;
     }
   else
@@ -890,7 +878,8 @@  want_inline_small_function_p (struct cgr
 				   | INLINE_HINT_loop_iterations
 				   | INLINE_HINT_loop_stride));
 
-      if (growth <= param_max_inline_insns_size)
+      if (growth <= opt_for_fn (to->decl,
+				param_max_inline_insns_size))
 	;
       /* Apply param_max_inline_insns_single limit.  Do not do so when
 	 hints suggests that inlining given function is very profitable.
@@ -902,15 +891,13 @@  want_inline_small_function_p (struct cgr
 		   || growth >= inline_insns_single (e->caller, true)
 		   || !big_speedup_p (e)))
 	{
-	  if (opt_for_fn (e->caller->decl, optimize) >= 3)
-            e->inline_failed = CIF_MAX_INLINE_INSNS_SINGLE_LIMIT;
-	  else
-            e->inline_failed = CIF_MAX_INLINE_INSNS_SINGLE_O2_LIMIT;
+          e->inline_failed = CIF_MAX_INLINE_INSNS_SINGLE_LIMIT;
 	  want_inline = false;
 	}
       else if (!DECL_DECLARED_INLINE_P (callee->decl)
 	       && !opt_for_fn (e->caller->decl, flag_inline_functions)
-	       && growth >= param_max_inline_insns_small)
+	       && growth >= opt_for_fn (to->decl,
+					param_max_inline_insns_small))
 	{
 	  /* growth_positive_p is expensive, always test it last.  */
           if (growth >= inline_insns_single (e->caller, false)
@@ -951,7 +938,7 @@  want_inline_small_function_p (struct cgr
 }
 
 /* EDGE is self recursive edge.
-   We hand two cases - when function A is inlining into itself
+   We handle two cases - when function A is inlining into itself
    or when function A is being inlined into another inliner copy of function
    A within function B.  
 
@@ -970,10 +957,12 @@  want_inline_self_recursive_call_p (struc
   char const *reason = NULL;
   bool want_inline = true;
   sreal caller_freq = 1;
-  int max_depth = param_max_inline_recursive_depth_auto;
+  int max_depth = opt_for_fn (outer_node->decl,
+			      param_max_inline_recursive_depth_auto);
 
   if (DECL_DECLARED_INLINE_P (edge->caller->decl))
-    max_depth = param_max_inline_recursive_depth;
+    max_depth = opt_for_fn (outer_node->decl,
+			    param_max_inline_recursive_depth);
 
   if (!edge->maybe_hot_p ())
     {
@@ -1035,7 +1024,8 @@  want_inline_self_recursive_call_p (struc
     {
       if (edge->sreal_frequency () * 100
           <= caller_freq
-	     * param_min_inline_recursive_probability)
+	     * opt_for_fn (outer_node->decl,
+			   param_min_inline_recursive_probability))
 	{
 	  reason = "frequency of recursive call is too small";
 	  want_inline = false;
@@ -1241,7 +1231,9 @@  edge_badness (struct cgraph_edge *edge,
 	      /* ... or when early optimizers decided to split and edge
 		 frequency still indicates splitting is a win ... */
 	      || (callee->split_part && !caller->split_part
-		  && freq * 100 < param_partial_inlining_entry_probability
+		  && freq * 100
+			 < opt_for_fn (caller->decl,
+				       param_partial_inlining_entry_probability)
 		  /* ... and do not overwrite user specified hints.   */
 		  && (!DECL_DECLARED_INLINE_P (edge->callee->decl)
 		      || DECL_DECLARED_INLINE_P (caller->decl)))))
@@ -1599,7 +1591,10 @@  static bool
 recursive_inlining (struct cgraph_edge *edge,
 		    vec<cgraph_edge *> *new_edges)
 {
-  int limit = param_max_inline_insns_recursive_auto;
+  cgraph_node *to  = (edge->caller->inlined_to
+		      ? edge->caller->inlined_to : edge->caller);
+  int limit = opt_for_fn (to->decl,
+			  param_max_inline_insns_recursive_auto);
   edge_heap_t heap (sreal::min ());
   struct cgraph_node *node;
   struct cgraph_edge *e;
@@ -1612,7 +1607,7 @@  recursive_inlining (struct cgraph_edge *
     node = node->inlined_to;
 
   if (DECL_DECLARED_INLINE_P (node->decl))
-    limit = param_max_inline_insns_recursive;
+    limit = opt_for_fn (to->decl, param_max_inline_insns_recursive);
 
   /* Make sure that function is small enough to be considered for inlining.  */
   if (estimate_size_after_inlining (node, edge)  >= limit)
@@ -1735,14 +1730,14 @@  recursive_inlining (struct cgraph_edge *
    allow the unit to grow.  */
 
 static int
-compute_max_insns (int insns)
+compute_max_insns (cgraph_node *node, int insns)
 {
   int max_insns = insns;
-  if (max_insns < param_large_unit_insns)
-    max_insns = param_large_unit_insns;
+  if (max_insns < opt_for_fn (node->decl, param_large_unit_insns))
+    max_insns = opt_for_fn (node->decl, param_large_unit_insns);
 
   return ((int64_t) max_insns
-	  * (100 + param_inline_unit_growth) / 100);
+	  * (100 + opt_for_fn (node->decl, param_inline_unit_growth)) / 100);
 }
 
 
@@ -1906,7 +1901,7 @@  inline_small_functions (void)
   struct cgraph_edge *edge;
   edge_heap_t edge_heap (sreal::min ());
   auto_bitmap updated_nodes;
-  int min_size, max_size;
+  int min_size;
   auto_vec<cgraph_edge *> new_indirect_edges;
   int initial_size = 0;
   struct cgraph_node **order = XCNEWVEC (cgraph_node *, symtab->cgraph_count);
@@ -1973,7 +1968,6 @@  inline_small_functions (void)
 	     initial_size);
 
   overall_size = initial_size;
-  max_size = compute_max_insns (overall_size);
   min_size = overall_size;
 
   /* Populate the heap with all edges we might inline.  */
@@ -2141,7 +2135,9 @@  inline_small_functions (void)
 	    edge_badness (edge, true);
 	}
 
-      if (overall_size + growth > max_size
+      where = edge->caller;
+
+      if (overall_size + growth > compute_max_insns (where, min_size)
 	  && !DECL_DISREGARD_INLINE_LIMITS (callee->decl))
 	{
 	  edge->inline_failed = CIF_INLINE_UNIT_GROWTH_LIMIT;
@@ -2164,7 +2160,6 @@  inline_small_functions (void)
 	 specific inliner.  */
       if (edge->recursive_p ())
 	{
-	  where = edge->caller;
 	  if (where->inlined_to)
 	    where = where->inlined_to;
 	  if (!recursive_inlining (edge,
@@ -2278,7 +2273,6 @@  inline_small_functions (void)
       if (min_size > overall_size)
 	{
 	  min_size = overall_size;
-	  max_size = compute_max_insns (min_size);
 
 	  if (dump_file)
 	    fprintf (dump_file, "New minimal size reached: %i\n", min_size);
Index: opts.c
===================================================================
--- opts.c	(revision 278629)
+++ opts.c	(working copy)
@@ -544,6 +544,10 @@  static const struct default_options defa
 
     /* -O3 parameters.  */
     { OPT_LEVELS_3_PLUS, OPT__param_max_inline_insns_auto_, NULL, 30 },
+    { OPT_LEVELS_3_PLUS, OPT__param_early_inlining_insns_, NULL, 14 },
+    { OPT_LEVELS_3_PLUS, OPT__param_inline_heuristics_hint_percent_, NULL, 600 },
+    { OPT_LEVELS_3_PLUS, OPT__param_inline_min_speedup_, NULL, 15 },
+    { OPT_LEVELS_3_PLUS, OPT__param_max_inline_insns_single_, NULL, 200 },
 
     /* -Ofast adds optimizations to -O3.  */
     { OPT_LEVELS_FAST, OPT_ffast_math, NULL, 1 },
Index: params.opt
===================================================================
--- params.opt	(revision 278629)
+++ params.opt	(working copy)
@@ -99,12 +99,8 @@  Common Joined UInteger Var(param_dse_max
 Maximum size (in bytes) of objects tracked bytewise by dead store elimination.
 
 -param=early-inlining-insns=
-Common Joined UInteger Var(param_early_inlining_insns) Init(14) Param
-Maximal estimated growth of function body caused by early inlining of single call with -O3 and -Ofast.
-
--param=early-inlining-insns-O2=
-Common Joined UInteger Var(param_early_inlining_insns_o2) Init(6) Param
-Maximal estimated growth of function body caused by early inlining of single call with -O1 and -O2.
+Common Joined UInteger Var(param_early_inlining_insns) Init(6) Optimization Param
+Maximal estimated growth of function body caused by early inlining of single call.
 
 -param=fsm-maximum-phi-arguments=
 Common Joined UInteger Var(param_fsm_maximum_phi_arguments) Init(100) IntegerRange(1, 999999) Param
@@ -179,23 +175,15 @@  Common Joined UInteger Var(param_hsa_gen
 Level of hsa debug stores verbosity.
 
 -param=inline-heuristics-hint-percent=
-Common Joined UInteger Var(param_inline_heuristics_hint_percent) Init(600) IntegerRange(100, 1000000) Param
-The scale (in percents) applied to inline-insns-single and auto limits when heuristics hints that inlining is very profitable with -O3 and -Ofast.
-
--param=inline-heuristics-hint-percent-O2=
-Common Joined UInteger Var(param_inline_heuristics_hint_percent_o2) Init(200) IntegerRange(100, 1000000) Param
+Common Joined UInteger Var(param_inline_heuristics_hint_percent) Init(200) Optimization IntegerRange(100, 1000000) Param
 The scale (in percents) applied to inline-insns-single and auto limits when heuristics hints that inlining is very profitable.
 
 -param=inline-min-speedup=
-Common Joined UInteger Var(param_inline_min_speedup) Init(15) IntegerRange(0, 100) Param
-The minimal estimated speedup allowing inliner to ignore inline-insns-single and inline-insns-auto with -O3 and -Ofast.
-
--param=inline-min-speedup-O2=
-Common Joined UInteger Var(param_inline_min_speedup_o2) Init(30) IntegerRange(0, 100) Param
+Common Joined UInteger Var(param_inline_min_speedup) Init(30) Optimization IntegerRange(0, 100) Param
 The minimal estimated speedup allowing inliner to ignore inline-insns-single and inline-insns-auto.
 
 -param=inline-unit-growth=
-Common Joined UInteger Var(param_inline_unit_growth) Init(40) Param
+Common Joined UInteger Var(param_inline_unit_growth) Init(40) Optimization Param
 How much can given compilation unit grow because of the inlining (in percent).
 
 -param=integer-share-limit=
@@ -295,23 +283,23 @@  Common Joined UInteger Var(param_l2_cach
 The size of L2 cache.
 
 -param=large-function-growth=
-Common Joined UInteger Var(param_large_function_growth) Init(100) Param
+Common Joined UInteger Var(param_large_function_growth) Optimization Init(100) Param
 Maximal growth due to inlining of large function (in percent).
 
 -param=large-function-insns=
-Common Joined UInteger Var(param_large_function_insns) Init(2700) Param
+Common Joined UInteger Var(param_large_function_insns) Optimization Init(2700) Param
 The size of function body to be considered large.
 
 -param=large-stack-frame=
-Common Joined UInteger Var(param_large_stack_frame) Init(256) Param
+Common Joined UInteger Var(param_large_stack_frame) Init(256) Optimization Param
 The size of stack frame to be considered large.
 
 -param=large-stack-frame-growth=
-Common Joined UInteger Var(param_stack_frame_growth) Init(1000) Param
+Common Joined UInteger Var(param_stack_frame_growth) Optimization Init(1000) Param
 Maximal stack frame growth due to inlining (in percent).
 
 -param=large-unit-insns=
-Common Joined UInteger Var(param_large_unit_insns) Init(10000) Param
+Common Joined UInteger Var(param_large_unit_insns) Optimization  Init(10000) Param
 The size of translation unit to be considered large.
 
 -param=lim-expensive=
@@ -471,35 +459,31 @@  Common Joined UInteger Var(param_max_inl
 The maximum number of instructions when automatically inlining.
 
 -param=max-inline-insns-recursive=
-Common Joined UInteger Var(param_max_inline_insns_recursive) Init(450) Param
+Common Joined UInteger Var(param_max_inline_insns_recursive) Optimization Init(450) Param
 The maximum number of instructions inline function can grow to via recursive inlining.
 
 -param=max-inline-insns-recursive-auto=
-Common Joined UInteger Var(param_max_inline_insns_recursive_auto) Init(450) Param
+Common Joined UInteger Var(param_max_inline_insns_recursive_auto) Optimization Init(450) Param
 The maximum number of instructions non-inline function can grow to via recursive inlining.
 
 -param=max-inline-insns-single=
-Common Joined UInteger Var(param_max_inline_insns_single) Init(200) Param
-The maximum number of instructions in a single function eligible for inlining with -O3 and -Ofast.
-
--param=max-inline-insns-single-O2=
-Common Joined UInteger Var(param_max_inline_insns_single_o2) Init(70) Param
+Common Joined UInteger Var(param_max_inline_insns_single) Optimization Init(70) Param
 The maximum number of instructions in a single function eligible for inlining.
 
 -param=max-inline-insns-size=
-Common Joined UInteger Var(param_max_inline_insns_size) Param
+Common Joined UInteger Var(param_max_inline_insns_size) Optimization Param
 The maximum number of instructions when inlining for size.
 
 -param=max-inline-insns-small=
-Common Joined UInteger Var(param_max_inline_insns_small) Param
+Common Joined UInteger Var(param_max_inline_insns_small) Optimization Param
 The maximum number of instructions when automatically inlining small functions.
 
 -param=max-inline-recursive-depth=
-Common Joined UInteger Var(param_max_inline_recursive_depth) Init(8) Param
+Common Joined UInteger Var(param_max_inline_recursive_depth) Optimization Init(8) Param
 The maximum depth of recursive inlining for inline functions.
 
 -param=max-inline-recursive-depth-auto=
-Common Joined UInteger Var(param_max_inline_recursive_depth_auto) Init(8) Param
+Common Joined UInteger Var(param_max_inline_recursive_depth_auto) Optimization Init(8) Param
 The maximum depth of recursive inlining for non-inline functions.
 
 -param=max-isl-operations=
@@ -679,7 +663,7 @@  Common Joined UInteger Var(param_min_cro
 The minimum number of matching instructions to consider for crossjumping.
 
 -param=min-inline-recursive-probability=
-Common Joined UInteger Var(param_min_inline_recursive_probability) Init(10) Param
+Common Joined UInteger Var(param_min_inline_recursive_probability) Init(10) Optimization Param
 Inline recursively only when the probability of call being executed exceeds the parameter.
 
 -param=min-insn-to-prefetch-ratio=
@@ -737,7 +721,7 @@  EnumValue
 Enum(parloops_schedule_type) String(runtime) Value(PARLOOPS_SCHEDULE_RUNTIME)
 
 -param=partial-inlining-entry-probability=
-Common Joined UInteger Var(param_partial_inlining_entry_probability) Init(70) IntegerRange(0, 100) Param
+Common Joined UInteger Var(param_partial_inlining_entry_probability) Init(70) Optimization IntegerRange(0, 100) Param
 Maximum probability of the entry BB of split region (in percent relative to entry BB of the function) to make partial inlining happen.
 
 -param=predictable-branch-outcome=
@@ -913,19 +897,19 @@  Common Joined UInteger Var(param_uninit_
 Maximum number of nested calls to search for control dependencies during uninitialized variable analysis.
 
 -param=uninlined-function-insns=
-Common Joined UInteger Var(param_uninlined_function_insns) Init(2) IntegerRange(0, 1000000) Param
+Common Joined UInteger Var(param_uninlined_function_insns) Init(2) Optimization IntegerRange(0, 1000000) Param
 Instruction accounted for function prologue, epilogue and other overhead.
 
 -param=uninlined-function-time=
-Common Joined UInteger Var(param_uninlined_function_time) IntegerRange(0, 1000000) Param
+Common Joined UInteger Var(param_uninlined_function_time) Optimization IntegerRange(0, 1000000) Param
 Time accounted for function prologue, epilogue and other overhead.
 
 -param=uninlined-thunk-insns=
-Common Joined UInteger Var(param_uninlined_function_thunk_insns) Init(2) IntegerRange(0, 1000000) Param
+Common Joined UInteger Var(param_uninlined_function_thunk_insns) Optimization Init(2) IntegerRange(0, 1000000) Param
 Instruction accounted for function thunk overhead.
 
 -param=uninlined-thunk-time=
-Common Joined UInteger Var(param_uninlined_function_thunk_time) Init(2) IntegerRange(0, 1000000) Param
+Common Joined UInteger Var(param_uninlined_function_thunk_time) Optimization Init(2) IntegerRange(0, 1000000) Param
 Time accounted for function thunk overhead.
 
 -param=unlikely-bb-count-fraction=
Index: testsuite/g++.dg/tree-ssa/pr53844.C
===================================================================
--- testsuite/g++.dg/tree-ssa/pr53844.C	(revision 278629)
+++ testsuite/g++.dg/tree-ssa/pr53844.C	(working copy)
@@ -1,5 +1,5 @@ 
 // { dg-do compile }
-// { dg-options "-O2 -fdump-tree-optimized-vops -fno-inline-functions --param max-inline-insns-single-O2=200" }
+// { dg-options "-O2 -fdump-tree-optimized-vops -fno-inline-functions --param max-inline-insns-single=200" }
 
 struct VBase;
 
Index: testsuite/g++.dg/tree-ssa/pr61034.C
===================================================================
--- testsuite/g++.dg/tree-ssa/pr61034.C	(revision 278629)
+++ testsuite/g++.dg/tree-ssa/pr61034.C	(working copy)
@@ -1,5 +1,5 @@ 
 // { dg-do compile }
-// { dg-options "-O2 -fdump-tree-fre3 -fdump-tree-optimized -fdelete-null-pointer-checks --param early-inlining-insns-O2=14 --param max-inline-insns-single-O2=200" }
+// { dg-options "-O2 -fdump-tree-fre3 -fdump-tree-optimized -fdelete-null-pointer-checks --param early-inlining-insns=14 --param max-inline-insns-single=200" }
 
 #define assume(x) if(!(x))__builtin_unreachable()
 
Index: testsuite/g++.dg/tree-ssa/pr8781.C
===================================================================
--- testsuite/g++.dg/tree-ssa/pr8781.C	(revision 278629)
+++ testsuite/g++.dg/tree-ssa/pr8781.C	(working copy)
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-O -fno-tree-sra -fdump-tree-fre1 --param early-inlining-insns-O2=14" } */
+/* { dg-options "-O -fno-tree-sra -fdump-tree-fre1 --param early-inlining-insns=14" } */
 
 int f();
 
Index: testsuite/g++.dg/warn/Wstringop-truncation-1.C
===================================================================
--- testsuite/g++.dg/warn/Wstringop-truncation-1.C	(revision 278629)
+++ testsuite/g++.dg/warn/Wstringop-truncation-1.C	(working copy)
@@ -1,7 +1,7 @@ 
 /* PR/tree-optimization/84480 - bogus -Wstringop-truncation despite
    assignment with an inlined string literal
    { dg-do compile }
-   { dg-options "-O2 -Wstringop-truncation --param early-inlining-insns-O2=14" }  */
+   { dg-options "-O2 -Wstringop-truncation --param early-inlining-insns=14" }  */
 
 #include <string.h>
 
Index: testsuite/gcc.dg/ipa/pr63416.c
===================================================================
--- testsuite/gcc.dg/ipa/pr63416.c	(revision 278629)
+++ testsuite/gcc.dg/ipa/pr63416.c	(working copy)
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-optimized --param early-inlining-insns-O2=14"  } */
+/* { dg-options "-O2 -fdump-tree-optimized --param early-inlining-insns=14"  } */
 #define _UNUSED_ __attribute__((__unused__))
 
 typedef int TEST_F30 (int *v);
Index: testsuite/gcc.dg/tree-ssa/ssa-thread-12.c
===================================================================
--- testsuite/gcc.dg/tree-ssa/ssa-thread-12.c	(revision 278629)
+++ testsuite/gcc.dg/tree-ssa/ssa-thread-12.c	(working copy)
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-thread2-details -fdump-tree-thread3-details -fdump-tree-thread4-details -fno-finite-loops --param early-inlining-insns-O2=14 -fno-inline-functions" } */
+/* { dg-options "-O2 -fdump-tree-thread2-details -fdump-tree-thread3-details -fdump-tree-thread4-details -fno-finite-loops --param early-inlining-insns=14 -fno-inline-functions" } */
 /* { dg-final { scan-tree-dump "FSM" "thread2" } } */
 /* { dg-final { scan-tree-dump "FSM" "thread3" } } */
 /* { dg-final { scan-tree-dump "FSM" "thread4" { xfail *-*-* } } } */
Index: testsuite/gcc.dg/vect/pr66142.c
===================================================================
--- testsuite/gcc.dg/vect/pr66142.c	(revision 278629)
+++ testsuite/gcc.dg/vect/pr66142.c	(working copy)
@@ -1,6 +1,6 @@ 
 /* PR middle-end/66142 */
 /* { dg-do compile } */
-/* { dg-additional-options "-ffast-math -fopenmp-simd --param early-inlining-insns-O2=14" } */
+/* { dg-additional-options "-ffast-math -fopenmp-simd --param early-inlining-insns=14" } */
 /* { dg-additional-options "-mavx" { target avx_runtime } } */
 
 struct A { float x, y; };
Index: testsuite/gcc.dg/winline-3.c
===================================================================
--- testsuite/gcc.dg/winline-3.c	(revision 278629)
+++ testsuite/gcc.dg/winline-3.c	(working copy)
@@ -1,5 +1,5 @@ 
 /* { dg-do compile } */
-/* { dg-options "-Winline -O2 --param max-inline-insns-single-O2=1 --param inline-min-speedup-O2=100 -fgnu89-inline" } */
+/* { dg-options "-Winline -O2 --param max-inline-insns-single=1 --param inline-min-speedup=100 -fgnu89-inline" } */
 
 void big (void);
 inline int q(void) /* { dg-warning "max-inline-insns-single" } */
Index: testsuite/gcc.target/powerpc/pr72804.c
===================================================================
--- testsuite/gcc.target/powerpc/pr72804.c	(revision 278629)
+++ testsuite/gcc.target/powerpc/pr72804.c	(working copy)
@@ -1,7 +1,7 @@ 
 /* { dg-do compile { target { lp64 } } } */
 /* { dg-skip-if "" { powerpc*-*-darwin* } } */
 /* { dg-require-effective-target powerpc_vsx_ok } */
-/* { dg-options "-O2 -mvsx -fno-inline-functions --param max-inline-insns-single-O2=200" } */
+/* { dg-options "-O2 -mvsx -fno-inline-functions --param max-inline-insns-single=200" } */
 
 __int128_t
 foo (__int128_t *src)