toplev.c (rest_of_compilation): Fix webizer pass ordering.

* 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.

From-SVN: r72721
This commit is contained in:
Jan Hubicka 2003-10-20 23:46:55 +02:00 committed by Jan Hubicka
parent ce01559bb7
commit d4d1ebc191
15 changed files with 103 additions and 155 deletions

View File

@ -1,3 +1,18 @@
2003-10-20 Jan Hubicka <jh@suse.cz>
* 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 <zack@codesourcery.com>
* fixinc/inclhack.def (hpux11_snprintf): New edit.

View File

@ -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

View File

@ -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"
{

View File

@ -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. */

View File

@ -1,3 +1,8 @@
2003-10-20 Jan Hubicka <jh@suse.cz>
* decl.c (start_cleanup_fn): Set DECL_DECLARED_INLINE_P to deffer
the expansion.
2003-10-20 Mark Mitchell <mark@codesourcery.com>
* Make-lang.in (c++.install-info): Remove.

View File

@ -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)
{

View File

@ -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}.

View File

@ -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. */

View File

@ -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:

View File

@ -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

View File

@ -1,3 +1,9 @@
2003-10-20 Jan Hubicka <jh@suse.cz>
* 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 <phil@codesourcery.com>
* gcc.dg/20021014-1.c: XFAIL for *-*-windiss targets.

View File

@ -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 <int I>
inline void g() { g<I-1>(); return; }

View File

@ -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*-*-* } } } */

View File

@ -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);

View File

@ -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);