+Wed Sep 3 16:55:25 CEST 2003 Jan Hubicka <jh@suse.cz>
+
+ * Makefile.in (c-objc-common.o): Kill gt-c-objc-common.h dependency.
+ * c-decl.c (finish_function): Kill arguments, always use cgraph path.
+ * c-objc-common.c: Kill include of gt-c-objc-common.h
+ (expand_deferred_fns, deffer_fn): Kill function.
+ (deferred_fns): Kill variable.
+ (finish_cdtor): Update finish_function call.
+ (c_objc_common_finish_file): Always call cgraph code.
+ * c-parse.c: Regenerate.
+ * c-parse.y: Regenerate.
+ * c-tree.h (finish_function): Update prototype.
+ * objc-acct.c (build_module_descriptor, finish_method_def):
+ Update call of finish_function.
+ * cgraphunit.c (cgraph_default_inline_p, cgraph_analyze_function): Add
+ forward prototype.
+ (cgraph_finalize_function): In non-unit-at-a-time mode analyze the
+ function and assemble it if needed.
+ (cgraph_finalize_compilation_unit): Do nothing in non-unit-at-a-time
+ mode.
+ (cgraph_optimize): Likewise.
+ (cgraph_expand_function): In non-unit-at-a-time mode keep function body
+ even when it has no inline callees.
+ * c-parse.in: Update calls to finish_function.
+
2003-09-03 Nick Clifton <nickc@redhat.com>
* config/arm/arm.h: Handle TARGET_CPU_iwmmxt.
c-objc-common.o : c-objc-common.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(C_TREE_H) $(RTL_H) insn-config.h $(INTEGRATE_H) $(EXPR_H) $(C_TREE_H) \
flags.h toplev.h tree-inline.h $(DIAGNOSTIC_H) $(VARRAY_H) \
- langhooks.h $(GGC_H) gt-c-objc-common.h $(TARGET_H) cgraph.h
+ langhooks.h $(GGC_H) $(TARGET_H) cgraph.h
c-aux-info.o : c-aux-info.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
$(C_TREE_H) flags.h toplev.h
c-convert.o : c-convert.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \
gt-expr.h gt-sdbout.h gt-optabs.h gt-bitmap.h \
gt-dwarf2out.h gt-ra-build.h gt-reg-stack.h gt-dwarf2asm.h \
gt-dbxout.h gt-c-common.h gt-c-decl.h gt-c-parse.h \
-gt-c-pragma.h gt-c-objc-common.h gtype-c.h gt-input.h gt-cfglayout.h \
+gt-c-pragma.h gtype-c.h gt-input.h gt-cfglayout.h \
gt-stringpool.h gt-langhooks.h : s-gtype ; @true
gtyp-gen.h: Makefile
all the way to assembler language output. The free the storage
for the function definition.
- This is called after parsing the body of the function definition.
-
- NESTED is nonzero if the function being finished is nested in another.
- CAN_DEFER_P is nonzero if the function may be deferred. */
+ This is called after parsing the body of the function definition. */
void
-finish_function (int nested, int can_defer_p)
+finish_function ()
{
tree fndecl = current_function_decl;
DECL_SAVED_INSNS, and we'll restore it in tree_rest_of_compilation. */
cfun = NULL;
- if (flag_unit_at_a_time && can_defer_p)
- {
- cgraph_finalize_function (fndecl, DECL_SAVED_TREE (fndecl));
- current_function_decl = NULL;
- return;
- }
-
- if (! nested)
- {
- /* Function is parsed.
- Generate RTL for the body of this function or defer
- it for later expansion. */
- 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. */
- if (flag_syntax_only)
- {
- current_function_decl = NULL;
- DECL_SAVED_TREE (fndecl) = NULL_TREE;
- return;
- }
-
- if (flag_inline_trees)
- {
- /* First, cache whether the current function is inlinable. Some
- predicates depend on cfun and current_function_decl to
- function completely. */
- timevar_push (TV_INTEGRATION);
- 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))
- /* Save function tree for inlining. Should return 0 if the
- language does not support function deferring or the
- function could not be deferred. */
- && defer_fn (fndecl))
- {
- /* Let the back-end know that this function exists. */
- (*debug_hooks->deferred_inline_function) (fndecl);
- timevar_pop (TV_INTEGRATION);
- current_function_decl = NULL;
- return;
- }
-
- /* Then, inline any functions called in it. */
- optimize_inline_calls (fndecl);
- timevar_pop (TV_INTEGRATION);
- }
-
- c_expand_body (fndecl);
-
- /* Keep the function body if it's needed for inlining or dumping. */
- if (uninlinable && !dump_enabled_p (TDI_all))
- {
- /* Allow the body of the function to be garbage collected. */
- DECL_SAVED_TREE (fndecl) = NULL_TREE;
- }
-
- /* Let the error reporting routines know that we're outside a
- function. For a nested function, this value is used in
- c_pop_function_context and then reset via pop_function_context. */
- current_function_decl = NULL;
- }
+ /* ??? Objc emits functions after finalizing the compilation unit.
+ This should be cleaned up later and this conditional removed. */
+ if (!cgraph_global_info_ready)
+ cgraph_finalize_function (fndecl, DECL_SAVED_TREE (fndecl));
+ else
+ c_expand_body (fndecl);
+ current_function_decl = NULL;
}
/* Generate the RTL for a deferred function FNDECL. */
/* Generate the RTL for the body of FNDECL. If NESTED_P is nonzero,
then we are already in the process of generating RTL for another
- function. If can_defer_p is zero, we won't attempt to defer the
- generation of RTL. */
+ function. */
static void
c_expand_body_1 (tree fndecl, int nested_p)
static bool c_tree_printer (pretty_printer *, text_info *);
static tree inline_forbidden_p (tree *, int *, void *);
-static void expand_deferred_fns (void);
static tree start_cdtor (int);
static void finish_cdtor (tree);
-static GTY(()) varray_type deferred_fns;
-
int
c_missing_noreturn_ok_p (tree decl)
{
mesg_implicit_function_declaration = 0;
}
- VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns");
-
return true;
}
-/* Register a function tree, so that its optimization and conversion
- to RTL is only done at the end of the compilation. */
-
-int
-defer_fn (tree fn)
-{
- VARRAY_PUSH_TREE (deferred_fns, fn);
-
- return 1;
-}
-
-/* Expand deferred functions for C and ObjC. */
-
-static void
-expand_deferred_fns (void)
-{
- unsigned int i;
- bool reconsider;
-
- do
- {
- reconsider = false;
- for (i = 0; i < VARRAY_ACTIVE_SIZE (deferred_fns); i++)
- {
- tree decl = VARRAY_TREE (deferred_fns, i);
-
- if (TREE_ASM_WRITTEN (decl))
- continue;
-
- /* "extern inline" says the symbol exists externally,
- which means we should *never* expand it locally
- unless we're actually inlining it. */
- /* ??? Why did we queue these in the first place? */
- if (DECL_DECLARED_INLINE_P (decl) && DECL_EXTERNAL (decl))
- continue;
-
- /* With flag_keep_inline_functions, we're emitting everything,
- so we never need to reconsider. */
- if (flag_keep_inline_functions)
- ;
- /* Must emit all public functions. C doesn't have COMDAT
- functions, so we don't need to check that, like C++. */
- else if (TREE_PUBLIC (decl))
- reconsider = true;
- /* Must emit if the symbol is referenced. */
- else if (TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
- reconsider = true;
- else
- continue;
-
- c_expand_deferred_function (decl);
- }
- }
- while (reconsider);
-
- deferred_fns = 0;
-}
-
static tree
start_cdtor (int method_type)
{
RECHAIN_STMTS (body, COMPOUND_BODY (body));
- finish_function (0, 0);
+ finish_function ();
}
/* Called at end of parsing, but before end-of-file processing. */
them based on linkage rules. */
merge_translation_unit_decls ();
- if (flag_unit_at_a_time)
- {
- cgraph_finalize_compilation_unit ();
- cgraph_optimize ();
- }
- else
- expand_deferred_fns ();
+ cgraph_finalize_compilation_unit ();
+ cgraph_optimize ();
if (static_ctors)
{
return false;
}
}
-
-#include "gt-c-objc-common.h"
{ DECL_SOURCE_LOCATION (current_function_decl) = $6;
store_parm_decls (); }
compstmt_or_error
- { finish_function (0, 1);
+ { finish_function ();
POP_DECLSPEC_STACK; }
| declspecs_ts setspecs declarator error
{ POP_DECLSPEC_STACK; }
{ DECL_SOURCE_LOCATION (current_function_decl) = $6;
store_parm_decls (); }
compstmt_or_error
- { finish_function (0, 1);
+ { finish_function ();
POP_DECLSPEC_STACK; }
| declspecs_nots setspecs notype_declarator error
{ POP_DECLSPEC_STACK; }
{ DECL_SOURCE_LOCATION (current_function_decl) = $5;
store_parm_decls (); }
compstmt_or_error
- { finish_function (0, 1);
+ { finish_function ();
POP_DECLSPEC_STACK; }
| setspecs notype_declarator error
{ POP_DECLSPEC_STACK; }
which called YYERROR1 again, and so on. */
compstmt
{ tree decl = current_function_decl;
- finish_function (1, 1);
+ finish_function ();
pop_function_context ();
add_decl_stmt (decl); }
;
which called YYERROR1 again, and so on. */
compstmt
{ tree decl = current_function_decl;
- finish_function (1, 1);
+ finish_function ();
pop_function_context ();
add_decl_stmt (decl); }
;
extern tree define_label (location_t, tree);
extern void finish_decl (tree, tree, tree);
extern tree finish_enum (tree, tree, tree);
-extern void finish_function (int, int);
+extern void finish_function (void);
extern tree finish_struct (tree, tree, tree);
extern tree get_parm_info (int);
extern tree grokfield (tree, tree, tree);
static tree record_call_1 (tree *, int *, void *);
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);
/* Statistics we collect about inlining algorithm. */
static int ncalls_inlined;
if needed. */
if (node->needed)
cgraph_mark_needed_node (node, 0);
+ if (!flag_unit_at_a_time)
+ cgraph_analyze_function (node);
if (/* Externally visible functions must be output. The exception are
COMDAT functions that must be output only when they are needed.
Similarly are handled deferred functions and
|| (DECL_ASSEMBLER_NAME_SET_P (decl)
&& TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
|| lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
- {
- cgraph_mark_needed_node (node, 1);
- }
+ cgraph_mark_needed_node (node, 1);
+ /* When not doing unit-at-a-time deffer only inline functions. */
+ else if (!flag_unit_at_a_time
+ && !DECL_EXTERNAL (decl)
+ && !node->origin
+ && (!DECL_INLINE (decl)
+ || (!node->local.disregard_inline_limits
+ /* When declared inline, deffer even the uninlinable functions.
+ This allows them to be elliminated when unused. */
+ && !DECL_DECLARED_INLINE_P (decl)
+ && (node->local.inlinable
+ || !cgraph_default_inline_p (node)))))
+ cgraph_mark_needed_node (node, 1);
+
+ if (!flag_unit_at_a_time)
+ while (cgraph_nodes_queue)
+ {
+ struct cgraph_node *n = cgraph_nodes_queue;
+ cgraph_nodes_queue = cgraph_nodes_queue->next_needed;
+ if (!n->origin)
+ cgraph_expand_function (n);
+ }
(*debug_hooks->deferred_inline_function) (decl);
}
{
struct cgraph_node *node;
+ if (!flag_unit_at_a_time)
+ return;
+
cgraph_varpool_assemble_pending_decls ();
if (!quiet_flag)
fprintf (stderr, "\nAnalyzing compilation unit\n");
via lang_expand_decl_stmt. */
(*lang_hooks.callgraph.expand_function) (decl);
- for (e = node->callers; e; e = e->next_caller)
- if (e->inline_call)
- break;
- if (!e)
- DECL_SAVED_TREE (decl) = NULL;
+ if (!flag_unit_at_a_time)
+ {
+ if (!node->local.inlinable
+ || (!node->local.disregard_inline_limits
+ && !cgraph_default_inline_p (node)))
+ DECL_SAVED_TREE (node->decl) = NULL;
+ }
+ else
+ {
+ for (e = node->callers; e; e = e->next_caller)
+ if (e->inline_call)
+ break;
+ if (!e)
+ DECL_SAVED_TREE (decl) = NULL;
+ }
current_function_decl = NULL;
}
void
cgraph_optimize (void)
{
+ if (!flag_unit_at_a_time)
+ return;
timevar_push (TV_CGRAPHOPT);
if (!quiet_flag)
fprintf (stderr, "Performing intraprocedural optimizations\n");
c_expand_expr_stmt (decelerator);
- finish_function (0, 0);
+ finish_function ();
return XEXP (DECL_RTL (init_function_decl), 0);
}
finish_method_def ()
{
lang_expand_function_end = objc_expand_function_end;
- finish_function (0, 1);
+ finish_function ();
lang_expand_function_end = NULL;
/* Required to implement _msgSuper. This must be done AFTER finish_function,