I am attempting to convince GCC to build target libraries with link-time
optimizations enabled. I am primarily interested in libgo, but this discussion
seems like it would be applicable to libstdc++, libgfortran, etc. The
benchmarking I've done suggests that LTOing libgo yields a 5-20% speedup on
various Go programs, which is quite substantial.

The trouble is convincing GCC's build system to apply the various LTO flags to
the correct places. Ian Taylor suggested the following to plumb -flto into
libgo compilation:

    $ make GOCFLAGS_FOR_TARGET="-g -O3 -flto"

This nearly works, and I believe there are analogous options that would apply to
the other target libraries that GCC builds.

The trouble is that while building libgo, the build system uses ar and ranlib
directly from binutils, without providing them with the LTO plugin that was
built earlier. This means that the LTO information is dropped on the floor, and
attempting to link with the built libgo archive will fail.

I have a simple patch to the top-level configure.ac that resolves the issue by
teaching the build system to use the gcc-ar and gcc-ranlib wrappers which were
built earlier and know how to pass the linker plugin to the underlying ar/ranlib
commands. The patch is small enough that I've included it at the end of this
email.

My question is whether this is a reasonable thing to do. It seems like using
the gcc-ar and gcc-ranlib wrappers strictly improves the situation, and won't
impact compilations that don't specify -flto. But I'm not familiar enough with
the build system to say for sure.

Does anyone have advice to offer? Has anyone tried convincing the build system
to compile some of the other target libraries (like libstdc++ or libgfortran)
with -flto?

diff --git a/configure.ac b/configure.ac
index 87f2aee05008..1c38ac5979ff 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3400,7 +3400,8 @@ ACX_CHECK_INSTALLED_TARGET_TOOL(WINDMC_FOR_TARGET, windmc)
 
 RAW_CXX_FOR_TARGET="$CXX_FOR_TARGET"
 
-GCC_TARGET_TOOL(ar, AR_FOR_TARGET, AR, [binutils/ar])
+GCC_TARGET_TOOL(ar, AR_FOR_TARGET, AR,
+               [gcc/gcc-ar -B$$r/$(HOST_SUBDIR)/gcc/])
 GCC_TARGET_TOOL(as, AS_FOR_TARGET, AS, [gas/as-new])
 GCC_TARGET_TOOL(cc, CC_FOR_TARGET, CC, [gcc/xgcc -B$$r/$(HOST_SUBDIR)/gcc/])
 dnl see comments for CXX_FOR_TARGET_FLAG_TO_PASS
@@ -3424,7 +3425,8 @@ GCC_TARGET_TOOL(nm, NM_FOR_TARGET, NM, [binutils/nm-new])
 GCC_TARGET_TOOL(objcopy, OBJCOPY_FOR_TARGET, OBJCOPY, [binutils/objcopy])
 GCC_TARGET_TOOL(objdump, OBJDUMP_FOR_TARGET, OBJDUMP, [binutils/objdump])
 GCC_TARGET_TOOL(otool, OTOOL_FOR_TARGET, OTOOL)
-GCC_TARGET_TOOL(ranlib, RANLIB_FOR_TARGET, RANLIB, [binutils/ranlib])
+GCC_TARGET_TOOL(ranlib, RANLIB_FOR_TARGET, RANLIB,
+               [gcc/gcc-ranlib -B$$r/$(HOST_SUBDIR)/gcc/])
 GCC_TARGET_TOOL(readelf, READELF_FOR_TARGET, READELF, [binutils/readelf])
 GCC_TARGET_TOOL(strip, STRIP_FOR_TARGET, STRIP, [binutils/strip-new])
 GCC_TARGET_TOOL(windres, WINDRES_FOR_TARGET, WINDRES, [binutils/windres])

Reply via email to