diff options
author | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-10-09 15:21:54 +0000 |
---|---|---|
committer | bstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-10-09 15:21:54 +0000 |
commit | 27e0321aadb8c2c656af795612836cf896f0557d (patch) | |
tree | 7624fc2d71c047c04fe2c3c927b645f19760fdee /gcc/passes.c | |
parent | cf4848768d6fbbbaec367eb8107504f1803091e2 (diff) | |
download | gcc-27e0321aadb8c2c656af795612836cf896f0557d.tar.gz |
2009-10-09 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 152583 after the LTO merge
inside trunk.
[during merge with trunk 152583 the version information from GCC
is used, not the checksum of the executable!]
* gcc/melt-runtime.h (melt_gccversionstr): added extern declaration.
* gcc/melt-runtime.c: Moved the #include before everything else.
Updated comment NOTE about gengtype - which is now compatible
with the trunk's.
(melt_gccversionstr): added declaration.
(load_checked_dynamic_module_index): use a gcc version string in
modules, not a checksum of the executable.
(melt_really_initialize): get a second argument for the gcc
version string. Initialize melt_gccversionstr with it.
(plugin_init): Build the gccversionstr out of gcc_version
structure.
(melt_initialize): calls melt_really_initialize with
version_string.
(melt_output_cfile_decl_impl): generates a genversionstr_melt
instead of a genchecksum_melt.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@152591 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/passes.c')
-rw-r--r-- | gcc/passes.c | 292 |
1 files changed, 252 insertions, 40 deletions
diff --git a/gcc/passes.c b/gcc/passes.c index 5b91698e179..5ed12060739 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -84,6 +84,7 @@ along with GCC; see the file COPYING3. If not see #include "tree-dump.h" #include "df.h" #include "predict.h" +#include "lto-streamer.h" #if defined (DWARF2_UNWIND_INFO) || defined (DWARF2_DEBUGGING_INFO) #include "dwarf2out.h" @@ -331,7 +332,8 @@ struct rtl_opt_pass pass_postreload = /* The root of the compilation pass tree, once constructed. */ -struct opt_pass *all_passes, *all_ipa_passes, *all_lowering_passes; +struct opt_pass *all_passes, *all_small_ipa_passes, *all_lowering_passes, + *all_regular_ipa_passes, *all_lto_gen_passes; /* A map from static pass id to optimization pass. */ struct opt_pass **passes_by_id; @@ -611,7 +613,9 @@ register_pass (struct register_pass_info *pass_info) /* 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 them. */ if (!position_pass (pass_info, &all_lowering_passes) - && !position_pass (pass_info, &all_ipa_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)) gcc_unreachable (); else @@ -658,7 +662,7 @@ register_pass (struct register_pass_info *pass_info) If we are optimizing, cgraph_optimize is then invoked: cgraph_optimize () - ipa_passes () -> all_ipa_passes + ipa_passes () -> all_small_ipa_passes cgraph_expand_all_functions () for each node N in the cgraph cgraph_expand_function (N) @@ -679,7 +683,6 @@ init_optimization_passes (void) p = &all_lowering_passes; NEXT_PASS (pass_warn_unused_result); NEXT_PASS (pass_diagnose_omp_blocks); - NEXT_PASS (pass_remove_useless_stmts); NEXT_PASS (pass_mudflap_1); NEXT_PASS (pass_lower_omp); NEXT_PASS (pass_lower_cf); @@ -694,7 +697,7 @@ init_optimization_passes (void) *p = NULL; /* Interprocedural optimization passes. */ - p = &all_ipa_passes; + p = &all_small_ipa_passes; NEXT_PASS (pass_ipa_function_and_variable_visibility); NEXT_PASS (pass_ipa_early_inline); { @@ -716,11 +719,16 @@ init_optimization_passes (void) NEXT_PASS (pass_referenced_vars); NEXT_PASS (pass_build_ssa); 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_early_inline); NEXT_PASS (pass_all_early_optimizations); { struct opt_pass **p = &pass_all_early_optimizations.pass.sub; - NEXT_PASS (pass_rebuild_cgraph_edges); - NEXT_PASS (pass_early_inline); NEXT_PASS (pass_remove_cgraph_callee_edges); NEXT_PASS (pass_rename_ssa_copies); NEXT_PASS (pass_ccp); @@ -747,13 +755,23 @@ init_optimization_passes (void) } NEXT_PASS (pass_ipa_increase_alignment); NEXT_PASS (pass_ipa_matrix_reorg); + *p = NULL; + + p = &all_regular_ipa_passes; + NEXT_PASS (pass_ipa_whole_program_visibility); 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); NEXT_PASS (pass_ipa_pta); - NEXT_PASS (pass_ipa_struct_reorg); + NEXT_PASS (pass_ipa_struct_reorg); + *p = NULL; + + 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; /* These passes are run after IPA passes on every function that is being @@ -1005,7 +1023,13 @@ init_optimization_passes (void) /* Register the passes with the tree dump code. */ register_dump_files (all_lowering_passes, PROP_gimple_any); - register_dump_files (all_ipa_passes, + register_dump_files (all_small_ipa_passes, + PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh + | PROP_cfg); + register_dump_files (all_regular_ipa_passes, + PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh + | PROP_cfg); + register_dump_files (all_lto_gen_passes, PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh | PROP_cfg); register_dump_files (all_passes, @@ -1032,8 +1056,11 @@ do_per_function (void (*callback) (void *data), void *data) push_cfun (DECL_STRUCT_FUNCTION (node->decl)); current_function_decl = node->decl; callback (data); - free_dominance_info (CDI_DOMINATORS); - free_dominance_info (CDI_POST_DOMINATORS); + if (!flag_wpa) + { + free_dominance_info (CDI_DOMINATORS); + free_dominance_info (CDI_POST_DOMINATORS); + } current_function_decl = NULL; pop_cfun (); ggc_collect (); @@ -1072,7 +1099,7 @@ do_per_function_toporder (void (*callback) (void *data), void *data) /* Allow possibly removed nodes to be garbage collected. */ order[i] = NULL; node->process = 0; - if (node->analyzed && (node->needed || node->reachable)) + if (node->analyzed) { push_cfun (DECL_STRUCT_FUNCTION (node->decl)); current_function_decl = node->decl; @@ -1346,7 +1373,7 @@ add_ipa_transform_pass (void *data) /* Execute summary generation for all of the passes in IPA_PASS. */ -static void +void execute_ipa_summary_passes (struct ipa_opt_pass_d *ipa_pass) { while (ipa_pass) @@ -1355,10 +1382,21 @@ execute_ipa_summary_passes (struct ipa_opt_pass_d *ipa_pass) /* Execute all of the IPA_PASSes in the list. */ if (ipa_pass->pass.type == IPA_PASS - && (!pass->gate || pass->gate ())) + && (!pass->gate || pass->gate ()) + && ipa_pass->generate_summary) { pass_init_dump_file (pass); + + /* If a timevar is present, start it. */ + if (pass->tv_id) + timevar_push (pass->tv_id); + ipa_pass->generate_summary (); + + /* Stop timevar. */ + if (pass->tv_id) + timevar_pop (pass->tv_id); + pass_fini_dump_file (pass); } ipa_pass = (struct ipa_opt_pass_d *)ipa_pass->pass.next; @@ -1407,19 +1445,11 @@ execute_one_ipa_transform_pass (struct cgraph_node *node, current_pass = NULL; } -static bool -execute_one_pass (struct opt_pass *pass) -{ - bool initializing_dump; - unsigned int todo_after = 0; - - /* IPA passes are executed on whole program, so cfun should be NULL. - Other passes need function context set. */ - if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS) - gcc_assert (!cfun && !current_function_decl); - else - gcc_assert (cfun && current_function_decl); +/* For the current function, execute all ipa transforms. */ +void +execute_all_ipa_transforms (void) +{ if (cfun && cfun->ipa_transforms_to_apply) { unsigned int i; @@ -1428,12 +1458,28 @@ execute_one_pass (struct opt_pass *pass) for (i = 0; i < VEC_length (ipa_opt_pass, cfun->ipa_transforms_to_apply); i++) execute_one_ipa_transform_pass (node, - VEC_index (ipa_opt_pass, + VEC_index (ipa_opt_pass, cfun->ipa_transforms_to_apply, i)); VEC_free (ipa_opt_pass, heap, cfun->ipa_transforms_to_apply); cfun->ipa_transforms_to_apply = NULL; } +} + +/* Execute PASS. */ + +static bool +execute_one_pass (struct opt_pass *pass) +{ + bool initializing_dump; + unsigned int todo_after = 0; + + /* IPA passes are executed on whole program, so cfun should be NULL. + Other passes need function context set. */ + if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS) + gcc_assert (!cfun && !current_function_decl); + else + gcc_assert (cfun && current_function_decl); current_pass = pass; @@ -1522,26 +1568,159 @@ execute_pass_list (struct opt_pass *pass) } /* Same as execute_pass_list but assume that subpasses of IPA passes - are local passes. */ + are local passes. If SET is not NULL, write out summaries of only + those node in SET. */ + +static void +ipa_write_summaries_2 (struct opt_pass *pass, cgraph_node_set set, + 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_summary + && (!pass->gate || pass->gate ())) + { + /* If a timevar is present, start it. */ + if (pass->tv_id) + timevar_push (pass->tv_id); + + ipa_pass->write_summary (set); + + /* 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_summaries_2 (pass->sub, set, state); + + pass = pass->next; + } +} + +/* Helper function of ipa_write_summaries. Creates and destroys the + decl state and calls ipa_write_summaries_2 for all passes that have + summaries. SET is the set of nodes to be written. */ + +static void +ipa_write_summaries_1 (cgraph_node_set set) +{ + struct lto_out_decl_state *state = lto_new_out_decl_state (); + lto_push_out_decl_state (state); + + ipa_write_summaries_2 (all_regular_ipa_passes, set, state); + ipa_write_summaries_2 (all_lto_gen_passes, set, state); + + gcc_assert (lto_get_out_decl_state () == state); + lto_pop_out_decl_state (); + lto_delete_out_decl_state (state); +} + +/* Write out summaries for all the nodes in the callgraph. */ + void -execute_ipa_pass_list (struct opt_pass *pass) +ipa_write_summaries (void) { - bool summaries_generated = false; - do + cgraph_node_set set; + struct cgraph_node **order; + int i, order_pos; + + if (!flag_generate_lto || errorcount || sorrycount) + return; + + lto_new_extern_inline_states (); + set = cgraph_node_set_new (); + + /* Create the callgraph set in the same order used in + cgraph_expand_all_functions. This mostly facilitates debugging, + since it causes the gimple file to be processed in the same order + as the source code. */ + order = XCNEWVEC (struct cgraph_node *, cgraph_n_nodes); + order_pos = cgraph_postorder (order); + gcc_assert (order_pos == cgraph_n_nodes); + + for (i = order_pos - 1; i >= 0; i--) + cgraph_node_set_add (set, order[i]); + + ipa_write_summaries_1 (set); + lto_delete_extern_inline_states (); + + free (order); + ggc_free (set); +} + + +/* Write all the 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) +{ + if (flag_generate_lto && !(errorcount || sorrycount)) + ipa_write_summaries_1 (set); +} + +/* Same as execute_pass_list but assume that subpasses of IPA passes + are local passes. */ + +static void +ipa_read_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->type == IPA_PASS && (!pass->gate || pass->gate ())) + + if (pass->gate == NULL || pass->gate ()) { - if (!summaries_generated) + if (pass->type == IPA_PASS && ipa_pass->read_summary) { - if (!quiet_flag && !cfun) - fprintf (stderr, " <summary generate>"); - execute_ipa_summary_passes ((struct ipa_opt_pass_d *) pass); + /* If a timevar is present, start it. */ + if (pass->tv_id) + timevar_push (pass->tv_id); + + ipa_pass->read_summary (); + + /* Stop timevar. */ + if (pass->tv_id) + timevar_pop (pass->tv_id); } - summaries_generated = true; + + if (pass->sub && pass->sub->type != GIMPLE_PASS) + ipa_read_summaries_1 (pass->sub); } + pass = pass->next; + } +} + + +/* Read all the summaries for all_regular_ipa_passes and all_lto_gen_passes. */ + +void +ipa_read_summaries (void) +{ + 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. */ +void +execute_ipa_pass_list (struct opt_pass *pass) +{ + do + { + gcc_assert (!current_function_decl); + gcc_assert (!cfun); + gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS); if (execute_one_pass (pass) && pass->sub) { if (pass->sub->type == GIMPLE_PASS) @@ -1553,13 +1732,46 @@ execute_ipa_pass_list (struct opt_pass *pass) else gcc_unreachable (); } - if (!current_function_decl) - cgraph_process_new_functions (); + gcc_assert (!current_function_decl); + cgraph_process_new_functions (); pass = pass->next; } while (pass); } +extern void debug_properties (unsigned int); +extern void dump_properties (FILE *, unsigned int); + +void +dump_properties (FILE *dump, unsigned int props) +{ + fprintf (dump, "Properties:\n"); + if (props & PROP_gimple_any) + fprintf (dump, "PROP_gimple_any\n"); + if (props & PROP_gimple_lcf) + fprintf (dump, "PROP_gimple_lcf\n"); + if (props & PROP_gimple_leh) + fprintf (dump, "PROP_gimple_leh\n"); + if (props & PROP_cfg) + fprintf (dump, "PROP_cfg\n"); + if (props & PROP_referenced_vars) + fprintf (dump, "PROP_referenced_vars\n"); + if (props & PROP_ssa) + fprintf (dump, "PROP_ssa\n"); + if (props & PROP_no_crit_edges) + fprintf (dump, "PROP_no_crit_edges\n"); + if (props & PROP_rtl) + fprintf (dump, "PROP_rtl\n"); + if (props & PROP_gimple_lomp) + fprintf (dump, "PROP_gimple_lomp\n"); +} + +void +debug_properties (unsigned int props) +{ + dump_properties (stderr, props); +} + /* Called by local passes to see if function is called by already processed nodes. Because we process nodes in topological order, this means that function is in recursive cycle or we introduced new direct calls. */ @@ -1571,7 +1783,7 @@ function_called_by_processed_nodes_p (void) { if (e->caller->decl == current_function_decl) continue; - if (!e->caller->analyzed || (!e->caller->needed && !e->caller->reachable)) + if (!e->caller->analyzed) continue; if (TREE_ASM_WRITTEN (e->caller->decl)) continue; |