This is the mail archive of the gcc@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]

-finline-functions tuning


Hi,

some people reported worse performance with -O3 as compared to -O2.
It seems that -finline-functions causes too many functions to be
inlined sometimes. This seems to be true especially in cases, where 
the authors of the code have used the inline keyword with some care.

This is especially bad for C++, where the inliner has some limits to
prevent excessive recursive inlining, so we may end up inlining comparably
large functions (which are not declared inline, but considered because they
fit below the inlining limit with -finline-functions) and then not inlining
functions which were declared inline, because we already inlined too much.

One possible solution is to still give functions declared inline a bonus
over the ones only inlined because of the compiler flag. Or use a lower
limit for the latter, which is the same.
This is what the RTL inlliner does anyway, so we also want to do it for the
C++ tree inliner as well. Unfortunately, for this, we need a new flag for the
functions, as we have to take a decision about this maybe multiple times
depending on the situation (previously inlined statements.)
[Note that the RTL inliner only had to take the decision once and then just
 set the inline flag; this was OK, as the decision did not consider
 auxiliary information only had to be taken 
 once, as no changing such as already inlined code.]
For the -finline-functions inlined functions, we just take half the limit of
the one for inline declared fns.

In my C++ benchmarks, the patch did prevent worse performance with -O3 (as
compared to -O2) in one case and in one it did not.
I'd like to hear your results.

Patch, which should be applied on top of v3 of my inliner patch against
3.0.1, is attached. It's also available via
http://www.garloff.de/kurt/freesoft/gcc/

Regards,
-- 
Kurt Garloff                   <kurt@garloff.de>         [Eindhoven, NL]
Physics: Plasma simulations  <K.Garloff@Phys.TUE.NL>  [TU Eindhoven, NL]
Linux: SCSI, Security          <garloff@suse.de>    [SuSE Nuernberg, DE]
 (See mail header or public key servers for PGP2 and GPG public keys.)
--- gcc/ChangeLog.orig	Mon Aug 20 20:47:50 2001
+++ gcc/ChangeLog	Thu Aug 30 12:38:09 2001
@@ -1,3 +1,13 @@
+2001-08-30  Kurt Garloff  <garloff@suse.de>
+
+	* tree.h: New decl flag inlined_function_flag to remember
+	that a fn has only been inlined because of -finline-functions
+	* toplev.c: Set it. Set current_functions_is_leaf.
+	* integrate.c: Use current_functions_is_leaf (2x) and 
+	inlined_function_flag. Fix optimize_size tuning.
+	* cp/optimize.c: Divide acceptable size by two for 
+	-finline-functions inlined fns.
+
 2001-08-19  Release Manager
 
 	* GCC 3.0.1 Released.
--- gcc/tree.h.orig	Thu Aug 16 15:00:09 2001
+++ gcc/tree.h	Thu Aug 30 11:52:47 2001
@@ -1505,6 +1505,10 @@
    where it is called.  */
 #define DECL_INLINE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.inline_flag)
 
+/* Nonzero in a FUNCTION_DECL means this function has been found inlinable
+   only by virtue of -finline-functions  */
+#define DID_INLINE_FUNC(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.inlined_function_flag)
+	
 /* In a FUNCTION_DECL, nonzero if the function cannot be inlined.  */
 #define DECL_UNINLINABLE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.uninlinable)
 
@@ -1680,7 +1684,8 @@
   unsigned non_addressable : 1;
   unsigned user_align : 1;
   unsigned uninlinable : 1;
-  /* Two unused bits.  */
+  unsigned inlined_function_flag : 1;
+  /* One unused bit.  */
 
   unsigned lang_flag_0 : 1;
   unsigned lang_flag_1 : 1;
--- gcc/toplev.c.orig	Sun Jul  1 16:36:59 2001
+++ gcc/toplev.c	Thu Aug 30 11:59:00 2001
@@ -2794,6 +2794,7 @@
 	  || flag_inline_functions)
 	{
 	  timevar_push (TV_INTEGRATION);
+	  current_function_is_leaf = leaf_function_p ();
 	  lose = function_cannot_inline_p (decl);
 	  timevar_pop (TV_INTEGRATION);
 	  if (lose || ! optimize)
@@ -2810,12 +2811,15 @@
 		  goto exit_rest_of_compilation;
 		}
 	    }
-	  else
-	    /* ??? Note that this has the effect of making it look
-		 like "inline" was specified for a function if we choose
-		 to inline it.  This isn't quite right, but it's
-		 probably not worth the trouble to fix.  */
+	  else {
+	    /* ??? Note that we used to just make it look like
+	         if "inline" keyword was specified for it.
+	         garloff@suse.de, 2001-08-30: Add another flag
+	         to remeber that we inline because of -finline-functions */
+	    if (! DECL_INLINE (decl))
+	      DID_INLINE_FUNC (decl) = 1;
 	    inlinable = DECL_INLINE (decl) = 1;
+	  }
 	}
 
       insns = get_insns ();
--- gcc/integrate.c.orig	Sun Jun 10 22:52:35 2001
+++ gcc/integrate.c	Thu Aug 30 12:02:29 2001
@@ -58,8 +58,8 @@
    all.  Assume 1 instruction for the call and 1.5 insns per argument.  */
 #define INTEGRATE_THRESHOLD(DECL) \
   (optimize_size \
-   ? (1 + (3 * list_length (DECL_ARGUMENTS (DECL))) / 2) \
-   : (8 * (8 + list_length (DECL_ARGUMENTS (DECL)))))
+   ? ( 3 + (4 * list_length (DECL_ARGUMENTS (DECL)))) \
+   : (64 + (8 * list_length (DECL_ARGUMENTS (DECL)))))
 #endif
 
 /* Decide whether a function with a target specific attribute
@@ -130,7 +130,7 @@
      MAX_INLINE_INSNS (-finline-limit-<n>).  For regular functions
      use the limit given by INTEGRATE_THRESHOLD.  */
 
-  int max_insns = (DECL_INLINE (fndecl))
+  int max_insns = (DECL_INLINE (fndecl) && !(DID_INLINE_FUNC (fndecl)))
 		   ? (MAX_INLINE_INSNS
 		      + 8 * list_length (DECL_ARGUMENTS (fndecl)))
 		   : INTEGRATE_THRESHOLD (fndecl);
@@ -165,6 +165,9 @@
   if (current_function_cannot_inline)
     return current_function_cannot_inline;
 
+  if (current_function_is_leaf)
+    max_insns *= 2;
+	
   /* If its not even close, don't even look.  */
   if (get_max_uid () > 3 * max_insns)
     return N_("function too large to be inline");
--- gcc/cp/decl.c.orig	Thu Aug 16 15:00:48 2001
+++ gcc/cp/decl.c	Thu Aug 30 11:55:19 2001
@@ -8872,9 +8872,13 @@
     DECL_DECLARED_INLINE_P (decl) = 1;
   /* We inline functions that are explicitly declared inline, or, when
      the user explicitly asks us to, all functions.  */
-  if (DECL_DECLARED_INLINE_P (decl) || flag_inline_trees == 2)
+  if (DECL_DECLARED_INLINE_P (decl))
     DECL_INLINE (decl) = 1;
-
+  if (flag_inline_trees == 2) {
+    if (!DECL_INLINE (decl))
+      DID_INLINE_FUNC (decl) = 1;
+    DECL_INLINE (decl) = 1;
+  }
   DECL_EXTERNAL (decl) = 1;
   if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
     {
--- gcc/cp/optimize.c.before	Thu Aug 30 12:39:39 2001
+++ gcc/cp/optimize.c	Thu Aug 30 12:05:41 2001
@@ -643,6 +643,11 @@
   if (DECL_UNINLINABLE (fn))
     return 0;
 
+  /* We may be here either because fn is declared inline or because
+   * we use -finline-functions. Punish second case. */
+  if (DID_INLINE_FUNC (fn))
+    max_inline_single /= 2;
+
   /* Assume it is not inlinable.  */
   inlinable = 0;
 
@@ -1134,6 +1139,7 @@
       DECL_SOURCE_FILE (clone) = DECL_SOURCE_FILE (fn);
       DECL_SOURCE_LINE (clone) = DECL_SOURCE_LINE (fn);
       DECL_INLINE (clone) = DECL_INLINE (fn);
+      DID_INLINE_FUNC (clone) = DID_INLINE_FUNC (fn);
       DECL_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn);
       DECL_COMDAT (clone) = DECL_COMDAT (fn);
       DECL_WEAK (clone) = DECL_WEAK (fn);

PGP signature


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