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