aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Hubicka <jh@suse.cz>2005-03-31 00:28:02 +0200
committerJan Hubicka <hubicka@gcc.gnu.org>2005-03-30 22:28:02 +0000
commitcd9c7bd28b72dd5c5a97f40f2f690db21f80c8e2 (patch)
treeddb809af63fbede05531dda040e688b7ae54b743
parentd19e9499fc4f7cf1bbcc48a8c7947d5818827a7f (diff)
downloadgcc-cd9c7bd28b72dd5c5a97f40f2f690db21f80c8e2.zip
gcc-cd9c7bd28b72dd5c5a97f40f2f690db21f80c8e2.tar.gz
gcc-cd9c7bd28b72dd5c5a97f40f2f690db21f80c8e2.tar.bz2
[multiple changes]
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. From-SVN: r97287
-rw-r--r--gcc/ChangeLog41
-rw-r--r--gcc/cgraph.c168
-rw-r--r--gcc/cgraph.h14
-rw-r--r--gcc/cgraphunit.c126
-rw-r--r--gcc/config/i386/i386.c4
-rw-r--r--gcc/cp/ChangeLog5
-rw-r--r--gcc/cp/decl2.c5
-rw-r--r--gcc/java/ChangeLog8
-rw-r--r--gcc/java/Make-lang.in4
-rw-r--r--gcc/java/class.c9
-rw-r--r--gcc/java/resource.c3
-rw-r--r--gcc/passes.c2
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/varpool-1.c23
-rw-r--r--gcc/toplev.c4
-rw-r--r--gcc/tree-optimize.c10
-rw-r--r--gcc/varasm.c8
17 files changed, 369 insertions, 69 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 9fac180..a7394c5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,44 @@
+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.
+
2005-03-30 Daniel Berlin <dberlin@dberlin.org>
* tree-ssa-alias.c (compute_flow_insensitive_aliasing): Make sure
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index b769f841..5ed13bc 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -84,6 +84,7 @@ The varpool data structure:
#include "coretypes.h"
#include "tm.h"
#include "tree.h"
+#include "tree-inline.h"
#include "langhooks.h"
#include "hashtab.h"
#include "toplev.h"
@@ -91,6 +92,7 @@ The varpool data structure:
#include "ggc.h"
#include "debug.h"
#include "target.h"
+#include "basic-block.h"
#include "cgraph.h"
#include "varray.h"
#include "output.h"
@@ -118,14 +120,21 @@ int cgraph_max_uid;
/* Set when whole unit has been analyzed so we can access global info. */
bool cgraph_global_info_ready = false;
+/* Set when the cgraph is fully build and the basic flags are computed. */
+bool cgraph_function_flags_ready = false;
+
/* Hash table used to convert declarations into nodes. */
static GTY((param_is (struct cgraph_varpool_node))) htab_t cgraph_varpool_hash;
/* Queue of cgraph nodes scheduled to be lowered and output. */
-struct cgraph_varpool_node *cgraph_varpool_nodes_queue;
+struct cgraph_varpool_node *cgraph_varpool_nodes_queue, *cgraph_varpool_first_unanalyzed_node;
+
/* The linked list of cgraph varpool nodes. */
-static GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes;
+static GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes;
+
+/* End of the varpool queue. Needs to be QTYed to work with PCH. */
+static GTY(()) struct cgraph_varpool_node *cgraph_varpool_last_needed_node;
static hashval_t hash_node (const void *);
static int eq_node (const void *, const void *);
@@ -533,6 +542,13 @@ cgraph_node_name (struct cgraph_node *node)
return lang_hooks.decl_printable_name (node->decl, 2);
}
+/* Return name of the node used in debug output. */
+static const char *
+cgraph_varpool_node_name (struct cgraph_varpool_node *node)
+{
+ return lang_hooks.decl_printable_name (node->decl, 2);
+}
+
/* Dump given cgraph node. */
void
dump_cgraph_node (FILE *f, struct cgraph_node *node)
@@ -598,6 +614,36 @@ dump_cgraph (FILE *f)
dump_cgraph_node (f, node);
}
+/* Dump given cgraph node. */
+void
+dump_cgraph_varpool_node (FILE *f, struct cgraph_varpool_node *node)
+{
+ fprintf (f, "%s:", cgraph_varpool_node_name (node));
+ if (DECL_INITIAL (node->decl))
+ fprintf (f, " initialized");
+ if (node->needed)
+ fprintf (f, " needed");
+ if (node->analyzed)
+ fprintf (f, " analyzed");
+ if (node->finalized)
+ fprintf (f, " finalized");
+ if (node->output)
+ fprintf (f, " output");
+ fprintf (f, "\n");
+}
+
+/* Dump the callgraph. */
+
+void
+dump_varpool (FILE *f)
+{
+ struct cgraph_varpool_node *node;
+
+ fprintf (f, "variable pool:\n\n");
+ for (node = cgraph_varpool_nodes; node; node = node->next_needed)
+ dump_cgraph_varpool_node (f, node);
+}
+
/* Returns a hash code for P. */
static hashval_t
@@ -671,20 +717,82 @@ change_decl_assembler_name (tree decl, tree name)
SET_DECL_ASSEMBLER_NAME (decl, name);
}
+/* Helper function for finalization code - add node into lists so it will
+ be analyzed and compiled. */
+void
+cgraph_varpool_enqueue_needed_node (struct cgraph_varpool_node *node)
+{
+ if (cgraph_varpool_last_needed_node)
+ cgraph_varpool_last_needed_node->next_needed = node;
+ cgraph_varpool_last_needed_node = node;
+ node->next_needed = NULL;
+ if (!cgraph_varpool_nodes_queue)
+ cgraph_varpool_nodes_queue = node;
+ if (!cgraph_varpool_first_unanalyzed_node)
+ cgraph_varpool_first_unanalyzed_node = node;
+ notice_global_symbol (node->decl);
+}
+
+/* Reset the queue of needed nodes. */
+void
+cgraph_varpool_reset_queue (void)
+{
+ cgraph_varpool_last_needed_node = NULL;
+ cgraph_varpool_nodes_queue = NULL;
+ cgraph_varpool_first_unanalyzed_node = NULL;
+}
+
/* Notify finalize_compilation_unit that given node is reachable
or needed. */
void
cgraph_varpool_mark_needed_node (struct cgraph_varpool_node *node)
{
if (!node->needed && node->finalized)
- {
- node->next_needed = cgraph_varpool_nodes_queue;
- cgraph_varpool_nodes_queue = node;
- notice_global_symbol (node->decl);
- }
+ cgraph_varpool_enqueue_needed_node (node);
node->needed = 1;
}
+/* Determine if variable 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 haven't
+ seen yet. */
+
+bool
+decide_is_variable_needed (struct cgraph_varpool_node *node, tree decl)
+{
+ /* 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 we decided it was needed before, but at the time we didn't have
+ the definition available, then it's still needed. */
+ 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;
+
+ 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. */
+
+ /* We want to emit COMDAT variables only when absolutely necessary. */
+ if (DECL_COMDAT (decl))
+ return false;
+ return true;
+}
+
void
cgraph_varpool_finalize_decl (tree decl)
{
@@ -695,47 +803,19 @@ cgraph_varpool_finalize_decl (tree decl)
or local (in C, has internal linkage). So do nothing more
if this function has already run. */
if (node->finalized)
- return;
- if (node->needed)
{
- node->next_needed = cgraph_varpool_nodes_queue;
- cgraph_varpool_nodes_queue = node;
- notice_global_symbol (decl);
+ if (cgraph_global_info_ready || !flag_unit_at_a_time)
+ cgraph_varpool_assemble_pending_decls ();
+ return;
}
+ if (node->needed)
+ cgraph_varpool_enqueue_needed_node (node);
node->finalized = true;
- if (/* Externally visible variables must be output. The exception are
- COMDAT functions that must be output only when they are needed. */
- (TREE_PUBLIC (decl) && !DECL_COMDAT (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))))
- {
- cgraph_varpool_mark_needed_node (node);
- }
-}
-
-bool
-cgraph_varpool_assemble_pending_decls (void)
-{
- bool changed = false;
-
- while (cgraph_varpool_nodes_queue)
- {
- struct cgraph_varpool_node *node = cgraph_varpool_nodes_queue;
- tree decl = node->decl;
-
- cgraph_varpool_nodes_queue = cgraph_varpool_nodes_queue->next_needed;
- if (!TREE_ASM_WRITTEN (decl) && !node->alias)
- {
- assemble_variable (decl, 0, 1, 0);
- changed = true;
- }
- node->next_needed = NULL;
- }
- return changed;
+ if (decide_is_variable_needed (node, decl))
+ cgraph_varpool_mark_needed_node (node);
+ if (cgraph_global_info_ready || !flag_unit_at_a_time)
+ cgraph_varpool_assemble_pending_decls ();
}
/* Return true when the DECL can possibly be inlined. */
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index b9a8d6e..e701e56 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -151,6 +151,12 @@ struct cgraph_varpool_node GTY(())
/* Set when function must be output - it is externally visible
or its address is taken. */
bool needed;
+ /* Needed variables might become dead by optimization. This flag
+ forces the variable to be output even if it appears dead otherwise. */
+ bool force_output;
+ /* Set once the variable has been instantiated and its callee
+ lists created. */
+ bool analyzed;
/* Set once it has been finalized so we consider it to be output. */
bool finalized;
/* Set when function is scheduled to be assembled. */
@@ -165,11 +171,14 @@ extern GTY(()) int cgraph_max_uid;
extern bool cgraph_global_info_ready;
extern GTY(()) struct cgraph_node *cgraph_nodes_queue;
+extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_first_unanalyzed_node;
extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes_queue;
/* In cgraph.c */
void dump_cgraph (FILE *);
void dump_cgraph_node (FILE *, struct cgraph_node *);
+void dump_varpool (FILE *);
+void dump_cgraph_varpool_node (FILE *, struct cgraph_varpool_node *);
void cgraph_remove_edge (struct cgraph_edge *);
void cgraph_remove_node (struct cgraph_node *);
void cgraph_node_remove_callees (struct cgraph_node *node);
@@ -190,14 +199,17 @@ struct cgraph_varpool_node *cgraph_varpool_node (tree decl);
struct cgraph_varpool_node *cgraph_varpool_node_for_asm (tree asmname);
void cgraph_varpool_mark_needed_node (struct cgraph_varpool_node *);
void cgraph_varpool_finalize_decl (tree);
-bool cgraph_varpool_assemble_pending_decls (void);
void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *);
bool cgraph_function_possibly_inlined_p (tree);
void cgraph_unnest_node (struct cgraph_node *node);
+void cgraph_varpool_enqueue_needed_node (struct cgraph_varpool_node *);
+void cgraph_varpool_reset_queue (void);
+bool decide_is_variable_needed (struct cgraph_varpool_node *, tree);
/* In cgraphunit.c */
bool cgraph_assemble_pending_functions (void);
+bool cgraph_varpool_assemble_pending_decls (void);
void cgraph_finalize_function (tree, bool);
void cgraph_finalize_compilation_unit (void);
void cgraph_create_edges (struct cgraph_node *, tree);
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 9fef33e..3bb143f 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 ");
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 1e9165f..fffc5f3 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -5889,10 +5889,6 @@ output_pic_addr_const (FILE *file, rtx x, int code)
break;
case SYMBOL_REF:
- /* Mark the decl as referenced so that cgraph will output the function. */
- if (SYMBOL_REF_DECL (x))
- mark_decl_referenced (SYMBOL_REF_DECL (x));
-
assemble_name (file, XSTR (x, 0));
if (!TARGET_MACHO && code == 'P' && ! SYMBOL_REF_LOCAL_P (x))
fputs ("@PLT", file);
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 859be9d..d232838 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,8 @@
+2005-03-31 Jan Hubicka <jh@suse.cz>
+
+ * decl2.c (finish_objects): Mark ctor as needed.
+ (cp_finish_file): Output variables only in nonunit-at-a-time.
+
2005-03-29 Richard Henderson <rth@redhat.com>
PR c/20519
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index 474e04e..78ba602 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -2110,6 +2110,7 @@ finish_objects (int method_type, int initp, tree body)
if (targetm.have_ctors_dtors)
{
rtx fnsym = XEXP (DECL_RTL (fn), 0);
+ cgraph_mark_needed_node (cgraph_node (fn));
if (method_type == 'I')
(* targetm.asm_out.constructor) (fnsym, initp);
else
@@ -2959,9 +2960,9 @@ cp_finish_file (void)
/* Ask the back end to emit functions and variables that are
enqueued. These emissions may result in marking more entities
as needed. */
- if (cgraph_assemble_pending_functions ())
+ if (!flag_unit_at_a_time && cgraph_assemble_pending_functions ())
reconsider = true;
- if (cgraph_varpool_assemble_pending_decls ())
+ if (!flag_unit_at_a_time && cgraph_varpool_assemble_pending_decls ())
reconsider = true;
retries++;
diff --git a/gcc/java/ChangeLog b/gcc/java/ChangeLog
index b46ec5b..3b11a3e 100644
--- a/gcc/java/ChangeLog
+++ b/gcc/java/ChangeLog
@@ -1,3 +1,11 @@
+2005-03-31 Jan Hubicka <jh@suse.cz>
+
+ * Make-lang.in (class.o, decl.o): Depend on cgraph.h.
+ * class.c: Include cgraph.h
+ (make_local_functoin_alias): Mark aslias as needed.
+ * resource.c: Include cgraph.h
+ (compile_resource_data): Go via cgraph interface.
+
2005-03-30 Ian Lance Taylor <ian@airs.com>
* parse.y (maybe_yank_clinit): Don't crash if bbody is NULL.
diff --git a/gcc/java/Make-lang.in b/gcc/java/Make-lang.in
index a6d2013..face962 100644
--- a/gcc/java/Make-lang.in
+++ b/gcc/java/Make-lang.in
@@ -299,13 +299,13 @@ java/check-init.o: java/check-init.c $(CONFIG_H) $(JAVA_TREE_H) $(SYSTEM_H) \
coretypes.h $(TM_H) toplev.h
java/class.o: java/class.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(JAVA_TREE_H) $(RTL_H) java/jcf.h java/parse.h toplev.h output.h $(GGC_H) \
- $(TARGET_H) function.h gt-java-class.h
+ $(TARGET_H) function.h gt-java-class.h cgraph.h
java/constants.o: java/constants.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h \
toplev.h $(SYSTEM_H) coretypes.h $(TM_H) $(GGC_H) gt-java-constants.h
java/decl.o: java/decl.c $(CONFIG_H) $(JAVA_TREE_H) $(RTL_H) java/jcf.h \
toplev.h flags.h $(SYSTEM_H) coretypes.h $(TM_H) function.h expr.h \
libfuncs.h except.h java/java-except.h $(GGC_H) real.h gt-java-decl.h \
- target.h
+ target.h cgraph.h
java/except.o: java/except.c $(CONFIG_H) $(JAVA_TREE_H) java/jcf.h real.h \
$(RTL_H) java/javaop.h java/java-opcodes.h except.h java/java-except.h \
toplev.h $(SYSTEM_H) coretypes.h $(TM_H) function.h
diff --git a/gcc/java/class.c b/gcc/java/class.c
index 5e2e535..1c7c3ab 100644
--- a/gcc/java/class.c
+++ b/gcc/java/class.c
@@ -45,6 +45,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "except.h"
#include "cgraph.h"
#include "tree-iterator.h"
+#include "cgraph.h"
/* DOS brain-damage */
#ifndef O_BINARY
@@ -910,6 +911,7 @@ build_utf8_ref (tree name)
layout_decl (decl, 0);
pushdecl (decl);
rest_of_decl_compilation (decl, global_bindings_p (), 0);
+ cgraph_varpool_mark_needed_node (cgraph_varpool_node (decl));
utf8_decl_list = decl;
make_decl_rtl (decl);
ref = build1 (ADDR_EXPR, utf8const_ptr_type, decl);
@@ -2436,8 +2438,11 @@ emit_register_classes (tree *list_p)
named_section_flags (JCR_SECTION_NAME, SECTION_WRITE);
assemble_align (POINTER_SIZE);
for (t = registered_class; t; t = TREE_CHAIN (t))
- assemble_integer (XEXP (DECL_RTL (t), 0),
- POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+ {
+ mark_decl_referenced (t);
+ assemble_integer (XEXP (DECL_RTL (t), 0),
+ POINTER_SIZE / BITS_PER_UNIT, POINTER_SIZE, 1);
+ }
#else
/* A target has defined TARGET_USE_JCR_SECTION, but doesn't have a
JCR_SECTION_NAME. */
diff --git a/gcc/java/resource.c b/gcc/java/resource.c
index 7f7d72a..5f11810 100644
--- a/gcc/java/resource.c
+++ b/gcc/java/resource.c
@@ -42,6 +42,7 @@ The Free Software Foundation is independent of Sun Microsystems, Inc. */
#include "target.h"
#include "expr.h"
#include "tree-iterator.h"
+#include "cgraph.h"
/* DOS brain-damage */
#ifndef O_BINARY
@@ -93,7 +94,7 @@ compile_resource_data (const char *name, const char *buffer, int length)
pushdecl (decl);
rest_of_decl_compilation (decl, global_bindings_p (), 0);
make_decl_rtl (decl);
- assemble_variable (decl, 1, 0, 0);
+ cgraph_varpool_finalize_decl (decl);
resources = tree_cons (NULL_TREE, decl, resources);
}
diff --git a/gcc/passes.c b/gcc/passes.c
index 17e42c4..988f4f2 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -225,7 +225,7 @@ rest_of_decl_compilation (tree decl,
(see gcc.c-torture/compile/920624-1.c) */
if ((at_end
|| !DECL_DEFER_OUTPUT (decl)
- || (flag_unit_at_a_time && DECL_INITIAL (decl)))
+ || DECL_INITIAL (decl))
&& !DECL_EXTERNAL (decl))
{
if (flag_unit_at_a_time && !cgraph_global_info_ready
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 35bc042..411540f 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2005-03-31 Jan Hubicka <jh@suse.cz>
+
+ * gcc.dg/varpool-1.c: New testcase.
+
2005-03-30 Joseph S. Myers <joseph@codesourcery.com>
PR c/772
diff --git a/gcc/testsuite/gcc.dg/varpool-1.c b/gcc/testsuite/gcc.dg/varpool-1.c
new file mode 100644
index 0000000..48f1cd3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/varpool-1.c
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+/* { dg-final { scan-assembler-not "unnecesary_static_initialized_variable" } } */
+
+static int unnecesary_static_initialized_variable;
+static int *unnecesary_static_initialized_variable2 =
+ &unnecesary_static_initialized_variable;
+static inline
+simplify_after_inline (int param1, int *param2)
+{
+ if (unnecesary_static_initialized_variable != param1)
+ return unnecesary_static_initialized_variable;
+ if (unnecesary_static_initialized_variable2 != param2)
+ return unnecesary_static_initialized_variable;
+}
+
+main ()
+{
+ return simplify_after_inline (unnecesary_static_initialized_variable,
+ unnecesary_static_initialized_variable2) +
+ simplify_after_inline (unnecesary_static_initialized_variable,
+ unnecesary_static_initialized_variable2);
+}
diff --git a/gcc/toplev.c b/gcc/toplev.c
index 5895d37..8cfd740 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -781,11 +781,11 @@ wrapup_global_declarations (tree *vec, int len)
bool needed = 1;
node = cgraph_varpool_node (decl);
- if (flag_unit_at_a_time && node->finalized)
+ if (node->finalized)
needed = 0;
else if (node->alias)
needed = 0;
- else if ((flag_unit_at_a_time && !cgraph_global_info_ready)
+ else if (!cgraph_global_info_ready
&& (TREE_USED (decl)
|| TREE_USED (DECL_ASSEMBLER_NAME (decl))))
/* needed */;
diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c
index bb31a0e..63131af 100644
--- a/gcc/tree-optimize.c
+++ b/gcc/tree-optimize.c
@@ -660,6 +660,16 @@ tree_rest_of_compilation (tree fndecl)
timevar_pop (TV_INTEGRATION);
}
}
+ /* We are not going to maintain the cgraph edges up to date.
+ Kill it so it won't confuse us. */
+ while (node->callees)
+ {
+ /* In non-unit-at-a-time we must mark all referenced functions as needed.
+ */
+ if (node->callees->callee->analyzed && !flag_unit_at_a_time)
+ cgraph_mark_needed_node (node->callees->callee);
+ cgraph_remove_edge (node->callees);
+ }
/* We are not going to maintain the cgraph edges up to date.
Kill it so it won't confuse us. */
diff --git a/gcc/varasm.c b/gcc/varasm.c
index cf323f4..9210c41 100644
--- a/gcc/varasm.c
+++ b/gcc/varasm.c
@@ -1883,7 +1883,13 @@ mark_decl_referenced (tree decl)
cgraph_mark_needed_node (cgraph_node (decl));
}
else if (TREE_CODE (decl) == VAR_DECL)
- cgraph_varpool_mark_needed_node (cgraph_varpool_node (decl));
+ {
+ struct cgraph_varpool_node *node = cgraph_varpool_node (decl);
+ cgraph_varpool_mark_needed_node (node);
+ /* C++ frontend use mark_decl_references to force COMDAT variables
+ to be output that might appear dead otherwise. */
+ node->force_output = true;
+ }
/* else do nothing - we can get various sorts of CST nodes here,
which do not need to be marked. */
}