Patchwork [build,lto] Only accept -fuse-linker-plugin if linker supports -plugin (PR lto/46944)

login
register
mail settings
Submitter Rainer Orth
Date March 14, 2011, 7:07 p.m.
Message ID <yddaagxseqd.fsf@manam.CeBiTec.Uni-Bielefeld.DE>
Download mbox | patch
Permalink /patch/86800/
State New
Headers show

Comments

Rainer Orth - March 14, 2011, 7:07 p.m.
Richard Guenther <rguenther@suse.de> writes:

>> > Can you update your patch with the tri-state solution?
>> 
>> Sure if the solution is deemed acceptable.  There isn't much point in
>> following that route if you see problems up front.
>
> If that solution avoids 3) then yes, I'm fine with going that route.
> Both 1) and 2) are very desirable anyway.

Here's the updated patch, which also incorporates Paolo's suggestion.
Bootstrapped without regressions on i386-pc-solaris2.11 with Sun as/ld
and GNU as/ld 2.21.  I couldn't really test the middle ground (gold 2.20
with limited plugin support) since even mainline gold doesn't work for
me yet.  What I've done is rebuild xgcc after manually changing
HAVE_LTO_PLUGIN to 1 in auto-host.h.  After I realized that I needed to
remove the existing specs file, that variant worked as expected in that
-plugin is only passed to the linker with an explicit
-fuse-linker-plugin.

I had to make a last-minute change when I realized that two other uses
of #ifdef HAVE_LTO_PLUGIN needed to be updated since that macro is now
always defined.  I'm running fresh bootstraps to make sure nothing broke
that way.

Ok for mainline if that passes, and perhaps also the 4.6 branch?

Thanks.
	Rainer


2011-02-05  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>

	PR lto/46944
	* configure.ac (gcc_cv_gld_major_version, gcc_cv_gld_minor):
	Handle in-tree gold.
	(ld_vers): Extract binutils version for gold.
	(gcc_cv_ld_hidden): Handle gold here.
	(gcc_cv_lto_plugin): Determine level of linker plugin support.
	* configure: Regenerate.
	* config.in: Regenerate.
	* gcc.c: Only use LTO plugin if HAVE_LTO_PLUGIN > 0, reject
	-fuse-linker-plugin otherwise.
	(LINK_PLUGIN_SPEC): Define.  Extract from LINK_COMMAND_SPEC.
	(LINK_COMMAND_SPEC): Use it.
	(main): Only look for LTOPLUGINSONAME if HAVE_LTO_PLUGIN > 0.
Richard Guenther - March 15, 2011, 9:42 a.m.
On Mon, 14 Mar 2011, Rainer Orth wrote:

> Richard Guenther <rguenther@suse.de> writes:
> 
> >> > Can you update your patch with the tri-state solution?
> >> 
> >> Sure if the solution is deemed acceptable.  There isn't much point in
> >> following that route if you see problems up front.
> >
> > If that solution avoids 3) then yes, I'm fine with going that route.
> > Both 1) and 2) are very desirable anyway.
> 
> Here's the updated patch, which also incorporates Paolo's suggestion.
> Bootstrapped without regressions on i386-pc-solaris2.11 with Sun as/ld
> and GNU as/ld 2.21.  I couldn't really test the middle ground (gold 2.20
> with limited plugin support) since even mainline gold doesn't work for
> me yet.  What I've done is rebuild xgcc after manually changing
> HAVE_LTO_PLUGIN to 1 in auto-host.h.  After I realized that I needed to
> remove the existing specs file, that variant worked as expected in that
> -plugin is only passed to the linker with an explicit
> -fuse-linker-plugin.
> 
> I had to make a last-minute change when I realized that two other uses
> of #ifdef HAVE_LTO_PLUGIN needed to be updated since that macro is now
> always defined.  I'm running fresh bootstraps to make sure nothing broke
> that way.
> 
> Ok for mainline if that passes, and perhaps also the 4.6 branch?

I'm ok with this for mainline - Paolo, can you double-check the
autofoo stuff?  As for 4.6 I'd like to give it a day or two on
trunk to allow people to report problems.

Thanks,
Richard.

> Thanks.
> 	Rainer
> 
> 
> 2011-02-05  Rainer Orth  <ro@CeBiTec.Uni-Bielefeld.DE>
> 
> 	PR lto/46944
> 	* configure.ac (gcc_cv_gld_major_version, gcc_cv_gld_minor):
> 	Handle in-tree gold.
> 	(ld_vers): Extract binutils version for gold.
> 	(gcc_cv_ld_hidden): Handle gold here.
> 	(gcc_cv_lto_plugin): Determine level of linker plugin support.
> 	* configure: Regenerate.
> 	* config.in: Regenerate.
> 	* gcc.c: Only use LTO plugin if HAVE_LTO_PLUGIN > 0, reject
> 	-fuse-linker-plugin otherwise.
> 	(LINK_PLUGIN_SPEC): Define.  Extract from LINK_COMMAND_SPEC.
> 	(LINK_COMMAND_SPEC): Use it.
> 	(main): Only look for LTOPLUGINSONAME if HAVE_LTO_PLUGIN > 0.
> 
> diff -r 71f0a0dc3338 gcc/configure.ac
> --- a/gcc/configure.ac	Mon Mar 14 19:57:51 2011 +0100
> +++ b/gcc/configure.ac	Mon Mar 14 19:59:05 2011 +0100
> @@ -1967,7 +1967,8 @@
>  esac 
>  
>  AC_MSG_CHECKING(what linker to use)
> -if test "$gcc_cv_ld" = ../ld/ld-new$build_exeext; then
> +if test "$gcc_cv_ld" = ../ld/ld-new$build_exeext \
> +   || test "$gcc_cv_ld" = ../gold/ld-new$build_exeext; then
>  	# Single tree build which includes ld.  We want to prefer it
>  	# over whatever linker top-level may have detected, since
>  	# we'll use what we're building after installation anyway.
> @@ -1978,6 +1979,8 @@
>  	    || grep 'EMUL = .*linux' ../ld/Makefile \
>  	    || grep 'EMUL = .*lynx' ../ld/Makefile) > /dev/null; then
>  	  in_tree_ld_is_elf=yes
> +	elif test "$ld_is_gold" = yes; then
> +	  in_tree_ld_is_elf=yes
>  	fi
>  	for f in $gcc_cv_ld_bfd_srcdir/configure $gcc_cv_ld_gld_srcdir/configure $gcc_cv_ld_gld_srcdir/configure.in $gcc_cv_ld_gld_srcdir/Makefile.in
>  	do
> @@ -2192,11 +2195,23 @@
>  changequote(,)dnl
>  if test $in_tree_ld != yes ; then
>    ld_ver=`$gcc_cv_ld --version 2>/dev/null | sed 1q`
> -  if test x"$ld_is_gold" = xyes; then
> -    gcc_cv_ld_hidden=yes
> -  elif echo "$ld_ver" | grep GNU > /dev/null; then
> -    ld_vers=`echo $ld_ver | sed -n \
> -	-e 's,^.*[	 ]\([0-9][0-9]*\.[0-9][0-9]*.*\)$,\1,p'`
> +  if echo "$ld_ver" | grep GNU > /dev/null; then
> +    if test x"$ld_is_gold" = xyes; then
> +      # GNU gold --version looks like this:
> +      #
> +      # GNU gold (GNU Binutils 2.21.51.20110225) 1.11
> +      #
> +      # We extract the binutils version which is more familiar and specific
> +      # than the gold version.
> +      ld_vers=`echo $ld_ver | sed -n \
> +	  -e 's,^[^)]*[	 ]\([0-9][0-9]*\.[0-9][0-9]*[^)]*\)) .*$,\1,p'`
> +    else
> +      # GNU ld --version looks like this:
> +      #
> +      # GNU ld (GNU Binutils) 2.21.51.20110225
> +      ld_vers=`echo $ld_ver | sed -n \
> +	  -e 's,^.*[	 ]\([0-9][0-9]*\.[0-9][0-9]*.*\)$,\1,p'`
> +    fi
>      ld_date=`echo $ld_ver | sed -n 's,^.*\([2-9][0-9][0-9][0-9]\)[-]*\([01][0-9]\)[-]*\([0-3][0-9]\).*$,\1\2\3,p'`
>      ld_vers_major=`expr "$ld_vers" : '\([0-9]*\)'`
>      ld_vers_minor=`expr "$ld_vers" : '[0-9]*\.\([0-9]*\)'`
> @@ -2235,7 +2250,9 @@
>    fi
>  else
>    gcc_cv_ld_hidden=yes
> -  if echo "$ld_ver" | grep GNU > /dev/null; then
> +  if test x"$ld_is_gold" = xyes; then
> +    :
> +  elif echo "$ld_ver" | grep GNU > /dev/null; then
>      if test 0"$ld_date" -lt 20020404; then
>        if test -n "$ld_date"; then
>  	# If there was date string, but was earlier than 2002-04-04, fail
> @@ -3173,23 +3190,27 @@
>  fi
>  
>  AC_MSG_CHECKING(linker plugin support)
> -gcc_cv_lto_plugin=no
> +gcc_cv_lto_plugin=0
>  if test -f liblto_plugin.la; then
>    if test $in_tree_ld = yes -a x"$ORIGINAL_PLUGIN_LD_FOR_TARGET=" = x"$gcc_cv_ld"; then
> -    if test x"$ld_is_gold" = xyes; then
> -      gcc_cv_lto_plugin=yes
> -    elif test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 21 -o "$gcc_cv_gld_major_version" -gt 2; then \
> -      gcc_cv_lto_plugin=yes
> +    if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 21 -o "$gcc_cv_gld_major_version" -gt 2; then
> +      gcc_cv_lto_plugin=2
> +    elif test "$ld_is_gold" = yes -a "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -eq 20; then
> +      gcc_cv_lto_plugin=1
> +
>      fi
> -  # Check if the linker supports --plugin-opt option
> -  elif $ORIGINAL_PLUGIN_LD_FOR_TARGET --help 2>/dev/null | grep plugin-opt > /dev/null; then
> -    gcc_cv_lto_plugin=yes
> +  elif echo "$ld_ver" | grep GNU > /dev/null; then
> +    # Require GNU ld or gold 2.21+ for plugin support by default.
> +    if test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -ge 21; then
> +      gcc_cv_lto_plugin=2
> +    # Allow -fuse-linker-plugin to enable plugin support in GNU gold 2.20.
> +    elif test "$ld_is_gold" = yes -a "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -eq 20; then
> +      gcc_cv_lto_plugin=1
> +    fi
>    fi
>  fi
> -if test x"$gcc_cv_lto_plugin" = xyes; then
> -  AC_DEFINE(HAVE_LTO_PLUGIN, 1,
> -[Define if your linker supports plugin.])
> -fi
> +AC_DEFINE_UNQUOTED(HAVE_LTO_PLUGIN, $gcc_cv_lto_plugin,
> +  [Define to the level of your linker's plugin support.])
>  AC_MSG_RESULT($gcc_cv_lto_plugin)
>  
>  case "$target" in
> diff -r 71f0a0dc3338 gcc/gcc.c
> --- a/gcc/gcc.c	Mon Mar 14 19:57:51 2011 +0100
> +++ b/gcc/gcc.c	Mon Mar 14 19:59:05 2011 +0100
> @@ -621,19 +621,37 @@
>  # endif
>  #endif
>  
> -/* Conditional to test whether plugin is used or not.
> +/* Conditional to test whether the LTO plugin is used or not.
>     FIXME: For slim LTO we will need to enable plugin unconditionally.  This
>     still cause problems with PLUGIN_LD != LD and when plugin is built but
>     not useable.  For GCC 4.6 we don't support slim LTO and thus we can enable
>     plugin only when LTO is enabled.  We still honor explicit
> -   -fuse-linker-plugin.  */
> -#ifdef HAVE_LTO_PLUGIN
> +   -fuse-linker-plugin if the linker used understands -plugin.  */
> +
> +/* The linker has some plugin support.  */
> +#if HAVE_LTO_PLUGIN > 0
> +/* The linker used has full plugin support, use LTO plugin by default.  */
> +#if HAVE_LTO_PLUGIN == 2
>  #define PLUGIN_COND "!fno-use-linker-plugin:%{flto|flto=*|fuse-linker-plugin"
>  #define PLUGIN_COND_CLOSE "}"
>  #else
> +/* The linker used has limited plugin support, use LTO plugin with explicit
> +   -fuse-linker-plugin.  */
>  #define PLUGIN_COND "fuse-linker-plugin"
>  #define PLUGIN_COND_CLOSE ""
>  #endif
> +#define LINK_PLUGIN_SPEC \
> +    "%{"PLUGIN_COND": \
> +    -plugin %(linker_plugin_file) \
> +    -plugin-opt=%(lto_wrapper) \
> +    -plugin-opt=-fresolution=%u.res \
> +    %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} \
> +    }"PLUGIN_COND_CLOSE
> +#else
> +/* The linker used doesn't support -plugin, reject -fuse-linker-plugin.  */
> +#define LINK_PLUGIN_SPEC "%{fuse-linker-plugin:\
> +    %e-fuse-linker-plugin is not supported in this configuration}"
> +#endif
>  
>  
>  /* -u* was put back because both BSD and SysV seem to support it.  */
> @@ -648,14 +666,9 @@
>  #ifndef LINK_COMMAND_SPEC
>  #define LINK_COMMAND_SPEC "\
>  %{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
> -    %(linker) \
> -    %{"PLUGIN_COND": \
> -    -plugin %(linker_plugin_file) \
> -    -plugin-opt=%(lto_wrapper) \
> -    -plugin-opt=-fresolution=%u.res \
> -    %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} \
> -    }"PLUGIN_COND_CLOSE" \
> -    %{flto|flto=*:%<fcompare-debug*} \
> +    %(linker) " \
> +    LINK_PLUGIN_SPEC \
> +    "%{flto|flto=*:%<fcompare-debug*} \
>      %{flto} %{flto=*} %l " LINK_PIE_SPEC \
>     "%X %{o*} %{e*} %{N} %{n} %{r}\
>      %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}}\
> @@ -6815,11 +6828,13 @@
>    if (num_linker_inputs > 0 && !seen_error () && print_subprocess_help < 2)
>      {
>        int tmp = execution_count;
> -#ifdef HAVE_LTO_PLUGIN
> +#if HAVE_LTO_PLUGIN > 0
> +#if HAVE_LTO_PLUGIN == 2
>        const char *fno_use_linker_plugin = "fno-use-linker-plugin";
>  #else
>        const char *fuse_linker_plugin = "fuse-linker-plugin";
>  #endif
> +#endif
>  
>        /* We'll use ld if we can't find collect2.  */
>        if (! strcmp (linker_name_spec, "collect2"))
> @@ -6829,7 +6844,8 @@
>  	    linker_name_spec = "ld";
>  	}
>  
> -#ifdef HAVE_LTO_PLUGIN
> +#if HAVE_LTO_PLUGIN > 0
> +#if HAVE_LTO_PLUGIN == 2
>        if (!switch_matches (fno_use_linker_plugin,
>  			   fno_use_linker_plugin + strlen (fno_use_linker_plugin), 0))
>  #else
> @@ -6843,6 +6859,7 @@
>  	  if (!linker_plugin_file_spec)
>  	    fatal_error ("-fuse-linker-plugin, but " LTOPLUGINSONAME " not found");
>  	}
> +#endif
>        lto_gcc_spec = argv[0];
>  
>        /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables
> 
> 
>
Rainer Orth - March 16, 2011, 9:23 a.m.
Richard Guenther <rguenther@suse.de> writes:

>> Ok for mainline if that passes, and perhaps also the 4.6 branch?
>
> I'm ok with this for mainline - Paolo, can you double-check the
> autofoo stuff?  As for 4.6 I'd like to give it a day or two on
> trunk to allow people to report problems.

Paolo, do you have any comments on the configure.ac part of the patch?

Thanks.
	Rainer
Paolo Bonzini - March 16, 2011, 9:27 a.m.
On 03/16/2011 10:23 AM, Rainer Orth wrote:
> >  I'm ok with this for mainline - Paolo, can you double-check the
> >  autofoo stuff?  As for 4.6 I'd like to give it a day or two on
> >  trunk to allow people to report problems.
>
> Paolo, do you have any comments on the configure.ac part of the patch?

It's okay.

I hope Binutils will never switch to 3.x, but that's not your fault.

Paolo
Rainer Orth - March 16, 2011, 9:43 a.m.
Paolo Bonzini <bonzini@gnu.org> writes:

>> Paolo, do you have any comments on the configure.ac part of the patch?
>
> It's okay.

Thanks, installed on mainline then.

> I hope Binutils will never switch to 3.x, but that's not your fault.

True: although there are some precautions for binutils > 2, I doubt they
are consistent.  Only if we could deprecate all binutils 2.x releases,
the GCC configure could be considerably simplified.

	Rainer
Rainer Orth - March 18, 2011, 9:26 a.m.
Richard Guenther <rguenther@suse.de> writes:

>> Ok for mainline if that passes, and perhaps also the 4.6 branch?
>
> I'm ok with this for mainline - Paolo, can you double-check the
> autofoo stuff?  As for 4.6 I'd like to give it a day or two on
> trunk to allow people to report problems.

The patch has been on mainline for two days now and I'm not aware of any
problems.  Unless someone objects, I'm going to apply it to 4.6 branch
later today.

	Rainer
Richard Guenther - March 18, 2011, 10:09 a.m.
On Fri, Mar 18, 2011 at 10:26 AM, Rainer Orth
<ro@cebitec.uni-bielefeld.de> wrote:
> Richard Guenther <rguenther@suse.de> writes:
>
>>> Ok for mainline if that passes, and perhaps also the 4.6 branch?
>>
>> I'm ok with this for mainline - Paolo, can you double-check the
>> autofoo stuff?  As for 4.6 I'd like to give it a day or two on
>> trunk to allow people to report problems.
>
> The patch has been on mainline for two days now and I'm not aware of any
> problems.  Unless someone objects, I'm going to apply it to 4.6 branch
> later today.

It seemed to have disabled linker-plugin support for old binutils
with --with-plugin-ld=/usr/local/bin/gold, explicit -fuse-linker-plugin says
it is not supported.  The system linker does not have plugin support
(nor gold).  /usr/local has gold from binutils 2.20.50.xxx.  So it seems that

    # Allow -fuse-linker-plugin to enable plugin support in GNU gold 2.20.
    elif test "$ld_is_gold" = yes -a "$ld_vers_major" -eq 2 -a
"$ld_vers_minor" -eq 20; then
      gcc_cv_lto_plugin=1
    fi

only allows explicit -fuse-linker-plugin for recent gold but based on checking
the system linker version (instead of that of --with-plugin-ld).  I'd say
allow explicit -fuse-linker-plugin always if --with-plugin-ld is specified.

Richard.
Rainer Orth - March 18, 2011, 10:16 a.m.
Richard Guenther <richard.guenther@gmail.com> writes:

> It seemed to have disabled linker-plugin support for old binutils
> with --with-plugin-ld=/usr/local/bin/gold, explicit -fuse-linker-plugin says
> it is not supported.  The system linker does not have plugin support
> (nor gold).  /usr/local has gold from binutils 2.20.50.xxx.  So it seems that
>
>     # Allow -fuse-linker-plugin to enable plugin support in GNU gold 2.20.
>     elif test "$ld_is_gold" = yes -a "$ld_vers_major" -eq 2 -a
> "$ld_vers_minor" -eq 20; then
>       gcc_cv_lto_plugin=1
>     fi
>
> only allows explicit -fuse-linker-plugin for recent gold but based on checking
> the system linker version (instead of that of --with-plugin-ld).  I'd say
> allow explicit -fuse-linker-plugin always if --with-plugin-ld is specified.

Agreed.  I'll have a look and refrain from installing on 4.6 until this
is resolved.  I wasn't even aware of --with-plugin-ld, which isn't
documented in install.texi ;-(  This stuff seems insanely complicated to
me, though: which user is supposed to deal with such complications?

	Rainer
Richard Guenther - March 18, 2011, 10:19 a.m.
On Fri, 18 Mar 2011, Rainer Orth wrote:

> Richard Guenther <richard.guenther@gmail.com> writes:
> 
> > It seemed to have disabled linker-plugin support for old binutils
> > with --with-plugin-ld=/usr/local/bin/gold, explicit -fuse-linker-plugin says
> > it is not supported.  The system linker does not have plugin support
> > (nor gold).  /usr/local has gold from binutils 2.20.50.xxx.  So it seems that
> >
> >     # Allow -fuse-linker-plugin to enable plugin support in GNU gold 2.20.
> >     elif test "$ld_is_gold" = yes -a "$ld_vers_major" -eq 2 -a
> > "$ld_vers_minor" -eq 20; then
> >       gcc_cv_lto_plugin=1
> >     fi
> >
> > only allows explicit -fuse-linker-plugin for recent gold but based on checking
> > the system linker version (instead of that of --with-plugin-ld).  I'd say
> > allow explicit -fuse-linker-plugin always if --with-plugin-ld is specified.
> 
> Agreed.  I'll have a look and refrain from installing on 4.6 until this
> is resolved.  I wasn't even aware of --with-plugin-ld, which isn't
> documented in install.texi ;-(  This stuff seems insanely complicated to
> me, though: which user is supposed to deal with such complications?

It's sort of historic ... with plugin support for GNU ld we can probably
drop this flag for 4.7 (eventually I'd even like to enforce the use
of the plugin all the time or disable LTO, just for the sake of reducing
the testing and bugreporting matrix ...).

I just noticed the above with the LTO setup of our SPEC testers
which are using somewhat old system tools.

Thanks,
Richard.
Rainer Orth - March 18, 2011, 10:23 a.m.
Richard Guenther <rguenther@suse.de> writes:

> It's sort of historic ... with plugin support for GNU ld we can probably

Could you or someone else who understands this stuff please document it
in install.texi then?  Thanks.

> drop this flag for 4.7 (eventually I'd even like to enforce the use
> of the plugin all the time or disable LTO, just for the sake of reducing
> the testing and bugreporting matrix ...).

This would mean no more LTO without GNU ld/gold, then?  Isn't this going
too far?

	Rainer
Richard Guenther - March 18, 2011, 10:34 a.m.
On Fri, 18 Mar 2011, Rainer Orth wrote:

> Richard Guenther <rguenther@suse.de> writes:
> 
> > It's sort of historic ... with plugin support for GNU ld we can probably
> 
> Could you or someone else who understands this stuff please document it
> in install.texi then?  Thanks.

I'll try.

> > drop this flag for 4.7 (eventually I'd even like to enforce the use
> > of the plugin all the time or disable LTO, just for the sake of reducing
> > the testing and bugreporting matrix ...).
> 
> This would mean no more LTO without GNU ld/gold, then?  Isn't this going
> too far?

I'm not sure - the collect2 path has known issues that are hard
to address and result in unexpected behavior, so it's probably
not a good service to our users to serve them half-broken LTO.

But I suppose we can discuss this when we also see a clear benefit
in removing the corresponding code in gcc.

Richard.
kk

Patch

diff -r 71f0a0dc3338 gcc/configure.ac
--- a/gcc/configure.ac	Mon Mar 14 19:57:51 2011 +0100
+++ b/gcc/configure.ac	Mon Mar 14 19:59:05 2011 +0100
@@ -1967,7 +1967,8 @@ 
 esac 
 
 AC_MSG_CHECKING(what linker to use)
-if test "$gcc_cv_ld" = ../ld/ld-new$build_exeext; then
+if test "$gcc_cv_ld" = ../ld/ld-new$build_exeext \
+   || test "$gcc_cv_ld" = ../gold/ld-new$build_exeext; then
 	# Single tree build which includes ld.  We want to prefer it
 	# over whatever linker top-level may have detected, since
 	# we'll use what we're building after installation anyway.
@@ -1978,6 +1979,8 @@ 
 	    || grep 'EMUL = .*linux' ../ld/Makefile \
 	    || grep 'EMUL = .*lynx' ../ld/Makefile) > /dev/null; then
 	  in_tree_ld_is_elf=yes
+	elif test "$ld_is_gold" = yes; then
+	  in_tree_ld_is_elf=yes
 	fi
 	for f in $gcc_cv_ld_bfd_srcdir/configure $gcc_cv_ld_gld_srcdir/configure $gcc_cv_ld_gld_srcdir/configure.in $gcc_cv_ld_gld_srcdir/Makefile.in
 	do
@@ -2192,11 +2195,23 @@ 
 changequote(,)dnl
 if test $in_tree_ld != yes ; then
   ld_ver=`$gcc_cv_ld --version 2>/dev/null | sed 1q`
-  if test x"$ld_is_gold" = xyes; then
-    gcc_cv_ld_hidden=yes
-  elif echo "$ld_ver" | grep GNU > /dev/null; then
-    ld_vers=`echo $ld_ver | sed -n \
-	-e 's,^.*[	 ]\([0-9][0-9]*\.[0-9][0-9]*.*\)$,\1,p'`
+  if echo "$ld_ver" | grep GNU > /dev/null; then
+    if test x"$ld_is_gold" = xyes; then
+      # GNU gold --version looks like this:
+      #
+      # GNU gold (GNU Binutils 2.21.51.20110225) 1.11
+      #
+      # We extract the binutils version which is more familiar and specific
+      # than the gold version.
+      ld_vers=`echo $ld_ver | sed -n \
+	  -e 's,^[^)]*[	 ]\([0-9][0-9]*\.[0-9][0-9]*[^)]*\)) .*$,\1,p'`
+    else
+      # GNU ld --version looks like this:
+      #
+      # GNU ld (GNU Binutils) 2.21.51.20110225
+      ld_vers=`echo $ld_ver | sed -n \
+	  -e 's,^.*[	 ]\([0-9][0-9]*\.[0-9][0-9]*.*\)$,\1,p'`
+    fi
     ld_date=`echo $ld_ver | sed -n 's,^.*\([2-9][0-9][0-9][0-9]\)[-]*\([01][0-9]\)[-]*\([0-3][0-9]\).*$,\1\2\3,p'`
     ld_vers_major=`expr "$ld_vers" : '\([0-9]*\)'`
     ld_vers_minor=`expr "$ld_vers" : '[0-9]*\.\([0-9]*\)'`
@@ -2235,7 +2250,9 @@ 
   fi
 else
   gcc_cv_ld_hidden=yes
-  if echo "$ld_ver" | grep GNU > /dev/null; then
+  if test x"$ld_is_gold" = xyes; then
+    :
+  elif echo "$ld_ver" | grep GNU > /dev/null; then
     if test 0"$ld_date" -lt 20020404; then
       if test -n "$ld_date"; then
 	# If there was date string, but was earlier than 2002-04-04, fail
@@ -3173,23 +3190,27 @@ 
 fi
 
 AC_MSG_CHECKING(linker plugin support)
-gcc_cv_lto_plugin=no
+gcc_cv_lto_plugin=0
 if test -f liblto_plugin.la; then
   if test $in_tree_ld = yes -a x"$ORIGINAL_PLUGIN_LD_FOR_TARGET=" = x"$gcc_cv_ld"; then
-    if test x"$ld_is_gold" = xyes; then
-      gcc_cv_lto_plugin=yes
-    elif test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 21 -o "$gcc_cv_gld_major_version" -gt 2; then \
-      gcc_cv_lto_plugin=yes
+    if test "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -ge 21 -o "$gcc_cv_gld_major_version" -gt 2; then
+      gcc_cv_lto_plugin=2
+    elif test "$ld_is_gold" = yes -a "$gcc_cv_gld_major_version" -eq 2 -a "$gcc_cv_gld_minor_version" -eq 20; then
+      gcc_cv_lto_plugin=1
+
     fi
-  # Check if the linker supports --plugin-opt option
-  elif $ORIGINAL_PLUGIN_LD_FOR_TARGET --help 2>/dev/null | grep plugin-opt > /dev/null; then
-    gcc_cv_lto_plugin=yes
+  elif echo "$ld_ver" | grep GNU > /dev/null; then
+    # Require GNU ld or gold 2.21+ for plugin support by default.
+    if test "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -ge 21; then
+      gcc_cv_lto_plugin=2
+    # Allow -fuse-linker-plugin to enable plugin support in GNU gold 2.20.
+    elif test "$ld_is_gold" = yes -a "$ld_vers_major" -eq 2 -a "$ld_vers_minor" -eq 20; then
+      gcc_cv_lto_plugin=1
+    fi
   fi
 fi
-if test x"$gcc_cv_lto_plugin" = xyes; then
-  AC_DEFINE(HAVE_LTO_PLUGIN, 1,
-[Define if your linker supports plugin.])
-fi
+AC_DEFINE_UNQUOTED(HAVE_LTO_PLUGIN, $gcc_cv_lto_plugin,
+  [Define to the level of your linker's plugin support.])
 AC_MSG_RESULT($gcc_cv_lto_plugin)
 
 case "$target" in
diff -r 71f0a0dc3338 gcc/gcc.c
--- a/gcc/gcc.c	Mon Mar 14 19:57:51 2011 +0100
+++ b/gcc/gcc.c	Mon Mar 14 19:59:05 2011 +0100
@@ -621,19 +621,37 @@ 
 # endif
 #endif
 
-/* Conditional to test whether plugin is used or not.
+/* Conditional to test whether the LTO plugin is used or not.
    FIXME: For slim LTO we will need to enable plugin unconditionally.  This
    still cause problems with PLUGIN_LD != LD and when plugin is built but
    not useable.  For GCC 4.6 we don't support slim LTO and thus we can enable
    plugin only when LTO is enabled.  We still honor explicit
-   -fuse-linker-plugin.  */
-#ifdef HAVE_LTO_PLUGIN
+   -fuse-linker-plugin if the linker used understands -plugin.  */
+
+/* The linker has some plugin support.  */
+#if HAVE_LTO_PLUGIN > 0
+/* The linker used has full plugin support, use LTO plugin by default.  */
+#if HAVE_LTO_PLUGIN == 2
 #define PLUGIN_COND "!fno-use-linker-plugin:%{flto|flto=*|fuse-linker-plugin"
 #define PLUGIN_COND_CLOSE "}"
 #else
+/* The linker used has limited plugin support, use LTO plugin with explicit
+   -fuse-linker-plugin.  */
 #define PLUGIN_COND "fuse-linker-plugin"
 #define PLUGIN_COND_CLOSE ""
 #endif
+#define LINK_PLUGIN_SPEC \
+    "%{"PLUGIN_COND": \
+    -plugin %(linker_plugin_file) \
+    -plugin-opt=%(lto_wrapper) \
+    -plugin-opt=-fresolution=%u.res \
+    %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} \
+    }"PLUGIN_COND_CLOSE
+#else
+/* The linker used doesn't support -plugin, reject -fuse-linker-plugin.  */
+#define LINK_PLUGIN_SPEC "%{fuse-linker-plugin:\
+    %e-fuse-linker-plugin is not supported in this configuration}"
+#endif
 
 
 /* -u* was put back because both BSD and SysV seem to support it.  */
@@ -648,14 +666,9 @@ 
 #ifndef LINK_COMMAND_SPEC
 #define LINK_COMMAND_SPEC "\
 %{!fsyntax-only:%{!c:%{!M:%{!MM:%{!E:%{!S:\
-    %(linker) \
-    %{"PLUGIN_COND": \
-    -plugin %(linker_plugin_file) \
-    -plugin-opt=%(lto_wrapper) \
-    -plugin-opt=-fresolution=%u.res \
-    %{!nostdlib:%{!nodefaultlibs:%:pass-through-libs(%(link_gcc_c_sequence))}} \
-    }"PLUGIN_COND_CLOSE" \
-    %{flto|flto=*:%<fcompare-debug*} \
+    %(linker) " \
+    LINK_PLUGIN_SPEC \
+    "%{flto|flto=*:%<fcompare-debug*} \
     %{flto} %{flto=*} %l " LINK_PIE_SPEC \
    "%X %{o*} %{e*} %{N} %{n} %{r}\
     %{s} %{t} %{u*} %{z} %{Z} %{!nostdlib:%{!nostartfiles:%S}}\
@@ -6815,11 +6828,13 @@ 
   if (num_linker_inputs > 0 && !seen_error () && print_subprocess_help < 2)
     {
       int tmp = execution_count;
-#ifdef HAVE_LTO_PLUGIN
+#if HAVE_LTO_PLUGIN > 0
+#if HAVE_LTO_PLUGIN == 2
       const char *fno_use_linker_plugin = "fno-use-linker-plugin";
 #else
       const char *fuse_linker_plugin = "fuse-linker-plugin";
 #endif
+#endif
 
       /* We'll use ld if we can't find collect2.  */
       if (! strcmp (linker_name_spec, "collect2"))
@@ -6829,7 +6844,8 @@ 
 	    linker_name_spec = "ld";
 	}
 
-#ifdef HAVE_LTO_PLUGIN
+#if HAVE_LTO_PLUGIN > 0
+#if HAVE_LTO_PLUGIN == 2
       if (!switch_matches (fno_use_linker_plugin,
 			   fno_use_linker_plugin + strlen (fno_use_linker_plugin), 0))
 #else
@@ -6843,6 +6859,7 @@ 
 	  if (!linker_plugin_file_spec)
 	    fatal_error ("-fuse-linker-plugin, but " LTOPLUGINSONAME " not found");
 	}
+#endif
       lto_gcc_spec = argv[0];
 
       /* Rebuild the COMPILER_PATH and LIBRARY_PATH environment variables