diff options
Diffstat (limited to 'gcc/tree-inline.c')
-rw-r--r-- | gcc/tree-inline.c | 45 |
1 files changed, 33 insertions, 12 deletions
diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 759b55e1418..1385e8389be 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -668,6 +668,7 @@ inlinable_function_p (fn, id) inline_data *id; { int inlinable; + int currfn_insns; /* If we've already decided this function shouldn't be inlined, there's no need to check again. */ @@ -676,6 +677,9 @@ inlinable_function_p (fn, id) /* Assume it is not inlinable. */ inlinable = 0; + + /* The number of instructions (estimated) of current function. */ + currfn_insns = DECL_NUM_STMTS (fn) * INSNS_PER_STMT; /* If we're not inlining things, then nothing is inlinable. */ if (! flag_inline_trees) @@ -689,10 +693,10 @@ inlinable_function_p (fn, id) else if (! DECL_INLINE (fn)) ; /* We can't inline functions that are too big. Only allow a single - function to eat up half of our budget. Make special allowance - for extern inline functions, though. */ + 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) - && DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS / 2) + && 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 @@ -704,15 +708,31 @@ inlinable_function_p (fn, id) /* Squirrel away the result so that we don't have to check again. */ DECL_UNINLINABLE (fn) = ! inlinable; - /* Even if this function is not itself too big to inline, it might - be that we've done so much inlining already that we don't want to - risk too much inlining any more and thus halve the acceptable - size. */ + /* In case we don't disregard the inlining limits and we basically + can inline this function, investigate further. */ if (! (*lang_hooks.tree_inlining.disregard_inline_limits) (fn) - && ((DECL_NUM_STMTS (fn) + (id ? id->inlined_stmts : 0)) * INSNS_PER_STMT - > MAX_INLINE_INSNS) - && DECL_NUM_STMTS (fn) * INSNS_PER_STMT > MAX_INLINE_INSNS / 4) - inlinable = 0; + && inlinable) + { + int sum_insns = (id ? id->inlined_stmts : 0) * INSNS_PER_STMT + + currfn_insns; + /* In the extreme case that we have exceeded the recursive inlining + limit by a huge factor (128), we just say no. Should not happen + in real life. */ + if (sum_insns > MAX_INLINE_INSNS * 128) + inlinable = 0; + /* If we did not hit the extreme limit, we use a linear function + with slope -1/MAX_INLINE_SLOPE to exceedingly decrease the + allowable size. We always allow a size of MIN_INLINE_INSNS + though. */ + else if ((sum_insns > MAX_INLINE_INSNS) + && (currfn_insns > MIN_INLINE_INSNS)) + { + int max_curr = MAX_INLINE_INSNS_SINGLE + - (sum_insns - MAX_INLINE_INSNS) / MAX_INLINE_SLOPE; + if (currfn_insns > max_curr) + inlinable = 0; + } + } if (inlinable && (*lang_hooks.tree_inlining.cannot_inline_tree_fn) (&fn)) inlinable = 0; @@ -968,7 +988,8 @@ expand_call_inline (tp, walk_subtrees, data) /* Our function now has more statements than it did before. */ DECL_NUM_STMTS (VARRAY_TREE (id->fns, 0)) += DECL_NUM_STMTS (fn); - id->inlined_stmts += DECL_NUM_STMTS (fn); + /* For accounting, subtract one for the saved call/ret. */ + id->inlined_stmts += DECL_NUM_STMTS (fn) - 1; /* Recurse into the body of the just inlined function. */ expand_calls_inline (inlined_body, id); |