diff mbox series

[u-boot,17/39] build: support building with Link Time Optimizations

Message ID 20210307042538.21229-18-marek.behun@nic.cz
State Superseded
Delegated to: Tom Rini
Headers show
Series U-Boot LTO (Sandbox + Some ARM boards) | expand

Commit Message

Marek Behún March 7, 2021, 4:25 a.m. UTC
Add plumbing for building U-Boot with Link Time Optimizations.

Signed-off-by: Marek Behún <marek.behun@nic.cz>
---
 Kbuild               |  2 ++
 Kconfig              | 19 +++++++++++++++++++
 Makefile             | 36 ++++++++++++++++++++++++++++++++++++
 scripts/Makefile.lib |  3 +++
 scripts/Makefile.spl | 14 ++++++++++++++
 5 files changed, 74 insertions(+)

Comments

Bin Meng March 9, 2021, 1:30 p.m. UTC | #1
On Sun, Mar 7, 2021 at 12:26 PM Marek Behún <marek.behun@nic.cz> wrote:
>
> Add plumbing for building U-Boot with Link Time Optimizations.
>
> Signed-off-by: Marek Behún <marek.behun@nic.cz>
> ---
>  Kbuild               |  2 ++
>  Kconfig              | 19 +++++++++++++++++++
>  Makefile             | 36 ++++++++++++++++++++++++++++++++++++
>  scripts/Makefile.lib |  3 +++
>  scripts/Makefile.spl | 14 ++++++++++++++
>  5 files changed, 74 insertions(+)
>
> diff --git a/Kbuild b/Kbuild
> index 1eac091594..bf52e54051 100644
> --- a/Kbuild
> +++ b/Kbuild
> @@ -10,6 +10,8 @@ generic-offsets-file := include/generated/generic-asm-offsets.h
>  always  := $(generic-offsets-file)
>  targets := lib/asm-offsets.s
>
> +CFLAGS_REMOVE_asm-offsets.o := $(LTO_CFLAGS)
> +
>  $(obj)/$(generic-offsets-file): $(obj)/lib/asm-offsets.s FORCE
>         $(call filechk,offsets,__GENERIC_ASM_OFFSETS_H__)
>
> diff --git a/Kconfig b/Kconfig
> index 86f0a39bb0..ceba53926f 100644
> --- a/Kconfig
> +++ b/Kconfig
> @@ -85,6 +85,25 @@ config SPL_OPTIMIZE_INLINING
>           do what it thinks is best, which is desirable in some cases for size
>           reasons.
>
> +config ARCH_SUPPORTS_LTO
> +       bool
> +
> +config LTO
> +       bool "Enable Link Time Optimizations"
> +       depends on ARCH_SUPPORTS_LTO
> +       default n

nits: this line is not needed as the default value is n if omitted

> +       help
> +         This option enables Link Time Optimization (LTO), a mechanism which
> +         allows the compiler to optimize between different compilation units.
> +
> +         This can optimize away dead code paths, resulting in smaller binary
> +         size (if CC_OPTIMIZE_FOR_SIZE is enabled).
> +
> +         This option is not available for every architecture and may
> +         introduce bugs.
> +
> +         If unsure, say n.
> +
>  config TPL_OPTIMIZE_INLINING
>         bool "Allow compiler to uninline functions marked 'inline' in TPL"
>         depends on TPL
> diff --git a/Makefile b/Makefile
> index 6dc47810ea..4eee0c4196 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -677,6 +677,28 @@ else
>  KBUILD_CFLAGS  += -O2
>  endif
>
> +LTO_CFLAGS :=
> +LTO_FINAL_LDFLAGS :=
> +export LTO_CFLAGS LTO_FINAL_LDFLAGS
> +ifdef CONFIG_LTO
> +       LTO_CFLAGS                      := -flto
> +       LTO_FINAL_LDFLAGS               := -fwhole-program

This one should not be necessary per my read of the GCC doc. Also in
your patch, it is only used in the SPL build.

> +
> +       CFLAGS_NON_EFI                  += $(LTO_CFLAGS)
> +
> +       ifeq ($(cc-name),clang)
> +               LTO_FINAL_LDFLAGS       += -flto
> +       else
> +               LTO_FINAL_LDFLAGS       += -fuse-linker-plugin -flto=jobserver
> +
> +               # use plugin aware tools
> +               AR                      = $(CROSS_COMPILE)gcc-ar
> +               NM                      = $(CROSS_COMPILE)gcc-nm
> +       endif
> +
> +       KBUILD_CFLAGS                   += $(LTO_CFLAGS)
> +endif
> +
>  KBUILD_CFLAGS += $(call cc-option,-fno-stack-protector)
>  KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks)
>
> @@ -1751,6 +1773,19 @@ ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(ARCH)/Makefile.postlink)
>
>  # Rule to link u-boot
>  # May be overridden by arch/$(ARCH)/config.mk
> +ifdef CONFIG_LTO
> +quiet_cmd_u-boot__ ?= LTO     $@
> +      cmd_u-boot__ ?=                                                          \
> +               $(CC) -nostdlib -nostartfiles                                   \
> +               $(LTO_FINAL_CFLAGS) $(c_flags)                                  \

LTO_FINAL_CFLAGS is not defined anywhere. I guess you wanted to use
LTO_FINAL_LDFLAGS?

> +               $(KBUILD_LDFLAGS:%=-Wl,%) $(LDFLAGS_u-boot:%=-Wl,%) -o $@       \
> +               -T u-boot.lds $(u-boot-init)                                    \
> +               -Wl,--start-group -Wl,--whole-archive                           \

--start-group should be dropped

> +                       $(u-boot-main)                                          \
> +               -Wl,--no-whole-archive -Wl,--end-group                          \
> +               $(PLATFORM_LIBS) -Wl,-Map,u-boot.map;                           \
> +               $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
> +else
>  quiet_cmd_u-boot__ ?= LD      $@
>        cmd_u-boot__ ?= $(LD) $(KBUILD_LDFLAGS) $(LDFLAGS_u-boot) -o $@          \
>                 -T u-boot.lds $(u-boot-init)                                    \
> @@ -1759,6 +1794,7 @@ quiet_cmd_u-boot__ ?= LD      $@
>                 --no-whole-archive --end-group                                  \
>                 $(PLATFORM_LIBS) -Map u-boot.map;                               \
>                 $(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
> +endif
>
>  quiet_cmd_smap = GEN     common/system_map.o
>  cmd_smap = \
> diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
> index 78543c6dd1..78bbebe7e9 100644
> --- a/scripts/Makefile.lib
> +++ b/scripts/Makefile.lib
> @@ -419,6 +419,9 @@ $(obj)/%_efi.so: $(obj)/%.o $(obj)/efi_crt0.o $(obj)/efi_reloc.o $(obj)/efi_free
>
>  targets += $(obj)/efi_crt0.o $(obj)/efi_reloc.o $(obj)/efi_freestanding.o
>
> +CFLAGS_REMOVE_efi_reloc.o := $(LTO_CFLAGS)
> +CFLAGS_REMOVE_efi_freestanding.o := $(LTO_CFLAGS)
> +
>  # ACPI
>  # ---------------------------------------------------------------------------
>  #
> diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
> index 889debb93c..6da5883442 100644
> --- a/scripts/Makefile.spl
> +++ b/scripts/Makefile.spl
> @@ -419,6 +419,19 @@ $(obj)/$(SPL_BIN).sym: $(obj)/$(SPL_BIN) FORCE
>
>  # Rule to link u-boot-spl
>  # May be overridden by arch/$(ARCH)/config.mk
> +ifdef CONFIG_LTO
> +quiet_cmd_u-boot-spl ?= LTO     $@
> +      cmd_u-boot-spl ?= (cd $(obj) &&                                          \
> +               $(CC) -nostdlib -nostartfiles $(LTO_FINAL_LDFLAGS) $(c_flags)   \
> +               $(KBUILD_LDFLAGS:%=-Wl,%) $(LDFLAGS_$(@F):%=-Wl,%)              \
> +               $(patsubst $(obj)/%,%,$(u-boot-spl-init))                       \
> +               -Wl,--start-group -Wl,--whole-archive                           \
> +                       $(patsubst $(obj)/%,%,$(u-boot-spl-main))               \
> +                       $(patsubst $(obj)/%,%,$(u-boot-spl-platdata))           \
> +               -Wl,--no-whole-archive -Wl,--end-group                          \
> +               $(PLATFORM_LIBS) -Wl,-Map,$(SPL_BIN).map -o $(SPL_BIN)          \
> +                       )
> +else
>  quiet_cmd_u-boot-spl ?= LD      $@
>        cmd_u-boot-spl ?= (cd $(obj) && \
>                 $(LD) $(KBUILD_LDFLAGS) $(LDFLAGS_$(@F))                \
> @@ -429,6 +442,7 @@ quiet_cmd_u-boot-spl ?= LD      $@
>                 --no-whole-archive --end-group                          \
>                 $(PLATFORM_LIBS) -Map $(SPL_BIN).map -o $(SPL_BIN)      \
>                         )
> +endif
>
>  $(obj)/$(SPL_BIN): $(u-boot-spl-platdata) $(u-boot-spl-init) \
>                 $(u-boot-spl-main) $(obj)/u-boot-spl.lds FORCE
> --

Regards,
Bin
Marek Behún March 11, 2021, 12:45 p.m. UTC | #2
On Tue, 9 Mar 2021 21:30:26 +0800
Bin Meng <bmeng.cn@gmail.com> wrote:

> > +config LTO
> > +       bool "Enable Link Time Optimizations"
> > +       depends on ARCH_SUPPORTS_LTO
> > +       default n  
> 
> nits: this line is not needed as the default value is n if omitted

This is for consistency. The other options in this file also use
"default n"

> > +ifdef CONFIG_LTO
> > +       LTO_CFLAGS                      := -flto
> > +       LTO_FINAL_LDFLAGS               := -fwhole-program  
> 
> This one should not be necessary per my read of the GCC doc. Also in
> your patch, it is only used in the SPL build.

I shall do some tests.

> > +ifdef CONFIG_LTO
> > +quiet_cmd_u-boot__ ?= LTO     $@
> > +      cmd_u-boot__ ?=                                                          \
> > +               $(CC) -nostdlib -nostartfiles                                   \
> > +               $(LTO_FINAL_CFLAGS) $(c_flags)                                  \  
> 
> LTO_FINAL_CFLAGS is not defined anywhere. I guess you wanted to use
> LTO_FINAL_LDFLAGS?

THX, I forgot to change it here. We will see if this variable is needed
(since it only contains -fwhole-program, which may be dropped)
> 
> > +               $(KBUILD_LDFLAGS:%=-Wl,%) $(LDFLAGS_u-boot:%=-Wl,%) -o $@       \
> > +               -T u-boot.lds $(u-boot-init)                                    \
> > +               -Wl,--start-group -Wl,--whole-archive                           \  
> 
> --start-group should be dropped

Will test
diff mbox series

Patch

diff --git a/Kbuild b/Kbuild
index 1eac091594..bf52e54051 100644
--- a/Kbuild
+++ b/Kbuild
@@ -10,6 +10,8 @@  generic-offsets-file := include/generated/generic-asm-offsets.h
 always  := $(generic-offsets-file)
 targets := lib/asm-offsets.s
 
+CFLAGS_REMOVE_asm-offsets.o := $(LTO_CFLAGS)
+
 $(obj)/$(generic-offsets-file): $(obj)/lib/asm-offsets.s FORCE
 	$(call filechk,offsets,__GENERIC_ASM_OFFSETS_H__)
 
diff --git a/Kconfig b/Kconfig
index 86f0a39bb0..ceba53926f 100644
--- a/Kconfig
+++ b/Kconfig
@@ -85,6 +85,25 @@  config SPL_OPTIMIZE_INLINING
 	  do what it thinks is best, which is desirable in some cases for size
 	  reasons.
 
+config ARCH_SUPPORTS_LTO
+	bool
+
+config LTO
+	bool "Enable Link Time Optimizations"
+	depends on ARCH_SUPPORTS_LTO
+	default n
+	help
+	  This option enables Link Time Optimization (LTO), a mechanism which
+	  allows the compiler to optimize between different compilation units.
+
+	  This can optimize away dead code paths, resulting in smaller binary
+	  size (if CC_OPTIMIZE_FOR_SIZE is enabled).
+
+	  This option is not available for every architecture and may
+	  introduce bugs.
+
+	  If unsure, say n.
+
 config TPL_OPTIMIZE_INLINING
 	bool "Allow compiler to uninline functions marked 'inline' in TPL"
 	depends on TPL
diff --git a/Makefile b/Makefile
index 6dc47810ea..4eee0c4196 100644
--- a/Makefile
+++ b/Makefile
@@ -677,6 +677,28 @@  else
 KBUILD_CFLAGS	+= -O2
 endif
 
+LTO_CFLAGS :=
+LTO_FINAL_LDFLAGS :=
+export LTO_CFLAGS LTO_FINAL_LDFLAGS
+ifdef CONFIG_LTO
+	LTO_CFLAGS			:= -flto
+	LTO_FINAL_LDFLAGS		:= -fwhole-program
+
+	CFLAGS_NON_EFI			+= $(LTO_CFLAGS)
+
+	ifeq ($(cc-name),clang)
+		LTO_FINAL_LDFLAGS	+= -flto
+	else
+		LTO_FINAL_LDFLAGS	+= -fuse-linker-plugin -flto=jobserver
+
+		# use plugin aware tools
+		AR			= $(CROSS_COMPILE)gcc-ar
+		NM			= $(CROSS_COMPILE)gcc-nm
+	endif
+
+	KBUILD_CFLAGS			+= $(LTO_CFLAGS)
+endif
+
 KBUILD_CFLAGS += $(call cc-option,-fno-stack-protector)
 KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks)
 
@@ -1751,6 +1773,19 @@  ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(ARCH)/Makefile.postlink)
 
 # Rule to link u-boot
 # May be overridden by arch/$(ARCH)/config.mk
+ifdef CONFIG_LTO
+quiet_cmd_u-boot__ ?= LTO     $@
+      cmd_u-boot__ ?= 								\
+		$(CC) -nostdlib -nostartfiles					\
+		$(LTO_FINAL_CFLAGS) $(c_flags)					\
+		$(KBUILD_LDFLAGS:%=-Wl,%) $(LDFLAGS_u-boot:%=-Wl,%) -o $@	\
+		-T u-boot.lds $(u-boot-init)					\
+		-Wl,--start-group -Wl,--whole-archive				\
+			$(u-boot-main)						\
+		-Wl,--no-whole-archive -Wl,--end-group				\
+		$(PLATFORM_LIBS) -Wl,-Map,u-boot.map;				\
+		$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
+else
 quiet_cmd_u-boot__ ?= LD      $@
       cmd_u-boot__ ?= $(LD) $(KBUILD_LDFLAGS) $(LDFLAGS_u-boot) -o $@		\
 		-T u-boot.lds $(u-boot-init)					\
@@ -1759,6 +1794,7 @@  quiet_cmd_u-boot__ ?= LD      $@
 		--no-whole-archive --end-group					\
 		$(PLATFORM_LIBS) -Map u-boot.map;				\
 		$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
+endif
 
 quiet_cmd_smap = GEN     common/system_map.o
 cmd_smap = \
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 78543c6dd1..78bbebe7e9 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -419,6 +419,9 @@  $(obj)/%_efi.so: $(obj)/%.o $(obj)/efi_crt0.o $(obj)/efi_reloc.o $(obj)/efi_free
 
 targets += $(obj)/efi_crt0.o $(obj)/efi_reloc.o $(obj)/efi_freestanding.o
 
+CFLAGS_REMOVE_efi_reloc.o := $(LTO_CFLAGS)
+CFLAGS_REMOVE_efi_freestanding.o := $(LTO_CFLAGS)
+
 # ACPI
 # ---------------------------------------------------------------------------
 #
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index 889debb93c..6da5883442 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -419,6 +419,19 @@  $(obj)/$(SPL_BIN).sym: $(obj)/$(SPL_BIN) FORCE
 
 # Rule to link u-boot-spl
 # May be overridden by arch/$(ARCH)/config.mk
+ifdef CONFIG_LTO
+quiet_cmd_u-boot-spl ?= LTO     $@
+      cmd_u-boot-spl ?= (cd $(obj) &&						\
+		$(CC) -nostdlib -nostartfiles $(LTO_FINAL_LDFLAGS) $(c_flags)	\
+		$(KBUILD_LDFLAGS:%=-Wl,%) $(LDFLAGS_$(@F):%=-Wl,%)		\
+		$(patsubst $(obj)/%,%,$(u-boot-spl-init))			\
+		-Wl,--start-group -Wl,--whole-archive				\
+			$(patsubst $(obj)/%,%,$(u-boot-spl-main))		\
+			$(patsubst $(obj)/%,%,$(u-boot-spl-platdata))		\
+		-Wl,--no-whole-archive -Wl,--end-group				\
+		$(PLATFORM_LIBS) -Wl,-Map,$(SPL_BIN).map -o $(SPL_BIN)		\
+			)
+else
 quiet_cmd_u-boot-spl ?= LD      $@
       cmd_u-boot-spl ?= (cd $(obj) && \
 		$(LD) $(KBUILD_LDFLAGS) $(LDFLAGS_$(@F))		\
@@ -429,6 +442,7 @@  quiet_cmd_u-boot-spl ?= LD      $@
 		--no-whole-archive --end-group				\
 		$(PLATFORM_LIBS) -Map $(SPL_BIN).map -o $(SPL_BIN)	\
 			)
+endif
 
 $(obj)/$(SPL_BIN): $(u-boot-spl-platdata) $(u-boot-spl-init) \
 		$(u-boot-spl-main) $(obj)/u-boot-spl.lds FORCE