LTO
Link Time Optimization (LTO) is the term for a class of optimizations done during linking. The linker is aware of all the translation units (TUs) and can optimize more compared to what conventional optimization passes by a compiler individually can do. The most important optimizations that linker does are inlining and code locality improvements. This can increase system performance at the cost of longer compile time.
This article will show the user how to enable LTO without the need for third party overlays and using recommended tested CFLAGS for the best performance and system stability (with either GCC or LLVM-based toolchains).
Benefits of LTO
- LTO can give double digit performance boosts for many programs.
- Can lower RAM usage per program making it very useful for limited memory systems.[1]
Downsides of LTO
- Can increase compile time by 2 to 3 times.
- Uses more RAM during compiling.
- Not all programs become faster or smaller.
- There is an increased chance of finding build-time or runtime bugs while using it.
- Always be prepared to try without it if something is acting odd.
Enabling LTO System-wide
GCC Systems
Enable LTO
To enable LTO package building on GCC systems, edit /etc/portage/make.conf then add LTO to the USE line and -flto
to the COMMON_FLAGS.
# These warnings indicate likely runtime problems with LTO, so promote them
# to errors. If a package fails to build with these, LTO should not be used there.
WARNING_FLAGS="-Werror=odr -Werror=lto-type-mismatch -Werror=strict-aliasing"
COMMON_FLAGS="-O2 -pipe -march=native -flto ${WARNING_FLAGS}"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS}"
FCFLAGS="${COMMON_FLAGS}"
FFLAGS="${COMMON_FLAGS}"
USE="lto"
With this, LTO is now enabled on the system for all future emerges.
With GCC you can also pass the number of processes to use for linking to the -flto
parameter using -flto=NUMBER-OF-PROCESSES
which will speed it up. Using -flto
on its own is normally all that is needed though as it automatically picks the best number of processes to use for the system.
LLVM Systems
Enable LTO
All that is needed is to -flto
to COMMON_FLAGS and lto
to USE:
# These warnings indicate likely runtime problems with LTO, so promote them
# to errors. If a package fails to build with these, LTO should not be used there.
#
# Clang will soon gain -Wstrict-aliasing as a real warning (noop for now):
# https://github.com/llvm/llvm-project/pull/74155
#
# Clang does not yet have -Wlto-type-mismatch:
# https://github.com/llvm/llvm-project/issues/56487
WARNING_FLAGS="-Werror=odr -Werror=strict-aliasing"
COMMON_FLAGS="-O2 -pipe -march=native -flto ${WARNING_FLAGS}"
CFLAGS="${COMMON_FLAGS}"
CXXFLAGS="${COMMON_FLAGS}"
FCFLAGS="${COMMON_FLAGS}"
FFLAGS="${COMMON_FLAGS}"
USE="lto"
USE Flags
On both GCC and LLVM systems, some packages required special fixes to work with LTO and this is enabled by setting globally the lto USE flag.
USE="lto"
Rust
To compile rust programs with LTO then, it will need to be enable in both COMMON_FLAGS and RUSTFLAGS otherwise it won't be applied.
RUSTFLAGS="${RUSTFLAGS} -Clinker-plugin-lto"
Troubleshooting, Fixing and Reporting LTO Issues
While LTO works without issue for most users thanks to the hard work of everyone in the community in Gentoo and beyond, there are still some packages that a user may run across that have been missed.
This section will show how to fix the issue for the their system and also report the issue (if needed) so it can be fixed for everyone to help make Gentoo better for everyone in the future.
Stable Systems
As of 2023-05-15, LTO fixes have mostly trickled down from testing to stable (e.g. ~amd64 to amd64). However, there may be exceptions, so before reporting, try the latest version of the package in the testing branch to see if it's already fixed and save themselves and the developers time and effort.
In this example, app-editors/emacs is used to show steps. However, please be aware this may already be fixed at the time of reading, so should only be viewed as an example of the troubleshooting steps LTO users to be followed.
root #
emerge --ask app-editors/emacs
In this example, on a stable amd64 system, Portage would compile version 28.2-r6. On the first sign of a build issues, check packages.gentoo.org if there is a version in testing. In this case, one would find that there is a version 28.3_rc1-r2 available.
In this case, the next step would be to temporarily accept the keyword for that version only so Portage only uses the testing version until the stable package version catches up to the fix.
To only accept the keyword for one version, then an =
is required before the package type and then the version number after:
=app-editors/emacs-28.3_rc1-r2
Then try to emerge the updated version:
root #
emerge --ask app-editors/emacs
If the package now compiles fine, then no reporting is needed by the user. If, however, it still fails, then continue to the next step.
Latest Version Issues
Existing Reports Procedure
First check if a bug already exsts for the problem at bugs.gentoo.org. Using the search tool, looking up "emacs lto" would show a reported bug already as bug #854360.
Next, compare the reported version to the version tested on the system. If the version are the same, then no action is needed however, if the tested version was newer,then adding a comment that the problem still exists in the version testing should be added to help save time for the person working on the bug.
New Bugs Procedure
In the case of no bug being open after searching, then opening a new report is one of the most helpful things a Gentoo user can do to help highlight issues.
Do remember there is no shame if a mistake is made so there is no need for a user to feel nervous as you will be guided on what extra information is needed if required.
A bad bug report is always preferred over a perfect report that never gets reported.
Information Required
A good title helps, for example "app-editors/emacs-28.3_rc1-r2: fails to compile with LTO"
A short description of the issue and what has been tried so far.
Steps to reproduce, preferably from a fresh stage3 install:
- Install stage3 <tarball name used>
- Enable lto in make.conf via flags, per above instructions
- Add
app-editors/emacs-28.3_rc1-r2
to package.accept_keywords - emerge -va app-editors/emacs
Attach the build.log to the bug report from the location portage gives.
Add the output of emerge --info to a section comment.
This may sound confusing the first time, however it's very easy after the first time, and can be fun to watch a reported bug get fixed in real time.
Disable LTO per Package
After reporting, it's still possible to workaround the issue until a fix is committed by disabling LTO using package.env.
Create nolto.conf
package.env configuration is a Portage feature that allows a user to set CFLAGS and other options on a per-package basis.
Create /etc/portage/env/nolto.conf with the following:
# Env setup to disable LTO and related warnings for problematic builds
DISABLE_LTO="-Wno-error=odr -Wno-error=lto-type-mismatch -Wno-error=strict-aliasing -fno-lto"
CFLAGS="${CFLAGS} ${DISABLE_LTO}"
CXXFLAGS="${CXXFLAGS} ${DISABLE_LTO}"
FCFLAGS="${FCFLAGS} ${DISABLE_LTO}"
FFLAGS="${FFLAGS} ${DISABLE_LTO}"
These is the configuration that Portage will use for packages defined in the next step.
Create package.env/noltobuild
Suppose further emacs is an problematic package, then /etc/portage/package.env/noltobuild would look like:
app-editors/emacs nolto.conf
Now compiling app-editors/emacs
on the user's system would no longer build with LTO and the compiling issue found at the start would be fixed as a workaround until a permanent fix is found in Gentoo.
See Also
- Clang — a C/C++/Objective-C/C++, CUDA, and RenderScript language front-end for the LLVM project
- LTO optimization of GCC
- Project:Toolchain/LTO — details the Toolchain project's position on Link Time Optimization.
References
- ↑ Teresa Johnson, Mehdi Amini, Xinliang David Li. ThinLTO - Building C++ Applications with Scalable Whole Program Optimization, September 27, 2017. Retrieved on May 5, 2024