FROMLIST: BACKPORT: kbuild: add support for clang LTO

This change adds the configuration option CONFIG_LTO_CLANG, and
build system support for clang's Link Time Optimization (LTO). In
preparation for LTO support for other compilers, potentially common
parts of the changes are gated behind CONFIG_LTO instead.

With -flto, instead of object files, clang produces LLVM bitcode,
which is compiled into a native object at link time, allowing the
final binary to be optimized globally. For more details, see:

  https://llvm.org/docs/LinkTimeOptimization.html

While the kernel normally uses GNU ld for linking, LLVM supports LTO
only with lld or GNU gold linkers. This patch set assumes gold will
be used with the LLVMgold plug-in to perform the LTO link step. Due
to potential incompatibilities with GNU ld, this change also adds
LDFINAL_vmlinux for using a different linker for the vmlinux_link
step, and defaults to using GNU ld.

Assuming LLVMgold.so is in LD_LIBRARY_PATH and CONFIG_LTO_CLANG has
been selected, an LTO kernel can be built simply by running make
CC=clang. LTO requires clang >= 5.0 and gold from binutils >= 2.27.

Bug: 62093296
Bug: 67506682
Change-Id: Ibcd9fc7ec501b4f30b43b4877897615645f8655f
(am from https://patchwork.kernel.org/patch/10060329/)
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
This commit is contained in:
Sami Tolvanen 2017-11-28 08:48:49 -08:00
parent 331f1f5c7b
commit 475bdd7d35
5 changed files with 276 additions and 34 deletions

View file

@ -53,9 +53,40 @@ archive_builtin()
${AR} rcsT${KBUILD_ARFLAGS} built-in.o \
${KBUILD_VMLINUX_INIT} \
${KBUILD_VMLINUX_MAIN}
if [ -n "${CONFIG_LTO_CLANG}" ]; then
mv -f built-in.o built-in.o.tmp
${LLVM_AR} rcsT${KBUILD_ARFLAGS} built-in.o $(${AR} t built-in.o.tmp)
rm -f built-in.o.tmp
fi
fi
}
# If CONFIG_LTO_CLANG is selected, collect generated symbol versions into
# .tmp_symversions
modversions()
{
if [ -z "${CONFIG_LTO_CLANG}" ]; then
return
fi
if [ -z "${CONFIG_MODVERSIONS}" ]; then
return
fi
rm -f .tmp_symversions
for a in built-in.o ${KBUILD_VMLINUX_LIBS}; do
for o in $(${AR} t $a); do
if [ -f ${o}.symversions ]; then
cat ${o}.symversions >> .tmp_symversions
fi
done
done
echo "-T .tmp_symversions"
}
# Link of vmlinux.o used for section mismatch analysis
# ${1} output file
modpost_link()
@ -70,7 +101,16 @@ modpost_link()
${KBUILD_VMLINUX_MAIN} \
--end-group"
fi
${LD} ${LDFLAGS} -r -o ${1} ${objects}
if [ -n "${CONFIG_LTO_CLANG}" ]; then
# This might take a while, so indicate that we're doing
# an LTO link
info LTO vmlinux.o
else
info LD vmlinux.o
fi
${LD} ${LDFLAGS} -r -o ${1} $(modversions) ${objects}
}
# Link of vmlinux
@ -82,7 +122,15 @@ vmlinux_link()
local objects
if [ "${SRCARCH}" != "um" ]; then
if [ -n "${CONFIG_THIN_ARCHIVES}" ]; then
local ld=${LD}
local ldflags="${LDFLAGS} ${LDFLAGS_vmlinux}"
if [ -n "${LDFINAL_vmlinux}" ]; then
ld=${LDFINAL_vmlinux}
ldflags="${LDFLAGS_FINAL_vmlinux} ${LDFLAGS_vmlinux}"
fi
if [[ -n "${CONFIG_THIN_ARCHIVES}" && -z "${CONFIG_LTO_CLANG}" ]]; then
objects="--whole-archive built-in.o ${1}"
else
objects="${KBUILD_VMLINUX_INIT} \
@ -92,8 +140,7 @@ vmlinux_link()
${1}"
fi
${LD} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2} \
-T ${lds} ${objects}
${ld} ${ldflags} -o ${2} -T ${lds} ${objects}
else
if [ -n "${CONFIG_THIN_ARCHIVES}" ]; then
objects="-Wl,--whole-archive built-in.o ${1}"
@ -113,7 +160,6 @@ vmlinux_link()
fi
}
# Create ${2} .o file with all symbols from the ${1} object file
kallsyms()
{
@ -164,6 +210,7 @@ cleanup()
rm -f .tmp_System.map
rm -f .tmp_kallsyms*
rm -f .tmp_version
rm -f .tmp_symversions
rm -f .tmp_vmlinux*
rm -f built-in.o
rm -f System.map
@ -209,15 +256,6 @@ case "${KCONFIG_CONFIG}" in
. "./${KCONFIG_CONFIG}"
esac
archive_builtin
#link vmlinux.o
info LD vmlinux.o
modpost_link vmlinux.o
# modpost vmlinux.o to check for section mismatches
${MAKE} -f "${srctree}/scripts/Makefile.modpost" vmlinux.o
# Update version
info GEN .version
if [ ! -r .version ]; then
@ -228,9 +266,24 @@ else
expr 0$(cat .old_version) + 1 >.version;
fi;
archive_builtin
#link vmlinux.o
modpost_link vmlinux.o
# modpost vmlinux.o to check for section mismatches
${MAKE} -f "${srctree}/scripts/Makefile.modpost" vmlinux.o
# final build of init/
${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init GCC_PLUGINS_CFLAGS="${GCC_PLUGINS_CFLAGS}"
if [ -n "${CONFIG_LTO_CLANG}" ]; then
# Re-use vmlinux.o, so we can avoid the slow LTO link step in
# vmlinux_link
KBUILD_VMLINUX_INIT=
KBUILD_VMLINUX_MAIN=vmlinux.o
fi
kallsymso=""
kallsyms_vmlinux=""
if [ -n "${CONFIG_KALLSYMS}" ]; then