This avoids all the complex work on simple things like clear_last_verified. It also makes eventually inlining all calls (for example the one with the small IPA pass hack) less code-duplicating.
I had to remove the asserts in favor of frees of DOM info in release_function_body as the old code released DOM info in various odd places. Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. Honza, does this look ok to you? Thanks, Richard. 2014-04-23 Richard Biener <rguent...@suse.de> * tree-pass.h (execute_pass_list): Adjust prototype. * passes.c (pass_manager::execute_early_local_passes): Adjust. (do_per_function): Change callback signature, push all actual work to the callbals. (do_per_function_toporder): Likewise. (execute_function_dump): Adjust. (execute_function_todo): Likewise. (clear_last_verified): Likewise. (verify_curr_properties): Likewise. (update_properties_after_pass): Likewise. (apply_ipa_transforms): Likewise. (execute_pass_list_1): Split out from ... (execute_pass_list): ... here. Adjust. (execute_ipa_pass_list): Likewise. * cgraphunit.c (cgraph_add_new_function): Adjust. (analyze_function): Likewise. (expand_function): Likewise. * cgraph.c (release_function_body): Free dominance info here instead of asserting it was magically freed elsewhere. Index: gcc/tree-pass.h =================================================================== *** gcc/tree-pass.h.orig 2014-04-23 14:55:25.640624814 +0200 --- gcc/tree-pass.h 2014-04-23 15:40:56.443436802 +0200 *************** extern gimple_opt_pass *make_pass_conver *** 587,593 **** extern opt_pass *current_pass; extern bool execute_one_pass (opt_pass *); ! extern void execute_pass_list (opt_pass *); extern void execute_ipa_pass_list (opt_pass *); extern void execute_ipa_summary_passes (ipa_opt_pass_d *); extern void execute_all_ipa_transforms (void); --- 587,593 ---- extern opt_pass *current_pass; extern bool execute_one_pass (opt_pass *); ! extern void execute_pass_list (function *, opt_pass *); extern void execute_ipa_pass_list (opt_pass *); extern void execute_ipa_summary_passes (ipa_opt_pass_d *); extern void execute_all_ipa_transforms (void); *************** extern bool function_called_by_processed *** 615,621 **** extern bool first_pass_instance; /* Declare for plugins. */ ! extern void do_per_function_toporder (void (*) (void *), void *); extern void disable_pass (const char *); extern void enable_pass (const char *); --- 615,621 ---- extern bool first_pass_instance; /* Declare for plugins. */ ! extern void do_per_function_toporder (void (*) (function *, void *), void *); extern void disable_pass (const char *); extern void enable_pass (const char *); Index: gcc/passes.c =================================================================== *** gcc/passes.c.orig 2014-04-23 14:55:25.642624814 +0200 --- gcc/passes.c 2014-04-23 15:41:02.414436391 +0200 *************** opt_pass::opt_pass (const pass_data &dat *** 132,138 **** void pass_manager::execute_early_local_passes () { ! execute_pass_list (pass_early_local_passes_1->sub); } unsigned int --- 132,138 ---- void pass_manager::execute_early_local_passes () { ! execute_pass_list (cfun, pass_early_local_passes_1->sub); } unsigned int *************** pass_manager::pass_manager (context *ctx *** 1498,1524 **** call CALLBACK on the current function. */ static void ! do_per_function (void (*callback) (void *data), void *data) { if (current_function_decl) ! callback (data); else { struct cgraph_node *node; FOR_EACH_DEFINED_FUNCTION (node) if (node->analyzed && gimple_has_body_p (node->decl) && (!node->clone_of || node->decl != node->clone_of->decl)) ! { ! push_cfun (DECL_STRUCT_FUNCTION (node->decl)); ! callback (data); ! if (!flag_wpa) ! { ! free_dominance_info (CDI_DOMINATORS); ! free_dominance_info (CDI_POST_DOMINATORS); ! } ! pop_cfun (); ! ggc_collect (); ! } } } --- 1498,1514 ---- call CALLBACK on the current function. */ static void ! do_per_function (void (*callback) (function *, void *data), void *data) { if (current_function_decl) ! callback (cfun, data); else { struct cgraph_node *node; FOR_EACH_DEFINED_FUNCTION (node) if (node->analyzed && gimple_has_body_p (node->decl) && (!node->clone_of || node->decl != node->clone_of->decl)) ! callback (DECL_STRUCT_FUNCTION (node->decl), data); } } *************** static GTY ((length ("nnodes"))) cgraph_ *** 1533,1544 **** call CALLBACK on the current function. This function is global so that plugins can use it. */ void ! do_per_function_toporder (void (*callback) (void *data), void *data) { int i; if (current_function_decl) ! callback (data); else { gcc_assert (!order); --- 1523,1534 ---- call CALLBACK on the current function. This function is global so that plugins can use it. */ void ! do_per_function_toporder (void (*callback) (function *, void *data), void *data) { int i; if (current_function_decl) ! callback (cfun, data); else { gcc_assert (!order); *************** do_per_function_toporder (void (*callbac *** 1554,1568 **** order[i] = NULL; node->process = 0; if (cgraph_function_with_gimple_body_p (node)) ! { ! cgraph_get_body (node); ! push_cfun (DECL_STRUCT_FUNCTION (node->decl)); ! callback (data); ! free_dominance_info (CDI_DOMINATORS); ! free_dominance_info (CDI_POST_DOMINATORS); ! pop_cfun (); ! ggc_collect (); ! } } } ggc_free (order); --- 1544,1550 ---- order[i] = NULL; node->process = 0; if (cgraph_function_with_gimple_body_p (node)) ! callback (DECL_STRUCT_FUNCTION (node->decl), data); } } ggc_free (order); *************** do_per_function_toporder (void (*callbac *** 1573,1586 **** /* Helper function to perform function body dump. */ static void ! execute_function_dump (void *data) { opt_pass *pass = (opt_pass *)data; ! if (dump_file && current_function_decl) { ! if (cfun->curr_properties & PROP_trees) ! dump_function_to_file (current_function_decl, dump_file, dump_flags); else print_rtl_with_bb (dump_file, get_insns (), dump_flags); --- 1555,1570 ---- /* Helper function to perform function body dump. */ static void ! execute_function_dump (function *fn, void *data) { opt_pass *pass = (opt_pass *)data; ! if (dump_file) { ! push_cfun (fn); ! ! if (fn->curr_properties & PROP_trees) ! dump_function_to_file (fn->decl, dump_file, dump_flags); else print_rtl_with_bb (dump_file, get_insns (), dump_flags); *************** execute_function_dump (void *data) *** 1588,1594 **** close the file before aborting. */ fflush (dump_file); ! if ((cfun->curr_properties & PROP_cfg) && (dump_flags & TDF_GRAPH)) { if (!pass->graph_dump_initialized) --- 1572,1578 ---- close the file before aborting. */ fflush (dump_file); ! if ((fn->curr_properties & PROP_cfg) && (dump_flags & TDF_GRAPH)) { if (!pass->graph_dump_initialized) *************** execute_function_dump (void *data) *** 1596,1603 **** clean_graph_dump_file (dump_file_name); pass->graph_dump_initialized = true; } ! print_graph_cfg (dump_file_name, cfun); } } } --- 1580,1589 ---- clean_graph_dump_file (dump_file_name); pass->graph_dump_initialized = true; } ! print_graph_cfg (dump_file_name, fn); } + + pop_cfun (); } } *************** pass_manager::dump_profile_report () con *** 1728,1740 **** /* Perform all TODO actions that ought to be done on each function. */ static void ! execute_function_todo (void *data) { unsigned int flags = (size_t)data; ! flags &= ~cfun->last_verified; if (!flags) return; /* Always cleanup the CFG before trying to update SSA. */ if (flags & TODO_cleanup_cfg) { --- 1714,1728 ---- /* Perform all TODO actions that ought to be done on each function. */ static void ! execute_function_todo (function *fn, void *data) { unsigned int flags = (size_t)data; ! flags &= ~fn->last_verified; if (!flags) return; + push_cfun (fn); + /* Always cleanup the CFG before trying to update SSA. */ if (flags & TODO_cleanup_cfg) { *************** execute_function_todo (void *data) *** 1774,1780 **** /* If we've seen errors do not bother running any verifiers. */ if (seen_error ()) ! return; #if defined ENABLE_CHECKING if (flags & TODO_verify_ssa --- 1762,1771 ---- /* If we've seen errors do not bother running any verifiers. */ if (seen_error ()) ! { ! pop_cfun (); ! return; ! } #if defined ENABLE_CHECKING if (flags & TODO_verify_ssa *************** execute_function_todo (void *data) *** 1793,1799 **** verify_rtl_sharing (); #endif ! cfun->last_verified = flags & TODO_verify_all; } /* Perform all TODO actions. */ --- 1784,1792 ---- verify_rtl_sharing (); #endif ! fn->last_verified = flags & TODO_verify_all; ! ! pop_cfun (); } /* Perform all TODO actions. */ *************** verify_interpass_invariants (void) *** 1855,1863 **** /* Clear the last verified flag. */ static void ! clear_last_verified (void *data ATTRIBUTE_UNUSED) { ! cfun->last_verified = 0; } /* Helper function. Verify that the properties has been turn into the --- 1848,1856 ---- /* Clear the last verified flag. */ static void ! clear_last_verified (function *fn, void *data ATTRIBUTE_UNUSED) { ! fn->last_verified = 0; } /* Helper function. Verify that the properties has been turn into the *************** clear_last_verified (void *data ATTRIBUT *** 1865,1874 **** #ifdef ENABLE_CHECKING static void ! verify_curr_properties (void *data) { unsigned int props = (size_t)data; ! gcc_assert ((cfun->curr_properties & props) == props); } #endif --- 1858,1867 ---- #ifdef ENABLE_CHECKING static void ! verify_curr_properties (function *fn, void *data) { unsigned int props = (size_t)data; ! gcc_assert ((fn->curr_properties & props) == props); } #endif *************** pass_fini_dump_file (opt_pass *pass) *** 1927,1937 **** properties. */ static void ! update_properties_after_pass (void *data) { opt_pass *pass = (opt_pass *) data; ! cfun->curr_properties = (cfun->curr_properties | pass->properties_provided) ! & ~pass->properties_destroyed; } /* Execute summary generation for all of the passes in IPA_PASS. */ --- 1920,1930 ---- properties. */ static void ! update_properties_after_pass (function *fn, void *data) { opt_pass *pass = (opt_pass *) data; ! fn->curr_properties = (fn->curr_properties | pass->properties_provided) ! & ~pass->properties_destroyed; } /* Execute summary generation for all of the passes in IPA_PASS. */ *************** execute_all_ipa_transforms (void) *** 2042,2055 **** /* Callback for do_per_function to apply all IPA transforms. */ static void ! apply_ipa_transforms (void *data) { ! struct cgraph_node *node = cgraph_get_node (current_function_decl); if (!node->global.inlined_to && node->ipa_transforms_to_apply.exists ()) { *(bool *)data = true; execute_all_ipa_transforms (); rebuild_cgraph_edges (); } } --- 2035,2053 ---- /* Callback for do_per_function to apply all IPA transforms. */ static void ! apply_ipa_transforms (function *fn, void *data) { ! struct cgraph_node *node = cgraph_get_node (fn->decl); if (!node->global.inlined_to && node->ipa_transforms_to_apply.exists ()) { + push_cfun (fn); *(bool *)data = true; execute_all_ipa_transforms (); rebuild_cgraph_edges (); + free_dominance_info (CDI_DOMINATORS); + free_dominance_info (CDI_POST_DOMINATORS); + pop_cfun (); + ggc_collect (); } } *************** execute_one_pass (opt_pass *pass) *** 2202,2221 **** return true; } ! void ! execute_pass_list (opt_pass *pass) { do { gcc_assert (pass->type == GIMPLE_PASS || pass->type == RTL_PASS); if (execute_one_pass (pass) && pass->sub) ! execute_pass_list (pass->sub); pass = pass->next; } while (pass); } /* Write out all LTO data. */ static void write_lto (void) --- 2200,2232 ---- return true; } ! static void ! execute_pass_list_1 (opt_pass *pass) { do { gcc_assert (pass->type == GIMPLE_PASS || pass->type == RTL_PASS); if (execute_one_pass (pass) && pass->sub) ! execute_pass_list_1 (pass->sub); pass = pass->next; } while (pass); } + void + execute_pass_list (function *fn, opt_pass *pass) + { + push_cfun (fn); + execute_pass_list_1 (pass); + if (fn->cfg) + { + free_dominance_info (CDI_DOMINATORS); + free_dominance_info (CDI_POST_DOMINATORS); + } + pop_cfun (); + } + /* Write out all LTO data. */ static void write_lto (void) *************** execute_ipa_pass_list (opt_pass *pass) *** 2539,2545 **** if (pass->sub->type == GIMPLE_PASS) { invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL); ! do_per_function_toporder ((void (*)(void *))execute_pass_list, pass->sub); invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL); } --- 2550,2557 ---- if (pass->sub->type == GIMPLE_PASS) { invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_START, NULL); ! do_per_function_toporder ((void (*)(function *, void *)) ! execute_pass_list, pass->sub); invoke_plugin_callbacks (PLUGIN_EARLY_GIMPLE_PASSES_END, NULL); } Index: gcc/cgraphunit.c =================================================================== *** gcc/cgraphunit.c.orig 2014-04-23 14:56:40.528619658 +0200 --- gcc/cgraphunit.c 2014-04-23 15:00:28.173603985 +0200 *************** cgraph_add_new_function (tree fndecl, bo *** 520,526 **** push_cfun (DECL_STRUCT_FUNCTION (fndecl)); gimple_register_cfg_hooks (); bitmap_obstack_initialize (NULL); ! execute_pass_list (passes->all_lowering_passes); passes->execute_early_local_passes (); bitmap_obstack_release (NULL); pop_cfun (); --- 520,526 ---- push_cfun (DECL_STRUCT_FUNCTION (fndecl)); gimple_register_cfg_hooks (); bitmap_obstack_initialize (NULL); ! execute_pass_list (cfun, passes->all_lowering_passes); passes->execute_early_local_passes (); bitmap_obstack_release (NULL); pop_cfun (); *************** analyze_function (struct cgraph_node *no *** 658,664 **** gimple_register_cfg_hooks (); bitmap_obstack_initialize (NULL); ! execute_pass_list (g->get_passes ()->all_lowering_passes); free_dominance_info (CDI_POST_DOMINATORS); free_dominance_info (CDI_DOMINATORS); compact_blocks (); --- 658,664 ---- gimple_register_cfg_hooks (); bitmap_obstack_initialize (NULL); ! execute_pass_list (cfun, g->get_passes ()->all_lowering_passes); free_dominance_info (CDI_POST_DOMINATORS); free_dominance_info (CDI_DOMINATORS); compact_blocks (); *************** expand_function (struct cgraph_node *nod *** 1771,1777 **** /* Signal the start of passes. */ invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL); ! execute_pass_list (g->get_passes ()->all_passes); /* Signal the end of passes. */ invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL); --- 1771,1777 ---- /* Signal the start of passes. */ invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL); ! execute_pass_list (cfun, g->get_passes ()->all_passes); /* Signal the end of passes. */ invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL); Index: gcc/cgraph.c =================================================================== *** gcc/cgraph.c.orig 2014-04-23 15:10:15.332563560 +0200 --- gcc/cgraph.c 2014-04-23 15:10:22.548563063 +0200 *************** release_function_body (tree decl) *** 1696,1703 **** } if (cfun->cfg) { ! gcc_assert (dom_computed[0] == DOM_NONE); ! gcc_assert (dom_computed[1] == DOM_NONE); clear_edges (); cfun->cfg = NULL; } --- 1696,1703 ---- } if (cfun->cfg) { ! free_dominance_info (CDI_DOMINATORS); ! free_dominance_info (CDI_POST_DOMINATORS); clear_edges (); cfun->cfg = NULL; }