> 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?
I have added the enum. We probably could merge flag_wpa, in_lto_p and inremental_link somehow. I will look into that incrementally. Here is updated patch which I have commited. 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 260960) +++ cgraphunit.c (working copy) @@ -2452,8 +2452,11 @@ if (flag_generate_lto || flag_generate_offload) targetm.asm_out.lto_start (); - if (!in_lto_p) + if (!in_lto_p + || flag_incremental_link == INCREMENTAL_LINK_LTO) { + if (!quiet_flag) + fprintf (stderr, "Streaming LTO\n"); if (g->have_offload) { section_name_prefix = OFFLOAD_SECTION_NAME_PREFIX; @@ -2472,7 +2475,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 != INCREMENTAL_LINK_LTO) + || !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 +2564,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 == INCREMENTAL_LINK_LTO) + && flag_lto && !flag_fat_lto_objects)) { timevar_pop (TV_CGRAPHOPT); return; Index: common.opt =================================================================== --- common.opt (revision 260960) +++ common.opt (working copy) @@ -48,9 +48,10 @@ ; 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 +enum incremental_link flag_incremental_link = INCREMENTAL_LINK_NONE ; 0 means straightforward implementation of complex divide acceptable. ; 1 means wide ranges of inputs must work for complex divide. Index: flag-types.h =================================================================== --- flag-types.h (revision 260960) +++ flag-types.h (working copy) @@ -261,6 +261,15 @@ | SANITIZE_BOUNDS_STRICT }; +/* Settings of flag_incremental_link. */ +enum incremental_link { + INCREMENTAL_LINK_NONE, + /* Do incremental linking and produce binary. */ + INCREMENTAL_LINK_NOLTO, + /* Do incremental linking and produce IL. */ + INCREMENTAL_LINK_LTO +}; + /* Different trace modes. */ enum sanitize_coverage_code { /* Trace PC. */ @@ -289,6 +298,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: ipa.c =================================================================== --- ipa.c (revision 260960) +++ ipa.c (working copy) @@ -130,9 +130,11 @@ 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 + == INCREMENTAL_LINK_LTO) + && dyn_cast <varpool_node *> (node) + ->ctor_useable_for_folding_p ())))) { /* Be sure that we will not optimize out alias target body. */ @@ -622,7 +624,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 == INCREMENTAL_LINK_LTO) { vnode->definition = false; (*debug_hooks->late_global_decl) (vnode->decl); @@ -640,8 +642,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 == INCREMENTAL_LINK_LTO) + || ((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 260960) +++ 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 260960) +++ lto/lto-lang.c (working copy) @@ -879,10 +879,30 @@ 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 = INCREMENTAL_LINK_LTO; flag_whole_program = 0; - flag_incremental_link = 1; + 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 = INCREMENTAL_LINK_NOLTO; + break; + case LTO_LINKER_OUTPUT_DYN: /* .so: PID library */ /* On some targets, like i386 it makes sense to build PIC library wihout -fpic for performance reasons. So no need to adjust flags. */ @@ -1269,7 +1289,8 @@ 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 == INCREMENTAL_LINK_LTO + || flag_wpa != NULL); /* Create the basic integer types. */ build_common_tree_nodes (flag_signed_char); Index: lto/lto.c =================================================================== --- lto/lto.c (revision 260960) +++ lto/lto.c (working copy) @@ -3257,7 +3257,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) Index: lto-cgraph.c =================================================================== --- lto-cgraph.c (revision 260960) +++ 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 260960) +++ lto-streamer-out.c (working copy) @@ -2406,7 +2406,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)) @@ -2438,7 +2440,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); Index: passes.c =================================================================== --- passes.c (revision 260960) +++ 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 260960) +++ 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 != INCREMENTAL_LINK_LTO) + || !flag_lto || flag_fat_lto_objects) { /* File-scope initialization for AddressSanitizer. */ if (flag_sanitize & SANITIZE_ADDRESS)