diff options
author | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-12-30 11:58:01 +0000 |
---|---|---|
committer | hubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4> | 2006-12-30 11:58:01 +0000 |
commit | 523c1122434af355049edacf489e8da82ee7709d (patch) | |
tree | 4ee7560469c1e50ca7f51f6e50bca995ec5871a0 | |
parent | 311a2fe08784f5d009281ab401fe4f143d4c2825 (diff) | |
download | gcc-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/ChangeLog | 20 | ||||
-rw-r--r-- | gcc/cgraph.c | 68 | ||||
-rw-r--r-- | gcc/cgraph.h | 17 | ||||
-rw-r--r-- | gcc/cgraphunit.c | 115 | ||||
-rw-r--r-- | gcc/omp-low.c | 2 | ||||
-rw-r--r-- | gcc/passes.c | 5 |
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); |