Linker-plugin-based LTO: Give explanation how to use linker-plugin-lto with full LTO
This commit is contained in:
parent
905b926967
commit
cd50e62277
1 changed files with 66 additions and 14 deletions
|
|
@ -3,20 +3,35 @@
|
|||
The `-C linker-plugin-lto` flag allows for deferring the LTO optimization
|
||||
to the actual linking step, which in turn allows for performing
|
||||
interprocedural optimizations across programming language boundaries if
|
||||
all the object files being linked were created by LLVM based toolchains.
|
||||
The prime example here would be linking Rust code together with
|
||||
Clang-compiled C/C++ code.
|
||||
all the object files being linked were created by LLVM-based toolchains
|
||||
using the **same** LTO mode: either thin LTO or fat LTO.
|
||||
The examples would be linking Rust code together with
|
||||
Clang-compiled C/C++ code and LLVM Flang-compiled Fortran code.
|
||||
|
||||
## Usage
|
||||
|
||||
There are two main cases how linker plugin based LTO can be used:
|
||||
There are two main cases how linker-plugin-based LTO can be used:
|
||||
|
||||
- compiling a Rust `staticlib` that is used as a C ABI dependency
|
||||
- compiling a Rust binary where `rustc` invokes the linker
|
||||
|
||||
In both cases the Rust code has to be compiled with `-C linker-plugin-lto` and
|
||||
the C/C++ code with `-flto` or `-flto=thin` so that object files are emitted
|
||||
as LLVM bitcode.
|
||||
In both cases, the Rust code must be compiled with `-C linker-plugin-lto`.
|
||||
By default, this enables thin LTO, so any interoperable language code must
|
||||
also be compiled in thin LTO mode. To use fat LTO with linker-plugin-based LTO,
|
||||
the `rustc` compiler requires the additional `-C lto=fat` flag, and the
|
||||
interoperable language must likewise be compiled in fat LTO mode. Note that
|
||||
interoperable language must be compiled using the LLVM infrastructure
|
||||
(see more details in [toolchain compability](#toolchain-compatibility)).
|
||||
|
||||
The following table summarizes how to enable thin LTO and fat LTO in
|
||||
different compilers:
|
||||
|
||||
| Compiler | Thin LTO | Fat LTO |
|
||||
|:---------|-----------------:|---------------:|
|
||||
| rustc | -Clto=thin | -Clto=fat |
|
||||
| clang | -flto=thin | -flto=full |
|
||||
| clang++ | -flto=thin | -flto=full |
|
||||
| flang | -flto=thin (WIP) | -flto=full |
|
||||
|
||||
### Rust `staticlib` as dependency in C/C++ program
|
||||
|
||||
|
|
@ -54,7 +69,7 @@ that an appropriate linker is used.
|
|||
Using `rustc` directly:
|
||||
|
||||
```bash
|
||||
# Compile C code with `-flto`
|
||||
# Compile C code with `-flto=thin`
|
||||
clang ./clib.c -flto=thin -c -o ./clib.o -O2
|
||||
# Create a static library from the C code
|
||||
ar crus ./libxyz.a ./clib.o
|
||||
|
|
@ -66,7 +81,7 @@ rustc -Clinker-plugin-lto -L. -Copt-level=2 -Clinker=clang -Clink-arg=-fuse-ld=l
|
|||
Using `cargo` directly:
|
||||
|
||||
```bash
|
||||
# Compile C code with `-flto`
|
||||
# Compile C code with `-flto=thin`
|
||||
clang ./clib.c -flto=thin -c -o ./clib.o -O2
|
||||
# Create a static library from the C code
|
||||
ar crus ./libxyz.a ./clib.o
|
||||
|
|
@ -75,6 +90,41 @@ ar crus ./libxyz.a ./clib.o
|
|||
RUSTFLAGS="-Clinker-plugin-lto -Clinker=clang -Clink-arg=-fuse-ld=lld" cargo build --release
|
||||
```
|
||||
|
||||
### Fortran code as a dependency in Rust
|
||||
|
||||
Rust code can also be linked together with Fortran code compiled by LLVM `flang`.
|
||||
The following examples demonstrate fat LTO usage, as LLVM `flang` has WIP status for
|
||||
thin LTO. The same approach can be applied to compile C and C++ code with fat LTO.
|
||||
|
||||
Using `rustc` directly:
|
||||
|
||||
```bash
|
||||
# Compile Fortran code with `-flto=full`
|
||||
flang ./ftnlib.f90 -flto=full -c -o ./ftnlib.f90.o -O3
|
||||
# Create a static library from the Fortran code
|
||||
ar crus ./libftn.a ./ftnlib.f90.o
|
||||
|
||||
# Invoke `rustc` with the additional arguments, `-Clto=fat` is mandatory
|
||||
rustc -Clinker-plugin-lto -Clto=fat -Clink-arg=path/to/libftn.a -Copt-level=3 -Clinker=flang -C default-linker-libraries=yes -Clink-arg=-fuse-ld=lld ./main.rs
|
||||
```
|
||||
|
||||
Using `cargo` directly:
|
||||
|
||||
```bash
|
||||
# Compile Fortran code with `-flto=full`
|
||||
flang ./ftnlib.f90 -flto=full -c -o ./ftnlib.f90.o -O3
|
||||
# Create a static library from the Fortran code
|
||||
ar crus ./libftn.a ./ftnlib.f90.o
|
||||
|
||||
# Set the linking arguments via RUSTFLAGS, `-Clto=fat` is mandatory
|
||||
RUSTFLAGS="-Clinker-plugin-lto -Clto=fat -Clink-arg=path/to/libftn.a -Clinker=flang -C default-linker-libraries=yes -Clink-arg=-fuse-ld=lld" cargo build --release
|
||||
```
|
||||
|
||||
Note, LLVM `flang` can be used as a linker driver starting from flang 21.1.8.
|
||||
The `-C default-linker-libraries=yes` option may be omitted if the Fortran
|
||||
runtime is not required; however, most Fortran code depends on the runtime,
|
||||
so enabling default linker libraries is usually necessary.
|
||||
|
||||
### Explicitly specifying the linker plugin to be used by `rustc`
|
||||
|
||||
If one wants to use a linker other than LLD, the LLVM linker plugin has to be
|
||||
|
|
@ -179,11 +229,13 @@ for clang, rust in sorted(version_map.items()):
|
|||
-->
|
||||
|
||||
In order for this kind of LTO to work, the LLVM linker plugin must be able to
|
||||
handle the LLVM bitcode produced by both `rustc` and `clang`.
|
||||
handle the LLVM bitcode produced by `rustc` and by compilers of all
|
||||
interoperable languages. A good rule of thumb is to use an LLVM linker plugin
|
||||
whose version is at least as new as the newest compiler involved.
|
||||
|
||||
Best results are achieved by using a `rustc` and `clang` that are based on the
|
||||
exact same version of LLVM. One can use `rustc -vV` in order to view the LLVM
|
||||
used by a given `rustc` version. Note that the version number given
|
||||
Best results are achieved by using a `rustc` and LLVM compilers that are based
|
||||
on the exact same version of LLVM. One can use `rustc -vV` in order to view
|
||||
the LLVM used by a given `rustc` version. Note that the version number given
|
||||
here is only an approximation as Rust sometimes uses unstable revisions of
|
||||
LLVM. However, the approximation is usually reliable.
|
||||
|
||||
|
|
@ -204,6 +256,6 @@ The following table shows known good combinations of toolchain versions.
|
|||
| 1.78 - 1.81 | 18 |
|
||||
| 1.82 - 1.86 | 19 |
|
||||
| 1.87 - 1.90 | 20 |
|
||||
| 1.91 - 1.92 | 21 |
|
||||
| 1.91 - 1.93 | 21 |
|
||||
|
||||
Note that the compatibility policy for this feature might change in the future.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue