Hi, the following pathch has been actually already committed to trunk by Martin yesterday, but is necessary if you have an older trunk. It allows an optimization pass to declare the functon finished by returning TODO_discard_function. The pass manager will then discard the function.
Martin 2015-11-04 Martin Liska <mli...@suse.cz> * cgraphunit.c (cgraph_node::expand_thunk): Call allocate_struct_function before init_function_start. (cgraph_node::expand): Use push_cfun and pop_cfun. * config/i386/i386.c (ix86_code_end): Call allocate_struct_function before init_function_start. * config/rs6000/rs6000.c (rs6000_code_end): Likewise. * function.c (init_function_start): Move preamble to all callers. * passes.c (do_per_function_toporder): Use push_cfun and pop_cfun. (execute_one_pass): Handle newly added TODO_discard_function. (execute_pass_list_1): Terminate if cfun equals to NULL. (execute_pass_list): Do not push and pop cfun, expect that cfun is set. * tree-pass.h (TODO_discard_function): Define. diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 43d3185..f73d9a7 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -1618,6 +1618,7 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk) fn_block = make_node (BLOCK); BLOCK_VARS (fn_block) = a; DECL_INITIAL (thunk_fndecl) = fn_block; + allocate_struct_function (thunk_fndecl, false); init_function_start (thunk_fndecl); cfun->is_thunk = 1; insn_locations_init (); @@ -1632,7 +1633,6 @@ cgraph_node::expand_thunk (bool output_asm_thunks, bool force_gimple_thunk) insn_locations_finalize (); init_insn_lengths (); free_after_compilation (cfun); - set_cfun (NULL); TREE_ASM_WRITTEN (thunk_fndecl) = 1; thunk.thunk_p = false; analyzed = false; @@ -1944,9 +1944,11 @@ cgraph_node::expand (void) bitmap_obstack_initialize (NULL); /* Initialize the RTL code for the function. */ - current_function_decl = decl; saved_loc = input_location; input_location = DECL_SOURCE_LOCATION (decl); + + gcc_assert (DECL_STRUCT_FUNCTION (decl)); + push_cfun (DECL_STRUCT_FUNCTION (decl)); init_function_start (decl); gimple_register_cfg_hooks (); @@ -2014,8 +2016,8 @@ cgraph_node::expand (void) /* Make sure that BE didn't give up on compiling. */ gcc_assert (TREE_ASM_WRITTEN (decl)); - set_cfun (NULL); - current_function_decl = NULL; + if (cfun) + pop_cfun (); /* It would make a lot more sense to output thunks before function body to get more forward and lest backwarding jumps. This however would need solving problem diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 66024e2..2a965f6 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -10958,6 +10958,7 @@ ix86_code_end (void) DECL_INITIAL (decl) = make_node (BLOCK); current_function_decl = decl; + allocate_struct_function (decl, false); init_function_start (decl); first_function_block_is_cold = false; /* Make sure unwind info is emitted for the thunk if needed. */ diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 271c3f9..8bdd646 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -34594,6 +34594,7 @@ rs6000_code_end (void) DECL_INITIAL (decl) = make_node (BLOCK); current_function_decl = decl; + allocate_struct_function (decl, false); init_function_start (decl); first_function_block_is_cold = false; /* Make sure unwind info is emitted for the thunk if needed. */ diff --git a/gcc/function.c b/gcc/function.c index aaf49a4..0d7cabc 100644 --- a/gcc/function.c +++ b/gcc/function.c @@ -4957,11 +4957,6 @@ init_dummy_function_start (void) void init_function_start (tree subr) { - if (subr && DECL_STRUCT_FUNCTION (subr)) - set_cfun (DECL_STRUCT_FUNCTION (subr)); - else - allocate_struct_function (subr, false); - /* Initialize backend, if needed. */ initialize_rtl (); diff --git a/gcc/passes.c b/gcc/passes.c index f87dcf4..08221ed 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -1706,7 +1706,12 @@ do_per_function_toporder (void (*callback) (function *, void *data), void *data) order[i] = NULL; node->process = 0; if (node->has_gimple_body_p ()) - callback (DECL_STRUCT_FUNCTION (node->decl), data); + { + struct function *fn = DECL_STRUCT_FUNCTION (node->decl); + push_cfun (fn); + callback (fn, data); + pop_cfun (); + } } symtab->remove_cgraph_removal_hook (hook); } @@ -2347,6 +2352,23 @@ execute_one_pass (opt_pass *pass) current_pass = NULL; + if (todo_after & TODO_discard_function) + { + gcc_assert (cfun); + /* As cgraph_node::release_body expects release dominators info, + we have to release it. */ + if (dom_info_available_p (CDI_DOMINATORS)) + free_dominance_info (CDI_DOMINATORS); + + if (dom_info_available_p (CDI_POST_DOMINATORS)) + free_dominance_info (CDI_POST_DOMINATORS); + + tree fn = cfun->decl; + pop_cfun (); + gcc_assert (!cfun); + cgraph_node::get (fn)->release_body (); + } + /* Signal this is a suitable GC collection point. */ if (!((todo_after | pass->todo_flags_finish) & TODO_do_not_ggc_collect)) ggc_collect (); @@ -2361,8 +2383,12 @@ execute_pass_list_1 (opt_pass *pass) { gcc_assert (pass->type == GIMPLE_PASS || pass->type == RTL_PASS); + + if (cfun == NULL) + return; if (execute_one_pass (pass) && pass->sub) - execute_pass_list_1 (pass->sub); + execute_pass_list_1 (pass->sub); + pass = pass->next; } while (pass); @@ -2371,14 +2397,13 @@ execute_pass_list_1 (opt_pass *pass) void execute_pass_list (function *fn, opt_pass *pass) { - push_cfun (fn); + gcc_assert (fn == cfun); execute_pass_list_1 (pass); - if (fn->cfg) + if (cfun && fn->cfg) { free_dominance_info (CDI_DOMINATORS); free_dominance_info (CDI_POST_DOMINATORS); } - pop_cfun (); } /* Write out all LTO data. */ diff --git a/gcc/passes.def b/gcc/passes.def index c0ab6b9..27b43df 100644 --- a/gcc/passes.def +++ b/gcc/passes.def @@ -125,6 +125,7 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_ipa_cp); NEXT_PASS (pass_ipa_cdtor_merge); NEXT_PASS (pass_target_clone); + NEXT_PASS (pass_ipa_hsa); NEXT_PASS (pass_ipa_inline); NEXT_PASS (pass_ipa_pure_const); NEXT_PASS (pass_ipa_reference); @@ -357,6 +358,7 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_nrv); NEXT_PASS (pass_cleanup_cfg_post_optimizing); NEXT_PASS (pass_warn_function_noreturn); + NEXT_PASS (pass_gen_hsail); NEXT_PASS (pass_expand); diff --git a/gcc/timevar.def b/gcc/timevar.def index b429faf..6fdee0f 100644 --- a/gcc/timevar.def +++ b/gcc/timevar.def @@ -94,6 +94,7 @@ DEFTIMEVAR (TV_WHOPR_WPA_IO , "whopr wpa I/O") DEFTIMEVAR (TV_WHOPR_PARTITIONING , "whopr partitioning") DEFTIMEVAR (TV_WHOPR_LTRANS , "whopr ltrans") DEFTIMEVAR (TV_IPA_REFERENCE , "ipa reference") +DEFTIMEVAR (TV_IPA_HSA , "ipa HSA") DEFTIMEVAR (TV_IPA_PROFILE , "ipa profile") DEFTIMEVAR (TV_IPA_AUTOFDO , "auto profile") DEFTIMEVAR (TV_IPA_PURE_CONST , "ipa pure const") diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index ba53cca..713f068 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -300,6 +300,9 @@ protected: /* Rebuild the callgraph edges. */ #define TODO_rebuild_cgraph_edges (1 << 22) +/* Release function body and stop pass manager. */ +#define TODO_discard_function (1 << 23) + /* Internally used in execute_function_todo(). */ #define TODO_update_ssa_any \ (TODO_update_ssa \ @@ -460,6 +463,7 @@ extern gimple_opt_pass *make_pass_strength_reduction (gcc::context *ctxt); extern gimple_opt_pass *make_pass_vtable_verify (gcc::context *ctxt); extern gimple_opt_pass *make_pass_ubsan (gcc::context *ctxt); extern gimple_opt_pass *make_pass_sanopt (gcc::context *ctxt); +extern gimple_opt_pass *make_pass_gen_hsail (gcc::context *ctxt); /* IPA Passes */ extern simple_ipa_opt_pass *make_pass_ipa_lower_emutls (gcc::context *ctxt); @@ -484,6 +488,7 @@ extern ipa_opt_pass_d *make_pass_ipa_cp (gcc::context *ctxt); extern ipa_opt_pass_d *make_pass_ipa_icf (gcc::context *ctxt); extern ipa_opt_pass_d *make_pass_ipa_devirt (gcc::context *ctxt); extern ipa_opt_pass_d *make_pass_ipa_reference (gcc::context *ctxt); +extern ipa_opt_pass_d *make_pass_ipa_hsa (gcc::context *ctxt); extern ipa_opt_pass_d *make_pass_ipa_pure_const (gcc::context *ctxt); extern simple_ipa_opt_pass *make_pass_ipa_pta (gcc::context *ctxt); extern simple_ipa_opt_pass *make_pass_ipa_tm (gcc::context *ctxt);