Skip to content

Commit c109498

Browse files
elkablotrini
authored andcommitted
build: support building with Link Time Optimizations
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. Note: clang may throw away linker list symbols it thinks are unused when compiling with LTO. To force these symbols to be included, we refer to them via the __ADDRESSABLE macro in a C file generated from compiled built-in.o files before linking. Signed-off-by: Marek Behún <[email protected]> Reviewed-by: Simon Glass <[email protected]>
1 parent 958f2e5 commit c109498

File tree

6 files changed

+149
-3
lines changed

6 files changed

+149
-3
lines changed

Kbuild

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ generic-offsets-file := include/generated/generic-asm-offsets.h
1010
always := $(generic-offsets-file)
1111
targets := lib/asm-offsets.s
1212

13+
CFLAGS_REMOVE_asm-offsets.o := $(LTO_CFLAGS)
14+
1315
$(obj)/$(generic-offsets-file): $(obj)/lib/asm-offsets.s FORCE
1416
$(call filechk,offsets,__GENERIC_ASM_OFFSETS_H__)
1517

Kconfig

+24
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,30 @@ config SPL_OPTIMIZE_INLINING
8585
do what it thinks is best, which is desirable in some cases for size
8686
reasons.
8787

88+
config ARCH_SUPPORTS_LTO
89+
bool
90+
91+
config LTO
92+
bool "Enable Link Time Optimizations"
93+
depends on ARCH_SUPPORTS_LTO
94+
default n
95+
help
96+
This option enables Link Time Optimization (LTO), a mechanism which
97+
allows the compiler to optimize between different compilation units.
98+
99+
This can optimize away dead code paths, resulting in smaller binary
100+
size (if CC_OPTIMIZE_FOR_SIZE is enabled).
101+
102+
This option is not available for every architecture and may
103+
introduce bugs.
104+
105+
Currently, when compiling with GCC, due to a weird bug regarding
106+
jobserver, the final linking will not respect make's --jobs argument.
107+
Instead all available processors will be used (as reported by the
108+
nproc command).
109+
110+
If unsure, say n.
111+
88112
config TPL_OPTIMIZE_INLINING
89113
bool "Allow compiler to uninline functions marked 'inline' in TPL"
90114
depends on TPL

Makefile

+65-2
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,31 @@ else
676676
KBUILD_CFLAGS += -O2
677677
endif
678678

679+
LTO_CFLAGS :=
680+
LTO_FINAL_LDFLAGS :=
681+
export LTO_CFLAGS LTO_FINAL_LDFLAGS
682+
ifdef CONFIG_LTO
683+
ifeq ($(cc-name),clang)
684+
LTO_CFLAGS += -flto
685+
LTO_FINAL_LDFLAGS += -flto
686+
687+
AR = $(shell $(CC) -print-prog-name=llvm-ar)
688+
NM = $(shell $(CC) -print-prog-name=llvm-nm)
689+
else
690+
NPROC := $(shell nproc 2>/dev/null || echo 1)
691+
LTO_CFLAGS += -flto=$(NPROC)
692+
LTO_FINAL_LDFLAGS += -fuse-linker-plugin -flto=$(NPROC)
693+
694+
# use plugin aware tools
695+
AR = $(CROSS_COMPILE)gcc-ar
696+
NM = $(CROSS_COMPILE)gcc-nm
697+
endif
698+
699+
CFLAGS_NON_EFI += $(LTO_CFLAGS)
700+
701+
KBUILD_CFLAGS += $(LTO_CFLAGS)
702+
endif
703+
679704
ifeq ($(CONFIG_STACKPROTECTOR),y)
680705
KBUILD_CFLAGS += $(call cc-option,-fstack-protector-strong)
681706
CFLAGS_EFI += $(call cc-option,-fno-stack-protector)
@@ -1708,8 +1733,45 @@ u-boot-swap.bin: u-boot.bin FORCE
17081733

17091734
ARCH_POSTLINK := $(wildcard $(srctree)/arch/$(ARCH)/Makefile.postlink)
17101735

1736+
# Generate linker list symbols references to force compiler to not optimize
1737+
# them away when compiling with LTO
1738+
ifdef CONFIG_LTO
1739+
u-boot-keep-syms-lto := keep-syms-lto.o
1740+
u-boot-keep-syms-lto_c := $(patsubst %.o,%.c,$(u-boot-keep-syms-lto))
1741+
1742+
quiet_cmd_keep_syms_lto = KSL $@
1743+
cmd_keep_syms_lto = \
1744+
NM=$(NM) $(srctree)/scripts/gen_ll_addressable_symbols.sh $^ >$@
1745+
1746+
quiet_cmd_keep_syms_lto_cc = KSLCC $@
1747+
cmd_keep_syms_lto_cc = \
1748+
$(CC) $(filter-out $(LTO_CFLAGS),$(c_flags)) -c -o $@ $<
1749+
1750+
$(u-boot-keep-syms-lto_c): $(u-boot-main)
1751+
$(call if_changed,keep_syms_lto)
1752+
$(u-boot-keep-syms-lto): $(u-boot-keep-syms-lto_c)
1753+
$(call if_changed,keep_syms_lto_cc)
1754+
else
1755+
u-boot-keep-syms-lto :=
1756+
endif
1757+
17111758
# Rule to link u-boot
17121759
# May be overridden by arch/$(ARCH)/config.mk
1760+
ifdef CONFIG_LTO
1761+
quiet_cmd_u-boot__ ?= LTO $@
1762+
cmd_u-boot__ ?= \
1763+
$(CC) -nostdlib -nostartfiles \
1764+
$(LTO_FINAL_LDFLAGS) $(c_flags) \
1765+
$(KBUILD_LDFLAGS:%=-Wl,%) $(LDFLAGS_u-boot:%=-Wl,%) -o $@ \
1766+
-T u-boot.lds $(u-boot-init) \
1767+
-Wl,--whole-archive \
1768+
$(u-boot-main) \
1769+
$(u-boot-keep-syms-lto) \
1770+
$(PLATFORM_LIBS) \
1771+
-Wl,--no-whole-archive \
1772+
-Wl,-Map,u-boot.map; \
1773+
$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
1774+
else
17131775
quiet_cmd_u-boot__ ?= LD $@
17141776
cmd_u-boot__ ?= $(LD) $(KBUILD_LDFLAGS) $(LDFLAGS_u-boot) -o $@ \
17151777
-T u-boot.lds $(u-boot-init) \
@@ -1718,6 +1780,7 @@ quiet_cmd_u-boot__ ?= LD $@
17181780
--no-whole-archive \
17191781
$(PLATFORM_LIBS) -Map u-boot.map; \
17201782
$(if $(ARCH_POSTLINK), $(MAKE) -f $(ARCH_POSTLINK) $@, true)
1783+
endif
17211784

17221785
quiet_cmd_smap = GEN common/system_map.o
17231786
cmd_smap = \
@@ -1726,7 +1789,7 @@ cmd_smap = \
17261789
$(CC) $(c_flags) -DSYSTEM_MAP="\"$${smap}\"" \
17271790
-c $(srctree)/common/system_map.c -o common/system_map.o
17281791

1729-
u-boot: $(u-boot-init) $(u-boot-main) u-boot.lds FORCE
1792+
u-boot: $(u-boot-init) $(u-boot-main) $(u-boot-keep-syms-lto) u-boot.lds FORCE
17301793
+$(call if_changed,u-boot__)
17311794
ifeq ($(CONFIG_KALLSYMS),y)
17321795
$(call cmd,smap)
@@ -2009,7 +2072,7 @@ CLEAN_FILES += include/bmp_logo.h include/bmp_logo_data.h tools/version.h \
20092072
boot* u-boot* MLO* SPL System.map fit-dtb.blob* \
20102073
u-boot-ivt.img.log u-boot-dtb.imx.log SPL.log u-boot.imx.log \
20112074
lpc32xx-* bl31.c bl31.elf bl31_*.bin image.map tispl.bin* \
2012-
idbloader.img flash.bin flash.log defconfig
2075+
idbloader.img flash.bin flash.log defconfig keep-syms-lto.c
20132076

20142077
# Directories & files removed with 'make mrproper'
20152078
MRPROPER_DIRS += include/config include/generated spl tpl \

scripts/Makefile.lib

+3
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,9 @@ $(obj)/%_efi.so: $(obj)/%.o $(obj)/efi_crt0.o $(obj)/efi_reloc.o $(obj)/efi_free
419419

420420
targets += $(obj)/efi_crt0.o $(obj)/efi_reloc.o $(obj)/efi_freestanding.o
421421

422+
CFLAGS_REMOVE_efi_reloc.o := $(LTO_CFLAGS)
423+
CFLAGS_REMOVE_efi_freestanding.o := $(LTO_CFLAGS)
424+
422425
# ACPI
423426
# ---------------------------------------------------------------------------
424427
#

scripts/Makefile.spl

+43-1
Original file line numberDiff line numberDiff line change
@@ -448,8 +448,48 @@ quiet_cmd_sym ?= SYM $@
448448
$(obj)/$(SPL_BIN).sym: $(obj)/$(SPL_BIN) FORCE
449449
$(call if_changed,sym)
450450

451+
# Generate linker list symbols references to force compiler to not optimize
452+
# them away when compiling with LTO
453+
ifdef CONFIG_LTO
454+
u-boot-spl-keep-syms-lto := $(obj)/keep-syms-lto.o
455+
u-boot-spl-keep-syms-lto_c := \
456+
$(patsubst $(obj)/%.o,$(obj)/%.c,$(u-boot-spl-keep-syms-lto))
457+
458+
quiet_cmd_keep_syms_lto = KSL $@
459+
cmd_keep_syms_lto = \
460+
NM=$(NM) $(srctree)/scripts/gen_ll_addressable_symbols.sh $^ >$@
461+
462+
quiet_cmd_keep_syms_lto_cc = KSLCC $@
463+
cmd_keep_syms_lto_cc = \
464+
$(CC) $(filter-out $(LTO_CFLAGS),$(c_flags)) -c -o $@ $<
465+
466+
$(u-boot-spl-keep-syms-lto_c): $(u-boot-spl-main) $(u-boot-spl-platdata)
467+
$(call if_changed,keep_syms_lto)
468+
$(u-boot-spl-keep-syms-lto): $(u-boot-spl-keep-syms-lto_c)
469+
$(call if_changed,keep_syms_lto_cc)
470+
else
471+
u-boot-spl-keep-syms-lto :=
472+
endif
473+
451474
# Rule to link u-boot-spl
452475
# May be overridden by arch/$(ARCH)/config.mk
476+
ifdef CONFIG_LTO
477+
quiet_cmd_u-boot-spl ?= LTO $@
478+
cmd_u-boot-spl ?= \
479+
( \
480+
cd $(obj) && \
481+
$(CC) -nostdlib -nostartfiles $(LTO_FINAL_LDFLAGS) $(c_flags) \
482+
$(KBUILD_LDFLAGS:%=-Wl,%) $(LDFLAGS_$(@F):%=-Wl,%) \
483+
$(patsubst $(obj)/%,%,$(u-boot-spl-init)) \
484+
-Wl,--whole-archive \
485+
$(patsubst $(obj)/%,%,$(u-boot-spl-main)) \
486+
$(patsubst $(obj)/%,%,$(u-boot-spl-platdata)) \
487+
$(patsubst $(obj)/%,%,$(u-boot-spl-keep-syms-lto)) \
488+
$(PLATFORM_LIBS) \
489+
-Wl,--no-whole-archive \
490+
-Wl,-Map,$(SPL_BIN).map -o $(SPL_BIN) \
491+
)
492+
else
453493
quiet_cmd_u-boot-spl ?= LD $@
454494
cmd_u-boot-spl ?= \
455495
( \
@@ -462,9 +502,11 @@ quiet_cmd_u-boot-spl ?= LD $@
462502
--no-whole-archive \
463503
$(PLATFORM_LIBS) -Map $(SPL_BIN).map -o $(SPL_BIN) \
464504
)
505+
endif
465506

466507
$(obj)/$(SPL_BIN): $(u-boot-spl-platdata) $(u-boot-spl-init) \
467-
$(u-boot-spl-main) $(obj)/u-boot-spl.lds FORCE
508+
$(u-boot-spl-main) $(u-boot-spl-keep-syms-lto) \
509+
$(obj)/u-boot-spl.lds FORCE
468510
$(call if_changed,u-boot-spl)
469511

470512
$(sort $(u-boot-spl-init) $(u-boot-spl-main)): $(u-boot-spl-dirs) ;

scripts/gen_ll_addressable_symbols.sh

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/bin/bash
2+
# SPDX-License-Identifier: GPL-2.0+
3+
# Copyright (C) 2020 Marek Behún <[email protected]>
4+
5+
# Generate __ADDRESSABLE(symbol) for every linker list entry symbol, so that LTO
6+
# does not optimize these symbols away
7+
8+
set -e
9+
10+
echo '#include <common.h>'
11+
$NM "$@" 2>/dev/null | grep -oe '_u_boot_list_2_[a-zA-Z0-9_]*_2_[a-zA-Z0-9_]*' | \
12+
sort -u | sed -e 's/^\(.*\)/extern char \1[];\n__ADDRESSABLE(\1);/'

0 commit comments

Comments
 (0)