summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2006-12-30 11:58:01 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2006-12-30 11:58:01 +0000
commit523c1122434af355049edacf489e8da82ee7709d (patch)
tree4ee7560469c1e50ca7f51f6e50bca995ec5871a0
parent311a2fe08784f5d009281ab401fe4f143d4c2825 (diff)
downloadgcc-523c1122434af355049edacf489e8da82ee7709d.tar.gz
* cgraph.c (cgraph_exapnd_queue): Rename to...
(cgraph_new_nodes): ... this one. (cgraph_state): New global variable. (cgraph_add_new_function): Work in more cases. * cgraph.h (cgraph_expand_queue): Rename to ... (cgraph_new_nodes): ... this one. (cgraph_state): New enum and static variable. (cgraph_add_new_function): Update prototype. (cgraph_process_new_functions): New. * omp-low.c (expand_omp_parallel): Update. * cgraphunit.c (initialize_inline_failed): Declare early. (cgraph_process_new_functions): New function. (cgraph_assemble_pending_functions): Use it. (cgraph_expand_all_functions): Use it. (cgraph_optimize): Use it; set cgraph_state. * passes.c (execute_one_pass, execute_ipa_pass_list): Process new functions git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@120282 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog20
-rw-r--r--gcc/cgraph.c68
-rw-r--r--gcc/cgraph.h17
-rw-r--r--gcc/cgraphunit.c115
-rw-r--r--gcc/omp-low.c2
-rw-r--r--gcc/passes.c5
6 files changed, 178 insertions, 49 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 24a46cb97bd..b728b00e54c 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,23 @@
+2006-12-29 Jan Hubicka <jh@suse.cz>
+
+ * cgraph.c (cgraph_exapnd_queue): Rename to...
+ (cgraph_new_nodes): ... this one.
+ (cgraph_state): New global variable.
+ (cgraph_add_new_function): Work in more cases.
+ * cgraph.h (cgraph_expand_queue): Rename to ...
+ (cgraph_new_nodes): ... this one.
+ (cgraph_state): New enum and static variable.
+ (cgraph_add_new_function): Update prototype.
+ (cgraph_process_new_functions): New.
+ * omp-low.c (expand_omp_parallel): Update.
+ * cgraphunit.c (initialize_inline_failed): Declare early.
+ (cgraph_process_new_functions): New function.
+ (cgraph_assemble_pending_functions): Use it.
+ (cgraph_expand_all_functions): Use it.
+ (cgraph_optimize): Use it; set cgraph_state.
+ * passes.c (execute_one_pass, execute_ipa_pass_list): Process new
+ functions
+
2006-12-29 Kazu Hirata <kazu@codesourcery.com>
* tree-cfg.c (last_stmt_ptr): Remove.
diff --git a/gcc/cgraph.c b/gcc/cgraph.c
index d35b4db5a56..21e821c2b4d 100644
--- a/gcc/cgraph.c
+++ b/gcc/cgraph.c
@@ -97,10 +97,10 @@ struct cgraph_node *cgraph_nodes;
/* Queue of cgraph nodes scheduled to be lowered. */
struct cgraph_node *cgraph_nodes_queue;
-/* Queue of cgraph nodes scheduled to be expanded. This is a
+/* Queue of cgraph nodes scheduled to be added into cgraph. This is a
secondary queue used during optimization to accommodate passes that
may generate new functions that need to be optimized and expanded. */
-struct cgraph_node *cgraph_expand_queue;
+struct cgraph_node *cgraph_new_nodes;
/* Number of nodes in existence. */
int cgraph_n_nodes;
@@ -111,6 +111,9 @@ int cgraph_max_uid;
/* Set when whole unit has been analyzed so we can access global info. */
bool cgraph_global_info_ready = false;
+/* What state callgraph is in right now. */
+enum cgraph_state cgraph_state = CGRAPH_STATE_CONSTRUCTION;
+
/* Set when the cgraph is fully build and the basic flags are computed. */
bool cgraph_function_flags_ready = false;
@@ -911,23 +914,60 @@ cgraph_function_body_availability (struct cgraph_node *node)
return avail;
}
-/* Add the function FNDECL to the call graph. FNDECL is assumed to be
- in low GIMPLE form and ready to be processed by cgraph_finalize_function.
+/* Add the function FNDECL to the call graph.
+ Unlike cgraph_finalize_function, this function is intended to be used
+ by middle end and allows insertion of new function at arbitrary point
+ of compilation. The function can be either in high, low or SSA form
+ GIMPLE.
- When operating in unit-at-a-time, a new callgraph node is added to
- CGRAPH_EXPAND_QUEUE, which is processed after all the original
- functions in the call graph .
+ The function is assumed to be reachable and have address taken (so no
+ API breaking optimizations are performed on it).
- When not in unit-at-a-time, the new callgraph node is added to
- CGRAPH_NODES_QUEUE for cgraph_assemble_pending_functions to
- process. */
+ Main work done by this function is to enqueue the function for later
+ processing to avoid need the passes to be re-entrant. */
void
-cgraph_add_new_function (tree fndecl)
+cgraph_add_new_function (tree fndecl, bool lowered)
{
- struct cgraph_node *n = cgraph_node (fndecl);
- n->next_needed = cgraph_expand_queue;
- cgraph_expand_queue = n;
+ struct cgraph_node *node;
+ switch (cgraph_state)
+ {
+ case CGRAPH_STATE_CONSTRUCTION:
+ /* Just enqueue function to be processed at nearest occurence. */
+ node = cgraph_node (fndecl);
+ node->next_needed = cgraph_new_nodes;
+ if (lowered)
+ node->lowered = true;
+ cgraph_new_nodes = node;
+ break;
+
+ case CGRAPH_STATE_IPA:
+ case CGRAPH_STATE_EXPANSION:
+ /* Bring the function into finalized state and enqueue for later
+ analyzing and compilation. */
+ node = cgraph_node (fndecl);
+ node->local.local = false;
+ node->local.finalized = true;
+ node->reachable = node->needed = true;
+ if (lowered)
+ node->lowered = true;
+ node->next_needed = cgraph_new_nodes;
+ cgraph_new_nodes = node;
+ break;
+
+ case CGRAPH_STATE_FINISHED:
+ /* At the very end of compilation we have to do all the work up
+ to expansion. */
+ push_cfun (DECL_STRUCT_FUNCTION (fndecl));
+ current_function_decl = fndecl;
+ tree_register_cfg_hooks ();
+ if (!lowered)
+ tree_lowering_passes (fndecl);
+ tree_rest_of_compilation (fndecl);
+ pop_cfun ();
+ current_function_decl = NULL;
+ break;
+ }
}
#include "gt-cgraph.h"
diff --git a/gcc/cgraph.h b/gcc/cgraph.h
index 8d4fe750b05..e363819f166 100644
--- a/gcc/cgraph.h
+++ b/gcc/cgraph.h
@@ -254,9 +254,21 @@ extern GTY(()) struct cgraph_node *cgraph_nodes;
extern GTY(()) int cgraph_n_nodes;
extern GTY(()) int cgraph_max_uid;
extern bool cgraph_global_info_ready;
+enum cgraph_state
+{
+ /* Callgraph is being constructed. It is safe to add new functions. */
+ CGRAPH_STATE_CONSTRUCTION,
+ /* Callgraph is built and IPA passes are being run. */
+ CGRAPH_STATE_IPA,
+ /* Functions are now ordered and being passed to RTL expanders. */
+ CGRAPH_STATE_EXPANSION,
+ /* All cgraph expansion is done. */
+ CGRAPH_STATE_FINISHED
+};
+extern enum cgraph_state cgraph_state;
extern bool cgraph_function_flags_ready;
extern GTY(()) struct cgraph_node *cgraph_nodes_queue;
-extern GTY(()) struct cgraph_node *cgraph_expand_queue;
+extern GTY(()) struct cgraph_node *cgraph_new_nodes;
extern GTY(()) struct cgraph_asm_node *cgraph_asm_nodes;
extern GTY(()) int cgraph_order;
@@ -295,7 +307,7 @@ void cgraph_unnest_node (struct cgraph_node *);
enum availability cgraph_function_body_availability (struct cgraph_node *);
bool cgraph_is_master_clone (struct cgraph_node *);
struct cgraph_node *cgraph_master_clone (struct cgraph_node *);
-void cgraph_add_new_function (tree);
+void cgraph_add_new_function (tree, bool);
/* In cgraphunit.c */
void cgraph_finalize_function (tree, bool);
@@ -316,6 +328,7 @@ struct cgraph_node *cgraph_function_versioning (struct cgraph_node *,
void cgraph_analyze_function (struct cgraph_node *);
struct cgraph_node *save_inline_function_body (struct cgraph_node *);
void record_references_in_initializer (tree);
+bool cgraph_process_new_functions (void);
/* In ipa.c */
bool cgraph_remove_unreachable_nodes (bool, FILE *);
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 578b36c1983..0aa9f7de124 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -167,6 +167,7 @@ static void cgraph_expand_function (struct cgraph_node *);
static tree record_reference (tree *, int *, void *);
static void cgraph_output_pending_asms (void);
static void cgraph_increase_alignment (void);
+static void initialize_inline_failed (struct cgraph_node *);
/* Records tree nodes seen in record_reference. Simply using
walk_tree_without_duplicates doesn't guarantee each node is visited
@@ -262,6 +263,77 @@ decide_is_function_needed (struct cgraph_node *node, tree decl)
return false;
}
+/* Process CGRAPH_NEW_FUNCTIONS and perform actions neccesary to add these
+ functions into callgraph in a way so they look like ordinary reachable
+ functions inserted into callgraph already at construction time. */
+
+bool
+cgraph_process_new_functions (void)
+{
+ bool output = false;
+ tree fndecl;
+ struct cgraph_node *node;
+
+ /* Note that this queue may grow as its being processed, as the new
+ functions may generate new ones. */
+ while (cgraph_new_nodes)
+ {
+ node = cgraph_new_nodes;
+ fndecl = node->decl;
+ cgraph_new_nodes = cgraph_new_nodes->next_needed;
+ switch (cgraph_state)
+ {
+ case CGRAPH_STATE_CONSTRUCTION:
+ /* At construction time we just need to finalize function and move
+ it into reachable functions list. */
+
+ node->next_needed = NULL;
+ cgraph_finalize_function (fndecl, false);
+ cgraph_mark_reachable_node (node);
+ output = true;
+ break;
+
+ case CGRAPH_STATE_IPA:
+ /* When IPA optimization already started, do all essential
+ transformations that has been already performed on the whole
+ cgraph but not on this function. */
+
+ tree_register_cfg_hooks ();
+ if (!node->analyzed)
+ cgraph_analyze_function (node);
+ push_cfun (DECL_STRUCT_FUNCTION (fndecl));
+ current_function_decl = fndecl;
+ node->local.inlinable = tree_inlinable_function_p (fndecl);
+ node->local.self_insns = estimate_num_insns (fndecl);
+ node->local.disregard_inline_limits
+ = lang_hooks.tree_inlining.disregard_inline_limits (fndecl);
+ /* Inlining characteristics are maintained by the
+ cgraph_mark_inline. */
+ node->global.insns = node->local.self_insns;
+ initialize_inline_failed (node);
+ if (flag_really_no_inline && !node->local.disregard_inline_limits)
+ node->local.inlinable = 0;
+ free_dominance_info (CDI_POST_DOMINATORS);
+ free_dominance_info (CDI_DOMINATORS);
+ pop_cfun ();
+ current_function_decl = NULL;
+ break;
+
+ case CGRAPH_STATE_EXPANSION:
+ /* Functions created during expansion shall be compiled
+ directly. */
+ node->output = 0;
+ cgraph_expand_function (node);
+ break;
+
+ default:
+ gcc_unreachable ();
+ break;
+ }
+ }
+ return output;
+}
+
/* When not doing unit-at-a-time, output all functions enqueued.
Return true when such a functions were found. */
@@ -288,18 +360,7 @@ cgraph_assemble_pending_functions (void)
cgraph_expand_function (n);
output = true;
}
- }
-
- /* Process CGRAPH_EXPAND_QUEUE, these are functions created during
- the expansion process. Note that this queue may grow as its
- being processed, as the new functions may generate new ones. */
- while (cgraph_expand_queue)
- {
- struct cgraph_node *n = cgraph_expand_queue;
- cgraph_expand_queue = cgraph_expand_queue->next_needed;
- n->next_needed = NULL;
- cgraph_finalize_function (n->decl, false);
- output = true;
+ output |= cgraph_process_new_functions ();
}
return output;
@@ -1161,21 +1222,10 @@ cgraph_expand_all_functions (void)
cgraph_expand_function (node);
}
}
+ cgraph_process_new_functions ();
free (order);
- /* Process CGRAPH_EXPAND_QUEUE, these are functions created during
- the expansion process. Note that this queue may grow as its
- being processed, as the new functions may generate new ones. */
- while (cgraph_expand_queue)
- {
- node = cgraph_expand_queue;
- cgraph_expand_queue = cgraph_expand_queue->next_needed;
- node->next_needed = NULL;
- node->output = 0;
- node->lowered = DECL_STRUCT_FUNCTION (node->decl)->cfg != NULL;
- cgraph_expand_function (node);
- }
}
/* This is used to sort the node types by the cgraph order number. */
@@ -1383,6 +1433,9 @@ cgraph_optimize (void)
#endif
if (!flag_unit_at_a_time)
{
+ cgraph_assemble_pending_functions ();
+ cgraph_process_new_functions ();
+ cgraph_state = CGRAPH_STATE_FINISHED;
cgraph_output_pending_asms ();
varpool_assemble_pending_decls ();
varpool_output_debug_info ();
@@ -1408,6 +1461,7 @@ cgraph_optimize (void)
fprintf (cgraph_dump_file, "Marked ");
dump_cgraph (cgraph_dump_file);
}
+ cgraph_state = CGRAPH_STATE_IPA;
/* Don't run the IPA passes if there was any error or sorry messages. */
if (errorcount == 0 && sorrycount == 0)
@@ -1440,6 +1494,7 @@ cgraph_optimize (void)
cgraph_mark_functions_to_output ();
+ cgraph_state = CGRAPH_STATE_EXPANSION;
if (!flag_toplevel_reorder)
cgraph_output_in_order ();
else
@@ -1452,6 +1507,8 @@ cgraph_optimize (void)
varpool_assemble_pending_decls ();
varpool_output_debug_info ();
}
+ cgraph_process_new_functions ();
+ cgraph_state = CGRAPH_STATE_FINISHED;
if (cgraph_dump_file)
{
@@ -1581,14 +1638,8 @@ cgraph_build_static_cdtor (char which, tree body, int priority)
gimplify_function_tree (decl);
- /* ??? We will get called LATE in the compilation process. */
- if (cgraph_global_info_ready)
- {
- tree_lowering_passes (decl);
- tree_rest_of_compilation (decl);
- }
- else
- cgraph_finalize_function (decl, 0);
+ cgraph_add_new_function (decl, false);
+ cgraph_mark_needed_node (cgraph_node (decl));
if (targetm.have_ctors_dtors)
{
diff --git a/gcc/omp-low.c b/gcc/omp-low.c
index f3f4113b98c..e863568d5c4 100644
--- a/gcc/omp-low.c
+++ b/gcc/omp-low.c
@@ -2533,7 +2533,7 @@ expand_omp_parallel (struct omp_region *region)
single_succ_edge (new_bb)->flags = EDGE_FALLTHRU;
DECL_STRUCT_FUNCTION (child_fn)->curr_properties
= cfun->curr_properties;
- cgraph_add_new_function (child_fn);
+ cgraph_add_new_function (child_fn, true);
/* Convert OMP_RETURN into a RETURN_EXPR. */
if (exit_bb)
diff --git a/gcc/passes.c b/gcc/passes.c
index 38c95cdaf2b..458842163bc 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -947,6 +947,9 @@ execute_one_pass (struct tree_opt_pass *pass)
/* Run post-pass cleanup and verification. */
execute_todo (todo_after | pass->todo_flags_finish);
+ if (!current_function_decl)
+ cgraph_process_new_functions ();
+
/* Flush and close dump file. */
if (dump_file_name)
{
@@ -986,6 +989,8 @@ execute_ipa_pass_list (struct tree_opt_pass *pass)
gcc_assert (!cfun);
if (execute_one_pass (pass) && pass->sub)
do_per_function ((void (*)(void *))execute_pass_list, pass->sub);
+ if (!current_function_decl)
+ cgraph_process_new_functions ();
pass = pass->next;
}
while (pass);