* common.opt (ftoplevel-reorder): New option.
* cgraph.c (cgraph_asm_nodes): New global variable.
(cgraph_asm_last_node): New static variable.
(cgraph_order): New global variable.
(cgraph_create_node): Set new order field.
(cgraph_varpool_node): Likewise.
(decide_is_variable_needed): Return true if not
flag_toplevel_reorder.
(cgraph_add_asm_node): New function.
* cgraph.h (struct cgraph_node): Add order field.
(struct cgraph_varpool_node): Add order field.
(struct cgraph_asm_node): Define.
(cgraph_asm_nodes, cgraph_order): Declare.
(cgraph_add_asm_node): Declare.
* cgraphunit.c (cgraph_varpool_assemble_decl): New static
function.
(cgraph_varpool_assemble_pending_decls): Call it.
(cgraph_output_pending_asms): New static function.
(cgraph_finalize_compilation_unit): Call it.
(struct cgraph_order_sort): Define.
(cgraph_output_in_order): New static function.
(cgraph_optimize): Call cgraph_output_pending_asms. Add code for
!flag_toplevel_reorder case.
* c-parser.c: Include "cgraph.h".
(c_parser_asm_definition): Call cgraph_add_asm_node rather than
assemble_asm.
* Makefile.in (CRTSTUFF_CFLAGS): Use -fno-toplevel-reorder rather
than -fno-unit-at-a-time.
* doc/invoke.texi (Option Summary): Mention
-fno-toplevel-reorder.
(Optimize Options): Document -fno-toplevel-reorder. Mention it in
-funit-at-a-time documentation.
cp/:
* parser.c: Include "cgraph.h".
(cp_parser_asm_definition): Call cgraph_add_asm_node rather than
assemble_asm.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@109811
138bc75d-0d04-0410-961f-
82ee72b054a4
+2006-01-16 Ian Lance Taylor <ian@airs.com>
+
+ * common.opt (ftoplevel-reorder): New option.
+ * cgraph.c (cgraph_asm_nodes): New global variable.
+ (cgraph_asm_last_node): New static variable.
+ (cgraph_order): New global variable.
+ (cgraph_create_node): Set new order field.
+ (cgraph_varpool_node): Likewise.
+ (decide_is_variable_needed): Return true if not
+ flag_toplevel_reorder.
+ (cgraph_add_asm_node): New function.
+ * cgraph.h (struct cgraph_node): Add order field.
+ (struct cgraph_varpool_node): Add order field.
+ (struct cgraph_asm_node): Define.
+ (cgraph_asm_nodes, cgraph_order): Declare.
+ (cgraph_add_asm_node): Declare.
+ * cgraphunit.c (cgraph_varpool_assemble_decl): New static
+ function.
+ (cgraph_varpool_assemble_pending_decls): Call it.
+ (cgraph_output_pending_asms): New static function.
+ (cgraph_finalize_compilation_unit): Call it.
+ (struct cgraph_order_sort): Define.
+ (cgraph_output_in_order): New static function.
+ (cgraph_optimize): Call cgraph_output_pending_asms. Add code for
+ !flag_toplevel_reorder case.
+ * c-parser.c: Include "cgraph.h".
+ (c_parser_asm_definition): Call cgraph_add_asm_node rather than
+ assemble_asm.
+ * Makefile.in (CRTSTUFF_CFLAGS): Use -fno-toplevel-reorder rather
+ than -fno-unit-at-a-time.
+ * doc/invoke.texi (Option Summary): Mention
+ -fno-toplevel-reorder.
+ (Optimize Options): Document -fno-toplevel-reorder. Mention it in
+ -funit-at-a-time documentation.
+
2006-01-17 Hans-Peter Nilsson <hp@axis.com>
Kazu Hirata <kazu@codesourcery.com>
# Options to use when compiling crtbegin/end.
CRTSTUFF_CFLAGS = -O2 $(GCC_CFLAGS) $(INCLUDES) $(MULTILIB_CFLAGS) -g0 \
-finhibit-size-directive -fno-inline-functions -fno-exceptions \
- -fno-zero-initialized-in-bss -fno-unit-at-a-time \
+ -fno-zero-initialized-in-bss -fno-toplevel-reorder \
$(INHIBIT_LIBC_CFLAGS)
# Additional sources to handle exceptions; overridden by targets as needed.
#include "c-common.h"
#include "vec.h"
#include "target.h"
+#include "cgraph.h"
\f
/* Miscellaneous data and functions needed for the parser. */
c_parser_asm_definition (c_parser *parser)
{
tree asm_str = c_parser_simple_asm_expr (parser);
- /* ??? This only works sensibly in the presence of
- -fno-unit-at-a-time; file-scope asms really need to be passed to
- cgraph which needs to preserve the order of functions and
- file-scope asms. */
if (asm_str)
- assemble_asm (asm_str);
+ cgraph_add_asm_node (asm_str);
c_parser_skip_until_found (parser, CPP_SEMICOLON, "expected %<;%>");
}
/* Queue of cgraph nodes scheduled to be lowered and output. */
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;
/* End of the varpool queue. Needs to be QTYed to work with PCH. */
static GTY(()) struct cgraph_varpool_node *cgraph_varpool_last_needed_node;
+/* Linked list of cgraph asm nodes. */
+struct cgraph_asm_node *cgraph_asm_nodes;
+
+/* Last node in cgraph_asm_nodes. */
+static GTY(()) struct cgraph_asm_node *cgraph_asm_last_node;
+
+/* The order index of the next cgraph node to be created. This is
+ used so that we can sort the cgraph nodes in order by when we saw
+ them, to support -fno-toplevel-reorder. */
+int cgraph_order;
+
static hashval_t hash_node (const void *);
static int eq_node (const void *, const void *);
node = GGC_CNEW (struct cgraph_node);
node->next = cgraph_nodes;
node->uid = cgraph_max_uid++;
+ node->order = cgraph_order++;
if (cgraph_nodes)
cgraph_nodes->previous = node;
node->previous = NULL;
return *slot;
node = GGC_CNEW (struct cgraph_varpool_node);
node->decl = decl;
+ node->order = cgraph_order++;
node->next = cgraph_varpool_nodes;
cgraph_varpool_nodes = node;
*slot = node;
if (TREE_PUBLIC (decl) && !DECL_COMDAT (decl) && !DECL_EXTERNAL (decl))
return true;
- if (flag_unit_at_a_time)
+ /* When not reordering top level variables, we have to assume that
+ we are going to keep everything. */
+ if (flag_unit_at_a_time && flag_toplevel_reorder)
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;
cgraph_varpool_assemble_pending_decls ();
}
+/* Add a top-level asm statement to the list. */
+
+struct cgraph_asm_node *
+cgraph_add_asm_node (tree asm_str)
+{
+ struct cgraph_asm_node *node;
+
+ node = GGC_CNEW (struct cgraph_asm_node);
+ node->asm_str = asm_str;
+ node->order = cgraph_order++;
+ node->next = NULL;
+ if (cgraph_asm_nodes == NULL)
+ cgraph_asm_nodes = node;
+ else
+ cgraph_asm_last_node->next = node;
+ cgraph_asm_last_node = node;
+ return node;
+}
+
/* Return true when the DECL can possibly be inlined. */
bool
cgraph_function_possibly_inlined_p (tree decl)
gcov_type count;
/* Unique id of the node. */
int uid;
+ /* Ordering of all cgraph nodes. */
+ int order;
/* Set when function must be output - it is externally visible
or its address is taken. */
bool needed;
struct cgraph_varpool_node *next;
/* Pointer to the next function in cgraph_varpool_nodes_queue. */
struct cgraph_varpool_node *next_needed;
+ /* Ordering of all cgraph nodes. */
+ int order;
/* Set when function must be output - it is externally visible
or its address is taken. */
bool alias;
};
+/* Every top level asm statement is put into a cgraph_asm_node. */
+
+struct cgraph_asm_node GTY(())
+{
+ /* Next asm node. */
+ struct cgraph_asm_node *next;
+ /* String for this asm node. */
+ tree asm_str;
+ /* Ordering of all cgraph nodes. */
+ int order;
+};
+
extern GTY(()) struct cgraph_node *cgraph_nodes;
extern GTY(()) int cgraph_n_nodes;
extern GTY(()) int cgraph_max_uid;
extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_first_unanalyzed_node;
extern GTY(()) struct cgraph_varpool_node *cgraph_varpool_nodes_queue;
+extern GTY(()) struct cgraph_asm_node *cgraph_asm_nodes;
+extern GTY(()) int cgraph_order;
/* In cgraph.c */
void dump_cgraph (FILE *);
void cgraph_varpool_finalize_decl (tree);
void cgraph_redirect_edge_callee (struct cgraph_edge *, struct cgraph_node *);
+struct cgraph_asm_node *cgraph_add_asm_node (tree);
+
bool cgraph_function_possibly_inlined_p (tree);
void cgraph_unnest_node (struct cgraph_node *);
void cgraph_varpool_enqueue_needed_node (struct cgraph_varpool_node *);
verify_cgraph_node (node);
}
+/* Output one variable, if necessary. Return whether we output it. */
+static bool
+cgraph_varpool_assemble_decl (struct cgraph_varpool_node *node)
+{
+ tree decl = node->decl;
+
+ if (!TREE_ASM_WRITTEN (decl)
+ && !node->alias
+ && !DECL_EXTERNAL (decl)
+ && (TREE_CODE (decl) != VAR_DECL || !DECL_HAS_VALUE_EXPR_P (decl)))
+ {
+ assemble_variable (decl, 0, 1, 0);
+ /* Local static variables are never seen by check_global_declarations
+ so we need to output debug info by hand. */
+ if (DECL_CONTEXT (decl)
+ && (TREE_CODE (DECL_CONTEXT (decl)) == BLOCK
+ || TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
+ && errorcount == 0 && sorrycount == 0)
+ {
+ timevar_push (TV_SYMOUT);
+ (*debug_hooks->global_decl) (decl);
+ timevar_pop (TV_SYMOUT);
+ }
+ return true;
+ }
+
+ return false;
+}
/* Output all variables enqueued to be assembled. */
bool
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);
- /* Local static variables are never seen by check_global_declarations
- so we need to output debug info by hand. */
- if (DECL_CONTEXT (decl)
- && (TREE_CODE (DECL_CONTEXT (decl)) == BLOCK
- || TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL)
- && errorcount == 0 && sorrycount == 0)
- {
- timevar_push (TV_SYMOUT);
- (*debug_hooks->global_decl) (decl);
- timevar_pop (TV_SYMOUT);
- }
- changed = true;
- }
+ if (cgraph_varpool_assemble_decl (node))
+ changed = true;
node->next_needed = NULL;
}
return changed;
}
+/* Output all asm statements we have stored up to be output. */
+
+static void
+cgraph_output_pending_asms (void)
+{
+ struct cgraph_asm_node *can;
+
+ if (errorcount || sorrycount)
+ return;
+
+ for (can = cgraph_asm_nodes; can; can = can->next)
+ assemble_asm (can->asm_str);
+ cgraph_asm_nodes = NULL;
+}
+
/* Analyze the function scheduled to be output. */
static void
cgraph_analyze_function (struct cgraph_node *node)
if (!flag_unit_at_a_time)
{
+ cgraph_output_pending_asms ();
cgraph_assemble_pending_functions ();
return;
}
free (order);
}
+/* This is used to sort the node types by the cgraph order number. */
+
+struct cgraph_order_sort
+{
+ enum { ORDER_UNDEFINED = 0, ORDER_FUNCTION, ORDER_VAR, ORDER_ASM } kind;
+ union
+ {
+ struct cgraph_node *f;
+ struct cgraph_varpool_node *v;
+ struct cgraph_asm_node *a;
+ } u;
+};
+
+/* Output all functions, variables, and asm statements in the order
+ according to their order fields, which is the order in which they
+ appeared in the file. This implements -fno-toplevel-reorder. In
+ this mode we may output functions and variables which don't really
+ need to be output. */
+
+static void
+cgraph_output_in_order (void)
+{
+ int max;
+ size_t size;
+ struct cgraph_order_sort *nodes;
+ int i;
+ struct cgraph_node *pf;
+ struct cgraph_varpool_node *pv;
+ struct cgraph_asm_node *pa;
+
+ max = cgraph_order;
+ size = max * sizeof (struct cgraph_order_sort);
+ nodes = (struct cgraph_order_sort *) alloca (size);
+ memset (nodes, 0, size);
+
+ cgraph_varpool_analyze_pending_decls ();
+
+ for (pf = cgraph_nodes; pf; pf = pf->next)
+ {
+ if (pf->output)
+ {
+ i = pf->order;
+ gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
+ nodes[i].kind = ORDER_FUNCTION;
+ nodes[i].u.f = pf;
+ }
+ }
+
+ for (pv = cgraph_varpool_nodes_queue; pv; pv = pv->next_needed)
+ {
+ i = pv->order;
+ gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
+ nodes[i].kind = ORDER_VAR;
+ nodes[i].u.v = pv;
+ }
+
+ for (pa = cgraph_asm_nodes; pa; pa = pa->next)
+ {
+ i = pa->order;
+ gcc_assert (nodes[i].kind == ORDER_UNDEFINED);
+ nodes[i].kind = ORDER_ASM;
+ nodes[i].u.a = pa;
+ }
+ cgraph_asm_nodes = NULL;
+
+ for (i = 0; i < max; ++i)
+ {
+ switch (nodes[i].kind)
+ {
+ case ORDER_FUNCTION:
+ nodes[i].u.f->output = 0;
+ cgraph_expand_function (nodes[i].u.f);
+ break;
+
+ case ORDER_VAR:
+ cgraph_varpool_assemble_decl (nodes[i].u.v);
+ break;
+
+ case ORDER_ASM:
+ assemble_asm (nodes[i].u.a->asm_str);
+ break;
+
+ case ORDER_UNDEFINED:
+ break;
+
+ default:
+ gcc_unreachable ();
+ }
+ }
+}
+
/* Mark visibility of all functions.
A local function is one whose calls can occur only in the current
#endif
if (!flag_unit_at_a_time)
{
+ cgraph_output_pending_asms ();
cgraph_varpool_assemble_pending_decls ();
return;
}
#ifdef ENABLE_CHECKING
verify_cgraph ();
#endif
-
+
cgraph_mark_functions_to_output ();
- cgraph_expand_all_functions ();
- cgraph_varpool_remove_unreferenced_decls ();
- cgraph_varpool_assemble_pending_decls ();
+ if (!flag_toplevel_reorder)
+ cgraph_output_in_order ();
+ else
+ {
+ cgraph_output_pending_asms ();
+
+ cgraph_expand_all_functions ();
+ cgraph_varpool_remove_unreferenced_decls ();
+
+ cgraph_varpool_assemble_pending_decls ();
+ }
if (cgraph_dump_file)
{
Common Joined RejectNegative
-ftls-model=[global-dynamic|local-dynamic|initial-exec|local-exec] Set the default thread-local storage code generation model
+ftoplevel-reorder
+Common Report Var(flag_toplevel_reorder) Init(1)
+Reorder top level functions, variables, and asms
+
ftracer
Common Report Var(flag_tracer)
Perform superblock formation via tail duplication
+2006-01-16 Ian Lance Taylor <ian@airs.com>
+
+ * parser.c: Include "cgraph.h".
+ (cp_parser_asm_definition): Call cgraph_add_asm_node rather than
+ assemble_asm.
+
2006-01-16 Rafael Ávila de Espíndola <rafael.espindola@gmail.com>
* g++spec.c (lang_specific_spec_functions): Remove.
* parser.c (cp_parser_primary_expression): Document the grammar
for the built-in offsetof, a GNU extension.
-2005-01-04 Zdenek Dvorak <dvorakz@suse.cz>
+2006-01-04 Zdenek Dvorak <dvorakz@suse.cz>
PR c++/25632
* init.c (constant_value_1): Unshare use of DECL_INITIAL. Fix a typo
#include "toplev.h"
#include "output.h"
#include "target.h"
+#include "cgraph.h"
#include "c-common.h"
\f
}
}
else
- assemble_asm (string);
+ cgraph_add_asm_node (string);
}
/* Declarators [gram.dcl.decl] */
-fno-function-cse -fno-guess-branch-probability @gol
-fno-inline -fno-math-errno -fno-peephole -fno-peephole2 @gol
-funsafe-math-optimizations -funsafe-loop-optimizations -ffinite-math-only @gol
--fno-trapping-math -fno-zero-initialized-in-bss @gol
+-fno-toplevel-reorder -fno-trapping-math -fno-zero-initialized-in-bss @gol
-fomit-frame-pointer -foptimize-register-move @gol
-foptimize-sibling-calls -fprefetch-loop-arrays @gol
-fprofile-generate -fprofile-use @gol
Parse the whole compilation unit before starting to produce code.
This allows some extra optimizations to take place but consumes
more memory (in general). There are some compatibility issues
-with @emph{unit-at-at-time} mode:
+with @emph{unit-at-a-time} mode:
@itemize @bullet
@item
enabling @emph{unit-at-a-time} mode may change the order
in which functions, variables, and top-level @code{asm} statements
are emitted, and will likely break code relying on some particular
ordering. The majority of such top-level @code{asm} statements,
-though, can be replaced by @code{section} attributes.
+though, can be replaced by @code{section} attributes. The
+@option{fno-toplevel-reorder} option may be used to keep the ordering
+used in the input file, at the cost of some optimizations.
@item
@emph{unit-at-a-time} mode removes unreferenced static variables
Enabled at levels @option{-O2}, @option{-O3}.
+@item -fno-toplevel-reorder
+Do not reorder top-level functions, variables, and @code{asm}
+statements. Output them in the same order that they appear in the
+input file. When this option is used, unreferenced static variables
+will not be removed. This option is intended to support existing code
+which relies on a particular ordering. For new code, it is better to
+use attributes.
+
@item -fweb
@opindex fweb
Constructs webs as commonly used for register allocation purposes and assign