Mercurial > hg > CbC > CbC_gcc
diff gcc/lto/lto.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 |
parents | 04ced10e8804 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/lto/lto.c Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/lto/lto.c Thu Oct 25 07:37:49 2018 +0900 @@ -1,5 +1,5 @@ /* Top-level LTO routines. - Copyright (C) 2009-2017 Free Software Foundation, Inc. + Copyright (C) 2009-2018 Free Software Foundation, Inc. Contributed by CodeSourcery, Inc. This file is part of GCC. @@ -54,6 +54,7 @@ #include "stringpool.h" #include "fold-const.h" #include "attribs.h" +#include "builtins.h" /* Number of parallel tasks to run, -1 if we want to use GNU Make jobserver. */ @@ -316,7 +317,7 @@ if (VECTOR_TYPE_P (type)) { - hstate.add_int (TYPE_VECTOR_SUBPARTS (type)); + hstate.add_poly_int (TYPE_VECTOR_SUBPARTS (type)); hstate.add_int (TYPE_UNSIGNED (type)); } @@ -830,12 +831,19 @@ register_resolution (struct lto_file_decl_data *file_data, tree decl, enum ld_plugin_symbol_resolution resolution) { + bool existed; if (resolution == LDPR_UNKNOWN) return; if (!file_data->resolution_map) file_data->resolution_map = new hash_map<tree, ld_plugin_symbol_resolution>; - file_data->resolution_map->put (decl, resolution); + ld_plugin_symbol_resolution_t &res + = file_data->resolution_map->get_or_insert (decl, &existed); + if (!existed + || resolution == LDPR_PREVAILING_DEF_IRONLY + || resolution == LDPR_PREVAILING_DEF + || resolution == LDPR_PREVAILING_DEF_IRONLY_EXP) + res = resolution; } /* Register DECL with the global symbol table and change its @@ -878,6 +886,18 @@ decl, get_resolution (data_in, ix)); } +/* Check if T is a decl and needs register its resolution info. */ + +static void +lto_maybe_register_decl (struct data_in *data_in, tree t, unsigned ix) +{ + if (TREE_CODE (t) == VAR_DECL) + lto_register_var_decl_in_symtab (data_in, t, ix); + else if (TREE_CODE (t) == FUNCTION_DECL + && !fndecl_built_in_p (t)) + lto_register_function_decl_in_symtab (data_in, t, ix); +} + /* For the type T re-materialize it in the type variant list and the pointer/reference-to chains. */ @@ -1065,6 +1085,12 @@ TREE_FIXED_CST_PTR (t1), TREE_FIXED_CST_PTR (t2))) return false; + if (CODE_CONTAINS_STRUCT (code, TS_VECTOR)) + { + compare_values (VECTOR_CST_LOG2_NPATTERNS); + compare_values (VECTOR_CST_NELTS_PER_PATTERN); + } + if (CODE_CONTAINS_STRUCT (code, TS_DECL_COMMON)) { compare_values (DECL_MODE); @@ -1087,6 +1113,7 @@ { compare_values (DECL_PACKED); compare_values (DECL_NONADDRESSABLE_P); + compare_values (DECL_PADDING_P); compare_values (DECL_OFFSET_ALIGN); } else if (code == VAR_DECL) @@ -1165,6 +1192,7 @@ compare_values (TYPE_NONALIASED_COMPONENT); if (AGGREGATE_TYPE_P (t1)) compare_values (TYPE_TYPELESS_STORAGE); + compare_values (TYPE_EMPTY_P); compare_values (TYPE_PACKED); compare_values (TYPE_RESTRICT); compare_values (TYPE_USER_ALIGN); @@ -1194,8 +1222,8 @@ return false; if (CODE_CONTAINS_STRUCT (code, TS_OPTIMIZATION)) - if (memcmp (TREE_OPTIMIZATION (t1), TREE_OPTIMIZATION (t2), - sizeof (struct cl_optimization)) != 0) + if (!cl_optimization_option_eq (TREE_OPTIMIZATION (t1), + TREE_OPTIMIZATION (t2))) return false; if (CODE_CONTAINS_STRUCT (code, TS_BINFO)) @@ -1279,11 +1307,12 @@ if (CODE_CONTAINS_STRUCT (code, TS_VECTOR)) { - unsigned i; /* Note that the number of elements for EXPR has already been emitted in EXPR's header (see streamer_write_tree_header). */ - for (i = 0; i < VECTOR_CST_NELTS (t1); ++i) - compare_tree_edges (VECTOR_CST_ELT (t1, i), VECTOR_CST_ELT (t2, i)); + unsigned int count = vector_cst_encoded_nelts (t1); + for (unsigned int i = 0; i < count; ++i) + compare_tree_edges (VECTOR_CST_ENCODED_ELT (t1, i), + VECTOR_CST_ENCODED_ELT (t2, i)); } if (CODE_CONTAINS_STRUCT (code, TS_COMPLEX)) @@ -1608,7 +1637,25 @@ /* Fixup the streamer cache with the prevailing nodes according to the tree node mapping computed by compare_tree_sccs. */ if (len == 1) - streamer_tree_cache_replace_tree (cache, pscc->entries[0], from); + { + /* If we got a debug reference queued, see if the prevailing + tree has a debug reference and if not, register the one + for the tree we are about to throw away. */ + if (dref_queue.length () == 1) + { + dref_entry e = dref_queue.pop (); + gcc_assert (e.decl + == streamer_tree_cache_get_tree (cache, from)); + const char *sym; + unsigned HOST_WIDE_INT off; + if (!debug_hooks->die_ref_for_decl (pscc->entries[0], &sym, + &off)) + debug_hooks->register_external_die (pscc->entries[0], + e.sym, e.off); + } + lto_maybe_register_decl (data_in, pscc->entries[0], from); + streamer_tree_cache_replace_tree (cache, pscc->entries[0], from); + } else { tree *map2 = XALLOCAVEC (tree, 2 * len); @@ -1620,8 +1667,12 @@ qsort (map2, len, 2 * sizeof (tree), cmp_tree); qsort (map, len, 2 * sizeof (tree), cmp_tree); for (unsigned i = 0; i < len; ++i) - streamer_tree_cache_replace_tree (cache, map[2*i], - (uintptr_t)map2[2*i]); + { + lto_maybe_register_decl (data_in, map[2*i], + (uintptr_t)map2[2*i]); + streamer_tree_cache_replace_tree (cache, map[2*i], + (uintptr_t)map2[2*i]); + } } /* Free the tree nodes from the read SCC. */ @@ -1633,7 +1684,9 @@ free_node (scc->entries[i]); } - /* Drop DIE references. */ + /* Drop DIE references. + ??? Do as in the size-one SCC case which involves sorting + the queue. */ dref_queue.truncate (0); break; @@ -1659,6 +1712,36 @@ } +/* Compare types based on source file location. */ + +static int +cmp_type_location (const void *p1_, const void *p2_) +{ + tree *p1 = (tree*)(const_cast<void *>(p1_)); + tree *p2 = (tree*)(const_cast<void *>(p2_)); + if (*p1 == *p2) + return 0; + + tree tname1 = TYPE_NAME (*p1); + tree tname2 = TYPE_NAME (*p2); + expanded_location xloc1 = expand_location (DECL_SOURCE_LOCATION (tname1)); + expanded_location xloc2 = expand_location (DECL_SOURCE_LOCATION (tname2)); + + const char *f1 = lbasename (xloc1.file); + const char *f2 = lbasename (xloc2.file); + int r = strcmp (f1, f2); + if (r == 0) + { + int l1 = xloc1.line; + int l2 = xloc2.line; + if (l1 != l2) + return l1 - l2; + return xloc1.column - xloc2.column; + } + else + return r; +} + /* Read all the symbols from buffer DATA, using descriptors in DECL_DATA. RESOLUTIONS is the set of symbols picked by the linker (read from the resolution file when the linker plugin is being used). */ @@ -1675,6 +1758,7 @@ unsigned int i; const uint32_t *data_ptr, *data_end; uint32_t num_decl_states; + auto_vec<tree> odr_types; lto_input_block ib_main ((const char *) data + main_offset, header->main_size, decl_data->mode_table); @@ -1736,14 +1820,15 @@ seen_type = true; num_prevailing_types++; lto_fixup_prevailing_type (t); - } - /* Compute the canonical type of all types. - ??? Should be able to assert that !TYPE_CANONICAL. */ - if (TYPE_P (t) && !TYPE_CANONICAL (t)) - { - gimple_register_canonical_type (t); + + /* Compute the canonical type of all types. + Because SCC components are streamed in random (hash) order + we may have encountered the type before while registering + type canonical of a derived type in the same SCC. */ + if (!TYPE_CANONICAL (t)) + gimple_register_canonical_type (t); if (odr_type_p (t)) - register_odr_type (t); + odr_types.safe_push (t); } /* Link shared INTEGER_CSTs into TYPE_CACHED_VALUEs of its type which is also member of this SCC. */ @@ -1752,13 +1837,7 @@ cache_integer_cst (t); if (!flag_ltrans) { - /* Register variables and functions with the - symbol table. */ - if (TREE_CODE (t) == VAR_DECL) - lto_register_var_decl_in_symtab (data_in, t, from + i); - else if (TREE_CODE (t) == FUNCTION_DECL - && !DECL_BUILT_IN (t)) - lto_register_function_decl_in_symtab (data_in, t, from + i); + lto_maybe_register_decl (data_in, t, from + i); /* Scan the tree for references to global functions or variables and record those for later fixup. */ if (mentions_vars_p (t)) @@ -1811,6 +1890,15 @@ *slot = state; } + /* Sort types for the file before registering in ODR machinery. */ + if (lto_location_cache::current_cache) + lto_location_cache::current_cache->apply_location_cache (); + odr_types.qsort (cmp_type_location); + + /* Register ODR types. */ + for (unsigned i = 0; i < odr_types.length (); i++) + register_odr_type (odr_types[i]); + if (data_ptr != data_end) internal_error ("bytecode stream: garbage at the end of symbols section"); @@ -1987,7 +2075,7 @@ file_data = ggc_alloc<lto_file_decl_data> (); memset(file_data, 0, sizeof (struct lto_file_decl_data)); file_data->id = id; - file_data->section_hash_table = lto_obj_create_section_hash_table ();; + file_data->section_hash_table = lto_obj_create_section_hash_table (); lto_splay_tree_insert (file_ids, id, file_data); /* Maintain list in linker order */ @@ -2252,48 +2340,18 @@ static lto_file *current_lto_file; -/* Helper for qsort; compare partitions and return one with smaller size. - We sort from greatest to smallest so parallel build doesn't stale on the - longest compilation being executed too late. */ - -static int -cmp_partitions_size (const void *a, const void *b) -{ - const struct ltrans_partition_def *pa - = *(struct ltrans_partition_def *const *)a; - const struct ltrans_partition_def *pb - = *(struct ltrans_partition_def *const *)b; - return pb->insns - pa->insns; -} - -/* Helper for qsort; compare partitions and return one with smaller order. */ - -static int -cmp_partitions_order (const void *a, const void *b) -{ - const struct ltrans_partition_def *pa - = *(struct ltrans_partition_def *const *)a; - const struct ltrans_partition_def *pb - = *(struct ltrans_partition_def *const *)b; - int ordera = -1, orderb = -1; - - if (lto_symtab_encoder_size (pa->encoder)) - ordera = lto_symtab_encoder_deref (pa->encoder, 0)->order; - if (lto_symtab_encoder_size (pb->encoder)) - orderb = lto_symtab_encoder_deref (pb->encoder, 0)->order; - return orderb - ordera; -} - /* Actually stream out ENCODER into TEMP_FILENAME. */ static void -do_stream_out (char *temp_filename, lto_symtab_encoder_t encoder) +do_stream_out (char *temp_filename, lto_symtab_encoder_t encoder, int part) { lto_file *file = lto_obj_file_open (temp_filename, true); if (!file) fatal_error (input_location, "lto_obj_file_open() failed"); lto_set_current_out_file (file); + gcc_assert (!dump_file); + streamer_dump_file = dump_begin (TDI_lto_stream_out, NULL, part); ipa_write_optimization_summaries (encoder); free (CONST_CAST (char *, file->filename)); @@ -2301,6 +2359,11 @@ lto_set_current_out_file (NULL); lto_obj_file_close (file); free (file); + if (streamer_dump_file) + { + dump_end (TDI_lto_stream_out, streamer_dump_file); + streamer_dump_file = NULL; + } } /* Wait for forked process and signal errors. */ @@ -2333,14 +2396,14 @@ static void stream_out (char *temp_filename, lto_symtab_encoder_t encoder, - bool ARG_UNUSED (last)) + bool ARG_UNUSED (last), int part) { #ifdef HAVE_WORKING_FORK static int nruns; if (lto_parallelism <= 1) { - do_stream_out (temp_filename, encoder); + do_stream_out (temp_filename, encoder, part); return; } @@ -2360,12 +2423,12 @@ if (!cpid) { setproctitle ("lto1-wpa-streaming"); - do_stream_out (temp_filename, encoder); + do_stream_out (temp_filename, encoder, part); exit (0); } /* Fork failed; lets do the job ourseleves. */ else if (cpid == -1) - do_stream_out (temp_filename, encoder); + do_stream_out (temp_filename, encoder, part); else nruns++; } @@ -2373,13 +2436,13 @@ else { int i; - do_stream_out (temp_filename, encoder); + do_stream_out (temp_filename, encoder, part); for (i = 0; i < nruns; i++) wait_for_child (); } asm_nodes_output = true; #else - do_stream_out (temp_filename, encoder); + do_stream_out (temp_filename, encoder, part); #endif } @@ -2393,7 +2456,8 @@ ltrans_partition part; FILE *ltrans_output_list_stream; char *temp_filename; - vec <char *>temp_filenames = vNULL; + auto_vec <char *>temp_filenames; + auto_vec <int>temp_priority; size_t blen; /* Open the LTRANS output list. */ @@ -2421,15 +2485,6 @@ n_sets = ltrans_partitions.length (); - /* Sort partitions by size so small ones are compiled last. - FIXME: Even when not reordering we may want to output one list for parallel make - and other for final link command. */ - - if (!flag_profile_reorder_functions || !flag_profile_use) - ltrans_partitions.qsort (flag_toplevel_reorder - ? cmp_partitions_size - : cmp_partitions_order); - for (i = 0; i < n_sets; i++) { ltrans_partition part = ltrans_partitions[i]; @@ -2477,10 +2532,11 @@ } gcc_checking_assert (lto_symtab_encoder_size (part->encoder) || !i); - stream_out (temp_filename, part->encoder, i == n_sets - 1); + stream_out (temp_filename, part->encoder, i == n_sets - 1, i); part->encoder = NULL; + temp_priority.safe_push (part->insns); temp_filenames.safe_push (xstrdup (temp_filename)); } ltrans_output_list_stream = fopen (ltrans_output_list, "w"); @@ -2490,13 +2546,13 @@ for (i = 0; i < n_sets; i++) { unsigned int len = strlen (temp_filenames[i]); - if (fwrite (temp_filenames[i], 1, len, ltrans_output_list_stream) < len + if (fprintf (ltrans_output_list_stream, "%i\n", temp_priority[i]) < 0 + || fwrite (temp_filenames[i], 1, len, ltrans_output_list_stream) < len || fwrite ("\n", 1, 1, ltrans_output_list_stream) < 1) fatal_error (input_location, "writing to LTRANS output list %s: %m", ltrans_output_list); free (temp_filenames[i]); } - temp_filenames.release(); lto_stats.num_output_files += n_sets; @@ -2864,13 +2920,26 @@ /* Store resolutions into the symbol table. */ - ld_plugin_symbol_resolution_t *res; FOR_EACH_SYMBOL (snode) - if (snode->real_symbol_p () - && snode->lto_file_data - && snode->lto_file_data->resolution_map - && (res = snode->lto_file_data->resolution_map->get (snode->decl))) - snode->resolution = *res; + if (snode->externally_visible && snode->real_symbol_p () + && snode->lto_file_data && snode->lto_file_data->resolution_map + && !(TREE_CODE (snode->decl) == FUNCTION_DECL + && fndecl_built_in_p (snode->decl)) + && !(VAR_P (snode->decl) && DECL_HARD_REGISTER (snode->decl))) + { + ld_plugin_symbol_resolution_t *res; + + res = snode->lto_file_data->resolution_map->get (snode->decl); + if (!res || *res == LDPR_UNKNOWN) + { + if (snode->output_to_lto_symbol_table_p ()) + fatal_error (input_location, "missing resolution data for %s", + IDENTIFIER_POINTER + (DECL_ASSEMBLER_NAME (snode->decl))); + } + else + snode->resolution = *res; + } for (i = 0; all_file_decl_data[i]; i++) if (all_file_decl_data[i]->resolution_map) { @@ -2928,29 +2997,43 @@ all_file_decl_data[i]->current_decl_state = NULL; } - /* Finally merge the cgraph according to the decl merging decisions. */ - timevar_push (TV_IPA_LTO_CGRAPH_MERGE); - if (symtab->dump_file) - { - fprintf (symtab->dump_file, "Before merging:\n"); - symtab->dump (symtab->dump_file); - } if (!flag_ltrans) { + /* Finally merge the cgraph according to the decl merging decisions. */ + timevar_push (TV_IPA_LTO_CGRAPH_MERGE); + + gcc_assert (!dump_file); + dump_file = dump_begin (lto_link_dump_id, NULL); + + if (dump_file) + { + fprintf (dump_file, "Before merging:\n"); + symtab->dump (dump_file); + } lto_symtab_merge_symbols (); /* Removal of unreachable symbols is needed to make verify_symtab to pass; we are still having duplicated comdat groups containing local statics. We could also just remove them while merging. */ symtab->remove_unreachable_nodes (dump_file); + ggc_collect (); + + if (dump_file) + dump_end (lto_link_dump_id, dump_file); + dump_file = NULL; + timevar_pop (TV_IPA_LTO_CGRAPH_MERGE); } - ggc_collect (); symtab->state = IPA_SSA; - /* FIXME: Technically all node removals happening here are useless, because - WPA should not stream them. */ + /* All node removals happening here are useless, because + WPA should not stream them. Still always perform remove_unreachable_nodes + because we may reshape clone tree, get rid of dead masters of inline + clones and remove symbol entries for read-only variables we keep around + only to be able to constant fold them. */ if (flag_ltrans) - symtab->remove_unreachable_nodes (dump_file); - - timevar_pop (TV_IPA_LTO_CGRAPH_MERGE); + { + if (symtab->dump_file) + symtab->dump (symtab->dump_file); + symtab->remove_unreachable_nodes (symtab->dump_file); + } /* Indicate that the cgraph is built and ready. */ symtab->function_flags_ready = true; @@ -3108,19 +3191,19 @@ if (seen_error ()) return; - if (symtab->dump_file) - { - fprintf (symtab->dump_file, "Optimized "); - symtab->dump (symtab->dump_file); - } - - symtab_node::checking_verify_symtab_nodes (); - bitmap_obstack_release (NULL); - /* We are about to launch the final LTRANS phase, stop the WPA timer. */ timevar_pop (TV_WHOPR_WPA); timevar_push (TV_WHOPR_PARTITIONING); + + gcc_assert (!dump_file); + dump_file = dump_begin (partition_dump_id, NULL); + + if (dump_file) + symtab->dump (dump_file); + + symtab_node::checking_verify_symtab_nodes (); + bitmap_obstack_release (NULL); if (flag_lto_partition == LTO_PARTITION_1TO1) lto_1_to_1_map (); else if (flag_lto_partition == LTO_PARTITION_MAX) @@ -3148,6 +3231,9 @@ to globals with hidden visibility because they are accessed from multiple partitions. */ lto_promote_cross_file_statics (); + if (dump_file) + dump_end (partition_dump_id, dump_file); + dump_file = NULL; timevar_pop (TV_WHOPR_PARTITIONING); timevar_stop (TV_PHASE_OPT_GEN); @@ -3209,7 +3295,8 @@ lto_process_name (void) { if (flag_lto) - setproctitle ("lto1-lto"); + setproctitle (flag_incremental_link == INCREMENTAL_LINK_LTO + ? "lto1-inclink" : "lto1-lto"); if (flag_wpa) setproctitle ("lto1-wpa"); if (flag_ltrans) @@ -3333,7 +3420,9 @@ lto_promote_statics_nonwpa (); /* Annotate the CU DIE and mark the early debug phase as finished. */ + debuginfo_early_start (); debug_hooks->early_finish ("<artificial>"); + debuginfo_early_stop (); /* Let the middle end know that we have read and merged all of the input files. */