On Tue, 8 May 2018, Jan Hubicka wrote:
> Hi,
> this patch adds the symtab support for LTO incremental linking. Most of the
> code path is same for both modes of incremental link except hat we want to
> produce LTO object file rather than compile down to assembly.
>
> Only non-obvious changes are in ipa.c where I hit a bug where we stream in
> initializers that are going to be eliminated form the symbol table for no
> good reasons.
>
> Bootstrapped/regtested x86_64-linux with rest of the incremental link
> patchset.
>
> Honza
>
> * passes.c (ipa_write_summaries): Only modify statements if body
> is in memory.
> * cgraphunit.c (ipa_passes): Also produce intermeidate code when
> incrementally linking.
> (ipa_passes): Likewise.
> * lto-cgraph.c (lto_output_node): When incrementally linking do not
> pass down resolution info.
> * common.opt (flag_incremental_link): Update info.
> * gcc.c (plugin specs): Turn flinker-output=* to
> -plugin-opt=-linker-output-known
> * toplev.c (compile_file): Also cut compilation when doing incremental
> link.
> * flag-types. (enum lto_partition_model): Add
> LTO_LINKER_OUTPUT_NOLTOREL.
> (invoke.texi): Add -flinker-output docs.
> * ipa.c (symbol_table::remove_unreachable_nodes): Handle LTO incremental
> link same way as WPA; do not stream in dead initializers.
>
> * lang.opt (lto_linker_output): Add nolto-rel.
> * lto-lang.c (lto_post_options): Handle LTO_LINKER_OUTPUT_REL
> and LTO_LINKER_OUTPUT_NOLTOREL.
> (lto_init): Generate lto when doing incremental link.
> * lto.c (lto_precess_name): Add lto1-inclink.
> Index: cgraphunit.c
> ===================================================================
> --- cgraphunit.c (revision 260042)
> +++ cgraphunit.c (working copy)
> @@ -2452,8 +2452,10 @@
> if (flag_generate_lto || flag_generate_offload)
> targetm.asm_out.lto_start ();
>
> - if (!in_lto_p)
> + if (!in_lto_p || flag_incremental_link == 2)
Can we have an enum for flag_incremental_link pretty please?
Can't we arrange flag_wpa to be set for this and or merge the
various flags into a more intelligent enum?
> {
> + if (!quiet_flag)
> + fprintf (stderr, "Streaming LTO\n");
> if (g->have_offload)
> {
> section_name_prefix = OFFLOAD_SECTION_NAME_PREFIX;
> @@ -2472,7 +2474,9 @@
> if (flag_generate_lto || flag_generate_offload)
> targetm.asm_out.lto_end ();
>
> - if (!flag_ltrans && (in_lto_p || !flag_lto || flag_fat_lto_objects))
> + if (!flag_ltrans
> + && ((in_lto_p && flag_incremental_link != 2)
> + || !flag_lto || flag_fat_lto_objects))
> execute_ipa_pass_list (passes->all_regular_ipa_passes);
> invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_END, NULL);
>
> @@ -2559,7 +2563,8 @@
>
> /* Do nothing else if any IPA pass found errors or if we are just
> streaming LTO. */
> if (seen_error ()
> - || (!in_lto_p && flag_lto && !flag_fat_lto_objects))
> + || ((!in_lto_p || flag_incremental_link == 2)
> + && flag_lto && !flag_fat_lto_objects))
> {
> timevar_pop (TV_CGRAPHOPT);
> return;
> Index: common.opt
> ===================================================================
> --- common.opt (revision 260042)
> +++ common.opt (working copy)
> @@ -48,7 +48,8 @@
>
> ; This variable is set to non-0 only by LTO front-end. 1 indicates that
> ; the output produced will be used for incrmeental linking (thus weak symbols
> -; can still be bound).
> +; can still be bound) and 2 indicates that the IL is going to be linked and
> +; and output to LTO object file.
> Variable
> int flag_incremental_link = 0
>
> Index: flag-types.h
> ===================================================================
> --- flag-types.h (revision 260042)
> +++ flag-types.h (working copy)
> @@ -289,6 +289,7 @@
> enum lto_linker_output {
> LTO_LINKER_OUTPUT_UNKNOWN,
> LTO_LINKER_OUTPUT_REL,
> + LTO_LINKER_OUTPUT_NOLTOREL,
> LTO_LINKER_OUTPUT_DYN,
> LTO_LINKER_OUTPUT_PIE,
> LTO_LINKER_OUTPUT_EXEC
> Index: gcc.c
> ===================================================================
> --- gcc.c (revision 260042)
> +++ gcc.c (working copy)
> @@ -961,6 +961,7 @@
> -plugin %(linker_plugin_file) \
> -plugin-opt=%(lto_wrapper) \
> -plugin-opt=-fresolution=%u.res \
> + %{flinker-output=*:-plugin-opt=-linker-output-known} \
>
> %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} \
> }" PLUGIN_COND_CLOSE
> #else
> Index: ipa.c
> ===================================================================
> --- ipa.c (revision 260042)
> +++ ipa.c (working copy)
> @@ -130,9 +130,9 @@
> constant folding. Keep references alive so partitioning
> knows about potential references. */
> || (VAR_P (node->decl)
> - && flag_wpa
> - && ctor_for_folding (node->decl)
> - != error_mark_node))))
> + && (flag_wpa || flag_incremental_link == 2)
> + && dyn_cast <varpool_node *> (node)
> + ->ctor_useable_for_folding_p ()))))
> {
> /* Be sure that we will not optimize out alias target
> body. */
> @@ -622,7 +622,7 @@
> fprintf (file, " %s", vnode->dump_name ());
> vnext = next_variable (vnode);
> /* Signal removal to the debug machinery. */
> - if (! flag_wpa)
> + if (! flag_wpa || flag_incremental_link == 2)
> {
> vnode->definition = false;
> (*debug_hooks->late_global_decl) (vnode->decl);
> @@ -640,8 +640,9 @@
> changed = true;
> }
> /* Keep body if it may be useful for constant folding. */
> - if ((init = ctor_for_folding (vnode->decl)) == error_mark_node
> - && !POINTER_BOUNDS_P (vnode->decl))
> + if ((flag_wpa || flag_incremental_link == 2)
> + || ((init = ctor_for_folding (vnode->decl)) == error_mark_node
> + && !POINTER_BOUNDS_P (vnode->decl)))
> vnode->remove_initializer ();
> else
> DECL_INITIAL (vnode->decl) = init;
> Index: lto/lang.opt
> ===================================================================
> --- lto/lang.opt (revision 260042)
> +++ lto/lang.opt (working copy)
> @@ -34,6 +34,9 @@
> Enum(lto_linker_output) String(rel) Value(LTO_LINKER_OUTPUT_REL)
>
> EnumValue
> +Enum(lto_linker_output) String(nolto-rel) Value(LTO_LINKER_OUTPUT_NOLTOREL)
> +
> +EnumValue
> Enum(lto_linker_output) String(dyn) Value(LTO_LINKER_OUTPUT_DYN)
>
> EnumValue
> Index: lto/lto-lang.c
> ===================================================================
> --- lto/lto-lang.c (revision 260042)
> +++ lto/lto-lang.c (working copy)
> @@ -879,7 +879,27 @@
> switch (flag_lto_linker_output)
> {
> case LTO_LINKER_OUTPUT_REL: /* .o: incremental link producing LTO IL */
> + /* Configure compiler same way as normal frontend would do with -flto:
> + this way we read the trees (declarations & types), symbol table,
> + optimization summaries and link them. Subsequently we output new LTO
> + file. */
> + flag_lto = "";
> + flag_incremental_link = 2;
> flag_whole_program = 0;
> + flag_wpa = 0;
> + flag_generate_lto = 1;
> + /* It would be cool to produce .o file directly, but our current
> + simple objects does not contain the lto symbol markers. Go the slow
> + way through the asm file. */
> + lang_hooks.lto.begin_section = lhd_begin_section;
> + lang_hooks.lto.append_data = lhd_append_data;
> + lang_hooks.lto.end_section = lhd_end_section;
> + if (flag_ltrans)
> + error ("-flinker-output=rel and -fltrans are mutually exclussive");
> + break;
> +
> + case LTO_LINKER_OUTPUT_NOLTOREL: /* .o: incremental link producing asm
> */
> + flag_whole_program = 0;
> flag_incremental_link = 1;
> break;
>
> @@ -1269,7 +1289,7 @@
> in_lto_p = true;
>
> /* We need to generate LTO if running in WPA mode. */
> - flag_generate_lto = (flag_wpa != NULL);
> + flag_generate_lto = (flag_incremental_link == 2 || flag_wpa != NULL);
>
> /* Create the basic integer types. */
> build_common_tree_nodes (flag_signed_char);
> Index: lto/lto.c
> ===================================================================
> --- lto/lto.c (revision 260042)
> +++ lto/lto.c (working copy)
> @@ -3257,7 +3257,7 @@
> lto_process_name (void)
> {
> if (flag_lto)
> - setproctitle ("lto1-lto");
> + setproctitle (flag_incremental_link == 2 ? "lto1-inclink" : "lto1-lto");
> if (flag_wpa)
> setproctitle ("lto1-wpa");
> if (flag_ltrans)
> Index: lto-cgraph.c
> ===================================================================
> --- lto-cgraph.c (revision 260042)
> +++ lto-cgraph.c (working copy)
> @@ -540,7 +540,10 @@
> bp_pack_value (&bp, node->thunk.thunk_p, 1);
> bp_pack_value (&bp, node->parallelized_function, 1);
> bp_pack_enum (&bp, ld_plugin_symbol_resolution,
> - LDPR_NUM_KNOWN, node->resolution);
> + LDPR_NUM_KNOWN,
> + /* When doing incremental link, we will get new resolution
> + info next time we process the file. */
> + flag_incremental_link ? LDPR_UNKNOWN : node->resolution);
> bp_pack_value (&bp, node->instrumentation_clone, 1);
> bp_pack_value (&bp, node->split_part, 1);
> streamer_write_bitpack (&bp);
> Index: lto-streamer-out.c
> ===================================================================
> --- lto-streamer-out.c (revision 260042)
> +++ lto-streamer-out.c (working copy)
> @@ -2406,7 +2406,8 @@
> }
> 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 != 2)
> /* Thunks have no body but they may be synthetized
> at WPA time. */
> || DECL_ARGUMENTS (node->decl))
> @@ -2438,7 +2439,7 @@
> 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 != 2))
> output_constructor (node);
> else
> copy_function_or_variable (node);
> Index: passes.c
> ===================================================================
> --- passes.c (revision 260042)
> +++ passes.c (working copy)
> @@ -2708,7 +2708,7 @@
> {
> struct cgraph_node *node = order[i];
>
> - if (node->has_gimple_body_p ())
> + if (gimple_has_body_p (node->decl))
> {
> /* When streaming out references to statements as part of some IPA
> pass summary, the statements need to have uids assigned and the
> Index: toplev.c
> ===================================================================
> --- toplev.c (revision 260042)
> +++ toplev.c (working copy)
> @@ -495,7 +495,8 @@
>
> /* Compilation unit is finalized. When producing non-fat LTO object, we
> are
> basically finished. */
> - if (in_lto_p || !flag_lto || flag_fat_lto_objects)
> + if ((in_lto_p && flag_incremental_link != 2)
> + || !flag_lto || flag_fat_lto_objects)
> {
> /* File-scope initialization for AddressSanitizer. */
> if (flag_sanitize & SANITIZE_ADDRESS)
>
>
--
Richard Biener <[email protected]>
SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB
21284 (AG Nuernberg)