diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 12 | ||||
-rw-r--r-- | gcc/cgraph.c | 20 | ||||
-rw-r--r-- | gcc/cgraph.h | 3 | ||||
-rw-r--r-- | gcc/cgraphunit.c | 111 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 2 | ||||
-rw-r--r-- | gcc/objc/objc-act.c | 5 | ||||
-rw-r--r-- | gcc/varasm.c | 2 |
8 files changed, 110 insertions, 50 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 8ecc67dff6c..92437ba59e8 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,15 @@ +2003-09-04 Richard Henderson <rth@redhat.com> + + * cgraph.c (cgraph_mark_reachable_node): Split out from ... + (cgraph_mark_needed_node): Remove needed argument. + * cgraph.h: Update to match. + * cgraphunit.c (decide_is_function_needed): Split out from ... + (cgraph_finalize_function): Reorg. Avoid deferred_inline_function + if we generated the function. + (record_call_1): Update for cgraph_mark_reachable_node. + * varasm.c (mark_referenced): Likewise. + * objc/objc-act.c (mark_referenced_methods): Likewise. + 2003-09-04 DJ Delorie <dj@redhat.com> * targhooks.c: Add comment explaining the migration process. diff --git a/gcc/cgraph.c b/gcc/cgraph.c index bd83f6a1946..8b4c0ccf13d 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -234,14 +234,11 @@ cgraph_remove_node (struct cgraph_node *node) /* Do not free the structure itself so the walk over chain can continue. */ } -/* Notify finalize_compilation_unit that given node is reachable - or needed. */ +/* Notify finalize_compilation_unit that given node is reachable. */ + void -cgraph_mark_needed_node (struct cgraph_node *node, int needed) +cgraph_mark_reachable_node (struct cgraph_node *node) { - if (needed) - node->needed = 1; - if (!node->reachable && DECL_SAVED_TREE (node->decl)) { node->reachable = 1; @@ -257,11 +254,20 @@ cgraph_mark_needed_node (struct cgraph_node *node, int needed) for (node2 = node->nested; node2; node2 = node2->next_nested) if (!node2->reachable) - cgraph_mark_needed_node (node2, 0); + cgraph_mark_reachable_node (node2); } } } +/* Likewise indicate that a node is needed, i.e. reachable via some + external means. */ + +void +cgraph_mark_needed_node (struct cgraph_node *node) +{ + node->needed = 1; + cgraph_mark_reachable_node (node); +} /* Record call from CALLER to CALLEE */ diff --git a/gcc/cgraph.h b/gcc/cgraph.h index f96ac0d0d59..aaa09a201e8 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -173,7 +173,8 @@ void cgraph_finalize_function (tree, tree); void cgraph_finalize_compilation_unit (void); void cgraph_create_edges (tree, tree); void cgraph_optimize (void); -void cgraph_mark_needed_node (struct cgraph_node *, int); +void cgraph_mark_needed_node (struct cgraph_node *); +void cgraph_mark_reachable_node (struct cgraph_node *); bool cgraph_inline_p (tree, tree); #endif /* GCC_CGRAPH_H */ diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 7188501c719..1476c8b3b23 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -62,6 +62,64 @@ static int overall_insns; record_calls_1. */ static htab_t visited_nodes; +/* Determine if function DECL is needed. That is, visible to something + either outside this translation unit, something magic in the system + configury, or (if not doing unit-at-a-time) to something we havn't + seen yet. */ + +static bool +decide_is_function_needed (struct cgraph_node *node, tree decl) +{ + /* If we decided it was needed before, but at the time we didn't have + the body of the function available, then it's still needed. We have + to go back and re-check its dependencies now. */ + if (node->needed) + return true; + + /* Externally visible functions must be output. The exception is + COMDAT functions that must be output only when they are needed. */ + if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) + return true; + + /* Constructors and destructors are reachable from the runtime by + some mechanism. */ + if (DECL_STATIC_CONSTRUCTOR (decl) || DECL_STATIC_DESTRUCTOR (decl)) + return true; + + /* If the user told us it is used, then it must be so. */ + if (lookup_attribute ("used", DECL_ATTRIBUTES (decl))) + return true; + + /* ??? If the assembler name is set by hand, it is possible to assemble + the name later after finalizing the function and the fact is noticed + in assemble_name then. This is arguably a bug. */ + if (DECL_ASSEMBLER_NAME_SET_P (decl) + && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl))) + return true; + + if (flag_unit_at_a_time) + return false; + + /* If not doing unit at a time, then we'll only defer this function + if its marked for inlining. Otherwise we want to emit it now. */ + + /* "extern inline" functions are never output locally. */ + if (DECL_EXTERNAL (decl)) + return false; + /* ??? */ + if (node->origin) + return false; + if (!DECL_INLINE (decl) + || (!node->local.disregard_inline_limits + /* When declared inline, defer 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)))) + return true; + + return false; +} + /* Analyze function once it is parsed. Set up the local information available - create cgraph edges for function calls via BODY. */ @@ -73,42 +131,16 @@ cgraph_finalize_function (tree decl, tree body ATTRIBUTE_UNUSED) node->decl = decl; node->local.finalized = true; - /* Function now has DECL_SAVED_TREE set. Enqueue it into cgraph_nodes_queue - if needed. */ - if (node->needed) - cgraph_mark_needed_node (node, 0); + /* 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); - 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 - external functions (GCC extension "extern inline") */ - (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl)) - /* ??? Constructors and destructors not called otherwise can be inlined - into single construction/destruction function per section to save some - resources. For now just mark it as reachable. */ - || DECL_STATIC_CONSTRUCTOR (decl) - || DECL_STATIC_DESTRUCTOR (decl) - /* Function whose name is output to the assembler file must be produced. - It is possible to assemble the name later after finalizing the function - and the fact is noticed in assemble_name then. */ - || (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); - /* 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 (decide_is_function_needed (node, decl)) + cgraph_mark_needed_node (node); + + /* If not unit at a time, go ahead and emit everything we've + found to be reachable at this time. */ if (!flag_unit_at_a_time) while (cgraph_nodes_queue) { @@ -118,7 +150,9 @@ cgraph_finalize_function (tree decl, tree body ATTRIBUTE_UNUSED) cgraph_expand_function (n); } - (*debug_hooks->deferred_inline_function) (decl); + /* If we've not yet emitted decl, tell the debug info about it. */ + if (flag_unit_at_a_time || !node->reachable) + (*debug_hooks->deferred_inline_function) (decl); } /* Walk tree and record all calls. Called via walk_tree. */ @@ -133,7 +167,7 @@ record_call_1 (tree *tp, int *walk_subtrees, void *data) { tree decl = TREE_OPERAND (*tp, 0); if (TREE_CODE (decl) == FUNCTION_DECL) - cgraph_mark_needed_node (cgraph_node (decl), 1); + cgraph_mark_needed_node (cgraph_node (decl)); } else if (TREE_CODE (*tp) == CALL_EXPR) { @@ -251,13 +285,14 @@ cgraph_finalize_compilation_unit (void) abort (); cgraph_analyze_function (node); + for (edge = node->callees; edge; edge = edge->next_callee) - { if (!edge->callee->reachable) - cgraph_mark_needed_node (edge->callee, 0); - } + cgraph_mark_reachable_node (edge->callee); + cgraph_varpool_assemble_pending_decls (); } + /* Collect entry points to the unit. */ if (cgraph_dump_file) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index ca8ea06d7fc..6f8668c608a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,8 @@ +2003-09-04 Richard Henderson <rth@redhat.com> + + * decl2.c (mark_member_pointers_and_eh_handlers): Update for + change in cgraph_mark_needed_node arguments. + 2003-09-02 Geoffrey Keating <geoffk@apple.com> PR 12161 diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index 7ca20c8ef30..20d97d469a0 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -2570,7 +2570,7 @@ mark_member_pointers_and_eh_handlers (tree *tp, { case PTRMEM_CST: if (TYPE_PTRMEMFUNC_P (TREE_TYPE (*tp))) - cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (*tp)), 1); + cgraph_mark_needed_node (cgraph_node (PTRMEM_CST_MEMBER (*tp))); break; /* EH handlers will emit EH tables referencing typeinfo. */ diff --git a/gcc/objc/objc-act.c b/gcc/objc/objc-act.c index 10cc88912fc..0e1c1beb92f 100644 --- a/gcc/objc/objc-act.c +++ b/gcc/objc/objc-act.c @@ -3981,13 +3981,14 @@ mark_referenced_methods () chain = CLASS_CLS_METHODS (impent->imp_context); while (chain) { - cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)), 1); + cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain))); chain = TREE_CHAIN (chain); } + chain = CLASS_NST_METHODS (impent->imp_context); while (chain) { - cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain)), 1); + cgraph_mark_needed_node (cgraph_node (METHOD_DEFINITION (chain))); chain = TREE_CHAIN (chain); } } diff --git a/gcc/varasm.c b/gcc/varasm.c index ac535212056..d327cb2d8c2 100644 --- a/gcc/varasm.c +++ b/gcc/varasm.c @@ -1662,7 +1662,7 @@ mark_referenced (tree id) { node = cgraph_node_for_identifier (id); if (node) - cgraph_mark_needed_node (node, 1); + cgraph_mark_needed_node (node); } vnode = cgraph_varpool_node_for_identifier (id); |