Eventually I'll succeed in making tree-optimize.c empty. At least the pass stuff I'm interested in get's better now.
Bootstrapped on x86_64-unknown-linux-gnu, testing in progress. Richard. 2012-04-12 Richard Guenther <rguent...@suse.de> * Makefile.in (cgraphunit.o): Add $(EXCEPT_H) dependency. * cgraph.h (tree_rest_of_compilation): Remove. * cgraph.c (cgraph_add_new_function): Move ... * cgraphunit.c (cgraph_add_new_function): ... here. (tree_rest_of_compilation): Make static. (cgraph_expand_function): Do not set cgraph_function_flags_ready. * tree-optimize.c (gate_all_optimizations, pass_all_optimizations, gate_all_early_local_passes, execute_all_early_local_passes, pass_early_local_passes, gate_all_early_optimizations, pass_all_early_optimizations): Move ... * passes.c (gate_all_optimizations, pass_all_optimizations, gate_all_early_local_passes, execute_all_early_local_passes, pass_early_local_passes, gate_all_early_optimizations, pass_all_early_optimizations): ... here. * tree-optimize.c (execute_free_datastructures): Remove. * tree-flow.h (execute_free_datastructures): Remove. * tree-optimize.c (execute_init_datastructures, pass_init_datastructures): Move ... * tree-ssa.c (execute_init_datastructures, pass_init_datastructures): ... here. * cfgexpand.c (gimple_expand_cfg): Inline-expand call to execute_free_datastructures. Index: gcc/Makefile.in =================================================================== *** gcc/Makefile.in.orig 2012-04-12 14:05:23.000000000 +0200 --- gcc/Makefile.in 2012-04-12 14:05:51.274596925 +0200 *************** cgraphunit.o : cgraphunit.c $(CONFIG_H) *** 2922,2928 **** $(FIBHEAP_H) output.h $(PARAMS_H) $(RTL_H) $(TIMEVAR_H) $(IPA_PROP_H) \ gt-cgraphunit.h tree-iterator.h $(COVERAGE_H) $(TREE_DUMP_H) \ tree-pretty-print.h gimple-pretty-print.h ipa-inline.h $(IPA_UTILS_H) \ ! $(LTO_STREAMER_H) output.h $(REGSET_H) cgraphbuild.o : cgraphbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) langhooks.h $(CGRAPH_H) intl.h pointer-set.h $(GIMPLE_H) \ $(TREE_FLOW_H) $(TREE_PASS_H) $(IPA_UTILS_H) $(EXCEPT_H) \ --- 2922,2928 ---- $(FIBHEAP_H) output.h $(PARAMS_H) $(RTL_H) $(TIMEVAR_H) $(IPA_PROP_H) \ gt-cgraphunit.h tree-iterator.h $(COVERAGE_H) $(TREE_DUMP_H) \ tree-pretty-print.h gimple-pretty-print.h ipa-inline.h $(IPA_UTILS_H) \ ! $(LTO_STREAMER_H) output.h $(REGSET_H) $(EXCEPT_H) cgraphbuild.o : cgraphbuild.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \ $(TREE_H) langhooks.h $(CGRAPH_H) intl.h pointer-set.h $(GIMPLE_H) \ $(TREE_FLOW_H) $(TREE_PASS_H) $(IPA_UTILS_H) $(EXCEPT_H) \ Index: gcc/cgraph.c =================================================================== *** gcc/cgraph.c.orig 2012-04-12 14:05:23.000000000 +0200 --- gcc/cgraph.c 2012-04-12 14:05:51.276596925 +0200 *************** cgraph_function_body_availability (struc *** 2397,2485 **** return avail; } - /* 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. - - The function is assumed to be reachable and have address taken (so no - API breaking optimizations are performed on it). - - 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, bool lowered) - { - struct cgraph_node *node; - switch (cgraph_state) - { - case CGRAPH_STATE_CONSTRUCTION: - /* Just enqueue function to be processed at nearest occurrence. */ - node = cgraph_create_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_IPA_SSA: - case CGRAPH_STATE_EXPANSION: - /* Bring the function into finalized state and enqueue for later - analyzing and compilation. */ - node = cgraph_get_create_node (fndecl); - node->local.local = false; - node->local.finalized = true; - node->reachable = node->needed = true; - if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION) - { - push_cfun (DECL_STRUCT_FUNCTION (fndecl)); - current_function_decl = fndecl; - gimple_register_cfg_hooks (); - bitmap_obstack_initialize (NULL); - execute_pass_list (all_lowering_passes); - execute_pass_list (pass_early_local_passes.pass.sub); - bitmap_obstack_release (NULL); - pop_cfun (); - current_function_decl = NULL; - - lowered = 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. */ - node = cgraph_create_node (fndecl); - if (lowered) - node->lowered = true; - cgraph_analyze_function (node); - push_cfun (DECL_STRUCT_FUNCTION (fndecl)); - current_function_decl = fndecl; - gimple_register_cfg_hooks (); - bitmap_obstack_initialize (NULL); - if (!gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl))) - execute_pass_list (pass_early_local_passes.pass.sub); - bitmap_obstack_release (NULL); - tree_rest_of_compilation (node); - pop_cfun (); - current_function_decl = NULL; - break; - } - - /* Set a personality if required and we already passed EH lowering. */ - if (lowered - && (function_needs_eh_personality (DECL_STRUCT_FUNCTION (fndecl)) - == eh_personality_lang)) - DECL_FUNCTION_PERSONALITY (fndecl) = lang_hooks.eh_personality (); - } - /* Worker for cgraph_node_can_be_local_p. */ static bool cgraph_node_cannot_be_local_p_1 (struct cgraph_node *node, --- 2397,2402 ---- Index: gcc/cgraph.h =================================================================== *** gcc/cgraph.h.orig 2012-04-12 14:05:23.000000000 +0200 --- gcc/cgraph.h 2012-04-12 14:05:51.276596925 +0200 *************** void cgraph_mark_if_needed (tree); *** 583,589 **** void cgraph_analyze_function (struct cgraph_node *); void cgraph_finalize_compilation_unit (void); void cgraph_optimize (void); - void tree_rest_of_compilation (struct cgraph_node *); void cgraph_mark_needed_node (struct cgraph_node *); void cgraph_mark_address_taken_node (struct cgraph_node *); void cgraph_mark_reachable_node (struct cgraph_node *); --- 583,588 ---- Index: gcc/cgraphunit.c =================================================================== *** gcc/cgraphunit.c.orig 2012-04-12 14:05:23.000000000 +0200 --- gcc/cgraphunit.c 2012-04-12 14:05:51.278596925 +0200 *************** along with GCC; see the file COPYING3. *** 142,153 **** --- 142,155 ---- #include "ipa-inline.h" #include "ipa-utils.h" #include "lto-streamer.h" + #include "except.h" #include "regset.h" /* FIXME: For reg_obstack. */ static void cgraph_expand_all_functions (void); static void cgraph_mark_functions_to_output (void); static void cgraph_expand_function (struct cgraph_node *); static void cgraph_output_pending_asms (void); + static void tree_rest_of_compilation (struct cgraph_node *); FILE *cgraph_dump_file; *************** cgraph_finalize_function (tree decl, boo *** 365,370 **** --- 367,458 ---- ggc_collect (); } + /* 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. + + The function is assumed to be reachable and have address taken (so no + API breaking optimizations are performed on it). + + 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, bool lowered) + { + struct cgraph_node *node; + switch (cgraph_state) + { + case CGRAPH_STATE_CONSTRUCTION: + /* Just enqueue function to be processed at nearest occurrence. */ + node = cgraph_create_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_IPA_SSA: + case CGRAPH_STATE_EXPANSION: + /* Bring the function into finalized state and enqueue for later + analyzing and compilation. */ + node = cgraph_get_create_node (fndecl); + node->local.local = false; + node->local.finalized = true; + node->reachable = node->needed = true; + if (!lowered && cgraph_state == CGRAPH_STATE_EXPANSION) + { + push_cfun (DECL_STRUCT_FUNCTION (fndecl)); + current_function_decl = fndecl; + gimple_register_cfg_hooks (); + bitmap_obstack_initialize (NULL); + execute_pass_list (all_lowering_passes); + execute_pass_list (pass_early_local_passes.pass.sub); + bitmap_obstack_release (NULL); + pop_cfun (); + current_function_decl = NULL; + + lowered = 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. */ + node = cgraph_create_node (fndecl); + if (lowered) + node->lowered = true; + cgraph_analyze_function (node); + push_cfun (DECL_STRUCT_FUNCTION (fndecl)); + current_function_decl = fndecl; + gimple_register_cfg_hooks (); + bitmap_obstack_initialize (NULL); + if (!gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl))) + execute_pass_list (pass_early_local_passes.pass.sub); + bitmap_obstack_release (NULL); + tree_rest_of_compilation (node); + pop_cfun (); + current_function_decl = NULL; + break; + + default: + gcc_unreachable (); + } + + /* Set a personality if required and we already passed EH lowering. */ + if (lowered + && (function_needs_eh_personality (DECL_STRUCT_FUNCTION (fndecl)) + == eh_personality_lang)) + DECL_FUNCTION_PERSONALITY (fndecl) = lang_hooks.eh_personality (); + } + /* C99 extern inline keywords allow changing of declaration after function has been finalized. We need to re-decide if we want to mark the function as needed then. */ *************** assemble_thunks_and_aliases (struct cgra *** 1770,1779 **** } } ! /* For functions-as-trees languages, this performs all optimization and ! compilation for FNDECL. */ ! void tree_rest_of_compilation (struct cgraph_node *node) { tree fndecl = node->decl; --- 1858,1867 ---- } } ! /* Perform IPA transforms and all further optimizations and compilation ! for FNDECL. */ ! static void tree_rest_of_compilation (struct cgraph_node *node) { tree fndecl = node->decl; *************** cgraph_expand_function (struct cgraph_no *** 1891,1898 **** /* Eliminate all call edges. This is important so the GIMPLE_CALL no longer points to the dead function body. */ cgraph_node_remove_callees (node); - - cgraph_function_flags_ready = true; } /* Return true when CALLER_DECL should be inlined into CALLEE_DECL. */ --- 1979,1984 ---- Index: gcc/tree-optimize.c =================================================================== *** gcc/tree-optimize.c.orig 2012-04-12 14:05:23.000000000 +0200 --- gcc/tree-optimize.c 2012-04-12 14:09:43.267583066 +0200 *************** along with GCC; see the file COPYING3. *** 46,152 **** #include "except.h" #include "plugin.h" - /* Gate: execute, or not, all of the non-trivial optimizations. */ - - static bool - gate_all_optimizations (void) - { - return (optimize >= 1 - /* Don't bother doing anything if the program has errors. - We have to pass down the queue if we already went into SSA */ - && (!seen_error () || gimple_in_ssa_p (cfun))); - } - - struct gimple_opt_pass pass_all_optimizations = - { - { - GIMPLE_PASS, - "*all_optimizations", /* name */ - gate_all_optimizations, /* gate */ - NULL, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_OPTIMIZE, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0 /* todo_flags_finish */ - } - }; - - /* Gate: execute, or not, all of the non-trivial optimizations. */ - - static bool - gate_all_early_local_passes (void) - { - /* Don't bother doing anything if the program has errors. */ - return (!seen_error () && !in_lto_p); - } - - static unsigned int - execute_all_early_local_passes (void) - { - /* Once this pass (and its sub-passes) are complete, all functions - will be in SSA form. Technically this state change is happening - a tad early, since the sub-passes have not yet run, but since - none of the sub-passes are IPA passes and do not create new - functions, this is ok. We're setting this value for the benefit - of IPA passes that follow. */ - if (cgraph_state < CGRAPH_STATE_IPA_SSA) - cgraph_state = CGRAPH_STATE_IPA_SSA; - return 0; - } - - struct simple_ipa_opt_pass pass_early_local_passes = - { - { - SIMPLE_IPA_PASS, - "early_local_cleanups", /* name */ - gate_all_early_local_passes, /* gate */ - execute_all_early_local_passes, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_EARLY_LOCAL, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - TODO_remove_functions /* todo_flags_finish */ - } - }; - - /* Gate: execute, or not, all of the non-trivial optimizations. */ - - static bool - gate_all_early_optimizations (void) - { - return (optimize >= 1 - /* Don't bother doing anything if the program has errors. */ - && !seen_error ()); - } - - struct gimple_opt_pass pass_all_early_optimizations = - { - { - GIMPLE_PASS, - "early_optimizations", /* name */ - gate_all_early_optimizations, /* gate */ - NULL, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ - TV_NONE, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0 /* todo_flags_finish */ - } - }; - /* Pass: cleanup the CFG just before expanding trees to RTL. This is just a round of label cleanups and case node grouping --- 46,51 ---- *************** struct gimple_opt_pass pass_cleanup_cfg_ *** 213,233 **** } }; - /* Pass: do the actions required to finish with tree-ssa optimization - passes. */ - - unsigned int - execute_free_datastructures (void) - { - free_dominance_info (CDI_DOMINATORS); - free_dominance_info (CDI_POST_DOMINATORS); - - /* And get rid of annotations we no longer need. */ - delete_tree_cfg_annotations (); - - return 0; - } - /* IPA passes, compilation of earlier functions or inlining might have changed some properties, such as marked functions nothrow, pure, const or noreturn. --- 112,117 ---- *************** struct gimple_opt_pass pass_fixup_cfg = *** 327,362 **** NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ - TV_NONE, /* tv_id */ - PROP_cfg, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0 /* todo_flags_finish */ - } - }; - - /* Do the actions required to initialize internal data structures used - in tree-ssa optimization passes. */ - - static unsigned int - execute_init_datastructures (void) - { - /* Allocate hash tables, arrays and other structures. */ - init_tree_ssa (cfun); - return 0; - } - - struct gimple_opt_pass pass_init_datastructures = - { - { - GIMPLE_PASS, - "*init_datastructures", /* name */ - NULL, /* gate */ - execute_init_datastructures, /* execute */ - NULL, /* sub */ - NULL, /* next */ - 0, /* static_pass_number */ TV_NONE, /* tv_id */ PROP_cfg, /* properties_required */ 0, /* properties_provided */ --- 211,216 ---- Index: gcc/tree-flow.h =================================================================== *** gcc/tree-flow.h.orig 2012-04-12 14:05:23.000000000 +0200 --- gcc/tree-flow.h 2012-04-12 14:05:51.278596925 +0200 *************** rtx addr_for_mem_ref (struct mem_address *** 853,859 **** void get_address_description (tree, struct mem_address *); tree maybe_fold_tmr (tree); - unsigned int execute_free_datastructures (void); unsigned int execute_fixup_cfg (void); bool fixup_noreturn_call (gimple stmt); --- 853,858 ---- Index: gcc/tree-ssa.c =================================================================== *** gcc/tree-ssa.c.orig 2012-04-12 14:05:23.000000000 +0200 --- gcc/tree-ssa.c 2012-04-12 14:05:51.278596925 +0200 *************** init_tree_ssa (struct function *fn) *** 1120,1125 **** --- 1120,1154 ---- init_phinodes (); } + /* Do the actions required to initialize internal data structures used + in tree-ssa optimization passes. */ + + static unsigned int + execute_init_datastructures (void) + { + /* Allocate hash tables, arrays and other structures. */ + init_tree_ssa (cfun); + return 0; + } + + struct gimple_opt_pass pass_init_datastructures = + { + { + GIMPLE_PASS, + "*init_datastructures", /* name */ + NULL, /* gate */ + execute_init_datastructures, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_NONE, /* tv_id */ + PROP_cfg, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0 /* todo_flags_finish */ + } + }; /* Deallocate memory associated with SSA data structures for FNDECL. */ Index: gcc/cfgexpand.c =================================================================== *** gcc/cfgexpand.c.orig 2012-04-12 14:05:23.000000000 +0200 --- gcc/cfgexpand.c 2012-04-12 14:05:51.279596925 +0200 *************** gimple_expand_cfg (void) *** 4555,4561 **** if (MAY_HAVE_DEBUG_INSNS) expand_debug_locations (); ! execute_free_datastructures (); timevar_push (TV_OUT_OF_SSA); finish_out_of_ssa (&SA); timevar_pop (TV_OUT_OF_SSA); --- 4555,4565 ---- if (MAY_HAVE_DEBUG_INSNS) expand_debug_locations (); ! /* Free stuff we no longer need after GIMPLE optimizations. */ ! free_dominance_info (CDI_DOMINATORS); ! free_dominance_info (CDI_POST_DOMINATORS); ! delete_tree_cfg_annotations (); ! timevar_push (TV_OUT_OF_SSA); finish_out_of_ssa (&SA); timevar_pop (TV_OUT_OF_SSA); Index: gcc/passes.c =================================================================== *** gcc/passes.c.orig 2012-04-10 16:51:16.000000000 +0200 --- gcc/passes.c 2012-04-12 14:12:02.789574738 +0200 *************** finish_optimization_passes (void) *** 281,286 **** --- 281,387 ---- timevar_pop (TV_DUMP); } + static unsigned int + execute_all_early_local_passes (void) + { + /* Once this pass (and its sub-passes) are complete, all functions + will be in SSA form. Technically this state change is happening + a tad early, since the sub-passes have not yet run, but since + none of the sub-passes are IPA passes and do not create new + functions, this is ok. We're setting this value for the benefit + of IPA passes that follow. */ + if (cgraph_state < CGRAPH_STATE_IPA_SSA) + cgraph_state = CGRAPH_STATE_IPA_SSA; + return 0; + } + + /* Gate: execute, or not, all of the non-trivial optimizations. */ + + static bool + gate_all_early_local_passes (void) + { + /* Don't bother doing anything if the program has errors. */ + return (!seen_error () && !in_lto_p); + } + + struct simple_ipa_opt_pass pass_early_local_passes = + { + { + SIMPLE_IPA_PASS, + "early_local_cleanups", /* name */ + gate_all_early_local_passes, /* gate */ + execute_all_early_local_passes, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_EARLY_LOCAL, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_remove_functions /* todo_flags_finish */ + } + }; + + /* Gate: execute, or not, all of the non-trivial optimizations. */ + + static bool + gate_all_early_optimizations (void) + { + return (optimize >= 1 + /* Don't bother doing anything if the program has errors. */ + && !seen_error ()); + } + + struct gimple_opt_pass pass_all_early_optimizations = + { + { + GIMPLE_PASS, + "early_optimizations", /* name */ + gate_all_early_optimizations, /* gate */ + NULL, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_NONE, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0 /* todo_flags_finish */ + } + }; + + /* Gate: execute, or not, all of the non-trivial optimizations. */ + + static bool + gate_all_optimizations (void) + { + return (optimize >= 1 + /* Don't bother doing anything if the program has errors. + We have to pass down the queue if we already went into SSA */ + && (!seen_error () || gimple_in_ssa_p (cfun))); + } + + struct gimple_opt_pass pass_all_optimizations = + { + { + GIMPLE_PASS, + "*all_optimizations", /* name */ + gate_all_optimizations, /* gate */ + NULL, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_OPTIMIZE, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0 /* todo_flags_finish */ + } + }; + static bool gate_rest_of_compilation (void) {