From 19489abdae422545cf21f5234f199cd9a7e664e5 Mon Sep 17 00:00:00 2001 From: hubicka Date: Mon, 20 Oct 2003 21:46:55 +0000 Subject: [PATCH] * toplev.c (rest_of_compilation): Fix webizer pass ordering. * cgraphunit.c (decide_is_function_needed): Fix test dealing with functions implicitly made inline. * cgraphunit.c (cgraph_decide_inlining_incrementally): New function. (cgraph_finalize_function): Use it. (cgraph_mark_inline): Allow incrmental decisions * invoke.texi (max-inline-slope, min-inline-insns): Kill. * params.def (PARAM_MAX_INLINE_SLOPE, PARAM_MIN_INLINE_INSNS): Kill. * tree-inline.c (limits_allow_inlining): Kill. (expand_call_inline): Always use unit-at-a-time path. * decl.c (start_cleanup_fn): Set DECL_DECLARED_INLINE_P to deffer the expansion. * testsuite/g++.dg/opt/inline4.C: Do not use min-inline-insns parameter. * testsuite/gcc.dg/inline-2.c: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@72721 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 15 ++++++ gcc/cgraphunit.c | 62 ++++++++++++++++++++++- gcc/config/i386/i386.md | 2 +- gcc/coverage.h | 1 + gcc/cp/ChangeLog | 5 ++ gcc/cp/decl.c | 2 + gcc/doc/invoke.texi | 16 ------ gcc/flags.h | 4 ++ gcc/opts.c | 7 --- gcc/params.def | 26 ---------- gcc/testsuite/ChangeLog | 6 +++ gcc/testsuite/g++.dg/opt/inline4.C | 2 +- gcc/testsuite/gcc.dg/inline-2.c | 3 +- gcc/toplev.c | 6 +-- gcc/tree-inline.c | 101 ++----------------------------------- 15 files changed, 103 insertions(+), 155 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 1e0075cd680..2d59559816a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2003-10-20 Jan Hubicka + + * toplev.c (rest_of_compilation): Fix webizer pass ordering. + + * cgraphunit.c (decide_is_function_needed): Fix test dealing + with functions implicitly made inline. + + * cgraphunit.c (cgraph_decide_inlining_incrementally): New function. + (cgraph_finalize_function): Use it. + (cgraph_mark_inline): Allow incrmental decisions + * invoke.texi (max-inline-slope, min-inline-insns): Kill. + * params.def (PARAM_MAX_INLINE_SLOPE, PARAM_MIN_INLINE_INSNS): Kill. + * tree-inline.c (limits_allow_inlining): Kill. + (expand_call_inline): Always use unit-at-a-time path. + 2003-10-20 Zack Weinberg * fixinc/inclhack.def (hpux11_snprintf): New edit. diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 7b85e77c226..c20367d1d00 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -49,6 +49,7 @@ static void cgraph_mark_local_functions (void); static void cgraph_optimize_function (struct cgraph_node *); static bool cgraph_default_inline_p (struct cgraph_node *n); static void cgraph_analyze_function (struct cgraph_node *node); +static void cgraph_decide_inlining_incrementally (struct cgraph_node *); /* Statistics we collect about inlining algorithm. */ static int ncalls_inlined; @@ -114,7 +115,7 @@ decide_is_function_needed (struct cgraph_node *node, tree decl) /* When declared inline, defer even the uninlinable functions. This allows them to be eliminated when unused. */ && !DECL_DECLARED_INLINE_P (decl) - && (node->local.inlinable || !cgraph_default_inline_p (node)))) + && (!node->local.inlinable || !cgraph_default_inline_p (node)))) return true; return false; @@ -206,7 +207,10 @@ cgraph_finalize_function (tree decl, bool nested) /* If not unit at a time, then we need to create the call graph now, so that called functions can be queued and emitted now. */ if (!flag_unit_at_a_time) - cgraph_analyze_function (node); + { + cgraph_analyze_function (node); + cgraph_decide_inlining_incrementally (node); + } if (decide_is_function_needed (node, decl)) cgraph_mark_needed_node (node); @@ -852,6 +856,7 @@ cgraph_mark_inline (struct cgraph_node *to, struct cgraph_node *what, to->global.insns = new_insns; if (!called && !what->needed && !what->origin + && flag_unit_at_a_time && !DECL_EXTERNAL (what->decl)) { if (!what->global.will_be_output) @@ -1221,6 +1226,59 @@ cgraph_decide_inlining (void) free (inlined_callees); } +/* Decide on the inlining. We do so in the topological order to avoid + expenses on updating datastructures. */ + +static void +cgraph_decide_inlining_incrementally (struct cgraph_node *node) +{ + struct cgraph_edge *e; + struct cgraph_node **inlined = + xmalloc (sizeof (struct cgraph_node *) * cgraph_n_nodes); + struct cgraph_node **inlined_callees = + xmalloc (sizeof (struct cgraph_node *) * cgraph_n_nodes); + int ninlined; + int ninlined_callees; + int y; + + ninlined = cgraph_inlined_into (node, inlined); + + /* First of all look for always inline functions. */ + for (e = node->callees; e; e = e->next_callee) + if (e->callee->local.disregard_inline_limits && !e->callee->output + && e->callee != node && !e->inline_call) + { + ninlined_callees = cgraph_inlined_callees (e->callee, inlined_callees); + cgraph_mark_inline (node, e->callee, inlined, ninlined, + inlined_callees, ninlined_callees); + for (y = 0; y < ninlined_callees; y++) + inlined_callees[y]->output = 0, node->aux = 0; + } + + /* Now do the automatic inlining. */ + for (e = node->callees; e; e = e->next_callee) + if (e->callee->local.inlinable && !e->callee->output + && e->callee != node && !e->inline_call + && cgraph_default_inline_p (e->callee) + && cgraph_check_inline_limits (node, e->callee, inlined, + ninlined)) + { + ninlined_callees = cgraph_inlined_callees (e->callee, inlined_callees); + cgraph_mark_inline (node, e->callee, inlined, ninlined, + inlined_callees, ninlined_callees); + for (y = 0; y < ninlined_callees; y++) + inlined_callees[y]->output = 0, node->aux = 0; + } + + /* Clear the flags set by cgraph_inlined_into. */ + for (y = 0; y < ninlined; y++) + inlined[y]->output = 0, node->aux = 0; + + free (inlined); + free (inlined_callees); +} + + /* Return true when CALLER_DECL should be inlined into CALLEE_DECL. */ bool diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 863dce5a4db..835480d3a47 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -16045,7 +16045,7 @@ (unspec:SF [(match_dup 2) (match_operand:SF 1 "register_operand" "")] UNSPEC_FPATAN)) - (clobber (match_dup 1))])] + (clobber (match_scratch:SF 3 ""))])] "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_unsafe_math_optimizations" { diff --git a/gcc/coverage.h b/gcc/coverage.h index 5ae27f805f2..9756bbaafa8 100644 --- a/gcc/coverage.h +++ b/gcc/coverage.h @@ -25,6 +25,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA extern void coverage_init (const char *); extern void coverage_finish (void); +extern void coverage_read_counts_file (void); /* Complete the coverage information for the current function. Once per function. */ diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1acee5ff415..c2cb189b8b2 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2003-10-20 Jan Hubicka + + * decl.c (start_cleanup_fn): Set DECL_DECLARED_INLINE_P to deffer + the expansion. + 2003-10-20 Mark Mitchell * Make-lang.in (c++.install-info): Remove. diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 8ca69d13989..0f1170c842e 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5073,6 +5073,8 @@ start_cleanup_fn (void) it is only called via a function pointer, but we avoid unnecessary emissions this way. */ DECL_INLINE (fndecl) = 1; + DECL_DECLARED_INLINE_P (fndecl) = 1; + DECL_INTERFACE_KNOWN (fndecl) = 1; /* Build the parameter. */ if (flag_use_cxa_atexit) { diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 4dbe1ee1c61..52bdd6d1362 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -4784,22 +4784,6 @@ larger binaries. Very high values are not advisable, as too large binaries may adversely affect runtime performance. The default value is 200. -@item max-inline-slope -After exceeding the maximum number of inlined instructions by repeated -inlining, a linear function is used to decrease the allowable size -for single functions. The slope of that function is the negative -reciprocal of the number specified here. -This parameter is ignored when @option{-funit-at-a-time} is used. -The default value is 32. - -@item min-inline-insns -The repeated inlining is throttled more and more by the linear function -after exceeding the limit. To avoid too much throttling, a minimum for -this function is specified here to allow repeated inlining for very small -functions even when a lot of repeated inlining already has been done. -This parameter is ignored when @option{-funit-at-a-time} is used. -The default value is 10. - @item large-function-insns The limit specifying really large functions. For functions greater than this limit inlining is constrained by @option{--param large-function-growth}. diff --git a/gcc/flags.h b/gcc/flags.h index 5b6f7283b6c..c2b2fad8f17 100644 --- a/gcc/flags.h +++ b/gcc/flags.h @@ -719,6 +719,10 @@ extern int flag_unit_at_a_time; extern int flag_web; +/* Nonzero means that we defer emitting functions until they are actually + used. */ +extern int flag_remove_unreachable_functions; + /* A string that's used when a random name is required. NULL means to make it really random. */ diff --git a/gcc/opts.c b/gcc/opts.c index 6439e26670f..dafd37104b4 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -1061,13 +1061,6 @@ common_handle_option (size_t scode, const char *arg, set_param_value ("max-inline-insns-single", value / 2); set_param_value ("max-inline-insns-auto", value / 2); set_param_value ("max-inline-insns-rtl", value); - if (value / 4 < MIN_INLINE_INSNS) - { - if (value / 4 > 10) - set_param_value ("min-inline-insns", value / 4); - else - set_param_value ("min-inline-insns", 10); - } break; case OPT_finstrument_functions: diff --git a/gcc/params.def b/gcc/params.def index c5dfca864d5..b08603b1f29 100644 --- a/gcc/params.def +++ b/gcc/params.def @@ -84,32 +84,6 @@ DEFPARAM (PARAM_MAX_INLINE_INSNS, "The maximum number of instructions by repeated inlining before gcc starts to throttle inlining", 200) -/* After the repeated inline limit has been exceeded (see - "max-inline-insns" parameter), a linear function is used to - decrease the size of single functions eligible for inlining. - The slope of this linear function is given the negative - reciprocal value (-1/x) of this parameter. - The default value is 32. - This linear function is used until it falls below a minimum - value specified by the "min-inline-insns" parameter. */ -DEFPARAM (PARAM_MAX_INLINE_SLOPE, - "max-inline-slope", - "The slope of the linear function throttling inlining after the recursive inlining limit has been reached is given by the negative reciprocal value of this parameter", - 32) - -/* When gcc has inlined so many instructions (by repeated - inlining) that the throttling limits the inlining very much, - inlining for very small functions is still desirable to - achieve good runtime performance. The size of single functions - (measured in gcc instructions) which will still be eligible for - inlining then is given by this parameter. It defaults to 130. - Only much later (after exceeding 128 times the recursive limit) - inlining is cut down completely. */ -DEFPARAM (PARAM_MIN_INLINE_INSNS, - "min-inline-insns", - "The number of instructions in a single functions still eligible to inlining after a lot recursive inlining", - 10) - /* For languages that (still) use the RTL inliner, we can specify limits for the RTL inliner separately. The parameter here defines the maximum number of RTL instructions diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 0f005e8bffc..20bac3351bd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2003-10-20 Jan Hubicka + + * testsuite/g++.dg/opt/inline4.C: Do not use min-inline-insns + parameter. + * testsuite/gcc.dg/inline-2.c: Likewise. + 2003-10-20 Phil Edwards * gcc.dg/20021014-1.c: XFAIL for *-*-windiss targets. diff --git a/gcc/testsuite/g++.dg/opt/inline4.C b/gcc/testsuite/g++.dg/opt/inline4.C index 2d3eb379648..1db4fe1860b 100644 --- a/gcc/testsuite/g++.dg/opt/inline4.C +++ b/gcc/testsuite/g++.dg/opt/inline4.C @@ -1,4 +1,4 @@ -// { dg-options "-O2 -ftemplate-depth-20000 --param min-inline-insns=100 --param max-inline-insns=3" } +// { dg-options "-O2 -ftemplate-depth-20000" } template inline void g() { g(); return; } diff --git a/gcc/testsuite/gcc.dg/inline-2.c b/gcc/testsuite/gcc.dg/inline-2.c index 28991bccb9f..80e7848aca2 100644 --- a/gcc/testsuite/gcc.dg/inline-2.c +++ b/gcc/testsuite/gcc.dg/inline-2.c @@ -11,7 +11,8 @@ static int foo(void) int bar(void) { - return foo() + 1; + /* Call twice to avoid bypassing the limit for functions called once. */ + return foo() + foo() + 1; } /* { dg-final { scan-assembler-not "jsr" { target alpha*-*-* } } } */ diff --git a/gcc/toplev.c b/gcc/toplev.c index 151f6c65280..a393c52003e 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -3364,9 +3364,6 @@ rest_of_compilation (tree decl) rest_of_handle_cfg (decl, insns); - if (flag_web) - rest_of_handle_web (decl, insns); - if (optimize > 0 || profile_arc_flag || flag_test_coverage || flag_branch_probabilities) { @@ -3394,6 +3391,9 @@ rest_of_compilation (tree decl) || flag_unroll_loops)) rest_of_handle_loop2 (decl, insns); + if (flag_web) + rest_of_handle_web (decl, insns); + if (flag_rerun_cse_after_loop) rest_of_handle_cse2 (decl, insns); diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 375a5702291..b827dfc1c29 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -119,7 +119,6 @@ static tree copy_body (inline_data *); static tree expand_call_inline (tree *, int *, void *); static void expand_calls_inline (tree *, inline_data *); static bool inlinable_function_p (tree); -static int limits_allow_inlining (tree, inline_data *); static tree remap_decl (tree, inline_data *); static tree remap_type (tree, inline_data *); #ifndef INLINER_FOR_JAVA @@ -1219,97 +1218,6 @@ inlinable_function_p (tree fn) return inlinable; } -/* We can't inline functions that are too big. Only allow a single - function to be of MAX_INLINE_INSNS_SINGLE size. Make special - allowance for extern inline functions, though. - - Return nonzero if the function FN can be inlined into the inlining - context ID. */ - -static int -limits_allow_inlining (tree fn, inline_data *id) -{ - int estimated_insns = 0; - size_t i; - - /* Don't even bother if the function is not inlinable. */ - if (!inlinable_function_p (fn)) - return 0; - - /* Investigate the size of the function. Return at once - if the function body size is too large. */ - if (!(*lang_hooks.tree_inlining.disregard_inline_limits) (fn)) - { - int currfn_max_inline_insns; - - /* If we haven't already done so, get an estimate of the number of - instructions that will be produces when expanding this function. */ - if (!DECL_ESTIMATED_INSNS (fn)) - DECL_ESTIMATED_INSNS (fn) - = (*lang_hooks.tree_inlining.estimate_num_insns) (fn); - estimated_insns = DECL_ESTIMATED_INSNS (fn); - - /* We may be here either because fn is declared inline or because - we use -finline-functions. For the second case, we are more - restrictive. - - FIXME: -finline-functions should imply -funit-at-a-time, it's - about equally expensive but unit-at-a-time produces - better code. */ - currfn_max_inline_insns = DECL_DECLARED_INLINE_P (fn) ? - MAX_INLINE_INSNS_SINGLE : MAX_INLINE_INSNS_AUTO; - - /* If the function is too big to be inlined, adieu. */ - if (estimated_insns > currfn_max_inline_insns) - return 0; - - /* We now know that we don't disregard the inlining limits and that - we basically should be able to inline this function. - We always allow inlining functions if we estimate that they are - smaller than MIN_INLINE_INSNS. Otherwise, investigate further. */ - if (estimated_insns > MIN_INLINE_INSNS) - { - int sum_insns = (id ? id->inlined_insns : 0) + estimated_insns; - - /* In the extreme case that we have exceeded the recursive inlining - limit by a huge factor (128), we just say no. - - FIXME: Should not happen in real life, but people have reported - that it actually does!? */ - if (sum_insns > MAX_INLINE_INSNS * 128) - return 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. */ - else if (sum_insns > MAX_INLINE_INSNS) - { - if (estimated_insns > currfn_max_inline_insns - - (sum_insns - MAX_INLINE_INSNS) / MAX_INLINE_SLOPE) - return 0; - } - } - } - - /* Don't allow recursive inlining. */ - for (i = 0; i < VARRAY_ACTIVE_SIZE (id->fns); ++i) - if (VARRAY_TREE (id->fns, i) == fn) - return 0; - - if (DECL_INLINED_FNS (fn)) - { - int j; - tree inlined_fns = DECL_INLINED_FNS (fn); - - for (j = 0; j < TREE_VEC_LENGTH (inlined_fns); ++j) - if (TREE_VEC_ELT (inlined_fns, j) == VARRAY_TREE (id->fns, 0)) - return 0; - } - - /* Go ahead, this function can be inlined. */ - return 1; -} - /* If *TP is a CALL_EXPR, replace it with its inline expansion. */ static tree @@ -1396,8 +1304,7 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data) return NULL_TREE; /* Turn forward declarations into real ones. */ - if (flag_unit_at_a_time) - fn = cgraph_node (fn)->decl; + fn = cgraph_node (fn)->decl; /* If fn is a declaration of a function in a nested scope that was globally declared inline, we don't set its DECL_INITIAL. @@ -1413,9 +1320,7 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data) /* Don't try to inline functions that are not well-suited to inlining. */ - if ((flag_unit_at_a_time - && (!DECL_SAVED_TREE (fn) || !cgraph_inline_p (id->current_decl, fn))) - || (!flag_unit_at_a_time && !limits_allow_inlining (fn, id))) + if (!DECL_SAVED_TREE (fn) || !cgraph_inline_p (id->current_decl, fn)) { if (warn_inline && DECL_INLINE (fn) && DECL_DECLARED_INLINE_P (fn) && !DECL_IN_SYSTEM_HEADER (fn)) @@ -1653,7 +1558,7 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data) id->inlined_insns += DECL_ESTIMATED_INSNS (fn) - 1; /* Update callgraph if needed. */ - if (id->decl && flag_unit_at_a_time) + if (id->decl) { cgraph_remove_call (id->decl, fn); cgraph_create_edges (id->decl, *inlined_body); -- 2.11.4.GIT