summaryrefslogtreecommitdiff
path: root/gcc/cgraphunit.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2005-03-30 22:28:02 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2005-03-30 22:28:02 +0000
commitc1dcd13cb59b3fb5c8c2448eeccc809a76df8c7f (patch)
treeddb809af63fbede05531dda040e688b7ae54b743 /gcc/cgraphunit.c
parent10eb6bce2f0f650de299e79316ba4e02863e7da8 (diff)
downloadgcc-c1dcd13cb59b3fb5c8c2448eeccc809a76df8c7f.tar.gz
2005-03-31 Jan Hubicka <jh@suse.cz>
2004-11-02 Jan Hubicka <jh@suse.cz> * cgraph.c (cgraph_varpool_node_name): New function. (dump_cgraph_varpool_node): New function. (dump_varpool): New function. * cgraphunit.c (cgraph_optimize): Dump varpool. 2004-10-16 Jan Hubicka <jh@suse.cz> * cgraph.c (decide_is_variable_needed): New function. (cgraph_varpool_finalize_decl): Use it. * cgraphunit.c (cgraph_optimize): Assemble_pending_decls when not doing unit-at-a-time. * final.c (output_addr_const): Do not call mark_referenced. * passes.c (rest_of_decl_compilation): ifdef out DECL_RTL_SET_P hack; always go via cgraph. * toplev.c (wrapup_global_declarations): Kill non-unit-at-a-time code. (check_global_declarations): Ifdef out code clearing DECL_RTL. * tree-optimize.c (execute_inline): Mark functions called. * i386.c (output_pic_addr_const): Do not call mark_decl_referenced. 2004-10-11 Jan Hubicka <jh@suse.cz> * cgraph.c (cgraph_varpool_first_unanalyzed_node): New global voriable (cgraph_varpool_last_needed_node): New static variable. (enqueue_needed_varpool_node): Break out from ...; add items to the end of queue; update first pointers. (cgraph_varpool_mark_needed_node): ... here. (cgraph_varpool_finalize_decl): Use enqueue_needed_varpool_node. (cgraph_varpool_assemble_pending_decls): Move to cgraphunit.c * cgraph.h (cgraph_varpool_node): Add analyzed field. (cgraph_varpool_first_unanalyzed_node): Declare. * cgraphunit.c: Include output.h. (cgraph_varpool_analyze_pending_decls): New function. (cgraph_varpool_assemble_pending_decls): Move from cgraph.c; bail out for errors, analyze pending decls. (cgraph_finalize_compilation_unit): Only analyze decls. (cgraph_optimize): Assemble the decls after expanding. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@97287 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/cgraphunit.c')
-rw-r--r--gcc/cgraphunit.c126
1 files changed, 117 insertions, 9 deletions
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 9fef33e9557..3bb143f9787 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -189,6 +189,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "intl.h"
#include "function.h"
#include "tree-gimple.h"
+#include "output.h"
#define INSNS_PER_CALL 10
@@ -281,6 +282,64 @@ decide_is_function_needed (struct cgraph_node *node, tree decl)
return false;
}
+/* Walk the decls we marked as neccesary and see if they reference new variables
+ or functions and add them into the worklists. */
+static bool
+cgraph_varpool_analyze_pending_decls (void)
+{
+ bool changed = false;
+ timevar_push (TV_CGRAPH);
+
+ while (cgraph_varpool_first_unanalyzed_node)
+ {
+ tree decl = cgraph_varpool_first_unanalyzed_node->decl;
+
+ cgraph_varpool_first_unanalyzed_node->analyzed = true;
+
+ cgraph_varpool_first_unanalyzed_node = cgraph_varpool_first_unanalyzed_node->next_needed;
+
+ if (DECL_INITIAL (decl))
+ cgraph_create_edges (NULL, DECL_INITIAL (decl));
+ changed = true;
+ }
+ timevar_pop (TV_CGRAPH);
+ return changed;
+}
+
+/* Optimization of function bodies might've rendered some variables as
+ unnecesary so we want to avoid these from being compiled.
+
+ This is done by prunning the queue and keeping only the variables that
+ really appear needed (ie thery are either externally visible or referenced
+ by compiled function). Re-doing the reachability analysis on variables
+ brings back the remaining variables referenced by these. */
+static void
+cgraph_varpool_remove_unreferenced_decls (void)
+{
+ struct cgraph_varpool_node *next, *node = cgraph_varpool_nodes_queue;
+
+ cgraph_varpool_reset_queue ();
+
+ if (errorcount || sorrycount)
+ return;
+
+ while (node)
+ {
+ tree decl = node->decl;
+ next = node->next_needed;
+ node->needed = 0;
+
+ if (node->finalized
+ && ((DECL_ASSEMBLER_NAME_SET_P (decl)
+ && TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)))
+ || node->force_output
+ || decide_is_variable_needed (node, decl)))
+ cgraph_varpool_mark_needed_node (node);
+
+ node = next;
+ }
+ cgraph_varpool_analyze_pending_decls ();
+}
/* When not doing unit-at-a-time, output all functions enqueued.
@@ -421,7 +480,7 @@ record_call_1 (tree *tp, int *walk_subtrees, void *data)
/* ??? Really, we should mark this decl as *potentially* referenced
by this function and re-examine whether the decl is actually used
after rtl has been generated. */
- if (TREE_STATIC (t))
+ if (TREE_STATIC (t) || DECL_EXTERNAL (t))
{
cgraph_varpool_mark_needed_node (cgraph_varpool_node (t));
if (lang_hooks.callgraph.analyze_expr)
@@ -639,6 +698,37 @@ verify_cgraph (void)
verify_cgraph_node (node);
}
+
+/* Output all variables enqueued to be assembled. */
+bool
+cgraph_varpool_assemble_pending_decls (void)
+{
+ bool changed = false;
+
+ if (errorcount || sorrycount)
+ return false;
+
+ /* EH might mark decls as needed during expansion. This should be safe since
+ we don't create references to new function, but it should not be used
+ elsewhere. */
+ cgraph_varpool_analyze_pending_decls ();
+
+ while (cgraph_varpool_nodes_queue)
+ {
+ tree decl = cgraph_varpool_nodes_queue->decl;
+ struct cgraph_varpool_node *node = cgraph_varpool_nodes_queue;
+
+ cgraph_varpool_nodes_queue = cgraph_varpool_nodes_queue->next_needed;
+ if (!TREE_ASM_WRITTEN (decl) && !node->alias && !DECL_EXTERNAL (decl))
+ {
+ assemble_variable (decl, 0, 1, 0);
+ changed = true;
+ }
+ node->next_needed = NULL;
+ }
+ return changed;
+}
+
/* Analyze the function scheduled to be output. */
static void
cgraph_analyze_function (struct cgraph_node *node)
@@ -681,6 +771,9 @@ void
cgraph_finalize_compilation_unit (void)
{
struct cgraph_node *node;
+ /* Keep track of already processed nodes when called multiple times for
+ intermodule optmization. */
+ static struct cgraph_node *first_analyzed;
finish_aliases_1 ();
@@ -690,15 +783,18 @@ cgraph_finalize_compilation_unit (void)
return;
}
- cgraph_varpool_assemble_pending_decls ();
if (!quiet_flag)
- fprintf (stderr, "\nAnalyzing compilation unit\n");
+ {
+ fprintf (stderr, "\nAnalyzing compilation unit");
+ fflush (stderr);
+ }
timevar_push (TV_CGRAPH);
+ cgraph_varpool_analyze_pending_decls ();
if (cgraph_dump_file)
{
fprintf (cgraph_dump_file, "Initial entry points:");
- for (node = cgraph_nodes; node; node = node->next)
+ for (node = cgraph_nodes; node != first_analyzed; node = node->next)
if (node->needed && DECL_SAVED_TREE (node->decl))
fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
fprintf (cgraph_dump_file, "\n");
@@ -732,7 +828,7 @@ cgraph_finalize_compilation_unit (void)
if (!edge->callee->reachable)
cgraph_mark_reachable_node (edge->callee);
- cgraph_varpool_assemble_pending_decls ();
+ cgraph_varpool_analyze_pending_decls ();
}
/* Collect entry points to the unit. */
@@ -740,7 +836,7 @@ cgraph_finalize_compilation_unit (void)
if (cgraph_dump_file)
{
fprintf (cgraph_dump_file, "Unit entry points:");
- for (node = cgraph_nodes; node; node = node->next)
+ for (node = cgraph_nodes; node != first_analyzed; node = node->next)
if (node->needed && DECL_SAVED_TREE (node->decl))
fprintf (cgraph_dump_file, " %s", cgraph_node_name (node));
fprintf (cgraph_dump_file, "\n\nInitial ");
@@ -750,7 +846,7 @@ cgraph_finalize_compilation_unit (void)
if (cgraph_dump_file)
fprintf (cgraph_dump_file, "\nReclaiming functions:");
- for (node = cgraph_nodes; node; node = node->next)
+ for (node = cgraph_nodes; node != first_analyzed; node = node->next)
{
tree decl = node->decl;
@@ -768,6 +864,7 @@ cgraph_finalize_compilation_unit (void)
fprintf (cgraph_dump_file, "\n\nReclaimed ");
dump_cgraph (cgraph_dump_file);
}
+ first_analyzed = cgraph_nodes;
ggc_collect ();
timevar_pop (TV_CGRAPH);
}
@@ -1766,9 +1863,16 @@ cgraph_optimize (void)
verify_cgraph ();
#endif
if (!flag_unit_at_a_time)
- return;
+ {
+ cgraph_varpool_assemble_pending_decls ();
+ return;
+ }
process_pending_assemble_externals ();
+
+ /* Frontend may output common variables after the unit has been finalized.
+ It is safe to deal with them here as they are always zero initialized. */
+ cgraph_varpool_analyze_pending_decls ();
timevar_push (TV_CGRAPHOPT);
if (!quiet_flag)
@@ -1788,6 +1892,7 @@ cgraph_optimize (void)
{
fprintf (cgraph_dump_file, "Optimized ");
dump_cgraph (cgraph_dump_file);
+ dump_varpool (cgraph_dump_file);
}
timevar_pop (TV_CGRAPHOPT);
@@ -1799,8 +1904,11 @@ cgraph_optimize (void)
#endif
cgraph_mark_functions_to_output ();
-
cgraph_expand_all_functions ();
+ cgraph_varpool_remove_unreferenced_decls ();
+
+ cgraph_varpool_assemble_pending_decls ();
+
if (cgraph_dump_file)
{
fprintf (cgraph_dump_file, "\nFinal ");