Add plumbing for building U-Boot with Link Time Optimizations.

When building with LTO, $(PLATFORM_LIBS) has to be in --whole-archive /
--no-whole-archive group, otherwise some functions declared in assembly
may not be resolved and linking may fail.

Signed-off-by: Marek Behún <marek.be...@nic.cz>
---
 Kbuild               |  2 ++
 Kconfig              | 24 ++++++++++++++++++++++++
 Makefile             | 37 +++++++++++++++++++++++++++++++++++++
 scripts/Makefile.lib |  3 +++
 scripts/Makefile.spl | 17 +++++++++++++++++
 5 files changed, 83 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..f8c1a77bed 100644
--- a/Kconfig
+++ b/Kconfig
@@ -85,6 +85,30 @@ 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.
+
+         Currently, when compiling with GCC, due to a weird bug regarding
+         jobserver, the final linking will not respect make's --jobs argument.
+         Instead all available processors will be used (as reported by the
+         nproc command).
+
+         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 c9b5fac7a9..952c165d8f 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
+       ifeq ($(cc-name),clang)
+               LTO_CFLAGS              += -flto
+               LTO_FINAL_LDFLAGS       += -flto
+       else
+               NPROC                   := $(shell nproc 2>/dev/null || echo 1)
+               LTO_CFLAGS              += -flto=$(NPROC)
+               LTO_FINAL_LDFLAGS       += -fuse-linker-plugin -flto=$(NPROC)
+
+               # use plugin aware tools
+               AR                      = $(CROSS_COMPILE)gcc-ar
+               NM                      = $(CROSS_COMPILE)gcc-nm
+       endif
+
+       CFLAGS_NON_EFI                  += $(LTO_CFLAGS)
+
+       KBUILD_CFLAGS                   += $(LTO_CFLAGS)
+endif
+
 KBUILD_CFLAGS += $(call cc-option,-fno-stack-protector)
 KBUILD_CFLAGS += $(call cc-option,-fno-delete-null-pointer-checks)
 
@@ -1746,6 +1768,20 @@ 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_LDFLAGS) $(c_flags)                                 
\
+               $(KBUILD_LDFLAGS:%=-Wl,%) $(LDFLAGS_u-boot:%=-Wl,%) -o $@       
\
+               -T u-boot.lds $(u-boot-init)                                    
\
+               -Wl,--whole-archive                                             
\
+                       $(u-boot-main)                                          
\
+                       $(PLATFORM_LIBS)                                        
\
+               -Wl,--no-whole-archive                                          
\
+               -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)                                    
\
@@ -1754,6 +1790,7 @@ quiet_cmd_u-boot__ ?= LD      $@
                --no-whole-archive                                              
\
                $(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 44ed6d6826..9c9d59635d 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -426,6 +426,22 @@ $(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,--whole-archive                                             
\
+                       $(patsubst $(obj)/%,%,$(u-boot-spl-main))               
\
+                       $(patsubst $(obj)/%,%,$(u-boot-spl-platdata))           
\
+                       $(PLATFORM_LIBS)                                        
\
+               -Wl,--no-whole-archive                                          
\
+               -Wl,-Map,$(SPL_BIN).map -o $(SPL_BIN)                           
\
+       )
+else
 quiet_cmd_u-boot-spl ?= LD      $@
       cmd_u-boot-spl ?= \
        (                                                               \
@@ -438,6 +454,7 @@ quiet_cmd_u-boot-spl ?= LD      $@
                --no-whole-archive                                      \
                $(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
-- 
2.26.2

Reply via email to