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:
parent
ce01559bb7
commit
d4d1ebc191
15 changed files with 103 additions and 155 deletions
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
{
|
||||
|
|
|
@ -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. */
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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}.
|
||||
|
|
|
@ -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. */
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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*-*-* } } } */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Add table
Reference in a new issue