On Sun, 27 Mar 2022 at 21:27, Simon Glass <s...@chromium.org> wrote: > > LTO (Link-Time Optimisation) is an very useful feature which can > significantly reduce the size of U-Boot binaries. So far it has been > made available for selected ARM boards and sandbox. > > However, incremental builds are much slower when LTO is used. For example, > an incremental build of sandbox takes 2.1 seconds on my machine, but 6.7 > seconds with LTO enabled.
This is something that has been bothering me too. I'd resorted to adding `# CONFIG_LTO is not set` to sandbox_defconfig because I couldn't work out how to stop .config being regenerated each build. But then the diff gets in the way and is difficult to manage. > Add a LTO_BUILD=n parameter to the build, so it can be disabled during > development if needed, for faster builds. If you go the build parameter route rather than config route to address this, could the flag be consistent e.g. with NO_SDL=1, which would mean NO_LTO=1? > Add some documentation about LTO while we are here. > > Signed-off-by: Simon Glass <s...@chromium.org> > --- > > Makefile | 18 +++++++++++++----- > arch/arm/config.mk | 4 ++-- > arch/arm/include/asm/global_data.h | 2 +- > doc/build/gcc.rst | 17 +++++++++++++++++ > scripts/Makefile.spl | 2 +- > 5 files changed, 34 insertions(+), 9 deletions(-) > > diff --git a/Makefile b/Makefile > index 06572ac07ee..c9585ddebfc 100644 > --- a/Makefile > +++ b/Makefile > @@ -434,6 +434,9 @@ KBUILD_CFLAGS += -fshort-wchar -fno-strict-aliasing > KBUILD_AFLAGS := -D__ASSEMBLY__ > KBUILD_LDFLAGS := > > +# Set this to "n" use of LTO for this build, e.g. LTO_BUILD=n > +LTO_BUILD ?= y > + > ifeq ($(cc-name),clang) > ifneq ($(CROSS_COMPILE),) > CLANG_TARGET := --target=$(notdir $(CROSS_COMPILE:%-=%)) > @@ -643,6 +646,11 @@ export CFLAGS_EFI # Compiler flags to add when building > EFI app > export CFLAGS_NON_EFI # Compiler flags to remove when building EFI app > export EFI_TARGET # binutils target if EFI is natively supported > > +export LTO_ENABLE > + > +# This is y if LTO is enabled for this build > +LTO_ENABLE=$(if $(CONFIG_LTO),$(LTO_BUILD),) > + > # If board code explicitly specified LDSCRIPT or CONFIG_SYS_LDSCRIPT, use > # that (or fail if absent). Otherwise, search for a linker script in a > # standard location. > @@ -690,16 +698,16 @@ endif > LTO_CFLAGS := > LTO_FINAL_LDFLAGS := > export LTO_CFLAGS LTO_FINAL_LDFLAGS > -ifdef CONFIG_LTO > +ifeq ($(LTO_ENABLE),y) > ifeq ($(cc-name),clang) > - LTO_CFLAGS += -flto > + LTO_CFLAGS += -DLTO_ENABLE -flto > LTO_FINAL_LDFLAGS += -flto > > AR = $(shell $(CC) > -print-prog-name=llvm-ar) > NM = $(shell $(CC) > -print-prog-name=llvm-nm) > else > NPROC := $(shell nproc 2>/dev/null || echo > 1) > - LTO_CFLAGS += -flto=$(NPROC) > + LTO_CFLAGS += -DLTO_ENABLE -flto=$(NPROC) > LTO_FINAL_LDFLAGS += -fuse-linker-plugin -flto=$(NPROC) > > # use plugin aware tools > @@ -1740,7 +1748,7 @@ ARCH_POSTLINK := $(wildcard > $(srctree)/arch/$(ARCH)/Makefile.postlink) > > # Generate linker list symbols references to force compiler to not optimize > # them away when compiling with LTO > -ifdef CONFIG_LTO > +ifeq ($(LTO_ENABLE),y) > u-boot-keep-syms-lto := keep-syms-lto.o > u-boot-keep-syms-lto_c := $(patsubst %.o,%.c,$(u-boot-keep-syms-lto)) > > @@ -1762,7 +1770,7 @@ endif > > # Rule to link u-boot > # May be overridden by arch/$(ARCH)/config.mk > -ifdef CONFIG_LTO > +ifeq ($(LTO_ENABLE),y) > quiet_cmd_u-boot__ ?= LTO $@ > cmd_u-boot__ ?= > \ > $(CC) -nostdlib -nostartfiles > \ > diff --git a/arch/arm/config.mk b/arch/arm/config.mk > index b107b1af27a..065dbec4064 100644 > --- a/arch/arm/config.mk > +++ b/arch/arm/config.mk > @@ -15,11 +15,11 @@ CFLAGS_NON_EFI := -fno-pic -ffixed-r9 -ffunction-sections > -fdata-sections \ > -fstack-protector-strong > CFLAGS_EFI := -fpic -fshort-wchar > > -ifneq ($(CONFIG_LTO)$(CONFIG_USE_PRIVATE_LIBGCC),yy) > +ifneq ($(LTO_ENABLE)$(CONFIG_USE_PRIVATE_LIBGCC),yy) > LDFLAGS_FINAL += --gc-sections > endif > > -ifndef CONFIG_LTO > +ifneq ($(LTO_ENABLE),y) > PLATFORM_RELFLAGS += -ffunction-sections -fdata-sections > endif > > diff --git a/arch/arm/include/asm/global_data.h > b/arch/arm/include/asm/global_data.h > index 085e12b5d4d..b255b195aa0 100644 > --- a/arch/arm/include/asm/global_data.h > +++ b/arch/arm/include/asm/global_data.h > @@ -98,7 +98,7 @@ struct arch_global_data { > > #include <asm-generic/global_data.h> > > -#if defined(__clang__) || defined(CONFIG_LTO) > +#if defined(__clang__) || defined(LTO_ENABLE) > > #define DECLARE_GLOBAL_DATA_PTR > #define gd get_gd() > diff --git a/doc/build/gcc.rst b/doc/build/gcc.rst > index 470a7aa3498..792be176aad 100644 > --- a/doc/build/gcc.rst > +++ b/doc/build/gcc.rst > @@ -152,6 +152,23 @@ of dtc is new enough. It also makes sure that pylibfdt > is present, if needed > Note that the :doc:`tools` are always built with the included version of > libfdt > so it is not possible to build U-Boot tools with a system libfdt, at present. > > +Link-time optimisation (LTO) > +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > + > +U-Boot supports link-time optimisation which can reduce the size of the final > +U-Boot binaries, particularly with SPL. > + > +At present this can be enabled by ARM boards by adding `CONFIG_LTO=y` into > the > +defconfig file. Other architectures are not supported. LTO is enabled by > default > +for sandbox. > + > +This does incur a link-time penalty of several seconds. For faster > incremental > +builds during development, you can disable it by setting `LTO_BUILD` to `n`. > + > +.. code-block:: bash > + > + LTO_BUILD=n make > + > Other build targets > ~~~~~~~~~~~~~~~~~~~ > > diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl > index 83a95ee4aa2..e3ca69c4449 100644 > --- a/scripts/Makefile.spl > +++ b/scripts/Makefile.spl > @@ -472,7 +472,7 @@ endif > > # Rule to link u-boot-spl > # May be overridden by arch/$(ARCH)/config.mk > -ifdef CONFIG_LTO > +ifeq ($(LTO_ENABLE),y) > quiet_cmd_u-boot-spl ?= LTO $@ > cmd_u-boot-spl ?= \ > ( > \ > -- > 2.35.1.1021.g381101b075-goog >