X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fpasses.c;h=7add1208069b7b0e33681642772b97e5e424efb1;hp=67ffffb350deb9e06db3e57da7e2290e4ca5a1fc;hb=f0727156003b474e6bd987b4d704f7929dad0fd2;hpb=77fce4cd57cbc9db7cdbc15bba96e178dbd0f879 diff --git a/gcc/passes.c b/gcc/passes.c index 67ffffb350d..7add1208069 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -137,7 +137,7 @@ rest_of_decl_compilation (tree decl, /* Can't defer this, because it needs to happen before any later function definitions are processed. */ - if (DECL_REGISTER (decl) && DECL_ASSEMBLER_NAME_SET_P (decl)) + if (DECL_ASSEMBLER_NAME_SET_P (decl) && DECL_REGISTER (decl)) make_decl_rtl (decl); /* Forward declarations for nested functions are not "external", @@ -158,8 +158,7 @@ rest_of_decl_compilation (tree decl, || DECL_INITIAL (decl)) && !DECL_EXTERNAL (decl)) { - if (flag_unit_at_a_time && !cgraph_global_info_ready - && TREE_CODE (decl) != FUNCTION_DECL) + if (TREE_CODE (decl) != FUNCTION_DECL) cgraph_varpool_finalize_decl (decl); else assemble_variable (decl, top_level, at_end, 0); @@ -175,7 +174,10 @@ rest_of_decl_compilation (tree decl, timevar_pop (TV_VARCONST); } - else if (TREE_CODE (decl) == TYPE_DECL) + else if (TREE_CODE (decl) == TYPE_DECL + /* Like in rest_of_type_compilation, avoid confusing the debug + information machinery when there are errors. */ + && !(sorrycount || errorcount)) { timevar_push (TV_SYMOUT); debug_hooks->type_decl (decl, !top_level); @@ -234,12 +236,12 @@ finish_optimization_passes (void) if (graph_dump_format != no_graph) for (i = TDI_end; (dfi = get_dump_file_info (i)) != NULL; ++i) if (dump_initialized_p (i) - && (dfi->flags & TDF_RTL) != 0 + && (dfi->flags & TDF_GRAPH) != 0 && (name = get_dump_file_name (i)) != NULL) - { - finish_graph_dump_file (name); - free (name); - } + { + finish_graph_dump_file (name); + free (name); + } timevar_pop (TV_DUMP); } @@ -418,7 +420,25 @@ next_pass_1 (struct tree_opt_pass **list, struct tree_opt_pass *pass) } -/* Construct the pass tree. */ +/* Construct the pass tree. The sequencing of passes is driven by + the cgraph routines: + + cgraph_finalize_compilation_unit () + for each node N in the cgraph + cgraph_analyze_function (N) + cgraph_lower_function (N) -> all_lowering_passes + + If we are optimizing, cgraph_optimize is then invoked: + + cgraph_optimize () + ipa_passes () -> all_ipa_passes + cgraph_expand_all_functions () + for each node N in the cgraph + cgraph_expand_function (N) + cgraph_lower_function (N) -> Now a NOP. + lang_hooks.callgraph.expand_function (DECL (N)) + tree_rest_of_compilation (DECL (N)) -> all_passes +*/ void init_optimization_passes (void) @@ -430,12 +450,15 @@ init_optimization_passes (void) p = &all_ipa_passes; NEXT_PASS (pass_early_ipa_inline); NEXT_PASS (pass_early_local_passes); + NEXT_PASS (pass_ipa_cp); NEXT_PASS (pass_ipa_inline); + NEXT_PASS (pass_ipa_reference); + NEXT_PASS (pass_ipa_pure_const); + NEXT_PASS (pass_ipa_type_escape); *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). */ + /* All passes needed to lower the function into shape optimizers can + operate on. */ p = &all_lowering_passes; NEXT_PASS (pass_remove_useless_stmts); NEXT_PASS (pass_mudflap_1); @@ -471,12 +494,11 @@ init_optimization_passes (void) 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_return_slot); - NEXT_PASS (pass_del_pta); NEXT_PASS (pass_rename_ssa_copies); NEXT_PASS (pass_early_warn_uninitialized); + NEXT_PASS (pass_eliminate_useless_stores); /* Initial scalar cleanups. */ NEXT_PASS (pass_ccp); @@ -489,10 +511,14 @@ init_optimization_passes (void) NEXT_PASS (pass_merge_phi); NEXT_PASS (pass_dominator); + /* The only copy propagation opportunities left after DOM + should be due to degenerate PHI nodes. So rather than + run the full copy propagator, just discover and copy + propagate away the degenerate PHI nodes. */ + NEXT_PASS (pass_phi_only_copy_prop); + 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); @@ -505,7 +531,13 @@ init_optimization_passes (void) NEXT_PASS (pass_may_alias); NEXT_PASS (pass_rename_ssa_copies); NEXT_PASS (pass_dominator); - NEXT_PASS (pass_copy_prop); + + /* The only copy propagation opportunities left after DOM + should be due to degenerate PHI nodes. So rather than + run the full copy propagator, just discover and copy + propagate away the degenerate PHI nodes. */ + NEXT_PASS (pass_phi_only_copy_prop); + NEXT_PASS (pass_dce); NEXT_PASS (pass_dse); NEXT_PASS (pass_may_alias); @@ -524,9 +556,15 @@ init_optimization_passes (void) NEXT_PASS (pass_reassoc); NEXT_PASS (pass_pre); NEXT_PASS (pass_sink_code); - NEXT_PASS (pass_loop); + NEXT_PASS (pass_tree_loop); NEXT_PASS (pass_dominator); - NEXT_PASS (pass_copy_prop); + + /* The only copy propagation opportunities left after DOM + should be due to degenerate PHI nodes. So rather than + run the full copy propagator, just discover and copy + propagate away the degenerate PHI nodes. */ + NEXT_PASS (pass_phi_only_copy_prop); + NEXT_PASS (pass_cd_dce); /* FIXME: If DCE is not run before checking for uninitialized uses, @@ -552,12 +590,13 @@ init_optimization_passes (void) NEXT_PASS (pass_cleanup_cfg_post_optimizing); *p = NULL; - p = &pass_loop.sub; - NEXT_PASS (pass_loop_init); + p = &pass_tree_loop.sub; + NEXT_PASS (pass_tree_loop_init); NEXT_PASS (pass_copy_prop); NEXT_PASS (pass_lim); - NEXT_PASS (pass_unswitch); + NEXT_PASS (pass_tree_unswitch); NEXT_PASS (pass_scev_cprop); + NEXT_PASS (pass_empty_loop); NEXT_PASS (pass_record_bounds); NEXT_PASS (pass_linear_transform); NEXT_PASS (pass_iv_canon); @@ -566,12 +605,25 @@ init_optimization_passes (void) /* 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); + NEXT_PASS (pass_tree_loop_done); + *p = NULL; + + p = &pass_vectorize.sub; + NEXT_PASS (pass_lower_vector_ssa); + NEXT_PASS (pass_dce_loop); *p = NULL; + p = &pass_loop2.sub; + NEXT_PASS (pass_rtl_loop_init); + NEXT_PASS (pass_rtl_move_loop_invariants); + NEXT_PASS (pass_rtl_unswitch); + NEXT_PASS (pass_rtl_unroll_and_peel_loops); + NEXT_PASS (pass_rtl_doloop); + NEXT_PASS (pass_rtl_loop_done); + *p = NULL; + p = &pass_rest_of_compilation.sub; NEXT_PASS (pass_remove_unnecessary_notes); NEXT_PASS (pass_init_function); @@ -587,9 +639,12 @@ init_optimization_passes (void) NEXT_PASS (pass_loop_optimize); NEXT_PASS (pass_jump_bypass); NEXT_PASS (pass_cfg); - NEXT_PASS (pass_profiling); + NEXT_PASS (pass_branch_prob); NEXT_PASS (pass_rtl_ifcvt); NEXT_PASS (pass_tracer); + /* Perform loop optimizations. It might be better to do them a bit + sooner, but we want the profile feedback to work more + efficiently. */ NEXT_PASS (pass_loop2); NEXT_PASS (pass_web); NEXT_PASS (pass_cse2); @@ -608,12 +663,6 @@ init_optimization_passes (void) 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); @@ -646,11 +695,9 @@ init_optimization_passes (void) #undef NEXT_PASS /* Register the passes with the tree dump code. */ + register_dump_files (all_ipa_passes, true, PROP_gimple_leh | PROP_cfg); 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); + register_dump_files (all_passes, false, PROP_gimple_leh | PROP_cfg); } static unsigned int last_verified; @@ -666,18 +713,28 @@ execute_todo (struct tree_opt_pass *pass, unsigned int flags, bool use_required) 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); - } - + /* Always cleanup the CFG before doing anything else. */ if (flags & TODO_cleanup_cfg) { if (current_loops) cleanup_tree_cfg_loop (); else cleanup_tree_cfg (); + + /* When cleanup_tree_cfg merges consecutive blocks, it may + perform some simplistic propagation when removing single + valued PHI nodes. This propagation may, in turn, cause the + SSA form to become out-of-date (see PR 22037). So, even + if the parent pass had not scheduled an SSA update, we may + still need to do one. */ + if (!(flags & TODO_update_ssa_any) && need_ssa_update_p ()) + flags |= TODO_update_ssa; + } + + if (flags & TODO_update_ssa_any) + { + unsigned update_flags = flags & TODO_update_ssa_any; + update_ssa (update_flags); } if ((flags & TODO_dump_func) @@ -687,7 +744,13 @@ execute_todo (struct tree_opt_pass *pass, unsigned int flags, bool use_required) dump_function_to_file (current_function_decl, dump_file, dump_flags); else if (properties & PROP_cfg) - print_rtl_with_bb (dump_file, get_insns ()); + { + print_rtl_with_bb (dump_file, get_insns ()); + + if (graph_dump_format != no_graph + && (dump_flags & TDF_GRAPH)) + print_rtl_graph_with_bb (dump_file_name, get_insns ()); + } else print_rtl (dump_file, get_insns ()); @@ -761,10 +824,15 @@ execute_one_pass (struct tree_opt_pass *pass) } if (initializing_dump - && graph_dump_format != no_graph + && dump_file + && graph_dump_format != no_graph && (pass->properties_provided & (PROP_cfg | PROP_rtl)) == (PROP_cfg | PROP_rtl)) - clean_graph_dump_file (dump_file_name); + { + get_dump_file_info (pass->static_pass_number)->flags |= TDF_GRAPH; + dump_flags |= TDF_GRAPH; + clean_graph_dump_file (dump_file_name); + } } /* If a timevar is present, start it. */