Mercurial > hg > CbC > CbC_gcc
diff gcc/passes.c @ 69:1b10fe6932e1
merge 69
author | Nobuyasu Oshiro <dimolto@cr.ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 21 Aug 2011 07:53:12 +0900 |
parents | 326d9e06c2e3 f6334be47118 |
children | ab0bcb71f44d |
line wrap: on
line diff
--- a/gcc/passes.c Tue Dec 14 03:58:33 2010 +0900 +++ b/gcc/passes.c Sun Aug 21 07:53:12 2011 +0900 @@ -1,6 +1,6 @@ /* Top level of GCC compilers (cc1, cc1plus, etc.) Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 + 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -25,21 +25,9 @@ Error messages and low-level interface to malloc also handled here. */ #include "config.h" -#undef FLOAT /* This is for hpux. They should change hpux. */ -#undef FFS /* Some systems define this in param.h. */ #include "system.h" #include "coretypes.h" #include "tm.h" -#include <signal.h> - -#ifdef HAVE_SYS_RESOURCE_H -# include <sys/resource.h> -#endif - -#ifdef HAVE_SYS_TIMES_H -# include <sys/times.h> -#endif - #include "line-map.h" #include "input.h" #include "tree.h" @@ -62,12 +50,11 @@ #include "graph.h" #include "regs.h" #include "timevar.h" -#include "diagnostic.h" +#include "diagnostic-core.h" #include "params.h" #include "reload.h" #include "dwarf2asm.h" #include "integrate.h" -#include "real.h" #include "debug.h" #include "target.h" #include "langhooks.h" @@ -124,7 +111,7 @@ /* Call from the debugger to get the current pass name. */ -void +DEBUG_FUNCTION void debug_pass (void) { print_current_pass (stderr); @@ -157,6 +144,7 @@ { /* We deferred calling assemble_alias so that we could collect other attributes such as visibility. Emit the alias now. */ + if (!in_lto_p) { tree alias; alias = lookup_attribute ("alias", DECL_ATTRIBUTES (decl)); @@ -191,10 +179,12 @@ || DECL_INITIAL (decl)) && !DECL_EXTERNAL (decl)) { - if (TREE_CODE (decl) != FUNCTION_DECL) + /* When reading LTO unit, we also read varpool, so do not + rebuild it. */ + if (in_lto_p && !at_end) + ; + else if (TREE_CODE (decl) != FUNCTION_DECL) varpool_finalize_decl (decl); - else - assemble_variable (decl, top_level, at_end, 0); } #ifdef ASM_FINISH_DECLARE_OBJECT @@ -210,7 +200,7 @@ 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)) + && !seen_error ()) { timevar_push (TV_SYMOUT); debug_hooks->type_decl (decl, !top_level); @@ -218,7 +208,10 @@ } /* Let cgraph know about the existence of variables. */ - if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl)) + if (in_lto_p && !at_end) + ; + else if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl) + && TREE_STATIC (decl)) varpool_node (decl); } @@ -229,7 +222,7 @@ { /* Avoid confusing the debug information machinery when there are errors. */ - if (errorcount != 0 || sorrycount != 0) + if (seen_error ()) return; timevar_push (TV_SYMOUT); @@ -284,7 +277,7 @@ { /* Early return if there were errors. We can run afoul of our consistency checks, and there's not really much point in fixing them. */ - return !(rtl_dump_and_exit || flag_syntax_only || errorcount || sorrycount); + return !(rtl_dump_and_exit || flag_syntax_only || seen_error ()); } struct gimple_opt_pass pass_rest_of_compilation = @@ -322,7 +315,7 @@ NULL, /* sub */ NULL, /* next */ 0, /* static_pass_number */ - TV_NONE, /* tv_id */ + TV_POSTRELOAD, /* tv_id */ PROP_rtl, /* properties_required */ 0, /* properties_provided */ 0, /* properties_destroyed */ @@ -596,7 +589,7 @@ pass = new_pass; break; default: - error ("Invalid pass positioning operation"); + error ("invalid pass positioning operation"); return false; } @@ -632,6 +625,8 @@ void register_pass (struct register_pass_info *pass_info) { + bool all_instances, success; + /* The checks below could fail in buggy plugins. Existing GCC passes should never fail these checks, so we mention plugin in the messages. */ @@ -647,46 +642,50 @@ pass_info->pass->name); /* Try to insert the new pass to the pass lists. We need to check - all three lists as the reference pass could be in one (or all) of + all five lists as the reference pass could be in one (or all) of them. */ - if (!position_pass (pass_info, &all_lowering_passes) - && !position_pass (pass_info, &all_small_ipa_passes) - && !position_pass (pass_info, &all_regular_ipa_passes) - && !position_pass (pass_info, &all_lto_gen_passes) - && !position_pass (pass_info, &all_passes)) + all_instances = pass_info->ref_pass_instance_number == 0; + success = position_pass (pass_info, &all_lowering_passes); + if (!success || all_instances) + success |= position_pass (pass_info, &all_small_ipa_passes); + if (!success || all_instances) + success |= position_pass (pass_info, &all_regular_ipa_passes); + if (!success || all_instances) + success |= position_pass (pass_info, &all_lto_gen_passes); + if (!success || all_instances) + success |= position_pass (pass_info, &all_passes); + if (!success) fatal_error ("pass %qs not found but is referenced by new pass %qs", pass_info->reference_pass_name, pass_info->pass->name); - else + + /* OK, we have successfully inserted the new pass. We need to register + the dump files for the newly added pass and its duplicates (if any). + Because the registration of plugin/backend passes happens after the + command-line options are parsed, the options that specify single + pass dumping (e.g. -fdump-tree-PASSNAME) cannot be used for new + passes. Therefore we currently can only enable dumping of + new passes when the 'dump-all' flags (e.g. -fdump-tree-all) + are specified. While doing so, we also delete the pass_list_node + objects created during pass positioning. */ + while (added_pass_nodes) { - /* OK, we have successfully inserted the new pass. We need to register - the dump files for the newly added pass and its duplicates (if any). - Because the registration of plugin/backend passes happens after the - command-line options are parsed, the options that specify single - pass dumping (e.g. -fdump-tree-PASSNAME) cannot be used for new - passes. Therefore we currently can only enable dumping of - new passes when the 'dump-all' flags (e.g. -fdump-tree-all) - are specified. While doing so, we also delete the pass_list_node - objects created during pass positioning. */ - while (added_pass_nodes) - { - struct pass_list_node *next_node = added_pass_nodes->next; - enum tree_dump_index tdi; - register_one_dump_file (added_pass_nodes->pass); - if (added_pass_nodes->pass->type == SIMPLE_IPA_PASS - || added_pass_nodes->pass->type == IPA_PASS) - tdi = TDI_ipa_all; - else if (added_pass_nodes->pass->type == GIMPLE_PASS) - tdi = TDI_tree_all; - else - tdi = TDI_rtl_all; - /* Check if dump-all flag is specified. */ - if (get_dump_file_info (tdi)->state) - get_dump_file_info (added_pass_nodes->pass->static_pass_number) - ->state = get_dump_file_info (tdi)->state; - XDELETE (added_pass_nodes); - added_pass_nodes = next_node; - } + struct pass_list_node *next_node = added_pass_nodes->next; + enum tree_dump_index tdi; + register_one_dump_file (added_pass_nodes->pass); + if (added_pass_nodes->pass->type == SIMPLE_IPA_PASS + || added_pass_nodes->pass->type == IPA_PASS) + tdi = TDI_ipa_all; + else if (added_pass_nodes->pass->type == GIMPLE_PASS) + tdi = TDI_tree_all; + else + tdi = TDI_rtl_all; + /* Check if dump-all flag is specified. */ + if (get_dump_file_info (tdi)->state) + get_dump_file_info (added_pass_nodes->pass->static_pass_number) + ->state = get_dump_file_info (tdi)->state; + XDELETE (added_pass_nodes); + added_pass_nodes = next_node; } } @@ -728,46 +727,32 @@ NEXT_PASS (pass_refactor_eh); NEXT_PASS (pass_lower_eh); NEXT_PASS (pass_build_cfg); - NEXT_PASS (pass_lower_complex_O0); - NEXT_PASS (pass_lower_vector); + #ifndef noCbC //NEXT_PASS (pass_warn_function_return); #else NEXT_PASS (pass_warn_function_return); #endif NEXT_PASS (pass_build_cgraph_edges); - NEXT_PASS (pass_inline_parameters); *p = NULL; /* Interprocedural optimization passes. */ p = &all_small_ipa_passes; + NEXT_PASS (pass_ipa_free_lang_data); NEXT_PASS (pass_ipa_function_and_variable_visibility); - NEXT_PASS (pass_ipa_early_inline); - { - struct opt_pass **p = &pass_ipa_early_inline.pass.sub; - NEXT_PASS (pass_early_inline); - NEXT_PASS (pass_inline_parameters); - NEXT_PASS (pass_rebuild_cgraph_edges); - } - NEXT_PASS (pass_ipa_free_lang_data); NEXT_PASS (pass_early_local_passes); { struct opt_pass **p = &pass_early_local_passes.pass.sub; NEXT_PASS (pass_fixup_cfg); - NEXT_PASS (pass_tree_profile); - NEXT_PASS (pass_cleanup_cfg); NEXT_PASS (pass_init_datastructures); NEXT_PASS (pass_expand_omp); NEXT_PASS (pass_referenced_vars); NEXT_PASS (pass_build_ssa); + NEXT_PASS (pass_lower_vector); NEXT_PASS (pass_early_warn_uninitialized); - /* Note that it is not strictly necessary to schedule an early - inline pass here. However, some test cases (e.g., - g++.dg/other/p334435.C g++.dg/other/i386-1.C) expect extern - inline functions to be inlined even at -O0. This does not - happen during the first early inline pass. */ NEXT_PASS (pass_rebuild_cgraph_edges); + NEXT_PASS (pass_inline_parameters); NEXT_PASS (pass_early_inline); NEXT_PASS (pass_all_early_optimizations); { @@ -791,21 +776,33 @@ NEXT_PASS (pass_cleanup_eh); NEXT_PASS (pass_profile); NEXT_PASS (pass_local_pure_const); + /* Split functions creates parts that are not run through + early optimizations again. It is thus good idea to do this + late. */ + NEXT_PASS (pass_split_functions); } NEXT_PASS (pass_release_ssa_names); NEXT_PASS (pass_rebuild_cgraph_edges); NEXT_PASS (pass_inline_parameters); } + NEXT_PASS (pass_ipa_tree_profile); + { + struct opt_pass **p = &pass_ipa_tree_profile.pass.sub; + NEXT_PASS (pass_feedback_split_functions); + } NEXT_PASS (pass_ipa_increase_alignment); NEXT_PASS (pass_ipa_matrix_reorg); + NEXT_PASS (pass_ipa_lower_emutls); *p = NULL; p = &all_regular_ipa_passes; NEXT_PASS (pass_ipa_whole_program_visibility); + NEXT_PASS (pass_ipa_profile); NEXT_PASS (pass_ipa_cp); + NEXT_PASS (pass_ipa_cdtor_merge); NEXT_PASS (pass_ipa_inline); + NEXT_PASS (pass_ipa_pure_const); NEXT_PASS (pass_ipa_reference); - NEXT_PASS (pass_ipa_pure_const); NEXT_PASS (pass_ipa_type_escape); NEXT_PASS (pass_ipa_pta); NEXT_PASS (pass_ipa_struct_reorg); @@ -813,7 +810,6 @@ p = &all_lto_gen_passes; NEXT_PASS (pass_ipa_lto_gimple_out); - NEXT_PASS (pass_ipa_lto_wpa_fixup); NEXT_PASS (pass_ipa_lto_finish_out); /* This must be the last LTO pass. */ *p = NULL; @@ -828,7 +824,6 @@ /* Initial scalar cleanups before alias computation. They ensure memory accesses are not indirect wherever possible. */ NEXT_PASS (pass_strip_predict_hints); - NEXT_PASS (pass_update_address_taken); NEXT_PASS (pass_rename_ssa_copies); NEXT_PASS (pass_complete_unrolli); NEXT_PASS (pass_ccp); @@ -884,20 +879,22 @@ { struct opt_pass **p = &pass_tree_loop.pass.sub; NEXT_PASS (pass_tree_loop_init); + NEXT_PASS (pass_lim); NEXT_PASS (pass_copy_prop); NEXT_PASS (pass_dce_loop); - NEXT_PASS (pass_lim); NEXT_PASS (pass_tree_unswitch); NEXT_PASS (pass_scev_cprop); NEXT_PASS (pass_record_bounds); NEXT_PASS (pass_check_data_deps); NEXT_PASS (pass_loop_distribution); - NEXT_PASS (pass_linear_transform); - NEXT_PASS (pass_graphite_transforms); + NEXT_PASS (pass_copy_prop); + NEXT_PASS (pass_graphite); { - struct opt_pass **p = &pass_graphite_transforms.pass.sub; + struct opt_pass **p = &pass_graphite.pass.sub; + NEXT_PASS (pass_graphite_transforms); + NEXT_PASS (pass_lim); + NEXT_PASS (pass_copy_prop); NEXT_PASS (pass_dce_loop); - NEXT_PASS (pass_lim); } NEXT_PASS (pass_iv_canon); NEXT_PASS (pass_if_conversion); @@ -942,11 +939,13 @@ NEXT_PASS (pass_forwprop); NEXT_PASS (pass_phiopt); NEXT_PASS (pass_fold_builtins); + NEXT_PASS (pass_optimize_widening_mul); NEXT_PASS (pass_tail_calls); NEXT_PASS (pass_rename_ssa_copies); NEXT_PASS (pass_uncprop); NEXT_PASS (pass_local_pure_const); } + NEXT_PASS (pass_lower_complex_O0); NEXT_PASS (pass_cleanup_eh); NEXT_PASS (pass_lower_resx); NEXT_PASS (pass_nrv); @@ -1021,6 +1020,8 @@ NEXT_PASS (pass_postreload_cse); NEXT_PASS (pass_gcse2); NEXT_PASS (pass_split_after_reload); + NEXT_PASS (pass_implicit_zee); + NEXT_PASS (pass_compare_elim_after_reload); NEXT_PASS (pass_branch_target_load_optimize1); NEXT_PASS (pass_thread_prologue_and_epilogue); NEXT_PASS (pass_rtl_dse2); @@ -1112,7 +1113,7 @@ keep the array visible to garbage collector to avoid reading collected out nodes. */ static int nnodes; -static GTY ((length ("nnodes"))) struct cgraph_node **order; +static GTY ((length ("nnodes"))) cgraph_node_ptr *order; /* If we are in IPA mode (i.e., current_function_decl is NULL), call function CALLBACK for every function in the call graph. Otherwise, @@ -1128,7 +1129,7 @@ else { gcc_assert (!order); - order = GGC_NEWVEC (struct cgraph_node *, cgraph_n_nodes); + order = ggc_alloc_vec_cgraph_node_ptr (cgraph_n_nodes); nnodes = cgraph_postorder (order); for (i = nnodes - 1; i >= 0; i--) order[i]->process = 1; @@ -1163,14 +1164,10 @@ execute_function_todo (void *data) { unsigned int flags = (size_t)data; - if (cfun->curr_properties & PROP_ssa) - flags |= TODO_verify_ssa; flags &= ~cfun->last_verified; if (!flags) return; - statistics_fini_pass (); - /* Always cleanup the CFG before trying to update SSA. */ if (flags & TODO_cleanup_cfg) { @@ -1196,15 +1193,13 @@ cfun->last_verified &= ~TODO_verify_ssa; } - if (flags & TODO_update_address_taken) - execute_update_addresses_taken (true); - if (flags & TODO_rebuild_alias) { - if (!(flags & TODO_update_address_taken)) - execute_update_addresses_taken (true); + execute_update_addresses_taken (); compute_may_aliases (); } + else if (optimize && (flags & TODO_update_address_taken)) + execute_update_addresses_taken (); if (flags & TODO_remove_unused_locals) remove_unused_locals (); @@ -1235,32 +1230,25 @@ } if (flags & TODO_rebuild_frequencies) - { - if (profile_status == PROFILE_GUESSED) - { - loop_optimizer_init (0); - add_noreturn_fake_exit_edges (); - mark_irreducible_loops (); - connect_infinite_loops_to_exit (); - estimate_bb_frequencies (); - remove_fake_exit_edges (); - loop_optimizer_finalize (); - } - else if (profile_status == PROFILE_READ) - counts_to_freqs (); - else - gcc_unreachable (); - } + rebuild_frequencies (); + + if (flags & TODO_rebuild_cgraph_edges) + rebuild_cgraph_edges (); + + /* If we've seen errors do not bother running any verifiers. */ + if (seen_error ()) + return; #if defined ENABLE_CHECKING - if (flags & TODO_verify_ssa) + if (flags & TODO_verify_ssa + || (current_loops && loops_state_satisfies_p (LOOP_CLOSED_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 (); + if (current_loops && loops_state_satisfies_p (LOOP_CLOSED_SSA)) + verify_loop_closed_ssa (false); if (flags & TODO_verify_rtl_sharing) verify_rtl_sharing (); #endif @@ -1278,9 +1266,13 @@ gcc_assert (flags & TODO_update_ssa_any); #endif + timevar_push (TV_TODO); + /* Inform the pass whether it is the first time it is run. */ first_pass_instance = (flags & TODO_mark_first_instance) != 0; + statistics_fini_pass (); + do_per_function (execute_function_todo, (void *)(size_t) flags); /* Always remove functions just as before inlining: IPA passes might be @@ -1309,6 +1301,8 @@ df problems. */ if (flags & TODO_df_finish) df_finish_pass ((flags & TODO_df_verify) != 0); + + timevar_pop (TV_TODO); } /* Verify invariants that should hold between passes. This is a place @@ -1317,9 +1311,7 @@ static void verify_interpass_invariants (void) { -#ifdef ENABLE_CHECKING - gcc_assert (!fold_deferring_overflow_warnings_p ()); -#endif + gcc_checking_assert (!fold_deferring_overflow_warnings_p ()); } /* Clear the last verified flag. */ @@ -1357,14 +1349,17 @@ if (dump_file && current_function_decl) { const char *dname, *aname; + struct cgraph_node *node = cgraph_node (current_function_decl); 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 + node->frequency == NODE_FREQUENCY_HOT ? " (hot)" - : cfun->function_frequency == FUNCTION_FREQUENCY_UNLIKELY_EXECUTED + : node->frequency == NODE_FREQUENCY_UNLIKELY_EXECUTED ? " (unlikely executed)" + : node->frequency == NODE_FREQUENCY_EXECUTED_ONCE + ? " (executed once)" : ""); } return initializing_dump; @@ -1487,6 +1482,7 @@ if (!cfun) return; node = cgraph_node (current_function_decl); + if (node->ipa_transforms_to_apply) { unsigned int i; @@ -1630,6 +1626,7 @@ static void ipa_write_summaries_2 (struct opt_pass *pass, cgraph_node_set set, + varpool_node_set vset, struct lto_out_decl_state *state) { while (pass) @@ -1646,7 +1643,11 @@ if (pass->tv_id) timevar_push (pass->tv_id); - ipa_pass->write_summary (set); + pass_init_dump_file (pass); + + ipa_pass->write_summary (set,vset); + + pass_fini_dump_file (pass); /* If a timevar is present, start it. */ if (pass->tv_id) @@ -1654,7 +1655,7 @@ } if (pass->sub && pass->sub->type != GIMPLE_PASS) - ipa_write_summaries_2 (pass->sub, set, state); + ipa_write_summaries_2 (pass->sub, set, vset, state); pass = pass->next; } @@ -1665,14 +1666,16 @@ summaries. SET is the set of nodes to be written. */ static void -ipa_write_summaries_1 (cgraph_node_set set) +ipa_write_summaries_1 (cgraph_node_set set, varpool_node_set vset) { struct lto_out_decl_state *state = lto_new_out_decl_state (); + compute_ltrans_boundary (state, set, vset); + lto_push_out_decl_state (state); - if (!flag_wpa) - ipa_write_summaries_2 (all_regular_ipa_passes, set, state); - ipa_write_summaries_2 (all_lto_gen_passes, set, state); + gcc_assert (!flag_wpa); + ipa_write_summaries_2 (all_regular_ipa_passes, set, vset, state); + ipa_write_summaries_2 (all_lto_gen_passes, set, vset, state); gcc_assert (lto_get_out_decl_state () == state); lto_pop_out_decl_state (); @@ -1685,13 +1688,14 @@ ipa_write_summaries (void) { cgraph_node_set set; + varpool_node_set vset; struct cgraph_node **order; + struct varpool_node *vnode; int i, order_pos; - if (!flag_generate_lto || errorcount || sorrycount) + if (!flag_generate_lto || seen_error ()) return; - lto_new_extern_inline_states (); set = cgraph_node_set_new (); /* Create the callgraph set in the same order used in @@ -1718,25 +1722,98 @@ renumber_gimple_stmt_uids (); pop_cfun (); } - cgraph_node_set_add (set, node); + if (node->analyzed) + cgraph_node_set_add (set, node); } + vset = varpool_node_set_new (); - ipa_write_summaries_1 (set); - lto_delete_extern_inline_states (); + for (vnode = varpool_nodes; vnode; vnode = vnode->next) + if (vnode->needed && !vnode->alias) + varpool_node_set_add (vset, vnode); + + ipa_write_summaries_1 (set, vset); free (order); ggc_free (set); + ggc_free (vset); } +/* Same as execute_pass_list but assume that subpasses of IPA passes + are local passes. If SET is not NULL, write out optimization summaries of + only those node in SET. */ -/* Write all the summaries for the cgraph nodes in SET. If SET is +static void +ipa_write_optimization_summaries_1 (struct opt_pass *pass, cgraph_node_set set, + varpool_node_set vset, + struct lto_out_decl_state *state) +{ + while (pass) + { + struct ipa_opt_pass_d *ipa_pass = (struct ipa_opt_pass_d *)pass; + gcc_assert (!current_function_decl); + gcc_assert (!cfun); + gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS); + if (pass->type == IPA_PASS + && ipa_pass->write_optimization_summary + && (!pass->gate || pass->gate ())) + { + /* If a timevar is present, start it. */ + if (pass->tv_id) + timevar_push (pass->tv_id); + + pass_init_dump_file (pass); + + ipa_pass->write_optimization_summary (set, vset); + + pass_fini_dump_file (pass); + + /* If a timevar is present, start it. */ + if (pass->tv_id) + timevar_pop (pass->tv_id); + } + + if (pass->sub && pass->sub->type != GIMPLE_PASS) + ipa_write_optimization_summaries_1 (pass->sub, set, vset, state); + + pass = pass->next; + } +} + +/* Write all the optimization summaries for the cgraph nodes in SET. If SET is NULL, write out all summaries of all nodes. */ void -ipa_write_summaries_of_cgraph_node_set (cgraph_node_set set) +ipa_write_optimization_summaries (cgraph_node_set set, varpool_node_set vset) { - if (flag_generate_lto && !(errorcount || sorrycount)) - ipa_write_summaries_1 (set); + struct lto_out_decl_state *state = lto_new_out_decl_state (); + cgraph_node_set_iterator csi; + compute_ltrans_boundary (state, set, vset); + + lto_push_out_decl_state (state); + for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi)) + { + struct cgraph_node *node = csi_node (csi); + /* When streaming out references to statements as part of some IPA + pass summary, the statements need to have uids assigned. + + For functions newly born at WPA stage we need to initialize + the uids here. */ + if (node->analyzed + && gimple_has_body_p (node->decl)) + { + push_cfun (DECL_STRUCT_FUNCTION (node->decl)); + renumber_gimple_stmt_uids (); + pop_cfun (); + } + } + + gcc_assert (flag_wpa); + ipa_write_optimization_summaries_1 (all_regular_ipa_passes, set, vset, state); + ipa_write_optimization_summaries_1 (all_lto_gen_passes, set, vset, state); + + gcc_assert (lto_get_out_decl_state () == state); + lto_pop_out_decl_state (); + lto_delete_out_decl_state (state); } /* Same as execute_pass_list but assume that subpasses of IPA passes @@ -1761,8 +1838,12 @@ if (pass->tv_id) timevar_push (pass->tv_id); + pass_init_dump_file (pass); + ipa_pass->read_summary (); + pass_fini_dump_file (pass); + /* Stop timevar. */ if (pass->tv_id) timevar_pop (pass->tv_id); @@ -1781,13 +1862,61 @@ void ipa_read_summaries (void) { - if (!flag_ltrans) - ipa_read_summaries_1 (all_regular_ipa_passes); + ipa_read_summaries_1 (all_regular_ipa_passes); ipa_read_summaries_1 (all_lto_gen_passes); } /* Same as execute_pass_list but assume that subpasses of IPA passes are local passes. */ + +static void +ipa_read_optimization_summaries_1 (struct opt_pass *pass) +{ + while (pass) + { + struct ipa_opt_pass_d *ipa_pass = (struct ipa_opt_pass_d *) pass; + + gcc_assert (!current_function_decl); + gcc_assert (!cfun); + gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS); + + if (pass->gate == NULL || pass->gate ()) + { + if (pass->type == IPA_PASS && ipa_pass->read_optimization_summary) + { + /* If a timevar is present, start it. */ + if (pass->tv_id) + timevar_push (pass->tv_id); + + pass_init_dump_file (pass); + + ipa_pass->read_optimization_summary (); + + pass_fini_dump_file (pass); + + /* Stop timevar. */ + if (pass->tv_id) + timevar_pop (pass->tv_id); + } + + if (pass->sub && pass->sub->type != GIMPLE_PASS) + ipa_read_optimization_summaries_1 (pass->sub); + } + pass = pass->next; + } +} + +/* Read all the summaries for all_regular_ipa_passes and all_lto_gen_passes. */ + +void +ipa_read_optimization_summaries (void) +{ + ipa_read_optimization_summaries_1 (all_regular_ipa_passes); + ipa_read_optimization_summaries_1 (all_lto_gen_passes); +} + +/* Same as execute_pass_list but assume that subpasses of IPA passes + are local passes. */ void execute_ipa_pass_list (struct opt_pass *pass) { @@ -1865,7 +1994,7 @@ extern void debug_properties (unsigned int); extern void dump_properties (FILE *, unsigned int); -void +DEBUG_FUNCTION void dump_properties (FILE *dump, unsigned int props) { fprintf (dump, "Properties:\n"); @@ -1887,9 +2016,13 @@ fprintf (dump, "PROP_rtl\n"); if (props & PROP_gimple_lomp) fprintf (dump, "PROP_gimple_lomp\n"); + if (props & PROP_gimple_lcx) + fprintf (dump, "PROP_gimple_lcx\n"); + if (props & PROP_cfglayout) + fprintf (dump, "PROP_cfglayout\n"); } -void +DEBUG_FUNCTION void debug_properties (unsigned int props) { dump_properties (stderr, props);