> 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)