--- gcc/ChangeLog.orig Sat Apr 27 15:05:06 2002 +++ gcc/ChangeLog Sat Apr 27 15:05:52 2002 @@ -1,3 +1,20 @@ +2002-04-24 Kurt Garloff + + * toplev.c: (rest_of_compilation): Set current_function_is_leaf + flag for integrate.c. Set DID_INLINE_FUNC flag if we inline + just because of -finline-functions. + * integrate.c: (INTEGRATE_THRESHOLD): Better tune for -Os. + Give leaf functions an inlining bonus. + * tree.h: (struct tree_decl): New flag inlined_function_flag + for functions inlined by -finline-functions. DID_INLINE_FUNC + accessor. + * tree-inline.c: (inlinable_function_p): Only allow half the + size for functions inlinable because of -finline-functions. + * c-decl.c: (grokdeclarator): Set DID_INLINE_FUNC flag. + * cp/decl.c: (grokfndecl): Likewise. + * cp/optimize: (maybe_clone_body): Copy DID_INLINE_FUNC for + clones. + 2002-04-23 Kurt Garloff * tree-inline.c (inlinable_function_p): Improve heuristics --- gcc/tree.h.orig Tue Apr 23 20:53:14 2002 +++ gcc/tree.h Sat Apr 27 01:38:27 2002 @@ -1611,6 +1611,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) @@ -1792,7 +1796,8 @@ unsigned non_addressable : 1; unsigned user_align : 1; unsigned uninlinable : 1; - /* Three unused bits. */ + unsigned inlined_function_flag : 1; + /* Two unused bits. */ unsigned lang_flag_0 : 1; unsigned lang_flag_1 : 1; --- gcc/tree-inline.c.orig Sat Apr 27 01:42:41 2002 +++ gcc/tree-inline.c Sat Apr 27 01:41:02 2002 @@ -669,6 +669,7 @@ { int inlinable; int currfn_insns; + int max_inline_insns_single = MAX_INLINE_INSNS_SINGLE; /* If we've already decided this function shouldn't be inlined, there's no need to check again. */ @@ -678,6 +679,12 @@ /* Assume it is not inlinable. */ inlinable = 0; + /* We may here either because fn is declared inline or because + we use -finline-functions. For the second case, we are more + restricitve. */ + if (DID_INLINE_FUNC (fn)) + max_inline_insns_single /= 2; + /* The number of instructions (estimated) of current function. */ currfn_insns = DECL_NUM_STMTS (fn) * INSNS_PER_STMT; @@ -696,7 +703,7 @@ function to be of MAX_INLINE_INSNS_SINGLE size. Make special allowance for extern inline functions, though. */ else if (! (*lang_hooks.tree_inlining.disregard_inline_limits) (fn) - && currfn_insns > MAX_INLINE_INSNS_SINGLE) + && currfn_insns > max_inline_insns_single) ; /* All is well. We can inline this function. Traditionally, GCC has refused to inline functions using alloca, or functions whose @@ -727,7 +734,7 @@ else if ((sum_insns > MAX_INLINE_INSNS) && (currfn_insns > MIN_INLINE_INSNS)) { - int max_curr = MAX_INLINE_INSNS_SINGLE + int max_curr = max_inline_insns_single - (sum_insns - MAX_INLINE_INSNS) / MAX_INLINE_SLOPE; if (currfn_insns > max_curr) inlinable = 0; --- gcc/c-decl.c.orig Tue Apr 16 15:33:21 2002 +++ gcc/c-decl.c Sat Apr 27 01:38:27 2002 @@ -5151,6 +5151,8 @@ needed, and let dwarf2 know that the function is inlinable. */ else if (flag_inline_trees == 2 && initialized) { + if (!DECL_INLINE (decl)) + DID_INLINE_FUNC (decl) = 1; DECL_INLINE (decl) = 1; DECL_DECLARED_INLINE_P (decl) = 0; } --- gcc/cp/decl.c.orig Tue Apr 16 15:42:59 2002 +++ gcc/cp/decl.c Sat Apr 27 14:28:27 2002 @@ -9014,13 +9014,19 @@ DECL_NOT_REALLY_EXTERN (decl) = 1; } + DID_INLINE_FUNC (decl) = 0; /* If the declaration was declared inline, mark it as such. */ if (inlinep) 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 && !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) @@ -14417,6 +14423,7 @@ DECL_DECLARED_INLINE_P (fndecl) = 1; + DID_INLINE_FUNC (fndecl) = 0; if (flag_default_inline) DECL_INLINE (fndecl) = 1; --- gcc/toplev.c.orig Tue Apr 23 20:53:12 2002 +++ gcc/toplev.c Sat Apr 27 01:38:27 2002 @@ -2400,6 +2400,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) @@ -2416,12 +2417,16 @@ 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 + the "inline" keyword was specified when we decide + to inline it (because of -finline-functions). + garloff@suse.de, 2002-04-24: Add another flag to + actually record this piece of information. */ + if (! DECL_INLINE (decl)) + DID_INLINE_FUNC (decl) = 1; inlinable = DECL_INLINE (decl) = 1; + } } insns = get_insns (); --- gcc/cp/optimize.c.orig Sun Dec 16 17:07:00 2001 +++ gcc/cp/optimize.c Sat Apr 27 01:38:27 2002 @@ -167,6 +167,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); --- gcc/print-tree.c.orig Wed Apr 24 12:23:18 2002 +++ gcc/print-tree.c Sat Apr 27 01:38:27 2002 @@ -342,6 +342,8 @@ if (TREE_CODE (node) == FUNCTION_DECL && DECL_INLINE (node)) fputs (" inline", file); + if (TREE_CODE (node) == FUNCTION_DECL && DID_INLINE_FUNC (node)) + fputs ("(opt)", file); if (TREE_CODE (node) == FUNCTION_DECL && DECL_BUILT_IN (node)) fputs (" built-in", file); if (TREE_CODE (node) == FUNCTION_DECL && DECL_BUILT_IN_NONANSI (node)) --- gcc/integrate.c.orig Sat Apr 27 10:47:14 2002 +++ gcc/integrate.c Sat Apr 27 14:24:31 2002 @@ -61,8 +61,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 @@ -171,7 +171,15 @@ /* For functions marked as inline increase the maximum size to MAX_INLINE_INSNS (-finline-limit-). For regular functions - use the limit given by INTEGRATE_THRESHOLD. */ + use the limit given by INTEGRATE_THRESHOLD. + Note that we don't differentiate between automatically inlined + functions (DID_INLINE_FUNC set) and functions declared inline + here, as too much inlining at RTL level does not cause so much + problems with compile-time resources and no recursive accounting + and limiting is done, so we also don't hurt runtime performance. + Also note that we use the recursive limit here, not the single + function limit, assuming tree inlining has done some inlining + already. */ int max_insns = (DECL_INLINE (fndecl)) ? (MAX_INLINE_INSNS @@ -208,6 +216,9 @@ if (current_function_cannot_inline) return current_function_cannot_inline; + if (current_function_is_leaf) + max_insns = (max_insns * 3) / 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");