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

Reply via email to