tree.h (DID_INLINE_FUNC): Remove macro.

2003-08-05  Steven Bosscher  <steven@gcc.gnu.org>

	* tree.h (DID_INLINE_FUNC): Remove macro.
	(DECL_DECLARED_INLINE_P): Move from c-tree.h and cp/cp-tree.h,
	add tree check for FUNCTION_DECL.
	(DECL_ESTIMATED_INSNS): Move from c-common.h and java/java-tree.h.
	(struct tree_decl): Rename inlined_function_flag to
	declared_inline_flag.
	* c-common.h (c_lang_decl): Remove.
	(DECL_ESTIMATED_INSNS): Remove.
	* c-tree.h (struct lang_decl): Don't include c_lang_decl.
	(DECL_DECLARED_INLINE_P): Remove.
	* c-decl.c (grokdeclarator): Update comment.  With -finline-functions,
	do not reset DECL_DECLARED_INLINE_P.  Don't use DID_INLINE_FUNC.
	(finish_function): Make uninlinable a bool.  Fixup call to
	tree_inlinable_function_p() and fix some code style issues.
	* cgraph.h (disgread_inline_limits): Fix spelling: `disregard'.
	* cgraph.c (dump_cgraph): Likewise.
	* cgraphunit.c (cgraph_decide_inlining): Likewise
	(cgraph_finalize_compilation_unit): Likewise.
	Also update call to tree_inlinable_function_p().
	(cgraph_default_inline_p): Don't use DID_INLINE_FUNC.  Instead
	look at DECL_DECLARED_INLINE and reverse logic.
	* print-tree.c (print_node): Likewise.
	* toplev.c (rest_of_handle_inlining): Don't use DID_INLINE_FUNC.
	* tree-inline.h (tree_inlinable_function_p): Make a bool.  Update
	prototype.
	* tree-inline.c (inlinable_function_p): Split up in this function to
	check for basic inlining inhibiting conditions, and new
	limits_allow_inlining() function.  Warn if inlining is impossible
	because the inline candidate calls alloca or uses sjlj exceptions.
	(limits_allow_inlining): this new function to check if the inlining
	limits are satisfied.  Throttle from currfn_max_inline_insns, not from
	MAX_INLINE_INSNS_SINGLE.  The latter only makes sense if
	MAX_INLINE_INSNS_AUTO and MAX_INLINE_INSNS_SINGLE are equal.
	Update prototypes.
	(tree_inlinable_function_p): Make a bool.  Update call to
	inlinable_function_p
	(expand_call_inline): Use limits_allow_inlining() when not in
	unit-at-a-time mode to decide on inlining.  Don't use DID_INLINE_FUNC,
	instead see if the function was declared `inline'.

cp/
	* cp-tree.h (struct lang_decl): Don't include c_lang_decl.
	(DECL_DECLARED_INLINE_P): Remove.
	* decl2.c (import_export_decl): Only look at DECL_DECLARED_INLINE_P
	if decl is a FUNCTION_DECL.  This never made sense, but now it is
	required to avoid a tree check failure.
	* decl.c (grokfndecl): Don't touch DID_INLINE_FUNC.
	* optimize.c (maybe_clone_body): Likewise.

java/
	* java-tree.h (DECL_ESTIMATED_INSNS): Remove.

From-SVN: r70174
This commit is contained in:
Steven Bosscher 2003-08-05 14:11:53 +00:00
parent 158aa0f72e
commit b3c3af2f63
19 changed files with 256 additions and 190 deletions

View File

@ -1,3 +1,45 @@
2003-08-05 Steven Bosscher <steven@gcc.gnu.org>
* tree.h (DID_INLINE_FUNC): Remove macro.
(DECL_DECLARED_INLINE_P): Move from c-tree.h and cp/cp-tree.h,
add tree check for FUNCTION_DECL.
(DECL_ESTIMATED_INSNS): Move from c-common.h and java/java-tree.h.
(struct tree_decl): Rename inlined_function_flag to
declared_inline_flag.
* c-common.h (c_lang_decl): Remove.
(DECL_ESTIMATED_INSNS): Remove.
* c-tree.h (struct lang_decl): Don't include c_lang_decl.
(DECL_DECLARED_INLINE_P): Remove.
* c-decl.c (grokdeclarator): Update comment. With -finline-functions,
do not reset DECL_DECLARED_INLINE_P. Don't use DID_INLINE_FUNC.
(finish_function): Make uninlinable a bool. Fixup call to
tree_inlinable_function_p() and fix some code style issues.
* cgraph.h (disgread_inline_limits): Fix spelling: `disregard'.
* cgraph.c (dump_cgraph): Likewise.
* cgraphunit.c (cgraph_decide_inlining): Likewise
(cgraph_finalize_compilation_unit): Likewise.
Also update call to tree_inlinable_function_p().
(cgraph_default_inline_p): Don't use DID_INLINE_FUNC. Instead
look at DECL_DECLARED_INLINE and reverse logic.
* print-tree.c (print_node): Likewise.
* toplev.c (rest_of_handle_inlining): Don't use DID_INLINE_FUNC.
* tree-inline.h (tree_inlinable_function_p): Make a bool. Update
prototype.
* tree-inline.c (inlinable_function_p): Split up in this function to
check for basic inlining inhibiting conditions, and new
limits_allow_inlining() function. Warn if inlining is impossible
because the inline candidate calls alloca or uses sjlj exceptions.
(limits_allow_inlining): this new function to check if the inlining
limits are satisfied. Throttle from currfn_max_inline_insns, not from
MAX_INLINE_INSNS_SINGLE. The latter only makes sense if
MAX_INLINE_INSNS_AUTO and MAX_INLINE_INSNS_SINGLE are equal.
Update prototypes.
(tree_inlinable_function_p): Make a bool. Update call to
inlinable_function_p
(expand_call_inline): Use limits_allow_inlining() when not in
unit-at-a-time mode to decide on inlining. Don't use DID_INLINE_FUNC,
instead see if the function was declared `inline'.
2003-08-05 Josef Zlomek <zlomekj@suse.cz>
* gcse.c (try_replace_reg): Fix updating of note.

View File

@ -346,22 +346,6 @@ extern void shadow_warning (enum sw_kind, const char *, tree);
extern int field_decl_cmp (const void *, const void *);
extern void resort_sorted_fields (void *, void *, gt_pointer_operator,
void *);
/* Extra information associated with a DECL. Other C dialects extend
this structure in various ways. The C front-end only uses this
structure for FUNCTION_DECLs; all other DECLs have a NULL
DECL_LANG_SPECIFIC field. */
struct c_lang_decl GTY(()) {
unsigned declared_inline : 1;
};
/* In a FUNCTION_DECL for which DECL_BUILT_IN does not hold, this is
the approximate number of statements in this function. There is
no need for this number to be exact; it is only used in various
heuristics regarding optimization. */
#define DECL_ESTIMATED_INSNS(NODE) \
(FUNCTION_DECL_CHECK (NODE)->decl.u1.i)
/* Switches common to the C front ends. */

View File

@ -4319,7 +4319,7 @@ grokdeclarator (tree declarator, tree declspecs,
}
else if (inlinep)
{
/* Assume that otherwise the function can be inlined. */
/* Record that the function is declared `inline'. */
DECL_DECLARED_INLINE_P (decl) = 1;
/* Do not mark bare declarations as DECL_INLINE. Doing so
@ -4337,12 +4337,7 @@ grokdeclarator (tree declarator, tree declspecs,
two things: let the function be deferred until it is actually
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;
}
DECL_INLINE (decl) = 1;
}
else
{
@ -6157,7 +6152,7 @@ finish_function (int nested, int can_defer_p)
/* Function is parsed.
Generate RTL for the body of this function or defer
it for later expansion. */
int uninlinable = 1;
bool uninlinable = true;
/* There's no reason to do any of the work here if we're only doing
semantic analysis; this code just generates RTL. */
@ -6174,14 +6169,14 @@ finish_function (int nested, int can_defer_p)
predicates depend on cfun and current_function_decl to
function completely. */
timevar_push (TV_INTEGRATION);
uninlinable = ! tree_inlinable_function_p (fndecl, 0);
uninlinable = !tree_inlinable_function_p (fndecl);
if (can_defer_p
/* We defer functions marked inline *even if* the function
itself is not inlinable. This is because we don't yet
know if the function will actually be used; we may be
able to avoid emitting it entirely. */
&& (! uninlinable || DECL_DECLARED_INLINE_P (fndecl))
&& (!uninlinable || DECL_DECLARED_INLINE_P (fndecl))
/* Save function tree for inlining. Should return 0 if the
language does not support function deferring or the
function could not be deferred. */

View File

@ -58,7 +58,6 @@ union lang_tree_node
struct lang_decl GTY(())
{
struct c_lang_decl base;
/* The return types and parameter types may have variable size.
This is a list of any SAVE_EXPRs that need to be evaluated to
compute those sizes. */
@ -100,12 +99,6 @@ struct lang_decl GTY(())
and C_RID_YYCODE is the token number wanted by Yacc. */
#define C_IS_RESERVED_WORD(ID) TREE_LANG_FLAG_0 (ID)
/* This function was declared inline. This flag controls the linkage
semantics of 'inline'; whether or not the function is inlined is
controlled by DECL_INLINE. */
#define DECL_DECLARED_INLINE_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->base.declared_inline)
/* In a RECORD_TYPE, a sorted array of the fields of the type. */
struct lang_type GTY(())
{

View File

@ -353,7 +353,7 @@ dump_cgraph (FILE *f)
if (DECL_SAVED_TREE (node->decl))
fprintf (f, " tree");
if (node->local.disgread_inline_limits)
if (node->local.disregard_inline_limits)
fprintf (f, " always_inline");
else if (node->local.inlinable)
fprintf (f, " inlinable");

View File

@ -33,10 +33,10 @@ struct cgraph_local_info GTY(())
/* Set once it has been finalized so we consider it to be output. */
bool finalized;
/* False when there is something making inlining impossible (such as va_arg) */
/* False when there something makes inlining impossible (such as va_arg). */
bool inlinable;
/* True when function should be inlined independently on it's size. */
bool disgread_inline_limits;
bool disregard_inline_limits;
/* Size of the function before inlining. */
int self_insns;
};

View File

@ -189,12 +189,12 @@ cgraph_finalize_compilation_unit (void)
/* First kill forward declaration so reverse inlining works properly. */
cgraph_create_edges (decl, DECL_SAVED_TREE (decl));
node->local.inlinable = tree_inlinable_function_p (decl, 1);
node->local.inlinable = tree_inlinable_function_p (decl);
DECL_ESTIMATED_INSNS (decl)
= (*lang_hooks.tree_inlining.estimate_num_insns) (decl);
node->local.self_insns = DECL_ESTIMATED_INSNS (decl);
if (node->local.inlinable)
node->local.disgread_inline_limits
node->local.disregard_inline_limits
= (*lang_hooks.tree_inlining.disregard_inline_limits) (decl);
for (edge = node->callees; edge; edge = edge->next_callee)
@ -321,7 +321,7 @@ cgraph_postorder (struct cgraph_node **order)
struct cgraph_edge *edge, last;
struct cgraph_node **stack =
xcalloc (sizeof (struct cgraph_node *), cgraph_n_nodes);
xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
/* We have to deal with cycles nicely, so use a depth first traversal
output algorithm. Ignore the fact that some functions won't need
@ -735,10 +735,10 @@ cgraph_default_inline_p (struct cgraph_node *n)
{
if (!DECL_INLINE (n->decl) || !DECL_SAVED_TREE (n->decl))
return false;
if (DID_INLINE_FUNC (n->decl))
return n->global.insns < MAX_INLINE_INSNS_AUTO;
else
if (DECL_DECLARED_INLINE_P (n->decl))
return n->global.insns < MAX_INLINE_INSNS_SINGLE;
else
return n->global.insns < MAX_INLINE_INSNS_AUTO;
}
/* We use greedy algorithm for inlining of small functions:
@ -756,7 +756,7 @@ cgraph_decide_inlining_of_small_functions (struct cgraph_node **inlined,
struct cgraph_node *node;
fibheap_t heap = fibheap_new ();
struct fibnode **heap_node =
xcalloc (sizeof (struct fibnode *), cgraph_max_uid);
xcalloc (cgraph_max_uid, sizeof (struct fibnode *));
int ninlined, ninlined_callees;
int max_insns = ((HOST_WIDEST_INT) initial_insns
* (100 + PARAM_VALUE (PARAM_INLINE_UNIT_GROWTH)) / 100);
@ -873,11 +873,11 @@ cgraph_decide_inlining (void)
struct cgraph_node *node;
int nnodes;
struct cgraph_node **order =
xcalloc (sizeof (struct cgraph_node *), cgraph_n_nodes);
xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
struct cgraph_node **inlined =
xcalloc (sizeof (struct cgraph_node *), cgraph_n_nodes);
xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
struct cgraph_node **inlined_callees =
xcalloc (sizeof (struct cgraph_node *), cgraph_n_nodes);
xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
int ninlined;
int ninlined_callees;
int i, y;
@ -917,7 +917,7 @@ cgraph_decide_inlining (void)
node = order[i];
for (e = node->callees; e; e = e->next_callee)
if (e->callee->local.disgread_inline_limits)
if (e->callee->local.disregard_inline_limits)
break;
if (!e)
continue;
@ -928,7 +928,7 @@ cgraph_decide_inlining (void)
ninlined = cgraph_inlined_into (order[i], inlined);
for (; e; e = e->next_callee)
{
if (e->inline_call || !e->callee->local.disgread_inline_limits)
if (e->inline_call || !e->callee->local.disregard_inline_limits)
continue;
if (e->callee->output || e->callee == node)
continue;
@ -1038,7 +1038,7 @@ cgraph_expand_functions (void)
{
struct cgraph_node *node;
struct cgraph_node **order =
xcalloc (sizeof (struct cgraph_node *), cgraph_n_nodes);
xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *));
int order_pos = 0;
int i;

View File

@ -1,3 +1,13 @@
2003-08-05 Steven Bosscher <steven@gcc.gnu.org>
* cp-tree.h (struct lang_decl): Don't include c_lang_decl.
(DECL_DECLARED_INLINE_P): Remove.
* decl2.c (import_export_decl): Only look at DECL_DECLARED_INLINE_P
if decl is a FUNCTION_DECL. This never made sense, but now it is
required to avoid a tree check failure.
* decl.c (grokfndecl): Don't touch DID_INLINE_FUNC.
* optimize.c (maybe_clone_body): Likewise.
2003-08-04 Roger Sayle <roger@eyesopen.com>
* decl.c (cxx_insert_default_attributes): Delete.

View File

@ -1637,8 +1637,6 @@ struct lang_type GTY(())
struct lang_decl_flags GTY(())
{
struct c_lang_decl base;
ENUM_BITFIELD(languages) language : 8;
unsigned operator_attr : 1;
@ -2849,12 +2847,6 @@ struct lang_decl GTY(())
/* We know what we're doing with this decl now. */
#define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE)
/* This function was declared inline. This flag controls the linkage
semantics of 'inline'; whether or not the function is inlined is
controlled by DECL_INLINE. */
#define DECL_DECLARED_INLINE_P(NODE) \
(DECL_LANG_SPECIFIC (NODE)->decl_flags.base.declared_inline)
/* DECL_EXTERNAL must be set on a decl until the decl is actually emitted,
so that assemble_external will work properly. So we have this flag to
tell us whether the decl is really not external. */

View File

@ -8885,19 +8885,14 @@ grokfndecl (tree ctype,
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))
if (DECL_DECLARED_INLINE_P (decl)
|| (flag_inline_trees == 2 && !DECL_INLINE (decl) && funcdef_flag))
DECL_INLINE (decl) = 1;
if (flag_inline_trees == 2 && !DECL_INLINE (decl) && funcdef_flag)
{
DID_INLINE_FUNC (decl) = 1;
DECL_INLINE (decl) = 1;
}
DECL_EXTERNAL (decl) = 1;
if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
@ -14248,8 +14243,6 @@ start_method (tree declspecs, tree declarator, tree attrlist)
check_template_shadow (fndecl);
DECL_DECLARED_INLINE_P (fndecl) = 1;
DID_INLINE_FUNC (fndecl) = 0;
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;

View File

@ -1743,7 +1743,8 @@ import_export_decl (tree decl)
if ((DECL_IMPLICIT_INSTANTIATION (decl)
|| DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl))
&& (flag_implicit_templates
|| (flag_implicit_inline_templates
|| (flag_implicit_inline_templates
&& TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl))))
{
if (!TREE_PUBLIC (decl))

View File

@ -159,7 +159,6 @@ maybe_clone_body (tree fn)
/* Update CLONE's source position information to match FN's. */
DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (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);

View File

@ -1,3 +1,7 @@
2003-08-05 Steven Bosscher <steven@gcc.gnu.org>
* java-tree.h (DECL_ESTIMATED_INSNS): Remove (moved to tree.h).
2003-08-03 Tom Tromey <tromey@redhat.com>
* java-tree.h (METHOD_TRANSIENT): Removed.

View File

@ -906,12 +906,6 @@ union lang_tree_node
/* The original WFL of a final variable. */
#define DECL_FIELD_FINAL_WFL(NODE) \
(DECL_LANG_SPECIFIC(NODE)->u.v.wfl)
/* In a FUNCTION_DECL for which DECL_BUILT_IN does not hold, this is
the approximate number of instructions in this function. There is
no need for this number to be exact; it is only used in various
heuristics regarding optimization. */
#define DECL_ESTIMATED_INSNS(NODE) \
(FUNCTION_DECL_CHECK (NODE)->decl.u1.i)
/* True if NODE is a local variable final. */
#define LOCAL_FINAL_P(NODE) (DECL_LANG_SPECIFIC (NODE) && DECL_FINAL (NODE))
/* True if NODE is a final field. */

View File

@ -317,10 +317,8 @@ print_node (FILE *file, const char *prefix, tree node, int indent)
if (TREE_CODE (node) == TYPE_DECL && TYPE_DECL_SUPPRESS_DEBUG (node))
fputs (" suppress-debug", file);
if (TREE_CODE (node) == FUNCTION_DECL && DID_INLINE_FUNC (node))
fputs (" autoinline", file);
else if (TREE_CODE (node) == FUNCTION_DECL && DECL_INLINE (node))
fputs (" inline", file);
if (TREE_CODE (node) == FUNCTION_DECL && DECL_INLINE (node))
fputs (DECL_DECLARED_INLINE_P (node) ? " inline" : " autoinline", file);
if (TREE_CODE (node) == FUNCTION_DECL && DECL_BUILT_IN (node))
fputs (" built-in", file);
if (TREE_CODE (node) == FUNCTION_DECL && DECL_NO_STATIC_CHAIN (node))

View File

@ -2532,16 +2532,8 @@ rest_of_handle_inlining (tree decl)
return true;
}
}
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;
else
inlinable = DECL_INLINE (decl) = 1;
}
}
insns = get_insns ();

View File

@ -116,7 +116,8 @@ static tree copy_body_r (tree *, int *, void *);
static tree copy_body (inline_data *);
static tree expand_call_inline (tree *, int *, void *);
static void expand_calls_inline (tree *, inline_data *);
static int inlinable_function_p (tree, inline_data *, int);
static bool inlinable_function_p (tree);
static int limits_allow_inlining (tree, inline_data *);
static tree remap_decl (tree, inline_data *);
#ifndef INLINER_FOR_JAVA
static tree initialize_inlined_parameters (inline_data *, tree, tree);
@ -873,10 +874,10 @@ declare_return_variable (struct inline_data *id, tree return_slot_addr,
/* Returns nonzero if a function can be inlined as a tree. */
int
tree_inlinable_function_p (tree fn, int nolimit)
bool
tree_inlinable_function_p (tree fn)
{
return inlinable_function_p (fn, NULL, nolimit);
return inlinable_function_p (fn);
}
/* If *TP is possibly call to alloca, return nonzero. */
@ -927,67 +928,58 @@ find_builtin_longjmp_call (tree exp)
return ret;
}
/* Returns nonzero if FN is a function that can be inlined into the
inlining context ID_. If ID_ is NULL, check whether the function
can be inlined at all. */
/* Returns nonzero if FN is a function that does not have any
fundamental inline blocking properties. */
static int
inlinable_function_p (tree fn, inline_data *id, int nolimit)
static bool
inlinable_function_p (tree fn)
{
int inlinable;
int currfn_insns = 0;
int max_inline_insns_single = MAX_INLINE_INSNS_SINGLE;
bool inlinable = true;
bool calls_builtin_longjmp = false;
bool calls_alloca = false;
/* If we've already decided this function shouldn't be inlined,
there's no need to check again. */
if (DECL_UNINLINABLE (fn))
return 0;
return false;
/* See if there is any language-specific reason it cannot be
inlined. (It is important that this hook be called early because
in C++ it may result in template instantiation.) */
in C++ it may result in template instantiation.)
If the function is not inlinable for language-specific reasons,
it is left up to the langhook to explain why. */
inlinable = !(*lang_hooks.tree_inlining.cannot_inline_tree_fn) (&fn);
/* If we don't have the function body available, we can't inline
it. */
if (! DECL_SAVED_TREE (fn))
return 0;
/* If we don't have the function body available, we can't inline it.
However, this should not be recorded since we also get here for
forward declared inline functions. Therefore, return at once. */
if (!DECL_SAVED_TREE (fn))
return false;
/* We may be here either because fn is declared inline or because
we use -finline-functions. For the second case, we are more
restrictive. */
if (DID_INLINE_FUNC (fn))
max_inline_insns_single = MAX_INLINE_INSNS_AUTO;
/* If we're not inlining at all, then we cannot inline this function. */
else if (!flag_inline_trees)
inlinable = false;
/* The number of instructions (estimated) of current function. */
if (!nolimit && !DECL_ESTIMATED_INSNS (fn))
DECL_ESTIMATED_INSNS (fn)
= (*lang_hooks.tree_inlining.estimate_num_insns) (fn);
currfn_insns = DECL_ESTIMATED_INSNS (fn);
/* Only try to inline functions if DECL_INLINE is set. This should be
true for all functions declared `inline', and for all other functions
as well with -finline-functions.
Don't think of disregarding DECL_INLINE when flag_inline_trees == 2;
it's the front-end that must set DECL_INLINE in this case, because
dwarf2out loses if a function that does not have DECL_INLINE set is
inlined anyway. That is why we have both DECL_INLINE and
DECL_DECLARED_INLINE_P. */
/* FIXME: When flag_inline_trees dies, the check for flag_unit_at_a_time
here should be redundant. */
else if (!DECL_INLINE (fn) && !flag_unit_at_a_time)
inlinable = false;
/* If we're not inlining things, then nothing is inlinable. */
if (! flag_inline_trees)
inlinable = 0;
/* If we're not inlining all functions and the function was not
declared `inline', we don't inline it. Don't think of
disregarding DECL_INLINE when flag_inline_trees == 2; it's the
front-end that must set DECL_INLINE in this case, because
dwarf2out loses if a function is inlined that doesn't have
DECL_INLINE set. */
else if (! DECL_INLINE (fn) && !nolimit)
inlinable = 0;
#ifdef INLINER_FOR_JAVA
/* Synchronized methods can't be inlined. This is a bug. */
else if (METHOD_SYNCHRONIZED (fn))
inlinable = 0;
inlinable = false;
#endif /* INLINER_FOR_JAVA */
/* 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. */
else if (!nolimit
&& ! (*lang_hooks.tree_inlining.disregard_inline_limits) (fn)
&& currfn_insns > max_inline_insns_single)
inlinable = 0;
/* We can't inline functions that call __builtin_longjmp at all.
The non-local goto machinery really requires the destination
be in a different function. If we allow the function calling
@ -995,70 +987,138 @@ inlinable_function_p (tree fn, inline_data *id, int nolimit)
__builtin_setjmp, Things will Go Awry. */
/* ??? Need front end help to identify "regular" non-local goto. */
else if (find_builtin_longjmp_call (DECL_SAVED_TREE (fn)))
inlinable = 0;
/* Refuse to inline alloca call unless user explicitly forced so as this may
change program's memory overhead drastically when the function using alloca
is called in loop. In GCC present in SPEC2000 inlining into schedule_block
cause it to require 2GB of ram instead of 256MB. */
calls_builtin_longjmp = true;
/* Refuse to inline alloca call unless user explicitly forced so as this
may change program's memory overhead drastically when the function
using alloca is called in loop. In GCC present in SPEC2000 inlining
into schedule_block cause it to require 2GB of ram instead of 256MB. */
else if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL
&& find_alloca_call (DECL_SAVED_TREE (fn)))
inlinable = 0;
calls_alloca = true;
if (calls_builtin_longjmp || calls_alloca)
{
/* See if we should warn about uninlinable functions. Previously,
some of these warnings would be issued while trying to expand
the function inline, but that would cause multiple warnings
about functions that would for example call alloca. But since
this a property of the function, just one warning is enough.
As a bonus we can now give more details about the reason why a
function is not inlinable.
We only warn for functions declared `inline' by the user. */
bool do_warning = (warn_inline
&& DECL_INLINE (fn)
&& DECL_DECLARED_INLINE_P (fn)
&& !DECL_IN_SYSTEM_HEADER (fn));
if (do_warning && calls_builtin_longjmp)
warning ("%Hfunction '%F' can never be inlined because it uses "
"setjmp-longjmp exception handling",
&DECL_SOURCE_LOCATION (fn), fn);
if (do_warning && calls_alloca)
warning ("%Hfunction '%F' can never be inlined because it uses "
"setjmp-longjmp exception handling",
&DECL_SOURCE_LOCATION (fn), fn);
inlinable = false;
}
/* Squirrel away the result so that we don't have to check again. */
DECL_UNINLINABLE (fn) = ! inlinable;
DECL_UNINLINABLE (fn) = !inlinable;
/* 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)
&& inlinable && !nolimit
&& currfn_insns > MIN_INLINE_INSNS)
{
int sum_insns = (id ? id->inlined_insns : 0) + 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)
{
int max_curr = MAX_INLINE_INSNS_SINGLE
- (sum_insns - MAX_INLINE_INSNS) / MAX_INLINE_SLOPE;
if (currfn_insns > max_curr)
inlinable = 0;
}
}
return inlinable;
}
/* Check again, language hooks may have modified it. */
if (! inlinable || DECL_UNINLINABLE (fn))
/* 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;
/* Don't do recursive inlining, either. We don't record this in
DECL_UNINLINABLE; we may be able to inline this function later. */
if (id)
/* 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))
{
size_t i;
int currfn_max_inline_insns;
for (i = 0; i < VARRAY_ACTIVE_SIZE (id->fns); ++i)
if (VARRAY_TREE (id->fns, i) == fn)
return 0;
/* 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);
if (DECL_INLINED_FNS (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 j;
tree inlined_fns = DECL_INLINED_FNS (fn);
int sum_insns = (id ? id->inlined_insns : 0) + estimated_insns;
for (j = 0; j < TREE_VEC_LENGTH (inlined_fns); ++j)
if (TREE_VEC_ELT (inlined_fns, j) == VARRAY_TREE (id->fns, 0))
return 0;
/* 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;
}
}
}
/* Return the result. */
return inlinable;
/* 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. */
@ -1166,9 +1226,9 @@ expand_call_inline (tree *tp, int *walk_subtrees, void *data)
inlining. */
if ((flag_unit_at_a_time
&& (!DECL_SAVED_TREE (fn) || !cgraph_inline_p (id->current_decl, fn)))
|| (!flag_unit_at_a_time && !inlinable_function_p (fn, id, 0)))
|| (!flag_unit_at_a_time && !limits_allow_inlining (fn, id)))
{
if (warn_inline && DECL_INLINE (fn) && !DID_INLINE_FUNC (fn)
if (warn_inline && DECL_INLINE (fn) && DECL_DECLARED_INLINE_P (fn)
&& !DECL_IN_SYSTEM_HEADER (fn))
{
warning ("%Hinlining failed in call to '%F'",

View File

@ -25,7 +25,7 @@ Boston, MA 02111-1307, USA. */
/* Function prototypes. */
void optimize_inline_calls (tree);
int tree_inlinable_function_p (tree, int);
bool tree_inlinable_function_p (tree);
tree walk_tree (tree*, walk_tree_fn, void*, void*);
tree walk_tree_without_duplicates (tree*, walk_tree_fn, void*);
tree copy_tree_r (tree*, int*, void*);

View File

@ -1473,10 +1473,12 @@ struct tree_type GTY(())
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)
/* Nonzero in a FUNCTION_DECL means that this function was declared inline,
such as via the `inline' keyword in C/C++. This flag controls the linkage
semantics of 'inline'; whether or not the function is inlined is
controlled by DECL_INLINE. */
#define DECL_DECLARED_INLINE_P(NODE) \
(FUNCTION_DECL_CHECK (NODE)->decl.declared_inline_flag)
/* In a FUNCTION_DECL, nonzero if the function cannot be inlined. */
#define DECL_UNINLINABLE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.uninlinable)
@ -1606,6 +1608,13 @@ struct tree_type GTY(())
#define DECL_POINTER_ALIAS_SET_KNOWN_P(NODE) \
(DECL_POINTER_ALIAS_SET (NODE) != - 1)
/* In a FUNCTION_DECL for which DECL_BUILT_IN does not hold, this is
the approximate number of statements in this function. There is
no need for this number to be exact; it is only used in various
heuristics regarding optimization. */
#define DECL_ESTIMATED_INSNS(NODE) \
(FUNCTION_DECL_CHECK (NODE)->decl.u1.i)
struct function;
struct tree_decl GTY(())
@ -1646,7 +1655,7 @@ struct tree_decl GTY(())
unsigned user_align : 1;
unsigned uninlinable : 1;
unsigned thread_local_flag : 1;
unsigned inlined_function_flag : 1;
unsigned declared_inline_flag : 1;
unsigned unused : 3;
/* three unused bits. */