2005-05-19 Paolo Bonzini * cgraphunit.c (ipa_passes): Moved from tree-optimize.c. * passes.c (dump_flags, in_gimple_form, all_passes, all_ipa_passes, all_lowering_passes, register_one_dump_file, register_dump_files, next_pass_1, last_verified, execute_todo, execute_one_pass, execute_pass_list, execute_ipa_pass_list): Moved from tree-optimize.c. (init_optimization_passes): Moved from tree-optimize.c, adding the RTL optimizations. * tree-dump.h (dump_info_p, dump_flag): Moved from tree.h. * tree-optimize.c (dump_flags, in_gimple_form, all_passes, all_ipa_passes, all_lowering_passes, register_one_dump_file, register_dump_files, next_pass_1, last_verified, execute_todo, execute_one_pass, execute_pass_list, execute_ipa_pass_list, init_tree_optimization_passes, ipa_passes): Delete. * tree-pass.h (enum tree_dump_index): Moved from tree.h, removing the RTL dumps. (TDF_*, get_dump_file_name, dump_enabled_p, dump_initialized_p, dump_begin, dump_end, dump_node, dump_switch_p, dump_flag_name): Moved from tree.h. (ipa_passes): Remove. (all_passes, all_ipa_passes, all_lowering_passes): Now extern. * tree.h (enum tree_dump_index, TDF_*, get_dump_file_name, dump_enabled_p, dump_initialized_p, dump_begin, dump_end, dump_node, dump_switch_p, dump_flag_name): Moved to tree-pass.h. (dump_info_p, dump_flag): Moved to tree-dump.h. Index: cgraphunit.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/cgraphunit.c,v retrieving revision 1.107 diff -p -u -r1.107 cgraphunit.c --- cgraphunit.c 20 May 2005 08:05:07 -0000 1.107 +++ cgraphunit.c 25 May 2005 16:31:09 -0000 @@ -1089,6 +1089,16 @@ cgraph_preserve_function_body_p (tree de return false; } +static void +ipa_passes (void) +{ + cfun = NULL; + tree_register_cfg_hooks (); + bitmap_obstack_initialize (NULL); + execute_ipa_pass_list (all_ipa_passes); + bitmap_obstack_release (NULL); +} + /* Perform simple optimizations based on callgraph. */ void Index: passes.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/passes.c,v retrieving revision 2.90 diff -p -u -r2.90 passes.c --- passes.c 27 Apr 2005 21:35:20 -0000 2.90 +++ passes.c 18 May 2005 10:29:55 -0000 @@ -78,6 +78,8 @@ #include "opts.h" #include "coverage.h" #include "value-prof.h" +#include "tree-inline.h" +#include "tree-flow.h" #include "tree-pass.h" #include "tree-dump.h" @@ -98,6 +99,9 @@ declarations for e.g. AIX 4.x. */ #endif +/* Global variables used to communicate with passes. */ +int dump_flags; +bool in_gimple_form; /* This is called from various places for FUNCTION_DECL, VAR_DECL, @@ -254,3 +290,539 @@ 0 /* letter */ }; + + +/* The root of the compilation pass tree, once constructed. */ +struct tree_opt_pass *all_passes, *all_ipa_passes, *all_lowering_passes; + +/* Iterate over the pass tree allocating dump file numbers. We want + to do this depth first, and independent of whether the pass is + enabled or not. */ + +static void +register_one_dump_file (struct tree_opt_pass *pass, bool ipa, int n) +{ + char *dot_name, *flag_name, *glob_name; + char num[10]; + + /* See below in next_pass_1. */ + num[0] = '\0'; + if (pass->static_pass_number != -1) + sprintf (num, "%d", ((int) pass->static_pass_number < 0 + ? 1 : pass->static_pass_number)); + + dot_name = concat (".", pass->name, num, NULL); + if (ipa) + { + flag_name = concat ("ipa-", pass->name, num, NULL); + glob_name = concat ("ipa-", pass->name, NULL); + /* First IPA dump is cgraph that is dumped via separate channels. */ + pass->static_pass_number = dump_register (dot_name, flag_name, glob_name, + TDF_IPA, n + 1, 0); + } + else if (pass->properties_provided & PROP_trees) + { + flag_name = concat ("tree-", pass->name, num, NULL); + glob_name = concat ("tree-", pass->name, NULL); + pass->static_pass_number = dump_register (dot_name, flag_name, glob_name, + TDF_TREE, n + TDI_tree_all, 0); + } + else + { + flag_name = concat ("rtl-", pass->name, num, NULL); + glob_name = concat ("rtl-", pass->name, NULL); + pass->static_pass_number = dump_register (dot_name, flag_name, glob_name, + TDF_RTL, n, pass->letter); + } +} + +static int +register_dump_files (struct tree_opt_pass *pass, bool ipa, int properties) +{ + static int n = 0; + do + { + int new_properties; + int pass_number; + + pass->properties_required = properties; + new_properties = + (properties | pass->properties_provided) & ~pass->properties_destroyed; + + /* Reset the counter when we reach RTL-based passes. */ + if ((new_properties ^ pass->properties_required) & PROP_rtl) + n = 0; + + pass_number = n; + if (pass->name) + n++; + + if (pass->sub) + new_properties = register_dump_files (pass->sub, ipa, new_properties); + + /* If we have a gate, combine the properties that we could have with + and without the pass being examined. */ + if (pass->gate) + properties &= new_properties; + else + properties = new_properties; + + pass->properties_provided = properties; + if (pass->name) + register_one_dump_file (pass, ipa, pass_number); + + pass = pass->next; + } + while (pass); + + return properties; +} + +/* Add a pass to the pass list. Duplicate the pass if it's already + in the list. */ + +static struct tree_opt_pass ** +next_pass_1 (struct tree_opt_pass **list, struct tree_opt_pass *pass) +{ + + /* A nonzero static_pass_number indicates that the + pass is already in the list. */ + if (pass->static_pass_number) + { + struct tree_opt_pass *new; + + new = xmalloc (sizeof (*new)); + memcpy (new, pass, sizeof (*new)); + + /* Indicate to register_dump_files that this pass has duplicates, + and so it should rename the dump file. The first instance will + be -1, and be number of duplicates = -static_pass_number - 1. + Subsequent instances will be > 0 and just the duplicate number. */ + if (pass->name) + { + pass->static_pass_number -= 1; + new->static_pass_number = -pass->static_pass_number; + } + + *list = new; + } + else + { + pass->static_pass_number = -1; + *list = pass; + } + + return &(*list)->next; + +} + +/* Construct the pass tree. */ + +void +init_optimization_passes (void) +{ + struct tree_opt_pass **p; + +#define NEXT_PASS(PASS) (p = next_pass_1 (p, &PASS)) + /* Intraprocedural optimization passes. */ + p = &all_ipa_passes; + NEXT_PASS (pass_ipa_inline); + *p = NULL; + + /* All passes needed to lower the function into shape optimizers can operate + on. These passes are performed before interprocedural passes, unlike rest + of local passes (all_passes). */ + p = &all_lowering_passes; + NEXT_PASS (pass_remove_useless_stmts); + NEXT_PASS (pass_mudflap_1); + NEXT_PASS (pass_lower_cf); + NEXT_PASS (pass_lower_eh); + NEXT_PASS (pass_build_cfg); + NEXT_PASS (pass_lower_complex_O0); + NEXT_PASS (pass_lower_vector); + NEXT_PASS (pass_warn_function_return); + NEXT_PASS (pass_tree_profile); + *p = NULL; + + p = &all_passes; + NEXT_PASS (pass_fixup_cfg); + NEXT_PASS (pass_init_datastructures); + NEXT_PASS (pass_all_optimizations); + NEXT_PASS (pass_warn_function_noreturn); + NEXT_PASS (pass_mudflap_2); + NEXT_PASS (pass_free_datastructures); + NEXT_PASS (pass_expand); + NEXT_PASS (pass_rest_of_compilation); + NEXT_PASS (pass_clean_state); + *p = NULL; + + p = &pass_all_optimizations.sub; + NEXT_PASS (pass_referenced_vars); + NEXT_PASS (pass_create_structure_vars); + NEXT_PASS (pass_build_ssa); + NEXT_PASS (pass_build_pta); + NEXT_PASS (pass_may_alias); + NEXT_PASS (pass_del_pta); + NEXT_PASS (pass_rename_ssa_copies); + NEXT_PASS (pass_early_warn_uninitialized); + + /* Initial scalar cleanups. */ + NEXT_PASS (pass_ccp); + NEXT_PASS (pass_fre); + NEXT_PASS (pass_dce); + NEXT_PASS (pass_forwprop); + NEXT_PASS (pass_vrp); + NEXT_PASS (pass_copy_prop); + NEXT_PASS (pass_dce); + NEXT_PASS (pass_merge_phi); + NEXT_PASS (pass_dominator); + + NEXT_PASS (pass_phiopt); + NEXT_PASS (pass_build_pta); + NEXT_PASS (pass_may_alias); + NEXT_PASS (pass_del_pta); + NEXT_PASS (pass_tail_recursion); + NEXT_PASS (pass_profile); + NEXT_PASS (pass_ch); + NEXT_PASS (pass_stdarg); + NEXT_PASS (pass_lower_complex); + NEXT_PASS (pass_sra); + /* FIXME: SRA may generate arbitrary gimple code, exposing new + aliased and call-clobbered variables. As mentioned below, + pass_may_alias should be a TODO item. */ + NEXT_PASS (pass_may_alias); + NEXT_PASS (pass_rename_ssa_copies); + NEXT_PASS (pass_dominator); + NEXT_PASS (pass_copy_prop); + NEXT_PASS (pass_dce); + NEXT_PASS (pass_dse); + NEXT_PASS (pass_may_alias); + NEXT_PASS (pass_forwprop); + NEXT_PASS (pass_phiopt); + NEXT_PASS (pass_store_ccp); + NEXT_PASS (pass_store_copy_prop); + NEXT_PASS (pass_fold_builtins); + /* FIXME: May alias should a TODO but for 4.0.0, + we add may_alias right after fold builtins + which can create arbitrary GIMPLE. */ + NEXT_PASS (pass_may_alias); + NEXT_PASS (pass_cse_reciprocals); + NEXT_PASS (pass_split_crit_edges); + NEXT_PASS (pass_reassoc); + NEXT_PASS (pass_pre); + NEXT_PASS (pass_sink_code); + NEXT_PASS (pass_loop); + NEXT_PASS (pass_dominator); + NEXT_PASS (pass_copy_prop); + NEXT_PASS (pass_cd_dce); + + /* FIXME: If DCE is not run before checking for uninitialized uses, + we may get false warnings (e.g., testsuite/gcc.dg/uninit-5.c). + However, this also causes us to misdiagnose cases that should be + real warnings (e.g., testsuite/gcc.dg/pr18501.c). + + To fix the false positives in uninit-5.c, we would have to + account for the predicates protecting the set and the use of each + variable. Using a representation like Gated Single Assignment + may help. */ + NEXT_PASS (pass_late_warn_uninitialized); + NEXT_PASS (pass_dse); + NEXT_PASS (pass_forwprop); + NEXT_PASS (pass_phiopt); + NEXT_PASS (pass_tail_calls); + NEXT_PASS (pass_rename_ssa_copies); + NEXT_PASS (pass_uncprop); + NEXT_PASS (pass_del_ssa); + NEXT_PASS (pass_nrv); + NEXT_PASS (pass_remove_useless_vars); + NEXT_PASS (pass_mark_used_blocks); + NEXT_PASS (pass_cleanup_cfg_post_optimizing); + *p = NULL; + + p = &pass_loop.sub; + NEXT_PASS (pass_loop_init); + NEXT_PASS (pass_copy_prop); + NEXT_PASS (pass_lim); + NEXT_PASS (pass_unswitch); + NEXT_PASS (pass_scev_cprop); + NEXT_PASS (pass_record_bounds); + NEXT_PASS (pass_linear_transform); + NEXT_PASS (pass_iv_canon); + NEXT_PASS (pass_if_conversion); + NEXT_PASS (pass_vectorize); + /* NEXT_PASS (pass_may_alias) cannot be done again because the + vectorizer creates alias relations that are not supported by + pass_may_alias. */ + NEXT_PASS (pass_lower_vector_ssa); + NEXT_PASS (pass_complete_unroll); + NEXT_PASS (pass_iv_optimize); + NEXT_PASS (pass_loop_done); + *p = NULL; + + p = &pass_rest_of_compilation.sub; + NEXT_PASS (pass_remove_unnecessary_notes); + NEXT_PASS (pass_init_function); + NEXT_PASS (pass_jump); + NEXT_PASS (pass_insn_locators_initialize); + NEXT_PASS (pass_rtl_eh); + NEXT_PASS (pass_initial_value_sets); + NEXT_PASS (pass_unshare_all_rtl); + NEXT_PASS (pass_instantiate_virtual_regs); + NEXT_PASS (pass_jump2); + NEXT_PASS (pass_cse); + NEXT_PASS (pass_gcse); + NEXT_PASS (pass_loop_optimize); + NEXT_PASS (pass_jump_bypass); + NEXT_PASS (pass_cfg); + NEXT_PASS (pass_profiling); + NEXT_PASS (pass_rtl_ifcvt); + NEXT_PASS (pass_tracer); + NEXT_PASS (pass_loop2); + NEXT_PASS (pass_web); + NEXT_PASS (pass_cse2); + NEXT_PASS (pass_life); + NEXT_PASS (pass_combine); + NEXT_PASS (pass_if_after_combine); + NEXT_PASS (pass_partition_blocks); + NEXT_PASS (pass_regmove); + NEXT_PASS (pass_split_all_insns); + NEXT_PASS (pass_mode_switching); + NEXT_PASS (pass_recompute_reg_usage); + NEXT_PASS (pass_sms); + NEXT_PASS (pass_sched); + NEXT_PASS (pass_local_alloc); + NEXT_PASS (pass_global_alloc); + NEXT_PASS (pass_postreload); + *p = NULL; + + p = &pass_profiling.sub; + NEXT_PASS (pass_branch_prob); + NEXT_PASS (pass_value_profile_transformations); + NEXT_PASS (pass_remove_death_notes); + *p = NULL; + + p = &pass_postreload.sub; + NEXT_PASS (pass_postreload_cse); + NEXT_PASS (pass_gcse2); + NEXT_PASS (pass_flow2); + NEXT_PASS (pass_stack_adjustments); + NEXT_PASS (pass_peephole2); + NEXT_PASS (pass_if_after_reload); + NEXT_PASS (pass_regrename); + NEXT_PASS (pass_reorder_blocks); + NEXT_PASS (pass_branch_target_load_optimize); + NEXT_PASS (pass_leaf_regs); + NEXT_PASS (pass_sched2); + NEXT_PASS (pass_split_before_regstack); + NEXT_PASS (pass_stack_regs); + NEXT_PASS (pass_compute_alignments); + NEXT_PASS (pass_duplicate_computed_gotos); + NEXT_PASS (pass_variable_tracking); + NEXT_PASS (pass_free_cfg); + NEXT_PASS (pass_machine_reorg); + NEXT_PASS (pass_purge_lineno_notes); + NEXT_PASS (pass_cleanup_barriers); + NEXT_PASS (pass_delay_slots); + NEXT_PASS (pass_split_for_shorten_branches); + NEXT_PASS (pass_convert_to_eh_region_ranges); + NEXT_PASS (pass_shorten_branches); + NEXT_PASS (pass_set_nothrow_function_flags); + NEXT_PASS (pass_final); + *p = NULL; + +#undef NEXT_PASS + + /* Register the passes with the tree dump code. */ + register_dump_files (all_lowering_passes, false, PROP_gimple_any); + register_dump_files (all_passes, false, PROP_gimple_leh + | PROP_cfg); + register_dump_files (all_ipa_passes, true, PROP_gimple_leh + | PROP_cfg); +} + +static unsigned int last_verified; + +static void +execute_todo (struct tree_opt_pass *pass, unsigned int flags, bool use_required) +{ + int properties + = use_required ? pass->properties_required : pass->properties_provided; + +#if defined ENABLE_CHECKING + if (need_ssa_update_p ()) + gcc_assert (flags & TODO_update_ssa_any); +#endif + + if (flags & TODO_update_ssa_any) + { + unsigned update_flags = flags & TODO_update_ssa_any; + update_ssa (update_flags); + } + + if (flags & TODO_cleanup_cfg) + { + if (current_loops) + cleanup_tree_cfg_loop (); + else + cleanup_tree_cfg (); + } + + if ((flags & TODO_dump_func) + && dump_file && current_function_decl) + { + if (properties & PROP_trees) + dump_function_to_file (current_function_decl, + dump_file, dump_flags); + else if (properties & PROP_cfg) + print_rtl_with_bb (dump_file, get_insns ()); + else + print_rtl (dump_file, get_insns ()); + + /* Flush the file. If verification fails, we won't be able to + close the file before aborting. */ + fflush (dump_file); + } + if ((flags & TODO_dump_cgraph) + && dump_file && !current_function_decl) + { + dump_cgraph (dump_file); + /* Flush the file. If verification fails, we won't be able to + close the file before aborting. */ + fflush (dump_file); + } + + if (flags & TODO_ggc_collect) + { + ggc_collect (); + } + +#if defined ENABLE_CHECKING + if ((pass->properties_required & PROP_ssa) + && !(pass->properties_destroyed & PROP_ssa)) + verify_ssa (true); + if (flags & TODO_verify_flow) + verify_flow_info (); + if (flags & TODO_verify_stmts) + verify_stmts (); + if (flags & TODO_verify_loops) + verify_loop_closed_ssa (); +#endif +} + +static bool +execute_one_pass (struct tree_opt_pass *pass) +{ + unsigned int todo; + + /* See if we're supposed to run this pass. */ + if (pass->gate && !pass->gate ()) + return false; + + /* Note that the folders should only create gimple expressions. + This is a hack until the new folder is ready. */ + in_gimple_form = (pass->properties_provided & PROP_trees) != 0; + + /* Run pre-pass verification. */ + todo = pass->todo_flags_start & ~last_verified; + if (todo) + execute_todo (pass, todo, true); + + /* If a dump file name is present, open it if enabled. */ + if (pass->static_pass_number != -1) + { + bool initializing_dump = !dump_initialized_p (pass->static_pass_number); + dump_file_name = get_dump_file_name (pass->static_pass_number); + dump_file = dump_begin (pass->static_pass_number, &dump_flags); + if (dump_file && current_function_decl) + { + const char *dname, *aname; + dname = lang_hooks.decl_printable_name (current_function_decl, 2); + aname = (IDENTIFIER_POINTER + (DECL_ASSEMBLER_NAME (current_function_decl))); + fprintf (dump_file, "\n;; Function %s (%s)%s\n\n", dname, aname, + cfun->function_frequency == FUNCTION_FREQUENCY_HOT + ? " (hot)" + : cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED + ? " (unlikely executed)" + : ""); + } + + if (initializing_dump + && graph_dump_format != no_graph + && (pass->properties_provided & (PROP_cfg | PROP_rtl)) + == (PROP_cfg | PROP_rtl)) + clean_graph_dump_file (dump_file_name); + } + + /* If a timevar is present, start it. */ + if (pass->tv_id) + timevar_push (pass->tv_id); + + /* Do it! */ + if (pass->execute) + pass->execute (); + + /* Stop timevar. */ + if (pass->tv_id) + timevar_pop (pass->tv_id); + + /* Run post-pass cleanup and verification. */ + todo = pass->todo_flags_finish; + last_verified = todo & TODO_verify_all; + if (todo) + execute_todo (pass, todo, false); + + /* Flush and close dump file. */ + if (dump_file_name) + { + free ((char *) dump_file_name); + dump_file_name = NULL; + } + if (dump_file) + { + dump_end (pass->static_pass_number, dump_file); + dump_file = NULL; + } + + return true; +} + +void +execute_pass_list (struct tree_opt_pass *pass) +{ + do + { + if (execute_one_pass (pass) && pass->sub) + execute_pass_list (pass->sub); + pass = pass->next; + } + while (pass); +} + +/* Same as execute_pass_list but assume that subpasses of IPA passes + are local passes. */ +void +execute_ipa_pass_list (struct tree_opt_pass *pass) +{ + do + { + if (execute_one_pass (pass) && pass->sub) + { + struct cgraph_node *node; + for (node = cgraph_nodes; node; node = node->next) + if (node->analyzed) + { + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); + current_function_decl = node->decl; + execute_pass_list (pass); + free_dominance_info (CDI_DOMINATORS); + free_dominance_info (CDI_POST_DOMINATORS); + current_function_decl = NULL; + pop_cfun (); + ggc_collect (); + } + } + pass = pass->next; + } + while (pass); +} Index: tree-dump.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-dump.h,v retrieving revision 1.10 diff -p -u -r1.10 tree-dump.h --- tree-dump.h 15 Feb 2005 15:53:47 -0000 1.10 +++ tree-dump.h 7 Jun 2005 10:17:12 -0000 @@ -23,6 +23,9 @@ Software Foundation, 59 Temple Place - S #define GCC_TREE_DUMP_H #include "splay-tree.h" +#include "tree-pass.h" + +typedef struct dump_info *dump_info_p; /* Flags used with queue functions. */ #define DUMP_NONE 0 @@ -87,6 +90,7 @@ extern void queue_and_dump_index (dump_i extern void queue_and_dump_type (dump_info_p, tree); extern void dump_function (enum tree_dump_index, tree); extern void dump_function_to_file (tree, FILE *, int); +extern int dump_flag (dump_info_p, int, tree); extern unsigned int dump_register (const char *, const char *, const char *, int, unsigned int, int); Index: tree-optimize.c =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-optimize.c,v retrieving revision 2.98 diff -p -u -r2.98 tree-optimize.c --- tree-optimize.c 17 May 2005 20:28:22 -0000 2.98 +++ tree-optimize.c 18 May 2005 10:30:39 -0000 @@ -51,13 +51,6 @@ #include "cfgloop.h" #include "except.h" -/* Global variables used to communicate with passes. */ -int dump_flags; -bool in_gimple_form; - -/* The root of the compilation pass tree, once constructed. */ -static struct tree_opt_pass *all_passes, *all_ipa_passes, * all_lowering_passes; - /* Gate: execute, or not, all of the non-trivial optimizations. */ static bool @@ -232,469 +244,7 @@ static struct tree_opt_pass pass_init_da 0 /* letter */ }; -/* Iterate over the pass tree allocating dump file numbers. We want - to do this depth first, and independent of whether the pass is - enabled or not. */ - -static void -register_one_dump_file (struct tree_opt_pass *pass, bool ipa, int n) -{ - char *dot_name, *flag_name, *glob_name; - char num[10]; - - /* See below in next_pass_1. */ - num[0] = '\0'; - if (pass->static_pass_number != -1) - sprintf (num, "%d", ((int) pass->static_pass_number < 0 - ? 1 : pass->static_pass_number)); - - dot_name = concat (".", pass->name, num, NULL); - if (ipa) - { - flag_name = concat ("ipa-", pass->name, num, NULL); - glob_name = concat ("ipa-", pass->name, NULL); - /* First IPA dump is cgraph that is dumped via separate channels. */ - pass->static_pass_number = dump_register (dot_name, flag_name, glob_name, - TDF_IPA, n + 1, 0); - } - else if (pass->properties_provided & PROP_trees) - { - flag_name = concat ("tree-", pass->name, num, NULL); - glob_name = concat ("tree-", pass->name, NULL); - pass->static_pass_number = dump_register (dot_name, flag_name, glob_name, - TDF_TREE, n + TDI_tree_all, 0); - } - else - { - flag_name = concat ("rtl-", pass->name, num, NULL); - glob_name = concat ("rtl-", pass->name, NULL); - pass->static_pass_number = dump_register (dot_name, flag_name, glob_name, - TDF_RTL, n, pass->letter); - } -} - -static int -register_dump_files (struct tree_opt_pass *pass, bool ipa, int properties) -{ - static int n = 0; - do - { - int new_properties; - int pass_number; - - pass->properties_required = properties; - new_properties = - (properties | pass->properties_provided) & ~pass->properties_destroyed; - - /* Reset the counter when we reach RTL-based passes. */ - if ((pass->properties_provided ^ pass->properties_required) & PROP_rtl) - n = 0; - - pass_number = n; - if (pass->name) - n++; - - if (pass->sub) - new_properties = register_dump_files (pass->sub, ipa, new_properties); - - /* If we have a gate, combine the properties that we could have with - and without the pass being examined. */ - if (pass->gate) - properties &= new_properties; - else - properties = new_properties; - - pass->properties_provided = properties; - if (pass->name) - register_one_dump_file (pass, ipa, pass_number); - - pass = pass->next; - } - while (pass); - - return properties; -} - -/* Add a pass to the pass list. Duplicate the pass if it's already - in the list. */ - -static struct tree_opt_pass ** -next_pass_1 (struct tree_opt_pass **list, struct tree_opt_pass *pass) -{ - - /* A nonzero static_pass_number indicates that the - pass is already in the list. */ - if (pass->static_pass_number) - { - struct tree_opt_pass *new; - - new = xmalloc (sizeof (*new)); - memcpy (new, pass, sizeof (*new)); - - /* Indicate to register_dump_files that this pass has duplicates, - and so it should rename the dump file. The first instance will - be -1, and be number of duplicates = -static_pass_number - 1. - Subsequent instances will be > 0 and just the duplicate number. */ - if (pass->name) - { - pass->static_pass_number -= 1; - new->static_pass_number = -pass->static_pass_number; - } - - *list = new; - } - else - { - pass->static_pass_number = -1; - *list = pass; - } - - return &(*list)->next; - -} - -/* Construct the pass tree. */ - -void -init_tree_optimization_passes (void) -{ - struct tree_opt_pass **p; - -#define NEXT_PASS(PASS) (p = next_pass_1 (p, &PASS)) - /* Intraprocedural optimization passes. */ - p = &all_ipa_passes; - NEXT_PASS (pass_ipa_inline); - *p = NULL; - - /* All passes needed to lower the function into shape optimizers can operate - on. These passes are performed before interprocedural passes, unlike rest - of local passes (all_passes). */ - p = &all_lowering_passes; - NEXT_PASS (pass_remove_useless_stmts); - NEXT_PASS (pass_mudflap_1); - NEXT_PASS (pass_lower_cf); - NEXT_PASS (pass_lower_eh); - NEXT_PASS (pass_build_cfg); - NEXT_PASS (pass_lower_complex_O0); - NEXT_PASS (pass_lower_vector); - NEXT_PASS (pass_warn_function_return); - NEXT_PASS (pass_tree_profile); - *p = NULL; - - p = &all_passes; - NEXT_PASS (pass_fixup_cfg); - NEXT_PASS (pass_init_datastructures); - NEXT_PASS (pass_all_optimizations); - NEXT_PASS (pass_warn_function_noreturn); - NEXT_PASS (pass_mudflap_2); - NEXT_PASS (pass_free_datastructures); - NEXT_PASS (pass_expand); - NEXT_PASS (pass_rest_of_compilation); - *p = NULL; - - p = &pass_all_optimizations.sub; - NEXT_PASS (pass_referenced_vars); - NEXT_PASS (pass_create_structure_vars); - NEXT_PASS (pass_build_ssa); - NEXT_PASS (pass_build_pta); - NEXT_PASS (pass_may_alias); - NEXT_PASS (pass_del_pta); - NEXT_PASS (pass_rename_ssa_copies); - NEXT_PASS (pass_early_warn_uninitialized); - - /* Initial scalar cleanups. */ - NEXT_PASS (pass_ccp); - NEXT_PASS (pass_fre); - NEXT_PASS (pass_dce); - NEXT_PASS (pass_forwprop); - NEXT_PASS (pass_vrp); - NEXT_PASS (pass_copy_prop); - NEXT_PASS (pass_dce); - NEXT_PASS (pass_merge_phi); - NEXT_PASS (pass_dominator); - - NEXT_PASS (pass_phiopt); - NEXT_PASS (pass_build_pta); - NEXT_PASS (pass_may_alias); - NEXT_PASS (pass_del_pta); - NEXT_PASS (pass_tail_recursion); - NEXT_PASS (pass_profile); - NEXT_PASS (pass_ch); - NEXT_PASS (pass_stdarg); - NEXT_PASS (pass_lower_complex); - NEXT_PASS (pass_sra); - /* FIXME: SRA may generate arbitrary gimple code, exposing new - aliased and call-clobbered variables. As mentioned below, - pass_may_alias should be a TODO item. */ - NEXT_PASS (pass_may_alias); - NEXT_PASS (pass_rename_ssa_copies); - NEXT_PASS (pass_dominator); - NEXT_PASS (pass_copy_prop); - NEXT_PASS (pass_dce); - NEXT_PASS (pass_dse); - NEXT_PASS (pass_may_alias); - NEXT_PASS (pass_forwprop); - NEXT_PASS (pass_phiopt); - NEXT_PASS (pass_store_ccp); - NEXT_PASS (pass_store_copy_prop); - NEXT_PASS (pass_fold_builtins); - /* FIXME: May alias should a TODO but for 4.0.0, - we add may_alias right after fold builtins - which can create arbitrary GIMPLE. */ - NEXT_PASS (pass_may_alias); - NEXT_PASS (pass_cse_reciprocals); - NEXT_PASS (pass_split_crit_edges); - NEXT_PASS (pass_reassoc); - NEXT_PASS (pass_pre); - NEXT_PASS (pass_sink_code); - NEXT_PASS (pass_loop); - NEXT_PASS (pass_dominator); - NEXT_PASS (pass_copy_prop); - NEXT_PASS (pass_cd_dce); - /* FIXME: If DCE is not run before checking for uninitialized uses, - we may get false warnings (e.g., testsuite/gcc.dg/uninit-5.c). - However, this also causes us to misdiagnose cases that should be - real warnings (e.g., testsuite/gcc.dg/pr18501.c). - - To fix the false positives in uninit-5.c, we would have to - account for the predicates protecting the set and the use of each - variable. Using a representation like Gated Single Assignment - may help. */ - NEXT_PASS (pass_late_warn_uninitialized); - NEXT_PASS (pass_dse); - NEXT_PASS (pass_forwprop); - NEXT_PASS (pass_phiopt); - NEXT_PASS (pass_tail_calls); - NEXT_PASS (pass_rename_ssa_copies); - NEXT_PASS (pass_uncprop); - NEXT_PASS (pass_del_ssa); - NEXT_PASS (pass_nrv); - NEXT_PASS (pass_remove_useless_vars); - NEXT_PASS (pass_mark_used_blocks); - NEXT_PASS (pass_cleanup_cfg_post_optimizing); - *p = NULL; - - p = &pass_loop.sub; - NEXT_PASS (pass_loop_init); - NEXT_PASS (pass_copy_prop); - NEXT_PASS (pass_lim); - NEXT_PASS (pass_unswitch); - NEXT_PASS (pass_scev_cprop); - NEXT_PASS (pass_record_bounds); - NEXT_PASS (pass_linear_transform); - NEXT_PASS (pass_iv_canon); - NEXT_PASS (pass_if_conversion); - NEXT_PASS (pass_vectorize); - /* NEXT_PASS (pass_may_alias) cannot be done again because the - vectorizer creates alias relations that are not supported by - pass_may_alias. */ - NEXT_PASS (pass_lower_vector_ssa); - NEXT_PASS (pass_complete_unroll); - NEXT_PASS (pass_iv_optimize); - NEXT_PASS (pass_loop_done); - *p = NULL; - -#undef NEXT_PASS - - register_dump_files (all_lowering_passes, false, PROP_gimple_any); - register_dump_files (all_passes, false, PROP_gimple_leh - | PROP_cfg); - register_dump_files (all_ipa_passes, true, PROP_gimple_leh - | PROP_cfg); -} - -static unsigned int last_verified; - -static void -execute_todo (struct tree_opt_pass *pass, unsigned int flags, bool use_required) -{ - int properties - = use_required ? pass->properties_required : pass->properties_provided; - -#if defined ENABLE_CHECKING - if (need_ssa_update_p ()) - gcc_assert (flags & TODO_update_ssa_any); -#endif - - if (flags & TODO_update_ssa_any) - { - unsigned update_flags = flags & TODO_update_ssa_any; - update_ssa (update_flags); - } - - if (flags & TODO_cleanup_cfg) - { - if (current_loops) - cleanup_tree_cfg_loop (); - else - cleanup_tree_cfg (); - } - - if ((flags & TODO_dump_func) - && dump_file && current_function_decl) - { - if (properties & PROP_trees) - dump_function_to_file (current_function_decl, - dump_file, dump_flags); - else if (properties & PROP_cfg) - print_rtl_with_bb (dump_file, get_insns ()); - else - print_rtl (dump_file, get_insns ()); - - /* Flush the file. If verification fails, we won't be able to - close the file before dieing. */ - fflush (dump_file); - } - if ((flags & TODO_dump_cgraph) - && dump_file && !current_function_decl) - { - dump_cgraph (dump_file); - /* Flush the file. If verification fails, we won't be able to - close the file before aborting. */ - fflush (dump_file); - } - - if (flags & TODO_ggc_collect) - { - ggc_collect (); - } - -#if defined ENABLE_CHECKING - if ((pass->properties_required & PROP_ssa) - && !(pass->properties_destroyed & PROP_ssa)) - verify_ssa (true); - if (flags & TODO_verify_flow) - verify_flow_info (); - if (flags & TODO_verify_stmts) - verify_stmts (); - if (flags & TODO_verify_loops) - verify_loop_closed_ssa (); -#endif -} - -static bool -execute_one_pass (struct tree_opt_pass *pass) -{ - unsigned int todo; - - /* See if we're supposed to run this pass. */ - if (pass->gate && !pass->gate ()) - return false; - - /* Note that the folders should only create gimple expressions. - This is a hack until the new folder is ready. */ - in_gimple_form = (pass->properties_provided & PROP_trees) != 0; - - /* Run pre-pass verification. */ - todo = pass->todo_flags_start & ~last_verified; - if (todo) - execute_todo (pass, todo, true); - - /* If a dump file name is present, open it if enabled. */ - if (pass->static_pass_number != -1) - { - bool initializing_dump = !dump_initialized_p (pass->static_pass_number); - dump_file_name = get_dump_file_name (pass->static_pass_number); - dump_file = dump_begin (pass->static_pass_number, &dump_flags); - if (dump_file && current_function_decl) - { - const char *dname, *aname; - dname = lang_hooks.decl_printable_name (current_function_decl, 2); - aname = (IDENTIFIER_POINTER - (DECL_ASSEMBLER_NAME (current_function_decl))); - fprintf (dump_file, "\n;; Function %s (%s)%s\n\n", dname, aname, - cfun->function_frequency == FUNCTION_FREQUENCY_HOT - ? " (hot)" - : cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED - ? " (unlikely executed)" - : ""); - } - - if (initializing_dump - && graph_dump_format != no_graph - && (pass->properties_provided & (PROP_cfg | PROP_rtl)) - == (PROP_cfg | PROP_rtl)) - clean_graph_dump_file (dump_file_name); - } - - /* If a timevar is present, start it. */ - if (pass->tv_id) - timevar_push (pass->tv_id); - - /* Do it! */ - if (pass->execute) - pass->execute (); - - /* Stop timevar. */ - if (pass->tv_id) - timevar_pop (pass->tv_id); - - if (dump_file - && (pass->properties_provided & (PROP_cfg | PROP_rtl)) - == (PROP_cfg | PROP_rtl)) - print_rtl_with_bb (dump_file, get_insns ()); - - /* Run post-pass cleanup and verification. */ - todo = pass->todo_flags_finish; - last_verified = todo & TODO_verify_all; - if (todo) - execute_todo (pass, todo, false); - - /* Flush and close dump file. */ - if (dump_file_name) - { - free ((char *) dump_file_name); - dump_file_name = NULL; - } - if (dump_file) - { - dump_end (pass->static_pass_number, dump_file); - dump_file = NULL; - } - - return true; -} - -static void -execute_pass_list (struct tree_opt_pass *pass) -{ - do - { - if (execute_one_pass (pass) && pass->sub) - execute_pass_list (pass->sub); - pass = pass->next; - } - while (pass); -} - -/* Same as execute_pass_list but assume that subpasses of IPA passes - are local passes. */ -static void -execute_ipa_pass_list (struct tree_opt_pass *pass) -{ - do - { - if (execute_one_pass (pass) && pass->sub) - { - struct cgraph_node *node; - for (node = cgraph_nodes; node; node = node->next) - if (node->analyzed) - { - push_cfun (DECL_STRUCT_FUNCTION (node->decl)); - current_function_decl = node->decl; - execute_pass_list (pass); - free_dominance_info (CDI_DOMINATORS); - free_dominance_info (CDI_POST_DOMINATORS); - current_function_decl = NULL; - pop_cfun (); - ggc_collect (); - } - } - pass = pass->next; - } - while (pass); -} - + void tree_lowering_passes (tree fn) { @@ -678,18 +262,6 @@ tree_lowering_passes (tree fn) pop_cfun (); } -/* Execute all IPA passes. */ -void -ipa_passes (void) -{ - cfun = NULL; - tree_register_cfg_hooks (); - bitmap_obstack_initialize (NULL); - execute_ipa_pass_list (all_ipa_passes); - bitmap_obstack_release (NULL); -} - - /* Update recursively all inlined_to pointers of functions inlined into NODE to INLINED_TO. */ static void Index: tree-pass.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree-pass.h,v retrieving revision 2.35 diff -p -u -r2.35 tree-pass.h --- tree-pass.h 17 May 2005 09:55:24 -0000 2.35 +++ tree-pass.h 18 May 2005 10:30:40 -0000 @@ -23,6 +23,59 @@ Boston, MA 02111-1307, USA. */ #ifndef GCC_TREE_PASS_H #define GCC_TREE_PASS_H 1 +/* In tree-dump.c */ + +/* Different tree dump places. When you add new tree dump places, + extend the DUMP_FILES array in tree-dump.c. */ +enum tree_dump_index +{ + TDI_none, /* No dump */ + TDI_tu, /* dump the whole translation unit. */ + TDI_class, /* dump class hierarchy. */ + TDI_original, /* dump each function before optimizing it */ + TDI_generic, /* dump each function after genericizing it */ + TDI_nested, /* dump each function after unnesting it */ + TDI_inlined, /* dump each function after inlining + within it. */ + TDI_vcg, /* create a VCG graph file for each + function's flowgraph. */ + TDI_tree_all, /* enable all the GENERIC/GIMPLE dumps. */ + TDI_rtl_all, /* enable all the RTL dumps. */ + TDI_ipa_all, /* enable all the IPA dumps. */ + + TDI_cgraph, /* dump function call graph. */ + TDI_end +}; + +/* Bit masks to control dumping. Not all values are applicable to + all dumps. Add new ones at the end. When you define new + values, extend the DUMP_OPTIONS array in tree-dump.c */ +#define TDF_ADDRESS (1 << 0) /* dump node addresses */ +#define TDF_SLIM (1 << 1) /* don't go wild following links */ +#define TDF_RAW (1 << 2) /* don't unparse the function */ +#define TDF_DETAILS (1 << 3) /* show more detailed info about + each pass */ +#define TDF_STATS (1 << 4) /* dump various statistics about + each pass */ +#define TDF_BLOCKS (1 << 5) /* display basic block boundaries */ +#define TDF_VOPS (1 << 6) /* display virtual operands */ +#define TDF_LINENO (1 << 7) /* display statement line numbers */ +#define TDF_UID (1 << 8) /* display decl UIDs */ + +#define TDF_TREE (1 << 9) /* is a tree dump */ +#define TDF_RTL (1 << 10) /* is a RTL dump */ +#define TDF_IPA (1 << 11) /* is an IPA dump */ +#define TDF_STMTADDR (1 << 12) /* Address of stmt. */ + +extern char *get_dump_file_name (enum tree_dump_index); +extern int dump_enabled_p (enum tree_dump_index); +extern int dump_initialized_p (enum tree_dump_index); +extern FILE *dump_begin (enum tree_dump_index, int *); +extern void dump_end (enum tree_dump_index, FILE *); +extern void dump_node (tree, int, FILE *); +extern int dump_switch_p (const char *); +extern const char *dump_flag_name (enum tree_dump_index); + /* Global variables used to communicate with passes. */ extern FILE *dump_file; extern int dump_flags; @@ -154,7 +207,6 @@ struct dump_file_info #define TODO_verify_all \ (TODO_verify_ssa | TODO_verify_flow | TODO_verify_stmts) -extern void ipa_passes (void); extern void tree_lowering_passes (tree decl); extern struct tree_opt_pass pass_mudflap_1; @@ -291,4 +342,11 @@ extern struct tree_opt_pass pass_uncprop extern struct tree_opt_pass pass_shorten_branches; extern struct tree_opt_pass pass_set_nothrow_function_flags; extern struct tree_opt_pass pass_final; + +/* The root of the compilation pass tree, once constructed. */ +extern struct tree_opt_pass *all_passes, *all_ipa_passes, *all_lowering_passes; + +extern void execute_pass_list (struct tree_opt_pass *); +extern void execute_ipa_pass_list (struct tree_opt_pass *); + #endif /* GCC_TREE_PASS_H */ Index: tree.h =================================================================== RCS file: /cvs/gcc/gcc/gcc/tree.h,v retrieving revision 1.727 diff -p -u -r1.727 tree.h --- tree.h 11 May 2005 16:25:30 -0000 1.727 +++ tree.h 18 May 2005 10:30:50 -0000 @@ -3844,100 +3844,6 @@ typedef tree (*walk_tree_fn) (tree *, in extern tree walk_tree (tree*, walk_tree_fn, void*, struct pointer_set_t*); extern tree walk_tree_without_duplicates (tree*, walk_tree_fn, void*); -/* In tree-dump.c */ - -/* Different tree dump places. When you add new tree dump places, - extend the DUMP_FILES array in tree-dump.c. */ -enum tree_dump_index -{ - TDI_none, /* No dump */ - TDI_tu, /* dump the whole translation unit. */ - TDI_class, /* dump class hierarchy. */ - TDI_original, /* dump each function before optimizing it */ - TDI_generic, /* dump each function after genericizing it */ - TDI_nested, /* dump each function after unnesting it */ - TDI_inlined, /* dump each function after inlining - within it. */ - TDI_vcg, /* create a VCG graph file for each - function's flowgraph. */ - TDI_tree_all, /* enable all the GENERIC/GIMPLE dumps. */ - TDI_rtl_all, /* enable all the RTL dumps. */ - TDI_ipa_all, /* enable all the IPA dumps. */ - - TDI_cgraph, /* dump function call graph. */ - - DFI_MIN, /* For now, RTL dumps are placed here. */ - DFI_sibling = DFI_MIN, - DFI_eh, - DFI_jump, - DFI_cse, - DFI_gcse, - DFI_loop, - DFI_bypass, - DFI_cfg, - DFI_bp, - DFI_vpt, - DFI_ce1, - DFI_tracer, - DFI_loop2, - DFI_web, - DFI_cse2, - DFI_life, - DFI_combine, - DFI_ce2, - DFI_regmove, - DFI_sms, - DFI_sched, - DFI_lreg, - DFI_greg, - DFI_postreload, - DFI_gcse2, - DFI_flow2, - DFI_peephole2, - DFI_ce3, - DFI_rnreg, - DFI_bbro, - DFI_branch_target_load, - DFI_sched2, - DFI_stack, - DFI_vartrack, - DFI_mach, - DFI_dbr, - - TDI_end -}; - -/* Bit masks to control dumping. Not all values are applicable to - all dumps. Add new ones at the end. When you define new - values, extend the DUMP_OPTIONS array in tree-dump.c */ -#define TDF_ADDRESS (1 << 0) /* dump node addresses */ -#define TDF_SLIM (1 << 1) /* don't go wild following links */ -#define TDF_RAW (1 << 2) /* don't unparse the function */ -#define TDF_DETAILS (1 << 3) /* show more detailed info about - each pass */ -#define TDF_STATS (1 << 4) /* dump various statistics about - each pass */ -#define TDF_BLOCKS (1 << 5) /* display basic block boundaries */ -#define TDF_VOPS (1 << 6) /* display virtual operands */ -#define TDF_LINENO (1 << 7) /* display statement line numbers */ -#define TDF_UID (1 << 8) /* display decl UIDs */ - -#define TDF_TREE (1 << 9) /* is a tree dump */ -#define TDF_RTL (1 << 10) /* is a RTL dump */ -#define TDF_IPA (1 << 11) /* is an IPA dump */ -#define TDF_STMTADDR (1 << 12) /* Address of stmt. */ - -typedef struct dump_info *dump_info_p; - -extern char *get_dump_file_name (enum tree_dump_index); -extern int dump_flag (dump_info_p, int, tree); -extern int dump_enabled_p (enum tree_dump_index); -extern int dump_initialized_p (enum tree_dump_index); -extern FILE *dump_begin (enum tree_dump_index, int *); -extern void dump_end (enum tree_dump_index, FILE *); -extern void dump_node (tree, int, FILE *); -extern int dump_switch_p (const char *); -extern const char *dump_flag_name (enum tree_dump_index); /* Assign the RTX to declaration. */ extern void set_decl_rtl (tree, rtx);