Mercurial > hg > CbC > CbC_gcc
diff gcc/lto-streamer-out.c @ 131:84e7813d76e9
gcc-8.2
author | mir3636 |
---|---|
date | Thu, 25 Oct 2018 07:37:49 +0900 (2018-10-24) |
parents | 04ced10e8804 |
children | 1830386684a0 |
line wrap: on
line diff
--- a/gcc/lto-streamer-out.c Fri Oct 27 22:46:09 2017 +0900 +++ b/gcc/lto-streamer-out.c Thu Oct 25 07:37:49 2018 +0900 @@ -1,6 +1,6 @@ /* Write the GIMPLE representation to a file stream. - Copyright (C) 2009-2017 Free Software Foundation, Inc. + Copyright (C) 2009-2018 Free Software Foundation, Inc. Contributed by Kenneth Zadeck <zadeck@naturalbridge.com> Re-implemented by Diego Novillo <dnovillo@google.com> @@ -41,6 +41,8 @@ #include "builtins.h" #include "gomp-constants.h" #include "debug.h" +#include "omp-offload.h" +#include "print-tree.h" static void lto_write_tree (struct output_block*, tree, bool); @@ -64,6 +66,9 @@ create_output_block (enum lto_section_type section_type) { struct output_block *ob = XCNEW (struct output_block); + if (streamer_dump_file) + fprintf (streamer_dump_file, "Creating output block for %s\n", + lto_section_name [section_type]); ob->section_type = section_type; ob->decl_state = lto_get_out_decl_state (); @@ -129,9 +134,12 @@ if ((TREE_CODE (t) == PARM_DECL || TREE_CODE (t) == RESULT_DECL) && DECL_CONTEXT (t)) return variably_modified_type_p (TREE_TYPE (DECL_CONTEXT (t)), NULL_TREE); - /* IMPORTED_DECL is put into BLOCK and thus it never can be shared. */ + /* IMPORTED_DECL is put into BLOCK and thus it never can be shared. + We should no longer need to stream it. */ else if (TREE_CODE (t) == IMPORTED_DECL) - return false; + gcc_unreachable (); + else if (TREE_CODE (t) == LABEL_DECL) + return FORCED_LABEL (t) || DECL_NONLOCAL (t); else if (((VAR_P (t) && !TREE_STATIC (t)) || TREE_CODE (t) == TYPE_DECL || TREE_CODE (t) == CONST_DECL @@ -737,6 +745,14 @@ enum tree_code code; + if (streamer_dump_file) + { + print_node_brief (streamer_dump_file, " Streaming ", + expr, 4); + fprintf (streamer_dump_file, " to %s\n", + lto_section_name [ob->section_type]); + } + code = TREE_CODE (expr); if (CODE_CONTAINS_STRUCT (code, TS_TYPED)) @@ -747,10 +763,15 @@ if (CODE_CONTAINS_STRUCT (code, TS_VECTOR)) { - for (unsigned i = 0; i < VECTOR_CST_NELTS (expr); ++i) - DFS_follow_tree_edge (VECTOR_CST_ELT (expr, i)); + unsigned int count = vector_cst_encoded_nelts (expr); + for (unsigned int i = 0; i < count; ++i) + DFS_follow_tree_edge (VECTOR_CST_ENCODED_ELT (expr, i)); } + if (CODE_CONTAINS_STRUCT (code, TS_POLY_INT_CST)) + for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i) + DFS_follow_tree_edge (POLY_INT_CST_COEFF (expr, i)); + if (CODE_CONTAINS_STRUCT (code, TS_COMPLEX)) { DFS_follow_tree_edge (TREE_REALPART (expr)); @@ -783,10 +804,7 @@ DFS_follow_tree_edge (DECL_ATTRIBUTES (expr)); - /* Do not follow DECL_ABSTRACT_ORIGIN. We cannot handle debug information - for early inlining so drop it on the floor instead of ICEing in - dwarf2out.c. - We however use DECL_ABSTRACT_ORIGIN == error_mark_node to mark + /* We use DECL_ABSTRACT_ORIGIN == error_mark_node to mark declarations which should be eliminated by decl merging. Be sure none leaks to this point. */ gcc_assert (DECL_ABSTRACT_ORIGIN (expr) != error_mark_node); @@ -796,16 +814,11 @@ || TREE_CODE (expr) == PARM_DECL) && DECL_HAS_VALUE_EXPR_P (expr)) DFS_follow_tree_edge (DECL_VALUE_EXPR (expr)); - if (VAR_P (expr)) + if (VAR_P (expr) + && DECL_HAS_DEBUG_EXPR_P (expr)) DFS_follow_tree_edge (DECL_DEBUG_EXPR (expr)); } - if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON)) - { - if (TREE_CODE (expr) == TYPE_DECL) - DFS_follow_tree_edge (DECL_ORIGINAL_TYPE (expr)); - } - if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)) { /* Make sure we don't inadvertently set the assembler name. */ @@ -819,12 +832,12 @@ DFS_follow_tree_edge (DECL_BIT_FIELD_TYPE (expr)); DFS_follow_tree_edge (DECL_BIT_FIELD_REPRESENTATIVE (expr)); DFS_follow_tree_edge (DECL_FIELD_BIT_OFFSET (expr)); - DFS_follow_tree_edge (DECL_FCONTEXT (expr)); + gcc_checking_assert (!DECL_FCONTEXT (expr)); } if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL)) { - DFS_follow_tree_edge (DECL_VINDEX (expr)); + gcc_checking_assert (DECL_VINDEX (expr) == NULL); DFS_follow_tree_edge (DECL_FUNCTION_PERSONALITY (expr)); DFS_follow_tree_edge (DECL_FUNCTION_SPECIFIC_TARGET (expr)); DFS_follow_tree_edge (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (expr)); @@ -844,7 +857,9 @@ DFS_follow_tree_edge (TYPE_CONTEXT (expr)); /* TYPE_CANONICAL is re-computed during type merging, so no need to follow it here. */ - DFS_follow_tree_edge (TYPE_STUB_DECL (expr)); + /* Do not stream TYPE_STUB_DECL; it is not needed by LTO but currently + it can not be freed by free_lang_data without triggering ICEs in + langhooks. */ } if (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON)) @@ -888,30 +903,17 @@ if (CODE_CONTAINS_STRUCT (code, TS_BLOCK)) { for (tree t = BLOCK_VARS (expr); t; t = TREE_CHAIN (t)) - if (VAR_OR_FUNCTION_DECL_P (t) - && DECL_EXTERNAL (t)) - /* We have to stream externals in the block chain as - non-references. See also - tree-streamer-out.c:streamer_write_chain. */ - DFS_write_tree (ob, expr_state, t, ref_p, false); - else + { + /* We would have to stream externals in the block chain as + non-references but we should have dropped them in + free-lang-data. */ + gcc_assert (!VAR_OR_FUNCTION_DECL_P (t) || !DECL_EXTERNAL (t)); DFS_follow_tree_edge (t); + } DFS_follow_tree_edge (BLOCK_SUPERCONTEXT (expr)); - - /* Follow BLOCK_ABSTRACT_ORIGIN for the limited cases we can - handle - those that represent inlined function scopes. - For the drop rest them on the floor instead of ICEing - in dwarf2out.c, but keep the notion of whether the block - is an inlined block by refering to itself for the sake of - tree_nonartificial_location. */ - if (inlined_function_outer_scope_p (expr)) - { - tree ultimate_origin = block_ultimate_origin (expr); - DFS_follow_tree_edge (ultimate_origin); - } - else if (BLOCK_ABSTRACT_ORIGIN (expr)) - DFS_follow_tree_edge (expr); + DFS_follow_tree_edge (BLOCK_ABSTRACT_ORIGIN (expr)); + /* Do not follow BLOCK_NONLOCALIZED_VARS. We cannot handle debug information for early inlined BLOCKs so drop it on the floor instead of ICEing in dwarf2out.c. */ @@ -935,15 +937,10 @@ DFS_follow_tree_edge (t); DFS_follow_tree_edge (BINFO_OFFSET (expr)); DFS_follow_tree_edge (BINFO_VTABLE (expr)); - DFS_follow_tree_edge (BINFO_VPTR_FIELD (expr)); - - /* The number of BINFO_BASE_ACCESSES has already been emitted in - EXPR's bitfield section. */ - FOR_EACH_VEC_SAFE_ELT (BINFO_BASE_ACCESSES (expr), i, t) - DFS_follow_tree_edge (t); - - /* Do not walk BINFO_INHERITANCE_CHAIN, BINFO_SUBVTT_INDEX - and BINFO_VPTR_INDEX; these are used by C++ FE only. */ + + /* Do not walk BINFO_INHERITANCE_CHAIN, BINFO_SUBVTT_INDEX, + BINFO_BASE_ACCESSES and BINFO_VPTR_INDEX; these are used + by C++ FE only. */ } if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR)) @@ -1073,6 +1070,7 @@ { hstate.add_flag (DECL_PACKED (t)); hstate.add_flag (DECL_NONADDRESSABLE_P (t)); + hstate.add_flag (DECL_PADDING_P (t)); hstate.add_int (DECL_OFFSET_ALIGN (t)); } else if (code == VAR_DECL) @@ -1166,6 +1164,7 @@ hstate.commit_flag (); hstate.add_int (TYPE_PRECISION (t)); hstate.add_int (TYPE_ALIGN (t)); + hstate.add_int (TYPE_EMPTY_P (t)); } if (CODE_CONTAINS_STRUCT (code, TS_TRANSLATION_UNIT_DECL)) @@ -1193,8 +1192,15 @@ } if (CODE_CONTAINS_STRUCT (code, TS_VECTOR)) - for (unsigned i = 0; i < VECTOR_CST_NELTS (t); ++i) - visit (VECTOR_CST_ELT (t, i)); + { + unsigned int count = vector_cst_encoded_nelts (t); + for (unsigned int i = 0; i < count; ++i) + visit (VECTOR_CST_ENCODED_ELT (t, i)); + } + + if (CODE_CONTAINS_STRUCT (code, TS_POLY_INT_CST)) + for (unsigned int i = 0; i < NUM_POLY_INT_COEFFS; ++i) + visit (POLY_INT_CST_COEFF (t, i)); if (CODE_CONTAINS_STRUCT (code, TS_COMPLEX)) { @@ -1233,12 +1239,6 @@ be able to call get_symbol_initial_value. */ } - if (CODE_CONTAINS_STRUCT (code, TS_DECL_NON_COMMON)) - { - if (code == TYPE_DECL) - visit (DECL_ORIGINAL_TYPE (t)); - } - if (CODE_CONTAINS_STRUCT (code, TS_DECL_WITH_VIS)) { if (DECL_ASSEMBLER_NAME_SET_P (t)) @@ -1251,12 +1251,10 @@ visit (DECL_BIT_FIELD_TYPE (t)); visit (DECL_BIT_FIELD_REPRESENTATIVE (t)); visit (DECL_FIELD_BIT_OFFSET (t)); - visit (DECL_FCONTEXT (t)); } if (CODE_CONTAINS_STRUCT (code, TS_FUNCTION_DECL)) { - visit (DECL_VINDEX (t)); visit (DECL_FUNCTION_PERSONALITY (t)); visit (DECL_FUNCTION_SPECIFIC_TARGET (t)); visit (DECL_FUNCTION_SPECIFIC_OPTIMIZATION (t)); @@ -1273,7 +1271,6 @@ ; else visit (TYPE_CONTEXT (t)); - visit (TYPE_STUB_DECL (t)); } if (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON)) @@ -1319,11 +1316,9 @@ visit (b); visit (BINFO_OFFSET (t)); visit (BINFO_VTABLE (t)); - visit (BINFO_VPTR_FIELD (t)); - FOR_EACH_VEC_SAFE_ELT (BINFO_BASE_ACCESSES (t), i, b) - visit (b); /* Do not walk BINFO_INHERITANCE_CHAIN, BINFO_SUBVTT_INDEX - and BINFO_VPTR_INDEX; these are used by C++ FE only. */ + BINFO_BASE_ACCESSES and BINFO_VPTR_INDEX; these are used + by C++ FE only. */ } if (CODE_CONTAINS_STRUCT (code, TS_CONSTRUCTOR)) @@ -1619,6 +1614,13 @@ we stream out. */ gcc_assert (!in_dfs_walk); + if (streamer_dump_file) + { + print_node_brief (streamer_dump_file, " Streaming SCC of ", + expr, 4); + fprintf (streamer_dump_file, "\n"); + } + /* Start the DFS walk. */ /* Save ob state ... */ /* let's see ... */ @@ -1635,6 +1637,12 @@ streamer_write_uhwi (ob, ix); streamer_write_enum (ob->main_stream, LTO_tags, LTO_NUM_TAGS, lto_tree_code_to_tag (TREE_CODE (expr))); + if (streamer_dump_file) + { + print_node_brief (streamer_dump_file, " Finished SCC of ", + expr, 4); + fprintf (streamer_dump_file, "\n\n"); + } lto_stats.num_pickle_refs_output++; } } @@ -1929,6 +1937,7 @@ /* Write OMP SIMD related info. */ streamer_write_hwi (ob, loop->safelen); + streamer_write_hwi (ob, loop->unroll); streamer_write_hwi (ob, loop->dont_vectorize); streamer_write_hwi (ob, loop->force_vectorize); stream_write_tree (ob, loop->simduid, true); @@ -2029,6 +2038,14 @@ stream_output_location (ob, &bp, fn->function_start_locus); stream_output_location (ob, &bp, fn->function_end_locus); + /* Save the instance discriminator if present. */ + int *instance_number_p = NULL; + if (decl_to_instance_map) + instance_number_p = decl_to_instance_map->get (fn->decl); + bp_pack_value (&bp, !!instance_number_p, 1); + if (instance_number_p) + bp_pack_value (&bp, *instance_number_p, sizeof (int) * CHAR_BIT); + streamer_write_bitpack (&bp); } @@ -2055,6 +2072,10 @@ basic_block bb; struct output_block *ob; + if (streamer_dump_file) + fprintf (streamer_dump_file, "\nStreaming body of %s\n", + node->name ()); + function = node->decl; fn = DECL_STRUCT_FUNCTION (function); ob = create_output_block (LTO_section_function_body); @@ -2103,6 +2124,9 @@ debug info. */ if (gimple_has_body_p (function)) { + /* Fixup loops if required to match discovery done in the reader. */ + loop_optimizer_init (AVOID_CFG_MODIFICATIONS); + streamer_write_uhwi (ob, 1); output_struct_function_base (ob, fn); @@ -2160,6 +2184,7 @@ output_cfg (ob, fn); + loop_optimizer_finalize (); pop_cfun (); } else @@ -2169,6 +2194,9 @@ produce_asm (ob, function); destroy_output_block (ob); + if (streamer_dump_file) + fprintf (streamer_dump_file, "Finished streaming %s\n", + node->name ()); } /* Output the body of function NODE->DECL. */ @@ -2179,6 +2207,10 @@ tree var = node->decl; struct output_block *ob; + if (streamer_dump_file) + fprintf (streamer_dump_file, "\nStreaming constructor of %s\n", + node->name ()); + ob = create_output_block (LTO_section_function_body); clear_line_info (ob); @@ -2195,6 +2227,9 @@ produce_asm (ob, var); destroy_output_block (ob); + if (streamer_dump_file) + fprintf (streamer_dump_file, "Finished streaming %s\n", + node->name ()); } @@ -2266,6 +2301,8 @@ struct lto_in_decl_state *in_state; struct lto_out_decl_state *out_state = lto_get_out_decl_state (); + if (streamer_dump_file) + fprintf (streamer_dump_file, "Copying section for %s\n", name); lto_begin_section (section_name, false); free (section_name); @@ -2330,6 +2367,25 @@ return NULL_TREE; } +/* Remove functions that are no longer used from offload_funcs, and mark the + remaining ones with DECL_PRESERVE_P. */ + +static void +prune_offload_funcs (void) +{ + if (!offload_funcs) + return; + + unsigned ix, ix2; + tree *elem_ptr; + VEC_ORDERED_REMOVE_IF (*offload_funcs, ix, ix2, elem_ptr, + cgraph_node::get (*elem_ptr) == NULL); + + tree fn_decl; + FOR_EACH_VEC_ELT (*offload_funcs, ix, fn_decl) + DECL_PRESERVE_P (fn_decl) = 1; +} + /* Main entry point from the pass manager. */ void @@ -2340,6 +2396,8 @@ int i, n_nodes; lto_symtab_encoder_t encoder = lto_get_out_decl_state ()->symtab_node_encoder; + prune_offload_funcs (); + if (flag_checking) output = lto_bitmap_alloc (); @@ -2364,7 +2422,9 @@ } decl_state = lto_new_out_decl_state (); lto_push_out_decl_state (decl_state); - if (gimple_has_body_p (node->decl) || !flag_wpa + if (gimple_has_body_p (node->decl) + || (!flag_wpa + && flag_incremental_link != INCREMENTAL_LINK_LTO) /* Thunks have no body but they may be synthetized at WPA time. */ || DECL_ARGUMENTS (node->decl)) @@ -2396,7 +2456,8 @@ decl_state = lto_new_out_decl_state (); lto_push_out_decl_state (decl_state); if (DECL_INITIAL (node->decl) != error_mark_node - || !flag_wpa) + || (!flag_wpa + && flag_incremental_link != INCREMENTAL_LINK_LTO)) output_constructor (node); else copy_function_or_variable (node); @@ -2440,6 +2501,12 @@ for (index = 0; index < size; index++) { t = lto_tree_ref_encoder_get_tree (encoder, index); + if (streamer_dump_file) + { + fprintf (streamer_dump_file, " %i:", (int)index); + print_node_brief (streamer_dump_file, "", t, 4); + fprintf (streamer_dump_file, "\n"); + } if (!streamer_tree_cache_lookup (ob->writer_cache, t, NULL)) stream_write_tree (ob, t, false); } @@ -2550,13 +2617,11 @@ const char *comdat; unsigned char c; - /* None of the following kinds of symbols are needed in the - symbol table. */ - if (!TREE_PUBLIC (t) - || is_builtin_fn (t) - || DECL_ABSTRACT_P (t) - || (VAR_P (t) && DECL_HARD_REGISTER (t))) - return; + gcc_checking_assert (TREE_PUBLIC (t) + && (TREE_CODE (t) != FUNCTION_DECL + || !fndecl_built_in_p (t)) + && !DECL_ABSTRACT_P (t) + && (!VAR_P (t) || !DECL_HARD_REGISTER (t))); gcc_assert (VAR_OR_FUNCTION_DECL_P (t)); @@ -2644,45 +2709,6 @@ lto_write_data (&slot_num, 4); } -/* Return true if NODE should appear in the plugin symbol table. */ - -bool -output_symbol_p (symtab_node *node) -{ - struct cgraph_node *cnode; - if (!node->real_symbol_p ()) - return false; - /* We keep external functions in symtab for sake of inlining - and devirtualization. We do not want to see them in symbol table as - references unless they are really used. */ - cnode = dyn_cast <cgraph_node *> (node); - if (cnode && (!node->definition || DECL_EXTERNAL (cnode->decl)) - && cnode->callers) - return true; - - /* Ignore all references from external vars initializers - they are not really - part of the compilation unit until they are used by folding. Some symbols, - like references to external construction vtables can not be referred to at all. - We decide this at can_refer_decl_in_current_unit_p. */ - if (!node->definition || DECL_EXTERNAL (node->decl)) - { - int i; - struct ipa_ref *ref; - for (i = 0; node->iterate_referring (i, ref); i++) - { - if (ref->use == IPA_REF_ALIAS) - continue; - if (is_a <cgraph_node *> (ref->referring)) - return true; - if (!DECL_EXTERNAL (ref->referring->decl)) - return true; - } - return false; - } - return true; -} - - /* Write an IL symbol table to OB. SET and VSET are cgraph/varpool node sets we are outputting. */ @@ -2707,7 +2733,7 @@ { symtab_node *node = lsei_node (lsei); - if (!output_symbol_p (node) || DECL_EXTERNAL (node->decl)) + if (DECL_EXTERNAL (node->decl) || !node->output_to_lto_symbol_table_p ()) continue; write_symbol (cache, node->decl, &seen, false); } @@ -2716,7 +2742,7 @@ { symtab_node *node = lsei_node (lsei); - if (!output_symbol_p (node) || !DECL_EXTERNAL (node->decl)) + if (!DECL_EXTERNAL (node->decl) || !node->output_to_lto_symbol_table_p ()) continue; write_symbol (cache, node->decl, &seen, false); } @@ -2763,10 +2789,10 @@ continue; bp_pack_value (&bp, m, 8); bp_pack_enum (&bp, mode_class, MAX_MODE_CLASS, GET_MODE_CLASS (m)); - bp_pack_value (&bp, GET_MODE_SIZE (m), 8); - bp_pack_value (&bp, GET_MODE_PRECISION (m), 16); + bp_pack_poly_value (&bp, GET_MODE_SIZE (m), 16); + bp_pack_poly_value (&bp, GET_MODE_PRECISION (m), 16); bp_pack_value (&bp, GET_MODE_INNER (m), 8); - bp_pack_value (&bp, GET_MODE_NUNITS (m), 8); + bp_pack_poly_value (&bp, GET_MODE_NUNITS (m), 16); switch (GET_MODE_CLASS (m)) { case MODE_FRACT: @@ -2857,12 +2883,18 @@ } /* Write the global symbols. */ + if (streamer_dump_file) + fprintf (streamer_dump_file, "Outputting global stream\n"); lto_output_decl_state_streams (ob, out_state); num_fns = lto_function_decl_states.length (); for (idx = 0; idx < num_fns; idx++) { fn_out_state = lto_function_decl_states[idx]; + if (streamer_dump_file) + fprintf (streamer_dump_file, "Outputting stream for %s\n", + IDENTIFIER_POINTER + (DECL_ASSEMBLER_NAME (fn_out_state->fn_decl))); lto_output_decl_state_streams (ob, fn_out_state); }