diff mbox series

LTO incremental linking and early debug

Message ID 20180501160612.GB91663@kam.mff.cuni.cz
State New
Headers show
Series LTO incremental linking and early debug | expand

Commit Message

Jan Hubicka May 1, 2018, 4:06 p.m. UTC
Richard,
I have updated my patch for incremental linking into LTO bytecode, but it now breaks in
dwarf2out:
lto1: internal compiler error: in dwarf2out_die_ref_for_decl, at dwarf2out.c:5859
0x5d8a37 dwarf2out_die_ref_for_decl
        ../../gcc/dwarf2out.c:5858
0xa8c311 lto_write_tree_1
        ../../gcc/lto-streamer-out.c:423
0xa9539c lto_write_tree
        ../../gcc/lto-streamer-out.c:449
0xa9539c lto_output_tree_1
        ../../gcc/lto-streamer-out.c:483
0xa9539c DFS::DFS(output_block*, tree_node*, bool, bool, bool)
        ../../gcc/lto-streamer-out.c:670
0xa9656d lto_output_tree(output_block*, tree_node*, bool, bool)
        ../../gcc/lto-streamer-out.c:1642
0xa8c128 write_global_stream
        ../../gcc/lto-streamer-out.c:2496
0xa946be lto_output_decl_state_streams(output_block*, lto_out_decl_state*)
        ../../gcc/lto-streamer-out.c:2543
0xa946be produce_asm_for_decls()
        ../../gcc/lto-streamer-out.c:2870
0xaf1d3f write_lto
        ../../gcc/passes.c:2613
0xaf52fe ipa_write_summaries_1
        ../../gcc/passes.c:2674
0xaf52fe ipa_write_summaries()
        ../../gcc/passes.c:2734
0x8052e2 ipa_passes
        ../../gcc/cgraphunit.c:2470
0x8052e2 symbol_table::compile()
        ../../gcc/cgraphunit.c:2562
0x7701e7 lto_main()
        ../../gcc/lto/lto.c:3388

I guess that is early debug info. This happens in quite few testcases with the patch
attached.  I wonder how we should proceed with this one?


	* lto-plugin.c: Document options; add -linker-output-known;
	determine when to use rel and when nolto-rel output.

	* lto-wrapper.c (run_gcc): Look for -flinker-output=rel also in the
	list of options passed from the driver.
	* passes.c (ipa_write_summaries): Only modify statements if body
	is in memory.
	* cgrpahunit.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.

	* 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.

	* gcc.dg/lto/20081120-2_0.c: Add -flinker-output=nolto-rel
	* gcc.dg/lto/20090126-1_0.c: Likewise.
	* gcc.dg/lto/20091020-2_0.c: Likewise.
	* gcc.dg/lto/20081204-2_0.c: Likewise.
	* gcc.dg/lto/20091015-1_0.c: Likewise.
	* gcc.dg/lto/20090126-2_0.c: Likewiwe.
	* gcc.dg/lto/20090116_0.c: Likewise.
	* gcc.dg/lto/20081224_0.c: Likewise.
	* gcc.dg/lto/20091027-1_0.c: Likewise.
	* gcc.dg/lto/20090219_0.c: Likewise.
	* gcc.dg/lto/20081212-1_0.c: Likewise.
	* gcc.dg/lto/20091013-1_0.c: Likewise.
	* gcc.dg/lto/20081126_0.c: Likewise.
	* gcc.dg/lto/20090206-1_0.c: Likewise.
	* gcc.dg/lto/20091016-1_0.c: Likewise.
	* gcc.dg/lto/20081120-1_0.c: Likewise.
	* gcc.dg/lto/20091020-1_0.c: Likewise.
	* gcc.dg/lto/20100426_0.c: Likewise.
	* gcc.dg/lto/20081204-1_0.c: Likewise.
	* gcc.dg/lto/20091014-1_0.c: Likewise.
	* g++.dg/lto/20081109-1_0.C: Likewise.
	* g++.dg/lto/20100724-1_0.C: Likewise.
	* g++.dg/lto/20081204-1_0.C: Likewise.
	* g++.dg/lto/pr45679-2_0.C: Likewise.
	* g++.dg/lto/20110311-1_0.C: Likewise.
	* g++.dg/lto/20090302_0.C: Likewise.
	* g++.dg/lto/20081118_0.C: Likewise.
	* g++.dg/lto/20091002-2_0.C: Likewise.
	* g++.dg/lto/20081120-2_0.C: Likewise.
	* g++.dg/lto/20081123_0.C: Likewise.
	* g++.dg/lto/20090313_0.C: Likewise.
	* g++.dg/lto/pr54625-1_0.c: Likewise.
	* g++.dg/lto/pr48354-1_0.C: Likewise.
	* g++.dg/lto/20081219_0.C: Likewise.
	* g++.dg/lto/pr48042_0.C: Likewise.
	* g++.dg/lto/20101015-2_0.C: Likewise.
	* g++.dg/lto/pr45679-1_0.C: Likewise.
	* g++.dg/lto/20091026-1_0.C: Likewise.
	* g++.dg/lto/pr45621_0.C: Likewise.
	* g++.dg/lto/20081119-1_0.C: Likewise.
	* g++.dg/lto/20101010-4_0.C: Likewise.
	* g++.dg/lto/20081120-1_0.C: Likewise.
	* g++.dg/lto/20091002-1_0.C: Likewise.
	* g++.dg/lto/20091002-3_0.C: Likewise.
	* gfortran.dg/lto/20091016-1_0.f90: Likewise.
	* gfortran.dg/lto/pr47839_0.f90: Likewise.
	* gfortran.dg/lto/pr46911_0.f: Likewise.
	* gfortran.dg/lto/20091028-1_0.f90: Likewise.
	* gfortran.dg/lto/20091028-2_0.f90: Likewise.

Comments

Richard Biener May 2, 2018, 7:03 a.m. UTC | #1
On Tue, 1 May 2018, Jan Hubicka wrote:

> Richard,
> I have updated my patch for incremental linking into LTO bytecode, but it now breaks in
> dwarf2out:
> lto1: internal compiler error: in dwarf2out_die_ref_for_decl, at dwarf2out.c:5859
> 0x5d8a37 dwarf2out_die_ref_for_decl
>         ../../gcc/dwarf2out.c:5858
> 0xa8c311 lto_write_tree_1
>         ../../gcc/lto-streamer-out.c:423
> 0xa9539c lto_write_tree
>         ../../gcc/lto-streamer-out.c:449
> 0xa9539c lto_output_tree_1
>         ../../gcc/lto-streamer-out.c:483
> 0xa9539c DFS::DFS(output_block*, tree_node*, bool, bool, bool)
>         ../../gcc/lto-streamer-out.c:670
> 0xa9656d lto_output_tree(output_block*, tree_node*, bool, bool)
>         ../../gcc/lto-streamer-out.c:1642
> 0xa8c128 write_global_stream
>         ../../gcc/lto-streamer-out.c:2496
> 0xa946be lto_output_decl_state_streams(output_block*, lto_out_decl_state*)
>         ../../gcc/lto-streamer-out.c:2543
> 0xa946be produce_asm_for_decls()
>         ../../gcc/lto-streamer-out.c:2870
> 0xaf1d3f write_lto
>         ../../gcc/passes.c:2613
> 0xaf52fe ipa_write_summaries_1
>         ../../gcc/passes.c:2674
> 0xaf52fe ipa_write_summaries()
>         ../../gcc/passes.c:2734
> 0x8052e2 ipa_passes
>         ../../gcc/cgraphunit.c:2470
> 0x8052e2 symbol_table::compile()
>         ../../gcc/cgraphunit.c:2562
> 0x7701e7 lto_main()
>         ../../gcc/lto/lto.c:3388
> 
> I guess that is early debug info. This happens in quite few testcases with the patch
> attached.  I wonder how we should proceed with this one?

Hmm, if that's from ltrans stage then you probably need

Index: gcc/dwarf2out.c
===================================================================
--- gcc/dwarf2out.c     (revision 259764)
+++ gcc/dwarf2out.c     (working copy)
@@ -5835,7 +5835,7 @@ dwarf2out_die_ref_for_decl (tree decl, c
   /* During WPA stage we currently use DIEs to store the
      decl <-> label + offset map.  That's quite inefficient but it
      works for now.  */
-  if (flag_wpa)
+  if (in_lto_p)
     {
       dw_die_ref ref = get_AT_ref (die, DW_AT_abstract_origin);
       if (!ref)

we currently only ever end up here during LTRANS or compile stage.

Richard.

> 
> 	* lto-plugin.c: Document options; add -linker-output-known;
> 	determine when to use rel and when nolto-rel output.
> 
> 	* lto-wrapper.c (run_gcc): Look for -flinker-output=rel also in the
> 	list of options passed from the driver.
> 	* passes.c (ipa_write_summaries): Only modify statements if body
> 	is in memory.
> 	* cgrpahunit.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.
> 
> 	* 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.
> 
> 	* gcc.dg/lto/20081120-2_0.c: Add -flinker-output=nolto-rel
> 	* gcc.dg/lto/20090126-1_0.c: Likewise.
> 	* gcc.dg/lto/20091020-2_0.c: Likewise.
> 	* gcc.dg/lto/20081204-2_0.c: Likewise.
> 	* gcc.dg/lto/20091015-1_0.c: Likewise.
> 	* gcc.dg/lto/20090126-2_0.c: Likewiwe.
> 	* gcc.dg/lto/20090116_0.c: Likewise.
> 	* gcc.dg/lto/20081224_0.c: Likewise.
> 	* gcc.dg/lto/20091027-1_0.c: Likewise.
> 	* gcc.dg/lto/20090219_0.c: Likewise.
> 	* gcc.dg/lto/20081212-1_0.c: Likewise.
> 	* gcc.dg/lto/20091013-1_0.c: Likewise.
> 	* gcc.dg/lto/20081126_0.c: Likewise.
> 	* gcc.dg/lto/20090206-1_0.c: Likewise.
> 	* gcc.dg/lto/20091016-1_0.c: Likewise.
> 	* gcc.dg/lto/20081120-1_0.c: Likewise.
> 	* gcc.dg/lto/20091020-1_0.c: Likewise.
> 	* gcc.dg/lto/20100426_0.c: Likewise.
> 	* gcc.dg/lto/20081204-1_0.c: Likewise.
> 	* gcc.dg/lto/20091014-1_0.c: Likewise.
> 	* g++.dg/lto/20081109-1_0.C: Likewise.
> 	* g++.dg/lto/20100724-1_0.C: Likewise.
> 	* g++.dg/lto/20081204-1_0.C: Likewise.
> 	* g++.dg/lto/pr45679-2_0.C: Likewise.
> 	* g++.dg/lto/20110311-1_0.C: Likewise.
> 	* g++.dg/lto/20090302_0.C: Likewise.
> 	* g++.dg/lto/20081118_0.C: Likewise.
> 	* g++.dg/lto/20091002-2_0.C: Likewise.
> 	* g++.dg/lto/20081120-2_0.C: Likewise.
> 	* g++.dg/lto/20081123_0.C: Likewise.
> 	* g++.dg/lto/20090313_0.C: Likewise.
> 	* g++.dg/lto/pr54625-1_0.c: Likewise.
> 	* g++.dg/lto/pr48354-1_0.C: Likewise.
> 	* g++.dg/lto/20081219_0.C: Likewise.
> 	* g++.dg/lto/pr48042_0.C: Likewise.
> 	* g++.dg/lto/20101015-2_0.C: Likewise.
> 	* g++.dg/lto/pr45679-1_0.C: Likewise.
> 	* g++.dg/lto/20091026-1_0.C: Likewise.
> 	* g++.dg/lto/pr45621_0.C: Likewise.
> 	* g++.dg/lto/20081119-1_0.C: Likewise.
> 	* g++.dg/lto/20101010-4_0.C: Likewise.
> 	* g++.dg/lto/20081120-1_0.C: Likewise.
> 	* g++.dg/lto/20091002-1_0.C: Likewise.
> 	* g++.dg/lto/20091002-3_0.C: Likewise.
> 	* gfortran.dg/lto/20091016-1_0.f90: Likewise.
> 	* gfortran.dg/lto/pr47839_0.f90: Likewise.
> 	* gfortran.dg/lto/pr46911_0.f: Likewise.
> 	* gfortran.dg/lto/20091028-1_0.f90: Likewise.
> 	* gfortran.dg/lto/20091028-2_0.f90: Likewise.
> Index: gcc/cgraphunit.c
> ===================================================================
> --- gcc/cgraphunit.c	(revision 259789)
> +++ gcc/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)
>      {
> +      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: gcc/common.opt
> ===================================================================
> --- gcc/common.opt	(revision 259789)
> +++ gcc/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: gcc/doc/invoke.texi
> ===================================================================
> --- gcc/doc/invoke.texi	(revision 259789)
> +++ gcc/doc/invoke.texi	(working copy)
> @@ -12238,6 +12238,50 @@
>  object file names should not be used as arguments.  @xref{Overall
>  Options}.
>  
> +@item -flinker-output=@var{type}
> +@opindex -flinker-output
> +This option controls the code generation of the link time optimizer.  By
> +default the linker output is determined by the linker plugin automatically. For
> +debugging the compiler and in the case of incremental linking it may be useful
> +to control the type manually.
> +
> +If @var{type} is @samp{exec} the code generation is configured to produce static
> +binary. In this case @option{-fpic} and @option{-fpie} are both disabled.
> +
> +If @var{type} is @samp{dyn} the code generation is configured to produce shared
> +library. In this case @option{-fpic} or @option{-fPIC} is preserved.  These
> +options arenot implied to make it possible to build static libraries without
> +position independent code on architectures this is possible, i.e. on x86.
> +
> +If @var{type} is @samp{pie} the code generation is configured to produce
> +@option{-fpie} executable. This result in similar optimizations as @samp{exec}
> +except that @option{-fpie} is not disabled if specified at compilation time.
> +
> +If @var{type} is @samp{rel} the compiler assumes that incremental linking is
> +done.  The sections containing intermediate code for link-time optimization are
> +merged, pre-optimized, and output to the resulting object file. In addition if
> +@option{-ffat-lto-objects} is specified the binary code is produced for future
> +non-lto linking. The object file produced by incremental linking will be smaller
> +than a static library produced from the same object files.  At link-time the
> +result of incremental linking will also load faster to compiler than a static
> +library assuming that majority of objects in the library are used.
> +
> +Finally @samp{nolto-rel} configure compiler to for incremental linking where
> +code generation is forced, final binary is produced and the intermediate code
> +for later link-time optimization is stripped. When multiple object files are
> +linked together the resulting code will be optimized better than with link time
> +optimizations disabled (for example, the cross-module inlining will happen),
> +most of benefits of whole program optimizations are however lost. 
> +
> +During the incremental link (by @option{-r}) the linker plugin will default to
> +@option{rel}. With current interfaces to GNU Binutils it is however not
> +possible to link incrementally LTO objects and non-LTO objects into a single
> +mixed object file.  In the case any of object files in incremental link can not
> +be used for link-time optimization the linker plugin will output warning and
> +use @samp{nolto-rel}. To maintain the whole program optimization it is
> +recommended to link such objects into static library instead. Alternatively it
> +is possible to use H.J. Lu's binutils with support for mixed objects.
> +
>  @item -fuse-ld=bfd
>  @opindex fuse-ld=bfd
>  Use the @command{bfd} linker instead of the default linker.
> Index: gcc/flag-types.h
> ===================================================================
> --- gcc/flag-types.h	(revision 259789)
> +++ gcc/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/gcc.c
> ===================================================================
> --- gcc/gcc.c	(revision 259789)
> +++ gcc/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: gcc/lto/lang.opt
> ===================================================================
> --- gcc/lto/lang.opt	(revision 259789)
> +++ gcc/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: gcc/lto/lto-lang.c
> ===================================================================
> --- gcc/lto/lto-lang.c	(revision 259789)
> +++ gcc/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: gcc/lto-cgraph.c
> ===================================================================
> --- gcc/lto-cgraph.c	(revision 259789)
> +++ gcc/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: gcc/lto-wrapper.c
> ===================================================================
> --- gcc/lto-wrapper.c	(revision 259789)
> +++ gcc/lto-wrapper.c	(working copy)
> @@ -1054,6 +1054,7 @@
>    bool have_offload = false;
>    unsigned lto_argc = 0, ltoobj_argc = 0;
>    char **lto_argv, **ltoobj_argv;
> +  bool linker_output_rel = false;
>    bool skip_debug = false;
>    unsigned n_debugobj;
>  
> @@ -1106,9 +1107,12 @@
>  	  file_offset = (off_t) loffset;
>  	}
>        fd = open (filename, O_RDONLY | O_BINARY);
> +      /* Linker plugin passes -fresolution and -flinker-output options.  */
>        if (fd == -1)
>  	{
>  	  lto_argv[lto_argc++] = argv[i];
> +	  if (strcmp (argv[i], "-flinker-output=rel") == 0)
> +	    linker_output_rel = true;
>  	  continue;
>  	}
>  
> @@ -1173,6 +1177,11 @@
>  	  lto_mode = LTO_MODE_WHOPR;
>  	  break;
>  
> +	case OPT_flinker_output_:
> +	  linker_output_rel = !strcmp (option->arg, "rel");
> +	  break;
> +
> +
>  	default:
>  	  break;
>  	}
> @@ -1189,6 +1198,9 @@
>        fputc ('\n', stderr);
>      }
>  
> +  if (linker_output_rel)
> +    no_partition = true;
> +
>    if (no_partition)
>      {
>        lto_mode = LTO_MODE_LTO;
> Index: gcc/passes.c
> ===================================================================
> --- gcc/passes.c	(revision 259789)
> +++ gcc/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: gcc/testsuite/g++.dg/lto/20081109-1_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/20081109-1_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/20081109-1_0.C	(working copy)
> @@ -1,6 +1,6 @@
>  // { dg-lto-do link }
>  // { dg-require-effective-target fpic }
>  // { dg-lto-options {{-fPIC -flto -flto-partition=1to1}} }
> -// { dg-extra-ld-options "-fPIC -flto -flto-partition=1to1 -r -nostdlib -fno-exceptions" }
> +// { dg-extra-ld-options "-fPIC -flto -flto-partition=1to1 -r -nostdlib -fno-exceptions -flinker-output=nolto-rel" }
>  void func(); class Foo { };
>  void bar() { try { func(); } catch (Foo) { } };
> Index: gcc/testsuite/g++.dg/lto/20081118_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/20081118_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/20081118_0.C	(working copy)
> @@ -1,6 +1,7 @@
>  /* { dg-lto-do link } */
>  /* { dg-require-effective-target fpic } */
>  /* { dg-lto-options {{-fPIC -flto -flto-partition=1to1 -r -nostdlib}} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  
>  /* We used to ICE because of dangling pointers.  */
>  
> Index: gcc/testsuite/g++.dg/lto/20081119-1_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/20081119-1_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/20081119-1_0.C	(working copy)
> @@ -1,6 +1,7 @@
>  /* { dg-lto-do link } */
>  /* { dg-require-effective-target fpic } */
>  /* { dg-lto-options {{-fPIC -flto -flto-partition=1to1 -r -nostdlib}} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  
>  #include "20081119-1.h"
>  
> Index: gcc/testsuite/g++.dg/lto/20081120-1_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/20081120-1_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/20081120-1_0.C	(working copy)
> @@ -1,5 +1,6 @@
>  // { dg-lto-do link }
>  // { dg-lto-options {{-flto -r -nostdlib}} }
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  extern "C"
>  {
>   extern __inline __attribute__((__gnu_inline__)) int pthread_equal(int, int)
> Index: gcc/testsuite/g++.dg/lto/20081120-2_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/20081120-2_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/20081120-2_0.C	(working copy)
> @@ -1,5 +1,6 @@
>  // { dg-lto-do link }
>  // { dg-lto-options {{-flto -r -nostdlib}} }
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  template < typename > struct Foo
>  {
>   inline void rdstate() {
> Index: gcc/testsuite/g++.dg/lto/20081123_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/20081123_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/20081123_0.C	(working copy)
> @@ -1,6 +1,7 @@
>  // { dg-lto-do link }
>  // { dg-require-effective-target fpic }
>  // { dg-lto-options {{-flto -flto-partition=1to1 -r -nostdlib -fPIC}} }
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  
>  int
>  f(void)
> Index: gcc/testsuite/g++.dg/lto/20081204-1_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/20081204-1_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/20081204-1_0.C	(working copy)
> @@ -1,6 +1,7 @@
>  /* { dg-lto-do link } */
>  /* { dg-require-effective-target fpic } */
>  /* { dg-lto-options {{-flto -flto-partition=1to1 -fPIC -r -nostdlib}} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  
>  /* Tests for the absence during linking of:
>     lto1: error: type of '_ZTVN10__cxxabiv120__si_class_type_infoE' does
> Index: gcc/testsuite/g++.dg/lto/20081219_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/20081219_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/20081219_0.C	(working copy)
> @@ -1,7 +1,7 @@
>  // { dg-lto-do link }
>  // { dg-require-effective-target fpic }
>  // { dg-lto-options {{-fPIC -flto -flto-partition=1to1 -O2}} }
> -// { dg-extra-ld-options "-O2 -fPIC -flto -flto-partition=1to1 -r -nostdlib" }
> +// { dg-extra-ld-options "-O2 -fPIC -flto -flto-partition=1to1 -r -nostdlib -flinker-output=nolto-rel" }
>  
>  typedef long int ptrdiff_t;
>  extern "C"
> Index: gcc/testsuite/g++.dg/lto/20090302_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/20090302_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/20090302_0.C	(working copy)
> @@ -1,6 +1,7 @@
>  /* { dg-lto-do link } */
>  /* { dg-require-effective-target fpic } */
>  /* { dg-lto-options {{-fPIC -flto -flto-partition=1to1 -r -nostdlib}} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  struct Foo {
>    bool Mumble();
>    static void Bar() { if (foo_->Mumble()) foo_ = 0; }
> Index: gcc/testsuite/g++.dg/lto/20090313_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/20090313_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/20090313_0.C	(working copy)
> @@ -1,6 +1,6 @@
>  // { dg-lto-do link }
>  // { dg-require-effective-target fpic }
>  // { dg-lto-options {{-flto -flto-partition=1to1 -fPIC}} }
> -// { dg-extra-ld-options "-flto -flto-partition=1to1 -r -nostdlib" }
> +// { dg-extra-ld-options "-flto -flto-partition=1to1 -r -nostdlib -flinker-output=nolto-rel" }
>  
>  int X;
> Index: gcc/testsuite/g++.dg/lto/20091002-2_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/20091002-2_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/20091002-2_0.C	(working copy)
> @@ -1,7 +1,7 @@
>  // { dg-lto-do link }
>  // { dg-require-effective-target fpic }
>  // { dg-lto-options {{-fPIC}} }
> -// { dg-extra-ld-options "-fPIC -r -nostdlib" }
> +// { dg-extra-ld-options "-fPIC -r -nostdlib -flinker-output=nolto-rel" }
>  
>  class DataArray {
>      int max() const    { return 0; }
> Index: gcc/testsuite/g++.dg/lto/20091002-3_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/20091002-3_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/20091002-3_0.C	(working copy)
> @@ -1,7 +1,7 @@
>  // { dg-lto-do link }
>  // { dg-require-effective-target fpic }
>  // { dg-lto-options {{-fPIC}} }
> -// { dg-extra-ld-options "-fPIC -r -nostdlib" }
> +// { dg-extra-ld-options "-fPIC -r -nostdlib -flinker-output=nolto-rel" }
>  
>  template < class T > 
>  class DataArray {
> Index: gcc/testsuite/g++.dg/lto/20091026-1_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/20091026-1_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/20091026-1_0.C	(working copy)
> @@ -1,5 +1,5 @@
>  // { dg-lto-do link }
> -// { dg-extra-ld-options "-r -nostdlib" }
> +// { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" }
>  
>  #include "20091026-1_a.h"
>  cObject *cHead::find(const char *objname) const
> Index: gcc/testsuite/g++.dg/lto/20100724-1_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/20100724-1_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/20100724-1_0.C	(working copy)
> @@ -1,6 +1,6 @@
>  /* { dg-lto-do link } */
>  /* { dg-lto-options {{-ftoplevel-reorder -flto -flto-partition=none} {-ftoplevel-reorder -flto -flto-partition=1to1}} } */
> -/* { dg-extra-ld-options {-r -nostdlib} } */
> +/* { dg-extra-ld-options {-r -nostdlib -flinker-output=nolto-rel} } */
>  
>  struct Foo { virtual ~Foo(); };
>  struct Bar:public Foo { Bar() { } };
> Index: gcc/testsuite/g++.dg/lto/20101010-4_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/20101010-4_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/20101010-4_0.C	(working copy)
> @@ -1,5 +1,6 @@
>  // { dg-lto-do link }
>  // { dg-lto-options { { -std=c++0x -flto -r -nostdlib } { -std=c++0x -flto -g -r -nostdlib } } }
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  
>  typedef decltype(nullptr) nullptr_t;
>  class shared_ptr {
> Index: gcc/testsuite/g++.dg/lto/20101015-2_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/20101015-2_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/20101015-2_0.C	(working copy)
> @@ -1,6 +1,6 @@
>  // { dg-lto-do link }
>  // { dg-lto-options { { -flto } { -g -flto } } }
> -// { dg-extra-ld-options "-r -nostdlib" }
> +// { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" }
>  
>  struct Base { ~Base (); };
>  void fun(void) { struct Deriv : Base { } x; }
> Index: gcc/testsuite/g++.dg/lto/20110311-1_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/20110311-1_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/20110311-1_0.C	(working copy)
> @@ -1,5 +1,5 @@
>  /* { dg-lto-do link } */
> -/* { dg-extra-ld-options "-r -nostdlib" } */
> +/* { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" } */
>  
>  struct NullType {};
>  
> Index: gcc/testsuite/g++.dg/lto/pr45621_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/pr45621_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/pr45621_0.C	(working copy)
> @@ -1,5 +1,5 @@
>  // { dg-lto-do assemble }
> -// { dg-extra-ld-options "-O2 -fipa-cp-clone -flto -nostdlib -r" }
> +// { dg-extra-ld-options "-O2 -fipa-cp-clone -flto -nostdlib -r -flinker-output=nolto-rel" }
>  #include "pr45621.h"
>  
>  void
> Index: gcc/testsuite/g++.dg/lto/pr48042_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/pr48042_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/pr48042_0.C	(working copy)
> @@ -1,5 +1,5 @@
>  // { dg-lto-do link }
> -// { dg-extra-ld-options "-r -nostdlib -g" }
> +// { dg-extra-ld-options "-r -nostdlib -g -flinker-output=nolto-rel" }
>  
>  class A {
>      virtual int x() = 0;
> Index: gcc/testsuite/g++.dg/lto/pr48354-1_0.C
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/pr48354-1_0.C	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/pr48354-1_0.C	(working copy)
> @@ -1,6 +1,6 @@
>  // { dg-lto-do link }
>  // { dg-lto-options { { -g -flto } } }
> -// { dg-extra-ld-options "-r -nostdlib" }
> +// { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" }
>  
>  template<typename T> struct Identity { typedef T type; };
>  struct S {
> Index: gcc/testsuite/g++.dg/lto/pr54625-1_0.c
> ===================================================================
> --- gcc/testsuite/g++.dg/lto/pr54625-1_0.c	(revision 259789)
> +++ gcc/testsuite/g++.dg/lto/pr54625-1_0.c	(working copy)
> @@ -1,5 +1,5 @@
>  /* { dg-lto-do link } */
> -/* { dg-extra-ld-options { -r -nostdlib } } */
> +/* { dg-extra-ld-options { -r -nostdlib -flinker-output=nolto-rel } } */
>  
>  float a;
>  double sin ();
> Index: gcc/testsuite/gcc.dg/lto/20081120-1_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20081120-1_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20081120-1_0.c	(working copy)
> @@ -1,5 +1,6 @@
>  /* { dg-lto-do link } */
>  /* { dg-lto-options {{-flto -r -nostdlib}} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  extern int stat(void) __asm__("" "stat64");
>  extern inline int stat(void) { }
>  static void foo(void) { stat(); }
> Index: gcc/testsuite/gcc.dg/lto/20081120-2_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20081120-2_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20081120-2_0.c	(working copy)
> @@ -1,3 +1,4 @@
>  /* { dg-lto-do link } */
>  /* { dg-lto-options {{-flto -flto-partition=1to1 -r -nostdlib}} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  void bar(void) {}
> Index: gcc/testsuite/gcc.dg/lto/20081126_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20081126_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20081126_0.c	(working copy)
> @@ -1,6 +1,7 @@
>  /* { dg-lto-do link } */
>  /* { dg-skip-if "" { ! { i?86-*-* x86_64-*-* } } } */
>  /* { dg-lto-options {{-flto -r -nostdlib}} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  
>  int f(void) {
>    register int ri asm("edi");
> Index: gcc/testsuite/gcc.dg/lto/20081204-1_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20081204-1_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20081204-1_0.c	(working copy)
> @@ -1,6 +1,7 @@
>  /* { dg-lto-do link } */
>  /* { dg-require-effective-target fpic } */
>  /* { dg-lto-options {{-flto -flto-partition=1to1 -fPIC -r -nostdlib}} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  
>  /* Tests for the absence during linking of:
>     lto1: error: type of 'i' does not match original declaration  */
> Index: gcc/testsuite/gcc.dg/lto/20081204-2_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20081204-2_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20081204-2_0.c	(working copy)
> @@ -1,5 +1,6 @@
>  /* { dg-lto-do link } */
>  /* { dg-skip-if "" { ! { i?86-*-* x86_64-*-* } } } */
>  /* { dg-lto-options {{-w -flto -fPIC -r -nostdlib}} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  
>  register int ri asm("edi");
> Index: gcc/testsuite/gcc.dg/lto/20081212-1_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20081212-1_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20081212-1_0.c	(working copy)
> @@ -1,4 +1,5 @@
>  /* { dg-lto-do link } */
>  /* { dg-lto-options {{-r -nostdlib}} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  int exported_var = 42;
>  /* { dg-final { scan-symbol "exported_var" } } */
> Index: gcc/testsuite/gcc.dg/lto/20081224_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20081224_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20081224_0.c	(working copy)
> @@ -1,6 +1,7 @@
>  /* { dg-lto-do link } */
>  /* { dg-require-effective-target fpic } */
>  /* { dg-lto-options {{-flto -flto-partition=1to1 -r -nostdlib -fPIC}} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  #include "20081224_0.h"
>  
>  extern struct foo x;
> Index: gcc/testsuite/gcc.dg/lto/20090116_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20090116_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20090116_0.c	(working copy)
> @@ -1,7 +1,7 @@
>  /* { dg-lto-do link } */
>  /* { dg-require-effective-target fpic } */
>  /* { dg-lto-options {{-O1 -flto -flto-partition=1to1 -fPIC}} } */
> -/* { dg-extra-ld-options {-r -nostdlib -O0} } */
> +/* { dg-extra-ld-options {-r -nostdlib -O0 -flinker-output=nolto-rel} } */
>  
>  int foo(void) {
>   int ret, i;
> Index: gcc/testsuite/gcc.dg/lto/20090126-1_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20090126-1_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20090126-1_0.c	(working copy)
> @@ -1,6 +1,6 @@
>  /* { dg-lto-do link } */
>  /* { dg-lto-options {{-O0 -flto -flto-partition=1to1}} } */
> -/* { dg-extra-ld-options {-r -nostdlib -O2 -flto -flto-partition=1to1} } */
> +/* { dg-extra-ld-options {-r -nostdlib -O2 -flto -flto-partition=1to1 -flinker-output=nolto-rel} } */
>  
>  int main(int argc, char **argv) {
>    return 0;
> Index: gcc/testsuite/gcc.dg/lto/20090126-2_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20090126-2_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20090126-2_0.c	(working copy)
> @@ -1,7 +1,7 @@
>  /* { dg-lto-do link } */
>  /* { dg-require-effective-target fpic } */
>  /* { dg-lto-options {{-fPIC -O2 -flto -flto-partition=1to1}} } */
> -/* { dg-extra-ld-options {-fno-PIC -r -nostdlib -O2 -flto -flto-partition=1to1} } */
> +/* { dg-extra-ld-options {-fno-PIC -r -nostdlib -O2 -flto -flto-partition=1to1 -flinker-output=nolto-rel} } */
>  
>  int main(int argc, char **argv) {
>    return 0;
> Index: gcc/testsuite/gcc.dg/lto/20090206-1_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20090206-1_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20090206-1_0.c	(working copy)
> @@ -3,6 +3,7 @@
>  /* { dg-lto-options {{-fPIC -r -nostdlib -flto -flto-partition=1to1 -msse2}} } */
>  /* { dg-require-effective-target sse2 } */
>  /* { dg-suppress-ld-options {-fPIC -msse2} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  
>  typedef short v8hi __attribute__((__vector_size__(16)));
>  void func (void) {
> Index: gcc/testsuite/gcc.dg/lto/20090219_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20090219_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20090219_0.c	(working copy)
> @@ -1,6 +1,7 @@
>  /* { dg-lto-do link } */
>  /* { dg-require-effective-target fpic } */
>  /* { dg-lto-options {{-O3 -flto -flto-partition=1to1 -fPIC -r -nostdlib}} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  
>  struct Foo { int f1, f2, f3, f4, f5; };
>  
> Index: gcc/testsuite/gcc.dg/lto/20091013-1_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20091013-1_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20091013-1_0.c	(working copy)
> @@ -1,6 +1,7 @@
>  /* { dg-lto-do link } */
>  /* { dg-require-effective-target fpic } */
>  /* { dg-lto-options {{-fPIC -r -nostdlib -flto} {-fPIC -r -nostdlib -O2 -flto}} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  
>  void * HeapAlloc(void*,unsigned int,unsigned long);
>  
> Index: gcc/testsuite/gcc.dg/lto/20091014-1_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20091014-1_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20091014-1_0.c	(working copy)
> @@ -1,5 +1,6 @@
>  /* { dg-lto-do link } */
>  /* { dg-require-effective-target fpic } */
>  /* { dg-lto-options {{-fPIC -r -nostdlib -flto}} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  
>  /* Empty file.  See PR41173.  */
> Index: gcc/testsuite/gcc.dg/lto/20091015-1_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20091015-1_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20091015-1_0.c	(working copy)
> @@ -1,6 +1,7 @@
>  /* { dg-lto-do link } */
>  /* { dg-require-effective-target fpic } */
>  /* { dg-lto-options {{-fPIC -r -nostdlib -O2 -flto} {-fPIC -r -nostdlib -O2 -flto -flto-partition=1to1}} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  
>  #include "20091015-1_b.h"
>  void diagnostic_initialize (FILE **stream) { *stream = stderr; }
> Index: gcc/testsuite/gcc.dg/lto/20091016-1_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20091016-1_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20091016-1_0.c	(working copy)
> @@ -1,6 +1,7 @@
>  /* { dg-lto-do link } */
>  /* { dg-require-effective-target fpic } */
>  /* { dg-lto-options {{-fPIC -r -nostdlib -O2 -flto}} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  
>  typedef struct VEC_constructor_elt_gc { } VEC_constructor_elt_gc;
>  #include "20091016-1_a.h"
> Index: gcc/testsuite/gcc.dg/lto/20091020-1_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20091020-1_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20091020-1_0.c	(working copy)
> @@ -1,6 +1,7 @@
>  /* { dg-lto-do link } */
>  /* { dg-require-effective-target fpic } */
>  /* { dg-lto-options {{-fPIC -r -nostdlib -flto}} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  
>  typedef struct {
>      int NumPackStreams;
> Index: gcc/testsuite/gcc.dg/lto/20091020-2_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20091020-2_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20091020-2_0.c	(working copy)
> @@ -1,6 +1,7 @@
>  /* { dg-lto-do link } */
>  /* { dg-require-effective-target fpic } */
>  /* { dg-lto-options {{-fPIC -r -nostdlib -flto}} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  
>  typedef struct {
>      int NumPackStreams;
> Index: gcc/testsuite/gcc.dg/lto/20091027-1_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20091027-1_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20091027-1_0.c	(working copy)
> @@ -1,5 +1,5 @@
>  /* { dg-lto-do link } */
> -/* { dg-extra-ld-options "-r -nostdlib" } */
> +/* { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" } */
>  
>  typedef struct _xmlDict xmlDict;
>  struct _xmlDict {
> Index: gcc/testsuite/gcc.dg/lto/20100426_0.c
> ===================================================================
> --- gcc/testsuite/gcc.dg/lto/20100426_0.c	(revision 259789)
> +++ gcc/testsuite/gcc.dg/lto/20100426_0.c	(working copy)
> @@ -1,5 +1,6 @@
>  /* { dg-lto-do link } */
>  /* { dg-lto-options {{-r -nostdlib -flto -g}} } */
> +/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
>  
>  long Perl_my_htonl (long l)
>  {
> Index: gcc/testsuite/gfortran.dg/lto/20091016-1_0.f90
> ===================================================================
> --- gcc/testsuite/gfortran.dg/lto/20091016-1_0.f90	(revision 259789)
> +++ gcc/testsuite/gfortran.dg/lto/20091016-1_0.f90	(working copy)
> @@ -1,5 +1,6 @@
>  ! { dg-lto-do link }
>  ! { dg-lto-options {{-flto -g -fPIC -r -nostdlib} {-O -flto -g -fPIC -r -nostdlib}} }
> +! { dg-extra-ld-options "-flinker-output=nolto-rel" }
>  
>        FUNCTION makenumberstring(x)
>        IMPLICIT NONE
> Index: gcc/testsuite/gfortran.dg/lto/20091028-1_0.f90
> ===================================================================
> --- gcc/testsuite/gfortran.dg/lto/20091028-1_0.f90	(revision 259789)
> +++ gcc/testsuite/gfortran.dg/lto/20091028-1_0.f90	(working copy)
> @@ -1,5 +1,5 @@
>  ! { dg-lto-do link }
> -! { dg-extra-ld-options "-r -nostdlib -finline-functions" }
> +! { dg-extra-ld-options "-r -nostdlib -finline-functions -flinker-output=nolto-rel" }
>  
>  SUBROUTINE int_gen_ti_header_char( hdrbuf, hdrbufsize, itypesize, &
>                                DataHandle, Element, VarName, Data, code )
> Index: gcc/testsuite/gfortran.dg/lto/20091028-2_0.f90
> ===================================================================
> --- gcc/testsuite/gfortran.dg/lto/20091028-2_0.f90	(revision 259789)
> +++ gcc/testsuite/gfortran.dg/lto/20091028-2_0.f90	(working copy)
> @@ -1,5 +1,5 @@
>  ! { dg-lto-do link }
> -! { dg-extra-ld-options "-r -nostdlib -finline-functions" }
> +! { dg-extra-ld-options "-r -nostdlib -finline-functions -flinker-output=nolto-rel" }
>  
>  SUBROUTINE int_gen_ti_header_char( hdrbuf, hdrbufsize, itypesize, &
>                                DataHandle, Element, VarName, Data, code )
> Index: gcc/testsuite/gfortran.dg/lto/pr46911_0.f
> ===================================================================
> --- gcc/testsuite/gfortran.dg/lto/pr46911_0.f	(revision 259789)
> +++ gcc/testsuite/gfortran.dg/lto/pr46911_0.f	(working copy)
> @@ -1,6 +1,6 @@
>  ! { dg-lto-do link }
>  ! { dg-lto-options {{ -O2 -flto -g }} }
> -! { dg-extra-ld-options "-r -nostdlib" }
> +! { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" }
>        common/main1/ eps(2)
>        call dalie6s(iqmod6,1,wx,cor6d)
>        end
> Index: gcc/testsuite/gfortran.dg/lto/pr47839_0.f90
> ===================================================================
> --- gcc/testsuite/gfortran.dg/lto/pr47839_0.f90	(revision 259789)
> +++ gcc/testsuite/gfortran.dg/lto/pr47839_0.f90	(working copy)
> @@ -1,6 +1,6 @@
>  ! { dg-lto-do link }
>  ! { dg-lto-options {{ -g -flto }} }
> -! { dg-extra-ld-options "-r -nostdlib" }
> +! { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" }
>  
>  MODULE globalvar_mod
>  integer        :: xstop
> Index: gcc/toplev.c
> ===================================================================
> --- gcc/toplev.c	(revision 259789)
> +++ gcc/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)
> Index: lto-plugin/lto-plugin.c
> ===================================================================
> --- lto-plugin/lto-plugin.c	(revision 259789)
> +++ lto-plugin/lto-plugin.c	(working copy)
> @@ -27,10 +27,13 @@
>     More information at http://gcc.gnu.org/wiki/whopr/driver.
>  
>     This plugin should be passed the lto-wrapper options and will forward them.
> -   It also has 2 options of its own:
> +   It also has options at his own:
>     -debug: Print the command line used to run lto-wrapper.
>     -nop: Instead of running lto-wrapper, pass the original to the plugin. This
> -   only works if the input files are hybrid.  */
> +   only works if the input files are hybrid. 
> +   -linker-output-known: Do not determine linker output
> +   -sym-style={none,win32,underscore|uscore}
> +   -pass-through  */
>  
>  #ifdef HAVE_CONFIG_H
>  #include "config.h"
> @@ -159,6 +162,7 @@
>  
>  static struct plugin_file_info *claimed_files = NULL;
>  static unsigned int num_claimed_files = 0;
> +static unsigned int non_claimed_files = 0;
>  
>  /* List of files with offloading.  */
>  static struct plugin_offload_file *offload_files;
> @@ -185,6 +189,7 @@
>  static char *resolution_file = NULL;
>  static enum ld_plugin_output_file_type linker_output;
>  static int linker_output_set;
> +static int linker_output_known;
>  
>  /* The version of gold being used, or -1 if not gold.  The number is
>     MAJOR * 100 + MINOR.  */
> @@ -637,7 +642,8 @@
>  all_symbols_read_handler (void)
>  {
>    unsigned i;
> -  unsigned num_lto_args = num_claimed_files + lto_wrapper_num_args + 3;
> +  unsigned num_lto_args = num_claimed_files + lto_wrapper_num_args + 2
> +    	   + !linker_output_known;
>    char **lto_argv;
>    const char *linker_output_str = NULL;
>    const char **lto_arg_ptr;
> @@ -661,26 +667,37 @@
>    for (i = 0; i < lto_wrapper_num_args; i++)
>      *lto_arg_ptr++ = lto_wrapper_argv[i];
>  
> -  assert (linker_output_set);
> -  switch (linker_output)
> +  if (!linker_output_known)
>      {
> -    case LDPO_REL:
> -      linker_output_str = "-flinker-output=rel";
> -      break;
> -    case LDPO_DYN:
> -      linker_output_str = "-flinker-output=dyn";
> -      break;
> -    case LDPO_PIE:
> -      linker_output_str = "-flinker-output=pie";
> -      break;
> -    case LDPO_EXEC:
> -      linker_output_str = "-flinker-output=exec";
> -      break;
> -    default:
> -      message (LDPL_FATAL, "unsupported linker output %i", linker_output);
> -      break;
> +      assert (linker_output_set);
> +      switch (linker_output)
> +	{
> +	case LDPO_REL:
> +	  if (non_claimed_files)
> +	    {
> +	      message (LDPL_WARNING, "incremental linking of LTO and non-LTO "
> +		       "objects; using -flinker-output=nolto-rel which will "
> +		       "bypass whole program optimization");
> +	      linker_output_str = "-flinker-output=nolto-rel";
> +	    }
> +	  else
> +	    linker_output_str = "-flinker-output=rel";
> +	  break;
> +	case LDPO_DYN:
> +	  linker_output_str = "-flinker-output=dyn";
> +	  break;
> +	case LDPO_PIE:
> +	  linker_output_str = "-flinker-output=pie";
> +	  break;
> +	case LDPO_EXEC:
> +	  linker_output_str = "-flinker-output=exec";
> +	  break;
> +	default:
> +	  message (LDPL_FATAL, "unsupported linker output %i", linker_output);
> +	  break;
> +	}
> +      *lto_arg_ptr++ = xstrdup (linker_output_str);
>      }
> -  *lto_arg_ptr++ = xstrdup (linker_output_str);
>  
>    if (num_offload_files > 0)
>      {
> @@ -1108,6 +1125,7 @@
>    goto cleanup;
>  
>   err:
> +  non_claimed_files++;
>    free (lto_file.name);
>  
>   cleanup:
> @@ -1122,6 +1140,8 @@
>  static void
>  process_option (const char *option)
>  {
> +  if (strcmp (option, "-linker-output-known") == 0)
> +    linker_output_known = 1;
>    if (strcmp (option, "-debug") == 0)
>      debug = 1;
>    else if (strcmp (option, "-nop") == 0)
> 
> 
>
Jan Hubicka May 2, 2018, 10:04 a.m. UTC | #2
> 
> Hmm, if that's from ltrans stage then you probably need
> 
> Index: gcc/dwarf2out.c
> ===================================================================
> --- gcc/dwarf2out.c     (revision 259764)
> +++ gcc/dwarf2out.c     (working copy)
> @@ -5835,7 +5835,7 @@ dwarf2out_die_ref_for_decl (tree decl, c
>    /* During WPA stage we currently use DIEs to store the
>       decl <-> label + offset map.  That's quite inefficient but it
>       works for now.  */
> -  if (flag_wpa)
> +  if (in_lto_p)
>      {
>        dw_die_ref ref = get_AT_ref (die, DW_AT_abstract_origin);
>        if (!ref)
> 
> we currently only ever end up here during LTRANS or compile stage.

Makes sense, for incremental link use neither of the flags. It starts
same way as -flto-partition=none compilation...
Will give it a try.

Honza
diff mbox series

Patch

Index: gcc/cgraphunit.c
===================================================================
--- gcc/cgraphunit.c	(revision 259789)
+++ gcc/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)
     {
+      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: gcc/common.opt
===================================================================
--- gcc/common.opt	(revision 259789)
+++ gcc/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: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 259789)
+++ gcc/doc/invoke.texi	(working copy)
@@ -12238,6 +12238,50 @@ 
 object file names should not be used as arguments.  @xref{Overall
 Options}.
 
+@item -flinker-output=@var{type}
+@opindex -flinker-output
+This option controls the code generation of the link time optimizer.  By
+default the linker output is determined by the linker plugin automatically. For
+debugging the compiler and in the case of incremental linking it may be useful
+to control the type manually.
+
+If @var{type} is @samp{exec} the code generation is configured to produce static
+binary. In this case @option{-fpic} and @option{-fpie} are both disabled.
+
+If @var{type} is @samp{dyn} the code generation is configured to produce shared
+library. In this case @option{-fpic} or @option{-fPIC} is preserved.  These
+options arenot implied to make it possible to build static libraries without
+position independent code on architectures this is possible, i.e. on x86.
+
+If @var{type} is @samp{pie} the code generation is configured to produce
+@option{-fpie} executable. This result in similar optimizations as @samp{exec}
+except that @option{-fpie} is not disabled if specified at compilation time.
+
+If @var{type} is @samp{rel} the compiler assumes that incremental linking is
+done.  The sections containing intermediate code for link-time optimization are
+merged, pre-optimized, and output to the resulting object file. In addition if
+@option{-ffat-lto-objects} is specified the binary code is produced for future
+non-lto linking. The object file produced by incremental linking will be smaller
+than a static library produced from the same object files.  At link-time the
+result of incremental linking will also load faster to compiler than a static
+library assuming that majority of objects in the library are used.
+
+Finally @samp{nolto-rel} configure compiler to for incremental linking where
+code generation is forced, final binary is produced and the intermediate code
+for later link-time optimization is stripped. When multiple object files are
+linked together the resulting code will be optimized better than with link time
+optimizations disabled (for example, the cross-module inlining will happen),
+most of benefits of whole program optimizations are however lost. 
+
+During the incremental link (by @option{-r}) the linker plugin will default to
+@option{rel}. With current interfaces to GNU Binutils it is however not
+possible to link incrementally LTO objects and non-LTO objects into a single
+mixed object file.  In the case any of object files in incremental link can not
+be used for link-time optimization the linker plugin will output warning and
+use @samp{nolto-rel}. To maintain the whole program optimization it is
+recommended to link such objects into static library instead. Alternatively it
+is possible to use H.J. Lu's binutils with support for mixed objects.
+
 @item -fuse-ld=bfd
 @opindex fuse-ld=bfd
 Use the @command{bfd} linker instead of the default linker.
Index: gcc/flag-types.h
===================================================================
--- gcc/flag-types.h	(revision 259789)
+++ gcc/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/gcc.c
===================================================================
--- gcc/gcc.c	(revision 259789)
+++ gcc/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: gcc/lto/lang.opt
===================================================================
--- gcc/lto/lang.opt	(revision 259789)
+++ gcc/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: gcc/lto/lto-lang.c
===================================================================
--- gcc/lto/lto-lang.c	(revision 259789)
+++ gcc/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: gcc/lto-cgraph.c
===================================================================
--- gcc/lto-cgraph.c	(revision 259789)
+++ gcc/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: gcc/lto-wrapper.c
===================================================================
--- gcc/lto-wrapper.c	(revision 259789)
+++ gcc/lto-wrapper.c	(working copy)
@@ -1054,6 +1054,7 @@ 
   bool have_offload = false;
   unsigned lto_argc = 0, ltoobj_argc = 0;
   char **lto_argv, **ltoobj_argv;
+  bool linker_output_rel = false;
   bool skip_debug = false;
   unsigned n_debugobj;
 
@@ -1106,9 +1107,12 @@ 
 	  file_offset = (off_t) loffset;
 	}
       fd = open (filename, O_RDONLY | O_BINARY);
+      /* Linker plugin passes -fresolution and -flinker-output options.  */
       if (fd == -1)
 	{
 	  lto_argv[lto_argc++] = argv[i];
+	  if (strcmp (argv[i], "-flinker-output=rel") == 0)
+	    linker_output_rel = true;
 	  continue;
 	}
 
@@ -1173,6 +1177,11 @@ 
 	  lto_mode = LTO_MODE_WHOPR;
 	  break;
 
+	case OPT_flinker_output_:
+	  linker_output_rel = !strcmp (option->arg, "rel");
+	  break;
+
+
 	default:
 	  break;
 	}
@@ -1189,6 +1198,9 @@ 
       fputc ('\n', stderr);
     }
 
+  if (linker_output_rel)
+    no_partition = true;
+
   if (no_partition)
     {
       lto_mode = LTO_MODE_LTO;
Index: gcc/passes.c
===================================================================
--- gcc/passes.c	(revision 259789)
+++ gcc/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: gcc/testsuite/g++.dg/lto/20081109-1_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/20081109-1_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/20081109-1_0.C	(working copy)
@@ -1,6 +1,6 @@ 
 // { dg-lto-do link }
 // { dg-require-effective-target fpic }
 // { dg-lto-options {{-fPIC -flto -flto-partition=1to1}} }
-// { dg-extra-ld-options "-fPIC -flto -flto-partition=1to1 -r -nostdlib -fno-exceptions" }
+// { dg-extra-ld-options "-fPIC -flto -flto-partition=1to1 -r -nostdlib -fno-exceptions -flinker-output=nolto-rel" }
 void func(); class Foo { };
 void bar() { try { func(); } catch (Foo) { } };
Index: gcc/testsuite/g++.dg/lto/20081118_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/20081118_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/20081118_0.C	(working copy)
@@ -1,6 +1,7 @@ 
 /* { dg-lto-do link } */
 /* { dg-require-effective-target fpic } */
 /* { dg-lto-options {{-fPIC -flto -flto-partition=1to1 -r -nostdlib}} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 
 /* We used to ICE because of dangling pointers.  */
 
Index: gcc/testsuite/g++.dg/lto/20081119-1_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/20081119-1_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/20081119-1_0.C	(working copy)
@@ -1,6 +1,7 @@ 
 /* { dg-lto-do link } */
 /* { dg-require-effective-target fpic } */
 /* { dg-lto-options {{-fPIC -flto -flto-partition=1to1 -r -nostdlib}} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 
 #include "20081119-1.h"
 
Index: gcc/testsuite/g++.dg/lto/20081120-1_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/20081120-1_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/20081120-1_0.C	(working copy)
@@ -1,5 +1,6 @@ 
 // { dg-lto-do link }
 // { dg-lto-options {{-flto -r -nostdlib}} }
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 extern "C"
 {
  extern __inline __attribute__((__gnu_inline__)) int pthread_equal(int, int)
Index: gcc/testsuite/g++.dg/lto/20081120-2_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/20081120-2_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/20081120-2_0.C	(working copy)
@@ -1,5 +1,6 @@ 
 // { dg-lto-do link }
 // { dg-lto-options {{-flto -r -nostdlib}} }
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 template < typename > struct Foo
 {
  inline void rdstate() {
Index: gcc/testsuite/g++.dg/lto/20081123_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/20081123_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/20081123_0.C	(working copy)
@@ -1,6 +1,7 @@ 
 // { dg-lto-do link }
 // { dg-require-effective-target fpic }
 // { dg-lto-options {{-flto -flto-partition=1to1 -r -nostdlib -fPIC}} }
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 
 int
 f(void)
Index: gcc/testsuite/g++.dg/lto/20081204-1_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/20081204-1_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/20081204-1_0.C	(working copy)
@@ -1,6 +1,7 @@ 
 /* { dg-lto-do link } */
 /* { dg-require-effective-target fpic } */
 /* { dg-lto-options {{-flto -flto-partition=1to1 -fPIC -r -nostdlib}} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 
 /* Tests for the absence during linking of:
    lto1: error: type of '_ZTVN10__cxxabiv120__si_class_type_infoE' does
Index: gcc/testsuite/g++.dg/lto/20081219_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/20081219_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/20081219_0.C	(working copy)
@@ -1,7 +1,7 @@ 
 // { dg-lto-do link }
 // { dg-require-effective-target fpic }
 // { dg-lto-options {{-fPIC -flto -flto-partition=1to1 -O2}} }
-// { dg-extra-ld-options "-O2 -fPIC -flto -flto-partition=1to1 -r -nostdlib" }
+// { dg-extra-ld-options "-O2 -fPIC -flto -flto-partition=1to1 -r -nostdlib -flinker-output=nolto-rel" }
 
 typedef long int ptrdiff_t;
 extern "C"
Index: gcc/testsuite/g++.dg/lto/20090302_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/20090302_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/20090302_0.C	(working copy)
@@ -1,6 +1,7 @@ 
 /* { dg-lto-do link } */
 /* { dg-require-effective-target fpic } */
 /* { dg-lto-options {{-fPIC -flto -flto-partition=1to1 -r -nostdlib}} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 struct Foo {
   bool Mumble();
   static void Bar() { if (foo_->Mumble()) foo_ = 0; }
Index: gcc/testsuite/g++.dg/lto/20090313_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/20090313_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/20090313_0.C	(working copy)
@@ -1,6 +1,6 @@ 
 // { dg-lto-do link }
 // { dg-require-effective-target fpic }
 // { dg-lto-options {{-flto -flto-partition=1to1 -fPIC}} }
-// { dg-extra-ld-options "-flto -flto-partition=1to1 -r -nostdlib" }
+// { dg-extra-ld-options "-flto -flto-partition=1to1 -r -nostdlib -flinker-output=nolto-rel" }
 
 int X;
Index: gcc/testsuite/g++.dg/lto/20091002-2_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/20091002-2_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/20091002-2_0.C	(working copy)
@@ -1,7 +1,7 @@ 
 // { dg-lto-do link }
 // { dg-require-effective-target fpic }
 // { dg-lto-options {{-fPIC}} }
-// { dg-extra-ld-options "-fPIC -r -nostdlib" }
+// { dg-extra-ld-options "-fPIC -r -nostdlib -flinker-output=nolto-rel" }
 
 class DataArray {
     int max() const    { return 0; }
Index: gcc/testsuite/g++.dg/lto/20091002-3_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/20091002-3_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/20091002-3_0.C	(working copy)
@@ -1,7 +1,7 @@ 
 // { dg-lto-do link }
 // { dg-require-effective-target fpic }
 // { dg-lto-options {{-fPIC}} }
-// { dg-extra-ld-options "-fPIC -r -nostdlib" }
+// { dg-extra-ld-options "-fPIC -r -nostdlib -flinker-output=nolto-rel" }
 
 template < class T > 
 class DataArray {
Index: gcc/testsuite/g++.dg/lto/20091026-1_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/20091026-1_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/20091026-1_0.C	(working copy)
@@ -1,5 +1,5 @@ 
 // { dg-lto-do link }
-// { dg-extra-ld-options "-r -nostdlib" }
+// { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" }
 
 #include "20091026-1_a.h"
 cObject *cHead::find(const char *objname) const
Index: gcc/testsuite/g++.dg/lto/20100724-1_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/20100724-1_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/20100724-1_0.C	(working copy)
@@ -1,6 +1,6 @@ 
 /* { dg-lto-do link } */
 /* { dg-lto-options {{-ftoplevel-reorder -flto -flto-partition=none} {-ftoplevel-reorder -flto -flto-partition=1to1}} } */
-/* { dg-extra-ld-options {-r -nostdlib} } */
+/* { dg-extra-ld-options {-r -nostdlib -flinker-output=nolto-rel} } */
 
 struct Foo { virtual ~Foo(); };
 struct Bar:public Foo { Bar() { } };
Index: gcc/testsuite/g++.dg/lto/20101010-4_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/20101010-4_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/20101010-4_0.C	(working copy)
@@ -1,5 +1,6 @@ 
 // { dg-lto-do link }
 // { dg-lto-options { { -std=c++0x -flto -r -nostdlib } { -std=c++0x -flto -g -r -nostdlib } } }
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 
 typedef decltype(nullptr) nullptr_t;
 class shared_ptr {
Index: gcc/testsuite/g++.dg/lto/20101015-2_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/20101015-2_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/20101015-2_0.C	(working copy)
@@ -1,6 +1,6 @@ 
 // { dg-lto-do link }
 // { dg-lto-options { { -flto } { -g -flto } } }
-// { dg-extra-ld-options "-r -nostdlib" }
+// { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" }
 
 struct Base { ~Base (); };
 void fun(void) { struct Deriv : Base { } x; }
Index: gcc/testsuite/g++.dg/lto/20110311-1_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/20110311-1_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/20110311-1_0.C	(working copy)
@@ -1,5 +1,5 @@ 
 /* { dg-lto-do link } */
-/* { dg-extra-ld-options "-r -nostdlib" } */
+/* { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" } */
 
 struct NullType {};
 
Index: gcc/testsuite/g++.dg/lto/pr45621_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/pr45621_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/pr45621_0.C	(working copy)
@@ -1,5 +1,5 @@ 
 // { dg-lto-do assemble }
-// { dg-extra-ld-options "-O2 -fipa-cp-clone -flto -nostdlib -r" }
+// { dg-extra-ld-options "-O2 -fipa-cp-clone -flto -nostdlib -r -flinker-output=nolto-rel" }
 #include "pr45621.h"
 
 void
Index: gcc/testsuite/g++.dg/lto/pr48042_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/pr48042_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/pr48042_0.C	(working copy)
@@ -1,5 +1,5 @@ 
 // { dg-lto-do link }
-// { dg-extra-ld-options "-r -nostdlib -g" }
+// { dg-extra-ld-options "-r -nostdlib -g -flinker-output=nolto-rel" }
 
 class A {
     virtual int x() = 0;
Index: gcc/testsuite/g++.dg/lto/pr48354-1_0.C
===================================================================
--- gcc/testsuite/g++.dg/lto/pr48354-1_0.C	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/pr48354-1_0.C	(working copy)
@@ -1,6 +1,6 @@ 
 // { dg-lto-do link }
 // { dg-lto-options { { -g -flto } } }
-// { dg-extra-ld-options "-r -nostdlib" }
+// { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" }
 
 template<typename T> struct Identity { typedef T type; };
 struct S {
Index: gcc/testsuite/g++.dg/lto/pr54625-1_0.c
===================================================================
--- gcc/testsuite/g++.dg/lto/pr54625-1_0.c	(revision 259789)
+++ gcc/testsuite/g++.dg/lto/pr54625-1_0.c	(working copy)
@@ -1,5 +1,5 @@ 
 /* { dg-lto-do link } */
-/* { dg-extra-ld-options { -r -nostdlib } } */
+/* { dg-extra-ld-options { -r -nostdlib -flinker-output=nolto-rel } } */
 
 float a;
 double sin ();
Index: gcc/testsuite/gcc.dg/lto/20081120-1_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20081120-1_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20081120-1_0.c	(working copy)
@@ -1,5 +1,6 @@ 
 /* { dg-lto-do link } */
 /* { dg-lto-options {{-flto -r -nostdlib}} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 extern int stat(void) __asm__("" "stat64");
 extern inline int stat(void) { }
 static void foo(void) { stat(); }
Index: gcc/testsuite/gcc.dg/lto/20081120-2_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20081120-2_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20081120-2_0.c	(working copy)
@@ -1,3 +1,4 @@ 
 /* { dg-lto-do link } */
 /* { dg-lto-options {{-flto -flto-partition=1to1 -r -nostdlib}} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 void bar(void) {}
Index: gcc/testsuite/gcc.dg/lto/20081126_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20081126_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20081126_0.c	(working copy)
@@ -1,6 +1,7 @@ 
 /* { dg-lto-do link } */
 /* { dg-skip-if "" { ! { i?86-*-* x86_64-*-* } } } */
 /* { dg-lto-options {{-flto -r -nostdlib}} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 
 int f(void) {
   register int ri asm("edi");
Index: gcc/testsuite/gcc.dg/lto/20081204-1_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20081204-1_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20081204-1_0.c	(working copy)
@@ -1,6 +1,7 @@ 
 /* { dg-lto-do link } */
 /* { dg-require-effective-target fpic } */
 /* { dg-lto-options {{-flto -flto-partition=1to1 -fPIC -r -nostdlib}} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 
 /* Tests for the absence during linking of:
    lto1: error: type of 'i' does not match original declaration  */
Index: gcc/testsuite/gcc.dg/lto/20081204-2_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20081204-2_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20081204-2_0.c	(working copy)
@@ -1,5 +1,6 @@ 
 /* { dg-lto-do link } */
 /* { dg-skip-if "" { ! { i?86-*-* x86_64-*-* } } } */
 /* { dg-lto-options {{-w -flto -fPIC -r -nostdlib}} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 
 register int ri asm("edi");
Index: gcc/testsuite/gcc.dg/lto/20081212-1_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20081212-1_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20081212-1_0.c	(working copy)
@@ -1,4 +1,5 @@ 
 /* { dg-lto-do link } */
 /* { dg-lto-options {{-r -nostdlib}} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 int exported_var = 42;
 /* { dg-final { scan-symbol "exported_var" } } */
Index: gcc/testsuite/gcc.dg/lto/20081224_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20081224_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20081224_0.c	(working copy)
@@ -1,6 +1,7 @@ 
 /* { dg-lto-do link } */
 /* { dg-require-effective-target fpic } */
 /* { dg-lto-options {{-flto -flto-partition=1to1 -r -nostdlib -fPIC}} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 #include "20081224_0.h"
 
 extern struct foo x;
Index: gcc/testsuite/gcc.dg/lto/20090116_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20090116_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20090116_0.c	(working copy)
@@ -1,7 +1,7 @@ 
 /* { dg-lto-do link } */
 /* { dg-require-effective-target fpic } */
 /* { dg-lto-options {{-O1 -flto -flto-partition=1to1 -fPIC}} } */
-/* { dg-extra-ld-options {-r -nostdlib -O0} } */
+/* { dg-extra-ld-options {-r -nostdlib -O0 -flinker-output=nolto-rel} } */
 
 int foo(void) {
  int ret, i;
Index: gcc/testsuite/gcc.dg/lto/20090126-1_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20090126-1_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20090126-1_0.c	(working copy)
@@ -1,6 +1,6 @@ 
 /* { dg-lto-do link } */
 /* { dg-lto-options {{-O0 -flto -flto-partition=1to1}} } */
-/* { dg-extra-ld-options {-r -nostdlib -O2 -flto -flto-partition=1to1} } */
+/* { dg-extra-ld-options {-r -nostdlib -O2 -flto -flto-partition=1to1 -flinker-output=nolto-rel} } */
 
 int main(int argc, char **argv) {
   return 0;
Index: gcc/testsuite/gcc.dg/lto/20090126-2_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20090126-2_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20090126-2_0.c	(working copy)
@@ -1,7 +1,7 @@ 
 /* { dg-lto-do link } */
 /* { dg-require-effective-target fpic } */
 /* { dg-lto-options {{-fPIC -O2 -flto -flto-partition=1to1}} } */
-/* { dg-extra-ld-options {-fno-PIC -r -nostdlib -O2 -flto -flto-partition=1to1} } */
+/* { dg-extra-ld-options {-fno-PIC -r -nostdlib -O2 -flto -flto-partition=1to1 -flinker-output=nolto-rel} } */
 
 int main(int argc, char **argv) {
   return 0;
Index: gcc/testsuite/gcc.dg/lto/20090206-1_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20090206-1_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20090206-1_0.c	(working copy)
@@ -3,6 +3,7 @@ 
 /* { dg-lto-options {{-fPIC -r -nostdlib -flto -flto-partition=1to1 -msse2}} } */
 /* { dg-require-effective-target sse2 } */
 /* { dg-suppress-ld-options {-fPIC -msse2} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 
 typedef short v8hi __attribute__((__vector_size__(16)));
 void func (void) {
Index: gcc/testsuite/gcc.dg/lto/20090219_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20090219_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20090219_0.c	(working copy)
@@ -1,6 +1,7 @@ 
 /* { dg-lto-do link } */
 /* { dg-require-effective-target fpic } */
 /* { dg-lto-options {{-O3 -flto -flto-partition=1to1 -fPIC -r -nostdlib}} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 
 struct Foo { int f1, f2, f3, f4, f5; };
 
Index: gcc/testsuite/gcc.dg/lto/20091013-1_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20091013-1_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20091013-1_0.c	(working copy)
@@ -1,6 +1,7 @@ 
 /* { dg-lto-do link } */
 /* { dg-require-effective-target fpic } */
 /* { dg-lto-options {{-fPIC -r -nostdlib -flto} {-fPIC -r -nostdlib -O2 -flto}} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 
 void * HeapAlloc(void*,unsigned int,unsigned long);
 
Index: gcc/testsuite/gcc.dg/lto/20091014-1_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20091014-1_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20091014-1_0.c	(working copy)
@@ -1,5 +1,6 @@ 
 /* { dg-lto-do link } */
 /* { dg-require-effective-target fpic } */
 /* { dg-lto-options {{-fPIC -r -nostdlib -flto}} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 
 /* Empty file.  See PR41173.  */
Index: gcc/testsuite/gcc.dg/lto/20091015-1_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20091015-1_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20091015-1_0.c	(working copy)
@@ -1,6 +1,7 @@ 
 /* { dg-lto-do link } */
 /* { dg-require-effective-target fpic } */
 /* { dg-lto-options {{-fPIC -r -nostdlib -O2 -flto} {-fPIC -r -nostdlib -O2 -flto -flto-partition=1to1}} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 
 #include "20091015-1_b.h"
 void diagnostic_initialize (FILE **stream) { *stream = stderr; }
Index: gcc/testsuite/gcc.dg/lto/20091016-1_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20091016-1_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20091016-1_0.c	(working copy)
@@ -1,6 +1,7 @@ 
 /* { dg-lto-do link } */
 /* { dg-require-effective-target fpic } */
 /* { dg-lto-options {{-fPIC -r -nostdlib -O2 -flto}} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 
 typedef struct VEC_constructor_elt_gc { } VEC_constructor_elt_gc;
 #include "20091016-1_a.h"
Index: gcc/testsuite/gcc.dg/lto/20091020-1_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20091020-1_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20091020-1_0.c	(working copy)
@@ -1,6 +1,7 @@ 
 /* { dg-lto-do link } */
 /* { dg-require-effective-target fpic } */
 /* { dg-lto-options {{-fPIC -r -nostdlib -flto}} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 
 typedef struct {
     int NumPackStreams;
Index: gcc/testsuite/gcc.dg/lto/20091020-2_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20091020-2_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20091020-2_0.c	(working copy)
@@ -1,6 +1,7 @@ 
 /* { dg-lto-do link } */
 /* { dg-require-effective-target fpic } */
 /* { dg-lto-options {{-fPIC -r -nostdlib -flto}} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 
 typedef struct {
     int NumPackStreams;
Index: gcc/testsuite/gcc.dg/lto/20091027-1_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20091027-1_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20091027-1_0.c	(working copy)
@@ -1,5 +1,5 @@ 
 /* { dg-lto-do link } */
-/* { dg-extra-ld-options "-r -nostdlib" } */
+/* { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" } */
 
 typedef struct _xmlDict xmlDict;
 struct _xmlDict {
Index: gcc/testsuite/gcc.dg/lto/20100426_0.c
===================================================================
--- gcc/testsuite/gcc.dg/lto/20100426_0.c	(revision 259789)
+++ gcc/testsuite/gcc.dg/lto/20100426_0.c	(working copy)
@@ -1,5 +1,6 @@ 
 /* { dg-lto-do link } */
 /* { dg-lto-options {{-r -nostdlib -flto -g}} } */
+/* { dg-extra-ld-options "-flinker-output=nolto-rel" } */
 
 long Perl_my_htonl (long l)
 {
Index: gcc/testsuite/gfortran.dg/lto/20091016-1_0.f90
===================================================================
--- gcc/testsuite/gfortran.dg/lto/20091016-1_0.f90	(revision 259789)
+++ gcc/testsuite/gfortran.dg/lto/20091016-1_0.f90	(working copy)
@@ -1,5 +1,6 @@ 
 ! { dg-lto-do link }
 ! { dg-lto-options {{-flto -g -fPIC -r -nostdlib} {-O -flto -g -fPIC -r -nostdlib}} }
+! { dg-extra-ld-options "-flinker-output=nolto-rel" }
 
       FUNCTION makenumberstring(x)
       IMPLICIT NONE
Index: gcc/testsuite/gfortran.dg/lto/20091028-1_0.f90
===================================================================
--- gcc/testsuite/gfortran.dg/lto/20091028-1_0.f90	(revision 259789)
+++ gcc/testsuite/gfortran.dg/lto/20091028-1_0.f90	(working copy)
@@ -1,5 +1,5 @@ 
 ! { dg-lto-do link }
-! { dg-extra-ld-options "-r -nostdlib -finline-functions" }
+! { dg-extra-ld-options "-r -nostdlib -finline-functions -flinker-output=nolto-rel" }
 
 SUBROUTINE int_gen_ti_header_char( hdrbuf, hdrbufsize, itypesize, &
                               DataHandle, Element, VarName, Data, code )
Index: gcc/testsuite/gfortran.dg/lto/20091028-2_0.f90
===================================================================
--- gcc/testsuite/gfortran.dg/lto/20091028-2_0.f90	(revision 259789)
+++ gcc/testsuite/gfortran.dg/lto/20091028-2_0.f90	(working copy)
@@ -1,5 +1,5 @@ 
 ! { dg-lto-do link }
-! { dg-extra-ld-options "-r -nostdlib -finline-functions" }
+! { dg-extra-ld-options "-r -nostdlib -finline-functions -flinker-output=nolto-rel" }
 
 SUBROUTINE int_gen_ti_header_char( hdrbuf, hdrbufsize, itypesize, &
                               DataHandle, Element, VarName, Data, code )
Index: gcc/testsuite/gfortran.dg/lto/pr46911_0.f
===================================================================
--- gcc/testsuite/gfortran.dg/lto/pr46911_0.f	(revision 259789)
+++ gcc/testsuite/gfortran.dg/lto/pr46911_0.f	(working copy)
@@ -1,6 +1,6 @@ 
 ! { dg-lto-do link }
 ! { dg-lto-options {{ -O2 -flto -g }} }
-! { dg-extra-ld-options "-r -nostdlib" }
+! { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" }
       common/main1/ eps(2)
       call dalie6s(iqmod6,1,wx,cor6d)
       end
Index: gcc/testsuite/gfortran.dg/lto/pr47839_0.f90
===================================================================
--- gcc/testsuite/gfortran.dg/lto/pr47839_0.f90	(revision 259789)
+++ gcc/testsuite/gfortran.dg/lto/pr47839_0.f90	(working copy)
@@ -1,6 +1,6 @@ 
 ! { dg-lto-do link }
 ! { dg-lto-options {{ -g -flto }} }
-! { dg-extra-ld-options "-r -nostdlib" }
+! { dg-extra-ld-options "-r -nostdlib -flinker-output=nolto-rel" }
 
 MODULE globalvar_mod
 integer        :: xstop
Index: gcc/toplev.c
===================================================================
--- gcc/toplev.c	(revision 259789)
+++ gcc/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)
Index: lto-plugin/lto-plugin.c
===================================================================
--- lto-plugin/lto-plugin.c	(revision 259789)
+++ lto-plugin/lto-plugin.c	(working copy)
@@ -27,10 +27,13 @@ 
    More information at http://gcc.gnu.org/wiki/whopr/driver.
 
    This plugin should be passed the lto-wrapper options and will forward them.
-   It also has 2 options of its own:
+   It also has options at his own:
    -debug: Print the command line used to run lto-wrapper.
    -nop: Instead of running lto-wrapper, pass the original to the plugin. This
-   only works if the input files are hybrid.  */
+   only works if the input files are hybrid. 
+   -linker-output-known: Do not determine linker output
+   -sym-style={none,win32,underscore|uscore}
+   -pass-through  */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -159,6 +162,7 @@ 
 
 static struct plugin_file_info *claimed_files = NULL;
 static unsigned int num_claimed_files = 0;
+static unsigned int non_claimed_files = 0;
 
 /* List of files with offloading.  */
 static struct plugin_offload_file *offload_files;
@@ -185,6 +189,7 @@ 
 static char *resolution_file = NULL;
 static enum ld_plugin_output_file_type linker_output;
 static int linker_output_set;
+static int linker_output_known;
 
 /* The version of gold being used, or -1 if not gold.  The number is
    MAJOR * 100 + MINOR.  */
@@ -637,7 +642,8 @@ 
 all_symbols_read_handler (void)
 {
   unsigned i;
-  unsigned num_lto_args = num_claimed_files + lto_wrapper_num_args + 3;
+  unsigned num_lto_args = num_claimed_files + lto_wrapper_num_args + 2
+    	   + !linker_output_known;
   char **lto_argv;
   const char *linker_output_str = NULL;
   const char **lto_arg_ptr;
@@ -661,26 +667,37 @@ 
   for (i = 0; i < lto_wrapper_num_args; i++)
     *lto_arg_ptr++ = lto_wrapper_argv[i];
 
-  assert (linker_output_set);
-  switch (linker_output)
+  if (!linker_output_known)
     {
-    case LDPO_REL:
-      linker_output_str = "-flinker-output=rel";
-      break;
-    case LDPO_DYN:
-      linker_output_str = "-flinker-output=dyn";
-      break;
-    case LDPO_PIE:
-      linker_output_str = "-flinker-output=pie";
-      break;
-    case LDPO_EXEC:
-      linker_output_str = "-flinker-output=exec";
-      break;
-    default:
-      message (LDPL_FATAL, "unsupported linker output %i", linker_output);
-      break;
+      assert (linker_output_set);
+      switch (linker_output)
+	{
+	case LDPO_REL:
+	  if (non_claimed_files)
+	    {
+	      message (LDPL_WARNING, "incremental linking of LTO and non-LTO "
+		       "objects; using -flinker-output=nolto-rel which will "
+		       "bypass whole program optimization");
+	      linker_output_str = "-flinker-output=nolto-rel";
+	    }
+	  else
+	    linker_output_str = "-flinker-output=rel";
+	  break;
+	case LDPO_DYN:
+	  linker_output_str = "-flinker-output=dyn";
+	  break;
+	case LDPO_PIE:
+	  linker_output_str = "-flinker-output=pie";
+	  break;
+	case LDPO_EXEC:
+	  linker_output_str = "-flinker-output=exec";
+	  break;
+	default:
+	  message (LDPL_FATAL, "unsupported linker output %i", linker_output);
+	  break;
+	}
+      *lto_arg_ptr++ = xstrdup (linker_output_str);
     }
-  *lto_arg_ptr++ = xstrdup (linker_output_str);
 
   if (num_offload_files > 0)
     {
@@ -1108,6 +1125,7 @@ 
   goto cleanup;
 
  err:
+  non_claimed_files++;
   free (lto_file.name);
 
  cleanup:
@@ -1122,6 +1140,8 @@ 
 static void
 process_option (const char *option)
 {
+  if (strcmp (option, "-linker-output-known") == 0)
+    linker_output_known = 1;
   if (strcmp (option, "-debug") == 0)
     debug = 1;
   else if (strcmp (option, "-nop") == 0)