[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
This commit is contained in:
parent
d19e9499fc
commit
cd9c7bd28b
@ -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
|
||||
|
168
gcc/cgraph.c
168
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. */
|
||||
|
14
gcc/cgraph.h
14
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);
|
||||
|
126
gcc/cgraphunit.c
126
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 ");
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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++;
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
23
gcc/testsuite/gcc.dg/varpool-1.c
Normal file
23
gcc/testsuite/gcc.dg/varpool-1.c
Normal file
@ -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);
|
||||
}
|
@ -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 */;
|
||||
|
@ -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. */
|
||||
|
@ -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. */
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user