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> 2003-08-05 Josef Zlomek <zlomekj@suse.cz>
* gcse.c (try_replace_reg): Fix updating of note. * 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 int field_decl_cmp (const void *, const void *);
extern void resort_sorted_fields (void *, void *, gt_pointer_operator, extern void resort_sorted_fields (void *, void *, gt_pointer_operator,
void *); 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. */ /* Switches common to the C front ends. */

View File

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

View File

@ -58,7 +58,6 @@ union lang_tree_node
struct lang_decl GTY(()) struct lang_decl GTY(())
{ {
struct c_lang_decl base;
/* The return types and parameter types may have variable size. /* The return types and parameter types may have variable size.
This is a list of any SAVE_EXPRs that need to be evaluated to This is a list of any SAVE_EXPRs that need to be evaluated to
compute those sizes. */ compute those sizes. */
@ -100,12 +99,6 @@ struct lang_decl GTY(())
and C_RID_YYCODE is the token number wanted by Yacc. */ and C_RID_YYCODE is the token number wanted by Yacc. */
#define C_IS_RESERVED_WORD(ID) TREE_LANG_FLAG_0 (ID) #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. */ /* In a RECORD_TYPE, a sorted array of the fields of the type. */
struct lang_type GTY(()) struct lang_type GTY(())
{ {

View File

@ -353,7 +353,7 @@ dump_cgraph (FILE *f)
if (DECL_SAVED_TREE (node->decl)) if (DECL_SAVED_TREE (node->decl))
fprintf (f, " tree"); fprintf (f, " tree");
if (node->local.disgread_inline_limits) if (node->local.disregard_inline_limits)
fprintf (f, " always_inline"); fprintf (f, " always_inline");
else if (node->local.inlinable) else if (node->local.inlinable)
fprintf (f, " 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. */ /* Set once it has been finalized so we consider it to be output. */
bool finalized; 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; bool inlinable;
/* True when function should be inlined independently on it's size. */ /* 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. */ /* Size of the function before inlining. */
int self_insns; int self_insns;
}; };

View File

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

View File

@ -1637,8 +1637,6 @@ struct lang_type GTY(())
struct lang_decl_flags GTY(()) struct lang_decl_flags GTY(())
{ {
struct c_lang_decl base;
ENUM_BITFIELD(languages) language : 8; ENUM_BITFIELD(languages) language : 8;
unsigned operator_attr : 1; unsigned operator_attr : 1;
@ -2849,12 +2847,6 @@ struct lang_decl GTY(())
/* We know what we're doing with this decl now. */ /* We know what we're doing with this decl now. */
#define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE) #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, /* 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 so that assemble_external will work properly. So we have this flag to
tell us whether the decl is really not external. */ tell us whether the decl is really not external. */

View File

@ -8885,19 +8885,14 @@ grokfndecl (tree ctype,
DECL_NOT_REALLY_EXTERN (decl) = 1; DECL_NOT_REALLY_EXTERN (decl) = 1;
} }
DID_INLINE_FUNC (decl) = 0;
/* If the declaration was declared inline, mark it as such. */ /* If the declaration was declared inline, mark it as such. */
if (inlinep) if (inlinep)
DECL_DECLARED_INLINE_P (decl) = 1; DECL_DECLARED_INLINE_P (decl) = 1;
/* We inline functions that are explicitly declared inline, or, when /* We inline functions that are explicitly declared inline, or, when
the user explicitly asks us to, all functions. */ 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; 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; DECL_EXTERNAL (decl) = 1;
if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE) 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); check_template_shadow (fndecl);
DECL_DECLARED_INLINE_P (fndecl) = 1; DECL_DECLARED_INLINE_P (fndecl) = 1;
DID_INLINE_FUNC (fndecl) = 0;
if (flag_default_inline) if (flag_default_inline)
DECL_INLINE (fndecl) = 1; DECL_INLINE (fndecl) = 1;

View File

@ -1744,6 +1744,7 @@ import_export_decl (tree decl)
|| DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl)) || DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl))
&& (flag_implicit_templates && (flag_implicit_templates
|| (flag_implicit_inline_templates || (flag_implicit_inline_templates
&& TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)))) && DECL_DECLARED_INLINE_P (decl))))
{ {
if (!TREE_PUBLIC (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. */ /* Update CLONE's source position information to match FN's. */
DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn); DECL_SOURCE_LOCATION (clone) = DECL_SOURCE_LOCATION (fn);
DECL_INLINE (clone) = DECL_INLINE (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_DECLARED_INLINE_P (clone) = DECL_DECLARED_INLINE_P (fn);
DECL_COMDAT (clone) = DECL_COMDAT (fn); DECL_COMDAT (clone) = DECL_COMDAT (fn);
DECL_WEAK (clone) = DECL_WEAK (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> 2003-08-03 Tom Tromey <tromey@redhat.com>
* java-tree.h (METHOD_TRANSIENT): Removed. * java-tree.h (METHOD_TRANSIENT): Removed.

View File

@ -906,12 +906,6 @@ union lang_tree_node
/* The original WFL of a final variable. */ /* The original WFL of a final variable. */
#define DECL_FIELD_FINAL_WFL(NODE) \ #define DECL_FIELD_FINAL_WFL(NODE) \
(DECL_LANG_SPECIFIC(NODE)->u.v.wfl) (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. */ /* True if NODE is a local variable final. */
#define LOCAL_FINAL_P(NODE) (DECL_LANG_SPECIFIC (NODE) && DECL_FINAL (NODE)) #define LOCAL_FINAL_P(NODE) (DECL_LANG_SPECIFIC (NODE) && DECL_FINAL (NODE))
/* True if NODE is a final field. */ /* 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)) if (TREE_CODE (node) == TYPE_DECL && TYPE_DECL_SUPPRESS_DEBUG (node))
fputs (" suppress-debug", file); fputs (" suppress-debug", file);
if (TREE_CODE (node) == FUNCTION_DECL && DID_INLINE_FUNC (node)) if (TREE_CODE (node) == FUNCTION_DECL && DECL_INLINE (node))
fputs (" autoinline", file); fputs (DECL_DECLARED_INLINE_P (node) ? " inline" : " autoinline", file);
else if (TREE_CODE (node) == FUNCTION_DECL && DECL_INLINE (node))
fputs (" inline", file);
if (TREE_CODE (node) == FUNCTION_DECL && DECL_BUILT_IN (node)) if (TREE_CODE (node) == FUNCTION_DECL && DECL_BUILT_IN (node))
fputs (" built-in", file); fputs (" built-in", file);
if (TREE_CODE (node) == FUNCTION_DECL && DECL_NO_STATIC_CHAIN (node)) if (TREE_CODE (node) == FUNCTION_DECL && DECL_NO_STATIC_CHAIN (node))

View File

@ -2532,17 +2532,9 @@ rest_of_handle_inlining (tree decl)
return true; return true;
} }
} }
else { 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;
inlinable = DECL_INLINE (decl) = 1; inlinable = DECL_INLINE (decl) = 1;
} }
}
insns = get_insns (); 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 copy_body (inline_data *);
static tree expand_call_inline (tree *, int *, void *); static tree expand_call_inline (tree *, int *, void *);
static void expand_calls_inline (tree *, inline_data *); 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 *); static tree remap_decl (tree, inline_data *);
#ifndef INLINER_FOR_JAVA #ifndef INLINER_FOR_JAVA
static tree initialize_inlined_parameters (inline_data *, tree, tree); 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. */ /* Returns nonzero if a function can be inlined as a tree. */
int bool
tree_inlinable_function_p (tree fn, int nolimit) 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. */ /* If *TP is possibly call to alloca, return nonzero. */
@ -927,67 +928,58 @@ find_builtin_longjmp_call (tree exp)
return ret; return ret;
} }
/* Returns nonzero if FN is a function that can be inlined into the /* Returns nonzero if FN is a function that does not have any
inlining context ID_. If ID_ is NULL, check whether the function fundamental inline blocking properties. */
can be inlined at all. */
static int static bool
inlinable_function_p (tree fn, inline_data *id, int nolimit) inlinable_function_p (tree fn)
{ {
int inlinable; bool inlinable = true;
int currfn_insns = 0; bool calls_builtin_longjmp = false;
int max_inline_insns_single = MAX_INLINE_INSNS_SINGLE; bool calls_alloca = false;
/* If we've already decided this function shouldn't be inlined, /* If we've already decided this function shouldn't be inlined,
there's no need to check again. */ there's no need to check again. */
if (DECL_UNINLINABLE (fn)) if (DECL_UNINLINABLE (fn))
return 0; return false;
/* See if there is any language-specific reason it cannot be /* See if there is any language-specific reason it cannot be
inlined. (It is important that this hook be called early because 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); inlinable = !(*lang_hooks.tree_inlining.cannot_inline_tree_fn) (&fn);
/* If we don't have the function body available, we can't inline /* If we don't have the function body available, we can't inline it.
it. */ However, this should not be recorded since we also get here for
if (! DECL_SAVED_TREE (fn)) forward declared inline functions. Therefore, return at once. */
return 0; if (!DECL_SAVED_TREE (fn))
return false;
/* We may be here either because fn is declared inline or because /* If we're not inlining at all, then we cannot inline this function. */
we use -finline-functions. For the second case, we are more else if (!flag_inline_trees)
restrictive. */ inlinable = false;
if (DID_INLINE_FUNC (fn))
max_inline_insns_single = MAX_INLINE_INSNS_AUTO;
/* The number of instructions (estimated) of current function. */ /* Only try to inline functions if DECL_INLINE is set. This should be
if (!nolimit && !DECL_ESTIMATED_INSNS (fn)) true for all functions declared `inline', and for all other functions
DECL_ESTIMATED_INSNS (fn) as well with -finline-functions.
= (*lang_hooks.tree_inlining.estimate_num_insns) (fn);
currfn_insns = DECL_ESTIMATED_INSNS (fn); 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 #ifdef INLINER_FOR_JAVA
/* Synchronized methods can't be inlined. This is a bug. */ /* Synchronized methods can't be inlined. This is a bug. */
else if (METHOD_SYNCHRONIZED (fn)) else if (METHOD_SYNCHRONIZED (fn))
inlinable = 0; inlinable = false;
#endif /* INLINER_FOR_JAVA */ #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. /* We can't inline functions that call __builtin_longjmp at all.
The non-local goto machinery really requires the destination The non-local goto machinery really requires the destination
be in a different function. If we allow the function calling be in a different function. If we allow the function calling
@ -995,53 +987,122 @@ inlinable_function_p (tree fn, inline_data *id, int nolimit)
__builtin_setjmp, Things will Go Awry. */ __builtin_setjmp, Things will Go Awry. */
/* ??? Need front end help to identify "regular" non-local goto. */ /* ??? Need front end help to identify "regular" non-local goto. */
else if (find_builtin_longjmp_call (DECL_SAVED_TREE (fn))) else if (find_builtin_longjmp_call (DECL_SAVED_TREE (fn)))
inlinable = 0; 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 /* Refuse to inline alloca call unless user explicitly forced so as this
is called in loop. In GCC present in SPEC2000 inlining into schedule_block may change program's memory overhead drastically when the function
cause it to require 2GB of ram instead of 256MB. */ 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 else if (lookup_attribute ("always_inline", DECL_ATTRIBUTES (fn)) == NULL
&& find_alloca_call (DECL_SAVED_TREE (fn))) && 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. */ /* 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 return inlinable;
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;
}
}
/* Check again, language hooks may have modified it. */ /* We can't inline functions that are too big. Only allow a single
if (! inlinable || DECL_UNINLINABLE (fn)) function to be of MAX_INLINE_INSNS_SINGLE size. Make special
return 0; allowance for extern inline functions, though.
/* Don't do recursive inlining, either. We don't record this in Return nonzero if the function FN can be inlined into the inlining
DECL_UNINLINABLE; we may be able to inline this function later. */ context ID. */
if (id)
{ static int
limits_allow_inlining (tree fn, inline_data *id)
{
int estimated_insns = 0;
size_t i; 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) for (i = 0; i < VARRAY_ACTIVE_SIZE (id->fns); ++i)
if (VARRAY_TREE (id->fns, i) == fn) if (VARRAY_TREE (id->fns, i) == fn)
return 0; return 0;
@ -1055,10 +1116,9 @@ inlinable_function_p (tree fn, inline_data *id, int nolimit)
if (TREE_VEC_ELT (inlined_fns, j) == VARRAY_TREE (id->fns, 0)) if (TREE_VEC_ELT (inlined_fns, j) == VARRAY_TREE (id->fns, 0))
return 0; return 0;
} }
}
/* Return the result. */ /* Go ahead, this function can be inlined. */
return inlinable; return 1;
} }
/* If *TP is a CALL_EXPR, replace it with its inline expansion. */ /* 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. */ inlining. */
if ((flag_unit_at_a_time if ((flag_unit_at_a_time
&& (!DECL_SAVED_TREE (fn) || !cgraph_inline_p (id->current_decl, fn))) && (!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)) && !DECL_IN_SYSTEM_HEADER (fn))
{ {
warning ("%Hinlining failed in call to '%F'", warning ("%Hinlining failed in call to '%F'",

View File

@ -25,7 +25,7 @@ Boston, MA 02111-1307, USA. */
/* Function prototypes. */ /* Function prototypes. */
void optimize_inline_calls (tree); 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 (tree*, walk_tree_fn, void*, void*);
tree walk_tree_without_duplicates (tree*, walk_tree_fn, void*); tree walk_tree_without_duplicates (tree*, walk_tree_fn, void*);
tree copy_tree_r (tree*, int*, void*); tree copy_tree_r (tree*, int*, void*);

View File

@ -1473,10 +1473,12 @@ struct tree_type GTY(())
where it is called. */ where it is called. */
#define DECL_INLINE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.inline_flag) #define DECL_INLINE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.inline_flag)
/* Nonzero in a FUNCTION_DECL means this function has been found inlinable /* Nonzero in a FUNCTION_DECL means that this function was declared inline,
only by virtue of -finline-functions */ such as via the `inline' keyword in C/C++. This flag controls the linkage
#define DID_INLINE_FUNC(NODE) \ semantics of 'inline'; whether or not the function is inlined is
(FUNCTION_DECL_CHECK (NODE)->decl.inlined_function_flag) 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. */ /* In a FUNCTION_DECL, nonzero if the function cannot be inlined. */
#define DECL_UNINLINABLE(NODE) (FUNCTION_DECL_CHECK (NODE)->decl.uninlinable) #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) \ #define DECL_POINTER_ALIAS_SET_KNOWN_P(NODE) \
(DECL_POINTER_ALIAS_SET (NODE) != - 1) (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 function;
struct tree_decl GTY(()) struct tree_decl GTY(())
@ -1646,7 +1655,7 @@ struct tree_decl GTY(())
unsigned user_align : 1; unsigned user_align : 1;
unsigned uninlinable : 1; unsigned uninlinable : 1;
unsigned thread_local_flag : 1; unsigned thread_local_flag : 1;
unsigned inlined_function_flag : 1; unsigned declared_inline_flag : 1;
unsigned unused : 3; unsigned unused : 3;
/* three unused bits. */ /* three unused bits. */