X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Ftree-optimize.c;h=3d18d20a003c36568fda6ad8df88db8cf45aa4fe;hb=8899f79dd96b4323c6dad02242327d3e4edc01bd;hp=23b7046c60d4c3d7c2083e1464ba2e692c131ace;hpb=f018d957a72d418d69c6d2d8bc80c9415666a9f6;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/tree-optimize.c b/gcc/tree-optimize.c index 23b7046c60d..3d18d20a003 100644 --- a/gcc/tree-optimize.c +++ b/gcc/tree-optimize.c @@ -1,5 +1,5 @@ /* Top-level control of tree optimizations. - Copyright 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 + Copyright 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. Contributed by Diego Novillo @@ -24,32 +24,28 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "tree.h" -#include "rtl.h" #include "tm_p.h" -#include "hard-reg-set.h" #include "basic-block.h" #include "output.h" -#include "expr.h" -#include "diagnostic.h" -#include "basic-block.h" #include "flags.h" #include "tree-flow.h" #include "tree-dump.h" #include "timevar.h" #include "function.h" #include "langhooks.h" +#include "diagnostic-core.h" #include "toplev.h" #include "flags.h" #include "cgraph.h" #include "tree-inline.h" -#include "tree-mudflap.h" #include "tree-pass.h" #include "ggc.h" #include "cgraph.h" #include "graph.h" #include "cfgloop.h" #include "except.h" - +#include "plugin.h" +#include "regset.h" /* FIXME: For reg_obstack. */ /* Gate: execute, or not, all of the non-trivial optimizations. */ @@ -59,7 +55,7 @@ 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 */ - && (!(errorcount || sorrycount) || gimple_in_ssa_p (cfun))); + && (!seen_error () || gimple_in_ssa_p (cfun))); } struct gimple_opt_pass pass_all_optimizations = @@ -72,7 +68,7 @@ struct gimple_opt_pass pass_all_optimizations = NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ - TV_NONE, /* tv_id */ + TV_OPTIMIZE, /* tv_id */ 0, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ @@ -87,7 +83,21 @@ static bool gate_all_early_local_passes (void) { /* Don't bother doing anything if the program has errors. */ - return (!errorcount && !sorrycount && !in_lto_p); + 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 = @@ -96,11 +106,11 @@ struct simple_ipa_opt_pass pass_early_local_passes = SIMPLE_IPA_PASS, "early_local_cleanups", /* name */ gate_all_early_local_passes, /* gate */ - NULL, /* execute */ + execute_all_early_local_passes, /* execute */ NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ - TV_NONE, /* tv_id */ + TV_EARLY_LOCAL, /* tv_id */ 0, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ @@ -109,18 +119,6 @@ struct simple_ipa_opt_pass pass_early_local_passes = } }; -static unsigned int -execute_early_local_optimizations (void) -{ - /* First time we start with early optimization we need to advance - cgraph state so newly inserted functions are also early optimized. - However we execute early local optimizations for lately inserted - functions, in that case don't reset cgraph state back to IPA_SSA. */ - 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 @@ -128,7 +126,7 @@ gate_all_early_optimizations (void) { return (optimize >= 1 /* Don't bother doing anything if the program has errors. */ - && !(errorcount || sorrycount)); + && !seen_error ()); } struct gimple_opt_pass pass_all_early_optimizations = @@ -137,7 +135,7 @@ struct gimple_opt_pass pass_all_early_optimizations = GIMPLE_PASS, "early_optimizations", /* name */ gate_all_early_optimizations, /* gate */ - execute_early_local_optimizations, /* execute */ + NULL, /* execute */ NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ @@ -150,37 +148,6 @@ struct gimple_opt_pass pass_all_early_optimizations = } }; -/* Pass: cleanup the CFG just before expanding trees to RTL. - This is just a round of label cleanups and case node grouping - because after the tree optimizers have run such cleanups may - be necessary. */ - -static unsigned int -execute_cleanup_cfg_pre_ipa (void) -{ - cleanup_tree_cfg (); - return 0; -} - -struct gimple_opt_pass pass_cleanup_cfg = -{ - { - GIMPLE_PASS, - "cleanup_cfg", /* name */ - NULL, /* gate */ - execute_cleanup_cfg_pre_ipa, /* 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 */ - TODO_dump_func /* 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 @@ -190,11 +157,42 @@ struct gimple_opt_pass pass_cleanup_cfg = static unsigned int execute_cleanup_cfg_post_optimizing (void) { - fold_cond_expr_cond (); - cleanup_tree_cfg (); + unsigned int todo = 0; + if (cleanup_tree_cfg ()) + todo |= TODO_update_ssa; + maybe_remove_unreachable_handlers (); cleanup_dead_labels (); group_case_labels (); - return 0; + if ((flag_compare_debug_opt || flag_compare_debug) + && flag_dump_final_insns) + { + FILE *final_output = fopen (flag_dump_final_insns, "a"); + + if (!final_output) + { + error ("could not open final insn dump file %qs: %m", + flag_dump_final_insns); + flag_dump_final_insns = NULL; + } + else + { + int save_unnumbered = flag_dump_unnumbered; + int save_noaddr = flag_dump_noaddr; + + flag_dump_noaddr = flag_dump_unnumbered = 1; + fprintf (final_output, "\n"); + dump_enumerated_decls (final_output, dump_flags | TDF_NOUID); + flag_dump_noaddr = save_noaddr; + flag_dump_unnumbered = save_unnumbered; + if (fclose (final_output)) + { + error ("could not close final insn dump file %qs: %m", + flag_dump_final_insns); + flag_dump_final_insns = NULL; + } + } + } + return todo; } struct gimple_opt_pass pass_cleanup_cfg_post_optimizing = @@ -207,13 +205,12 @@ struct gimple_opt_pass pass_cleanup_cfg_post_optimizing = NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ - TV_NONE, /* tv_id */ + TV_TREE_CLEANUP_CFG, /* tv_id */ PROP_cfg, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ 0, /* todo_flags_start */ - TODO_dump_func /* todo_flags_finish */ - | TODO_remove_unused_locals + TODO_remove_unused_locals /* todo_flags_finish */ } }; @@ -232,8 +229,9 @@ execute_free_datastructures (void) return 0; } -/* Pass: fixup_cfg. IPA passes, compilation of earlier functions or inlining - might have changed some properties, such as marked functions nothrow. +/* IPA passes, compilation of earlier functions or inlining + might have changed some properties, such as marked functions nothrow, + pure, const or noreturn. Remove redundant edges and basic blocks, and create new ones if necessary. This pass can't be executed as stand alone pass from pass manager, because @@ -250,15 +248,20 @@ execute_fixup_cfg (void) edge_iterator ei; if (ENTRY_BLOCK_PTR->count) - count_scale = (cgraph_node (current_function_decl)->count * REG_BR_PROB_BASE - + ENTRY_BLOCK_PTR->count / 2) / ENTRY_BLOCK_PTR->count; + count_scale = ((cgraph_get_node (current_function_decl)->count + * REG_BR_PROB_BASE + ENTRY_BLOCK_PTR->count / 2) + / ENTRY_BLOCK_PTR->count); else count_scale = REG_BR_PROB_BASE; - ENTRY_BLOCK_PTR->count = cgraph_node (current_function_decl)->count; + ENTRY_BLOCK_PTR->count = cgraph_get_node (current_function_decl)->count; EXIT_BLOCK_PTR->count = (EXIT_BLOCK_PTR->count * count_scale + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE; + FOR_EACH_EDGE (e, ei, ENTRY_BLOCK_PTR->succs) + e->count = (e->count * count_scale + + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE; + FOR_EACH_BB (bb) { bb->count = (bb->count * count_scale @@ -269,25 +272,31 @@ execute_fixup_cfg (void) tree decl = is_gimple_call (stmt) ? gimple_call_fndecl (stmt) : NULL; - - if (decl - && gimple_call_flags (stmt) & (ECF_CONST - | ECF_PURE - | ECF_LOOPING_CONST_OR_PURE)) + if (decl) { - if (gimple_in_ssa_p (cfun)) + int flags = gimple_call_flags (stmt); + if (flags & (ECF_CONST | ECF_PURE | ECF_LOOPING_CONST_OR_PURE)) { - todo |= TODO_update_ssa | TODO_cleanup_cfg; - mark_symbols_for_renaming (stmt); - update_stmt (stmt); + if (gimple_purge_dead_abnormal_call_edges (bb)) + todo |= TODO_cleanup_cfg; + + if (gimple_in_ssa_p (cfun)) + { + todo |= TODO_update_ssa | TODO_cleanup_cfg; + update_stmt (stmt); + } } - } - maybe_clean_eh_stmt (stmt); + if (flags & ECF_NORETURN + && fixup_noreturn_call (stmt)) + todo |= TODO_cleanup_cfg; + } + + if (maybe_clean_eh_stmt (stmt) + && gimple_purge_dead_eh_edges (bb)) + todo |= TODO_cleanup_cfg; } - if (gimple_purge_dead_eh_edges (bb)) - todo |= TODO_cleanup_cfg; FOR_EACH_EDGE (e, ei, bb->succs) e->count = (e->count * count_scale + REG_BR_PROB_BASE / 2) / REG_BR_PROB_BASE; @@ -295,6 +304,13 @@ execute_fixup_cfg (void) if (count_scale != REG_BR_PROB_BASE) compute_function_frequency (); + /* We just processed all calls. */ + if (cfun->gimple_df) + { + VEC_free (gimple, gc, MODIFIED_NORETURN_CALLS (cfun)); + MODIFIED_NORETURN_CALLS (cfun) = NULL; + } + /* Dump a textual representation of the flowgraph. */ if (dump_file) gimple_dump_cfg (dump_file, dump_flags); @@ -379,7 +395,7 @@ tree_rest_of_compilation (tree fndecl) { location_t saved_loc; - timevar_push (TV_EXPAND); + timevar_push (TV_REST_OF_COMPILATION); gcc_assert (cgraph_global_info_ready); @@ -392,12 +408,6 @@ tree_rest_of_compilation (tree fndecl) input_location = DECL_SOURCE_LOCATION (fndecl); init_function_start (fndecl); - /* Even though we're inside a function body, we still don't want to - call expand_expr to calculate the size of a variable-sized array. - We haven't necessarily assigned RTL to all variables yet, so it's - not safe to try to expand expressions involving them. */ - cfun->dont_save_pending_sizes_p = 1; - gimple_register_cfg_hooks (); bitmap_obstack_initialize (®_obstack); /* FIXME, only at RTL generation*/ @@ -405,8 +415,15 @@ tree_rest_of_compilation (tree fndecl) execute_all_ipa_transforms (); /* Perform all tree transforms and optimizations. */ + + /* Signal the start of passes. */ + invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL); + execute_pass_list (all_passes); + /* Signal the end of passes. */ + invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL); + bitmap_obstack_release (®_obstack); /* Release the default bitmap obstack. */ @@ -430,17 +447,17 @@ tree_rest_of_compilation (tree fndecl) = TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type)); if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0) - warning (OPT_Wlarger_than_eq, "size of return value of %q+D is %u bytes", + warning (OPT_Wlarger_than_, "size of return value of %q+D is %u bytes", fndecl, size_as_int); else - warning (OPT_Wlarger_than_eq, "size of return value of %q+D is larger than %wd bytes", + warning (OPT_Wlarger_than_, "size of return value of %q+D is larger than %wd bytes", fndecl, larger_than_size); } } gimple_set_body (fndecl, NULL); if (DECL_STRUCT_FUNCTION (fndecl) == 0 - && !cgraph_node (fndecl)->origin) + && !cgraph_get_node (fndecl)->origin) { /* Stop pointing to the local nodes about to be freed. But DECL_INITIAL must remain nonzero so we know this @@ -454,5 +471,5 @@ tree_rest_of_compilation (tree fndecl) input_location = saved_loc; ggc_collect (); - timevar_pop (TV_EXPAND); + timevar_pop (TV_REST_OF_COMPILATION); }