Mercurial > hg > CbC > CbC_gcc
diff gcc/passes.c @ 145:1830386684a0
gcc-9.2.0
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 11:34:05 +0900 |
parents | 84e7813d76e9 |
children | 351920fa3827 |
line wrap: on
line diff
--- a/gcc/passes.c Thu Oct 25 07:37:49 2018 +0900 +++ b/gcc/passes.c Thu Feb 13 11:34:05 2020 +0900 @@ -1,5 +1,5 @@ /* Top level of GCC compilers (cc1, cc1plus, etc.) - Copyright (C) 1987-2018 Free Software Foundation, Inc. + Copyright (C) 1987-2020 Free Software Foundation, Inc. This file is part of GCC. @@ -87,8 +87,8 @@ void opt_pass::set_pass_param (unsigned int, bool) { - internal_error ("pass %s needs a set_pass_param implementation to handle the" - " extra argument in NEXT_PASS", name); + internal_error ("pass %s needs a %<set_pass_param%> implementation " + "to handle the extra argument in %<NEXT_PASS%>", name); } bool @@ -361,9 +361,9 @@ if (optimize > 0) { - dumps->dump_start (pass_profile_1->static_pass_number, NULL); + dumps->dump_start (pass_combine_1->static_pass_number, NULL); print_combine_total_stats (); - dumps->dump_finish (pass_profile_1->static_pass_number); + dumps->dump_finish (pass_combine_1->static_pass_number); } /* Do whatever is necessary to finish printing the graphs. */ @@ -459,6 +459,35 @@ }; // class pass_local_optimization_passes +const pass_data pass_data_ipa_remove_symbols = +{ + SIMPLE_IPA_PASS, /* type */ + "remove_symbols", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + TV_NONE, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_remove_functions | TODO_dump_symtab, /* todo_flags_finish */ +}; + +class pass_ipa_remove_symbols : public simple_ipa_opt_pass +{ +public: + pass_ipa_remove_symbols (gcc::context *ctxt) + : simple_ipa_opt_pass (pass_data_ipa_remove_symbols, ctxt) + {} + + /* opt_pass methods: */ + virtual bool gate (function *) + { + /* Don't bother doing anything if the program has errors. */ + return (!seen_error () && !in_lto_p); + } + +}; // class pass_local_optimization_passes + } // anon namespace simple_ipa_opt_pass * @@ -473,6 +502,12 @@ return new pass_local_optimization_passes (ctxt); } +simple_ipa_opt_pass * +make_pass_ipa_remove_symbols (gcc::context *ctxt) +{ + return new pass_ipa_remove_symbols (ctxt); +} + namespace { const pass_data pass_data_all_early_optimizations = @@ -986,9 +1021,9 @@ if (!*phase_name) { if (is_enable) - error ("unrecognized option -fenable"); + error ("unrecognized option %<-fenable%>"); else - error ("unrecognized option -fdisable"); + error ("unrecognized option %<-fdisable%>"); free (argstr); return; } @@ -996,9 +1031,9 @@ if (!pass || pass->static_pass_number == -1) { if (is_enable) - error ("unknown pass %s specified in -fenable", phase_name); + error ("unknown pass %s specified in %<-fenable%>", phase_name); else - error ("unknown pass %s specified in -fdisable", phase_name); + error ("unknown pass %s specified in %<-fdisable%>", phase_name); free (argstr); return; } @@ -1611,24 +1646,39 @@ } } -/* Because inlining might remove no-longer reachable nodes, we need to - keep the array visible to garbage collector to avoid reading collected - out nodes. */ -static int nnodes; -static GTY ((length ("nnodes"))) cgraph_node **order; - -#define uid_hash_t hash_set<int_hash <int, 0, -1> > - /* Hook called when NODE is removed and therefore should be excluded from order vector. DATA is a hash set with removed nodes. */ static void remove_cgraph_node_from_order (cgraph_node *node, void *data) { - uid_hash_t *removed_nodes = (uid_hash_t *)data; - removed_nodes->add (node->get_uid ()); + hash_set<cgraph_node *> *removed_nodes = (hash_set<cgraph_node *> *)data; + removed_nodes->add (node); +} + +/* Hook called when NODE is insert and therefore should be + excluded from removed_nodes. DATA is a hash set with removed nodes. */ + +static void +insert_cgraph_node_to_order (cgraph_node *node, void *data) +{ + hash_set<cgraph_node *> *removed_nodes = (hash_set<cgraph_node *> *)data; + removed_nodes->remove (node); } +/* Hook called when NODE is duplicated and therefore should be + excluded from removed_nodes. DATA is a hash set with removed nodes. */ + +static void +duplicate_cgraph_node_to_order (cgraph_node *node, cgraph_node *node2, + void *data) +{ + hash_set<cgraph_node *> *removed_nodes = (hash_set<cgraph_node *> *)data; + gcc_checking_assert (!removed_nodes->contains (node)); + removed_nodes->remove (node2); +} + + /* If we are in IPA mode (i.e., current_function_decl is NULL), call function CALLBACK for every function in the call graph. Otherwise, call CALLBACK on the current function. @@ -1642,26 +1692,30 @@ callback (cfun, data); else { - cgraph_node_hook_list *hook; - uid_hash_t removed_nodes; - gcc_assert (!order); - order = ggc_vec_alloc<cgraph_node *> (symtab->cgraph_count); + hash_set<cgraph_node *> removed_nodes; + unsigned nnodes = symtab->cgraph_count; + cgraph_node **order = XNEWVEC (cgraph_node *, nnodes); nnodes = ipa_reverse_postorder (order); for (i = nnodes - 1; i >= 0; i--) order[i]->process = 1; - hook = symtab->add_cgraph_removal_hook (remove_cgraph_node_from_order, - &removed_nodes); + cgraph_node_hook_list *removal_hook + = symtab->add_cgraph_removal_hook (remove_cgraph_node_from_order, + &removed_nodes); + cgraph_node_hook_list *insertion_hook + = symtab->add_cgraph_insertion_hook (insert_cgraph_node_to_order, + &removed_nodes); + cgraph_2node_hook_list *duplication_hook + = symtab->add_cgraph_duplication_hook (duplicate_cgraph_node_to_order, + &removed_nodes); for (i = nnodes - 1; i >= 0; i--) { cgraph_node *node = order[i]; /* Function could be inlined and removed as unreachable. */ - if (node == NULL || removed_nodes.contains (node->get_uid ())) + if (node == NULL || removed_nodes.contains (node)) continue; - /* Allow possibly removed nodes to be garbage collected. */ - order[i] = NULL; node->process = 0; if (node->has_gimple_body_p ()) { @@ -1671,11 +1725,12 @@ pop_cfun (); } } - symtab->remove_cgraph_removal_hook (hook); + symtab->remove_cgraph_removal_hook (removal_hook); + symtab->remove_cgraph_insertion_hook (insertion_hook); + symtab->remove_cgraph_duplication_hook (duplication_hook); + + free (order); } - ggc_free (order); - order = NULL; - nnodes = 0; } /* Helper function to perform function body dump. */ @@ -1738,12 +1793,12 @@ static struct profile_record *profile_record; /* Do profile consistency book-keeping for the pass with static number INDEX. - If SUBPASS is zero, we run _before_ the pass, and if SUBPASS is one, then - we run _after_ the pass. RUN is true if the pass really runs, or FALSE + RUN is true if the pass really runs, or FALSE if we are only book-keeping on passes that may have selectively disabled themselves on a given function. */ + static void -check_profile_consistency (int index, int subpass, bool run) +check_profile_consistency (int index, bool run) { pass_manager *passes = g->get_passes (); if (index == -1) @@ -1752,9 +1807,27 @@ profile_record = XCNEWVEC (struct profile_record, passes->passes_by_id_size); gcc_assert (index < passes->passes_by_id_size && index >= 0); - gcc_assert (subpass < 2); profile_record[index].run |= run; - account_profile_record (&profile_record[index], subpass); + profile_record_check_consistency (&profile_record[index]); +} + +/* Account profile the pass with static number INDEX. + RUN is true if the pass really runs, or FALSE + if we are only book-keeping on passes that may have selectively disabled + themselves on a given function. */ + +static void +account_profile (int index, bool run) +{ + pass_manager *passes = g->get_passes (); + if (index == -1) + return; + if (!profile_record) + profile_record = XCNEWVEC (struct profile_record, + passes->passes_by_id_size); + gcc_assert (index < passes->passes_by_id_size && index >= 0); + profile_record[index].run |= run; + profile_record_account_profile (&profile_record[index]); } /* Output profile consistency. */ @@ -1768,7 +1841,6 @@ void pass_manager::dump_profile_report () const { - int i, j; int last_freq_in = 0, last_count_in = 0, last_freq_out = 0, last_count_out = 0; gcov_type last_time = 0, last_size = 0; double rel_time_change, rel_size_change; @@ -1777,86 +1849,86 @@ if (!profile_record) return; fprintf (stderr, "\nProfile consistency report:\n\n"); - fprintf (stderr, "Pass name |mismatch in |mismated out|Overall\n"); - fprintf (stderr, " |freq count |freq count |size time\n"); + fprintf (stderr, " |mismatch |mismatch | |\n"); + fprintf (stderr, "Pass name |IN |IN |OUT |OUT |overall |\n"); + fprintf (stderr, " |freq |count |freq |count |size |time |\n"); - for (i = 0; i < passes_by_id_size; i++) - for (j = 0 ; j < 2; j++) - if (profile_record[i].run) - { - if (last_time) - rel_time_change = (profile_record[i].time[j] - - (double)last_time) * 100 / (double)last_time; - else - rel_time_change = 0; - if (last_size) - rel_size_change = (profile_record[i].size[j] - - (double)last_size) * 100 / (double)last_size; - else - rel_size_change = 0; - - if (profile_record[i].num_mismatched_freq_in[j] != last_freq_in - || profile_record[i].num_mismatched_freq_out[j] != last_freq_out - || profile_record[i].num_mismatched_count_in[j] != last_count_in - || profile_record[i].num_mismatched_count_out[j] != last_count_out - || rel_time_change || rel_size_change) - { - last_reported = i; - fprintf (stderr, "%-20s %s", - passes_by_id [i]->name, - j ? "(after TODO)" : " "); - if (profile_record[i].num_mismatched_freq_in[j] != last_freq_in) - fprintf (stderr, "| %+5i", - profile_record[i].num_mismatched_freq_in[j] - - last_freq_in); - else - fprintf (stderr, "| "); - if (profile_record[i].num_mismatched_count_in[j] != last_count_in) - fprintf (stderr, " %+5i", - profile_record[i].num_mismatched_count_in[j] - - last_count_in); - else - fprintf (stderr, " "); - if (profile_record[i].num_mismatched_freq_out[j] != last_freq_out) - fprintf (stderr, "| %+5i", - profile_record[i].num_mismatched_freq_out[j] - - last_freq_out); - else - fprintf (stderr, "| "); - if (profile_record[i].num_mismatched_count_out[j] != last_count_out) - fprintf (stderr, " %+5i", - profile_record[i].num_mismatched_count_out[j] - - last_count_out); - else - fprintf (stderr, " "); - - /* Size/time units change across gimple and RTL. */ - if (i == pass_expand_1->static_pass_number) - fprintf (stderr, "|----------"); - else - { - if (rel_size_change) - fprintf (stderr, "| %+8.4f%%", rel_size_change); - else - fprintf (stderr, "| "); - if (rel_time_change) - fprintf (stderr, " %+8.4f%%", rel_time_change); - } - fprintf (stderr, "\n"); - last_freq_in = profile_record[i].num_mismatched_freq_in[j]; - last_freq_out = profile_record[i].num_mismatched_freq_out[j]; - last_count_in = profile_record[i].num_mismatched_count_in[j]; - last_count_out = profile_record[i].num_mismatched_count_out[j]; - } - else if (j && last_reported != i) - { - last_reported = i; - fprintf (stderr, "%-20s ------------| | |\n", - passes_by_id [i]->name); - } - last_time = profile_record[i].time[j]; - last_size = profile_record[i].size[j]; - } + for (int i = 1; i < passes_by_id_size; i++) + if (profile_record[i].run) + { + if (last_time) + rel_time_change = (profile_record[i].time + - (double)last_time) * 100 / (double)last_time; + else + rel_time_change = 0; + if (last_size) + rel_size_change = (profile_record[i].size + - (double)last_size) * 100 / (double)last_size; + else + rel_size_change = 0; + + if (profile_record[i].num_mismatched_freq_in != last_freq_in + || profile_record[i].num_mismatched_freq_out != last_freq_out + || profile_record[i].num_mismatched_count_in != last_count_in + || profile_record[i].num_mismatched_count_out != last_count_out + || rel_time_change || rel_size_change) + { + last_reported = i; + fprintf (stderr, "%-33s", passes_by_id[i]->name); + if (profile_record[i].num_mismatched_freq_in != last_freq_in) + fprintf (stderr, "| %+5i", + profile_record[i].num_mismatched_freq_in + - last_freq_in); + else + fprintf (stderr, "| "); + if (profile_record[i].num_mismatched_count_in != last_count_in) + fprintf (stderr, "| %+5i", + profile_record[i].num_mismatched_count_in + - last_count_in); + else + fprintf (stderr, "| "); + if (profile_record[i].num_mismatched_freq_out != last_freq_out) + fprintf (stderr, "| %+5i", + profile_record[i].num_mismatched_freq_out + - last_freq_out); + else + fprintf (stderr, "| "); + if (profile_record[i].num_mismatched_count_out != last_count_out) + fprintf (stderr, "| %+5i", + profile_record[i].num_mismatched_count_out + - last_count_out); + else + fprintf (stderr, "| "); + + /* Size/time units change across gimple and RTL. */ + if (i == pass_expand_1->static_pass_number) + fprintf (stderr, "|----------|----------"); + else + { + if (rel_size_change) + fprintf (stderr, "| %+8.1f%%", rel_size_change); + else + fprintf (stderr, "| "); + if (rel_time_change) + fprintf (stderr, "| %+8.1f%%", rel_time_change); + else + fprintf (stderr, "| "); + } + fprintf (stderr, "|\n"); + last_freq_in = profile_record[i].num_mismatched_freq_in; + last_freq_out = profile_record[i].num_mismatched_freq_out; + last_count_in = profile_record[i].num_mismatched_count_in; + last_count_out = profile_record[i].num_mismatched_count_out; + } + else if (last_reported != i) + { + last_reported = i; + fprintf (stderr, "%-20s ------------| | | | | | |\n", + passes_by_id[i]->name); + } + last_time = profile_record[i].time; + last_size = profile_record[i].size; + } } /* Perform all TODO actions that ought to be done on each function. */ @@ -1872,26 +1944,12 @@ push_cfun (fn); - /* Always cleanup the CFG before trying to update SSA. */ + /* If we need to cleanup the CFG let it perform a needed SSA update. */ if (flags & TODO_cleanup_cfg) - { - 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 (cfun)) - flags |= TODO_update_ssa; - } - - if (flags & TODO_update_ssa_any) - { - unsigned update_flags = flags & TODO_update_ssa_any; - update_ssa (update_flags); - } + cleanup_tree_cfg (flags & TODO_update_ssa_any); + else if (flags & TODO_update_ssa_any) + update_ssa (flags & TODO_update_ssa_any); + gcc_assert (!need_ssa_update_p (fn)); if (flag_tree_pta && (flags & TODO_rebuild_alias)) compute_may_aliases (); @@ -2144,7 +2202,7 @@ static void execute_one_ipa_transform_pass (struct cgraph_node *node, - ipa_opt_pass_d *ipa_pass) + ipa_opt_pass_d *ipa_pass, bool do_not_collect) { opt_pass *pass = ipa_pass; unsigned int todo_after = 0; @@ -2163,20 +2221,20 @@ if (pass->tv_id != TV_NONE) timevar_push (pass->tv_id); + if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)) + check_profile_consistency (pass->static_pass_number, true); + /* Run pre-pass verification. */ execute_todo (ipa_pass->function_transform_todo_flags_start); /* Do it! */ todo_after = ipa_pass->function_transform (node); - if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)) - check_profile_consistency (pass->static_pass_number, 0, true); - /* Run post-pass cleanup and verification. */ execute_todo (todo_after); verify_interpass_invariants (); if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)) - check_profile_consistency (pass->static_pass_number, 1, true); + account_profile (pass->static_pass_number, true); /* Stop timevar. */ if (pass->tv_id != TV_NONE) @@ -2190,14 +2248,14 @@ redirect_edge_var_map_empty (); /* Signal this is a suitable GC collection point. */ - if (!(todo_after & TODO_do_not_ggc_collect)) + if (!do_not_collect && !(todo_after & TODO_do_not_ggc_collect)) ggc_collect (); } /* For the current function, execute all ipa transforms. */ void -execute_all_ipa_transforms (void) +execute_all_ipa_transforms (bool do_not_collect) { struct cgraph_node *node; if (!cfun) @@ -2209,7 +2267,8 @@ unsigned int i; for (i = 0; i < node->ipa_transforms_to_apply.length (); i++) - execute_one_ipa_transform_pass (node, node->ipa_transforms_to_apply[i]); + execute_one_ipa_transform_pass (node, node->ipa_transforms_to_apply[i], + do_not_collect); node->ipa_transforms_to_apply.release (); } } @@ -2311,8 +2370,13 @@ && pass->properties_provided != 0) return false; + /* We need to (re-)build cgraph edges as needed. */ + if (strstr (pass->name, "build_cgraph_edges") != NULL) + return false; + /* Don't skip df init; later RTL passes need it. */ - if (strstr (pass->name, "dfinit") != NULL) + if (strstr (pass->name, "dfinit") != NULL + || strstr (pass->name, "dfinish") != NULL) return false; if (!quiet_flag) @@ -2336,6 +2400,11 @@ if (strcmp (pass->name, "reload") == 0) reload_completed = 1; + /* Similar for pass "pro_and_epilogue" and the "epilogue_completed" global + variable. */ + if (strcmp (pass->name, "pro_and_epilogue") == 0) + epilogue_completed = 1; + /* The INSN_ADDRESSES vec is normally set up by shorten_branches; set it up for the benefit of passes that run after this. */ @@ -2387,8 +2456,8 @@ are not miscounted. */ if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)) { - check_profile_consistency (pass->static_pass_number, 0, false); - check_profile_consistency (pass->static_pass_number, 1, false); + check_profile_consistency (pass->static_pass_number, false); + account_profile (pass->static_pass_number, false); } current_pass = NULL; return false; @@ -2417,6 +2486,9 @@ if (pass->tv_id != TV_NONE) timevar_push (pass->tv_id); + if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)) + check_profile_consistency (pass->static_pass_number, true); + /* Run pre-pass verification. */ execute_todo (pass->todo_flags_start); @@ -2461,13 +2533,10 @@ do_per_function (update_properties_after_pass, pass); - if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)) - check_profile_consistency (pass->static_pass_number, 0, true); - /* Run post-pass cleanup and verification. */ execute_todo (todo_after | pass->todo_flags_finish | TODO_verify_il); if (profile_report && cfun && (cfun->curr_properties & PROP_cfg)) - check_profile_consistency (pass->static_pass_number, 1, true); + account_profile (pass->static_pass_number, true); verify_interpass_invariants (); @@ -2501,6 +2570,8 @@ if (!((todo_after | pass->todo_flags_finish) & TODO_do_not_ggc_collect)) ggc_collect (); + if (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS) + report_heap_memory_use (); return true; } @@ -2642,20 +2713,12 @@ { struct cgraph_node *node = order[i]; - if (gimple_has_body_p (node->decl)) + if (node->definition && node->need_lto_streaming) { - /* When streaming out references to statements as part of some IPA - pass summary, the statements need to have uids assigned and the - following does that for all the IPA passes here. Naturally, this - ordering then matches the one IPA-passes get in their stmt_fixup - hooks. */ - - push_cfun (DECL_STRUCT_FUNCTION (node->decl)); - renumber_gimple_stmt_uids (); - pop_cfun (); + if (gimple_has_body_p (node->decl)) + lto_prepare_function_for_streaming (node); + lto_set_symtab_encoder_in_partition (encoder, node); } - if (node->definition && node->need_lto_streaming) - lto_set_symtab_encoder_in_partition (encoder, node); } FOR_EACH_DEFINED_FUNCTION (node) @@ -2723,28 +2786,13 @@ ipa_write_optimization_summaries (lto_symtab_encoder_t encoder) { struct lto_out_decl_state *state = lto_new_out_decl_state (); - lto_symtab_encoder_iterator lsei; state->symtab_node_encoder = encoder; lto_output_init_mode_table (); lto_push_out_decl_state (state); - for (lsei = lsei_start_function_in_partition (encoder); - !lsei_end_p (lsei); lsei_next_function_in_partition (&lsei)) - { - struct cgraph_node *node = lsei_cgraph_node (lsei); - /* 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->definition - && gimple_has_body_p (node->decl)) - { - push_cfun (DECL_STRUCT_FUNCTION (node->decl)); - renumber_gimple_stmt_uids (); - pop_cfun (); - } - } + + /* Be sure that we did not forget to renumber stmt uids. */ + gcc_checking_assert (flag_wpa); gcc_assert (flag_wpa); pass_manager *passes = g->get_passes (); @@ -2778,6 +2826,8 @@ /* If a timevar is present, start it. */ if (pass->tv_id) timevar_push (pass->tv_id); + if (!quiet_flag) + fprintf (stderr, " <%s>", pass->name ? pass->name : ""); pass_init_dump_file (pass); @@ -2789,6 +2839,8 @@ /* Stop timevar. */ if (pass->tv_id) timevar_pop (pass->tv_id); + ggc_grow (); + report_heap_memory_use (); } if (pass->sub && pass->sub->type != GIMPLE_PASS) @@ -2829,6 +2881,8 @@ /* If a timevar is present, start it. */ if (pass->tv_id) timevar_push (pass->tv_id); + if (!quiet_flag) + fprintf (stderr, " <%s>", pass->name ? pass->name : ""); pass_init_dump_file (pass); @@ -2844,6 +2898,8 @@ if (pass->sub && pass->sub->type != GIMPLE_PASS) ipa_read_optimization_summaries_1 (pass->sub); + ggc_grow (); + report_heap_memory_use (); } pass = pass->next; } @@ -2993,7 +3049,7 @@ continue; if (TREE_ASM_WRITTEN (e->caller->decl)) continue; - if (!e->caller->process && !e->caller->global.inlined_to) + if (!e->caller->process && !e->caller->inlined_to) break; } if (dump_file && e) @@ -3003,5 +3059,3 @@ } return e != NULL; } - -#include "gt-passes.h"