Link-time optimization (LTO) (-flto) defers optimization until link time, when the compiler has the entire program visible. This enables optimizations across translation units—inlining functions from other files, eliminating unused code globally, and whole-program analysis.
gcc -O3 -flto -o app a.c b.c c.c
With -flto, each .c file is compiled to intermediate representation (not native code), then optimized and linked together at the end. This takes longer to compile but can produce significantly faster code.
Compilation process with LTO:
gcc -O3 -flto -c a.c -o a.o # intermediate representation, not native code gcc -O3 -flto -c b.c -o b.o gcc -O3 -flto -c c.c -o c.o gcc -O3 -flto a.o b.o c.o -o app # link and optimize together
Each object file is intermediate code. The linker (with -flto) reoptimizes and produces the final native code.
Advantages:
a.c can be inlined into b.cDisadvantages:
Use cases: LTO is most valuable for large programs with many files and clear unused code. For small programs or embedded systems with size constraints, it can be worth the extra compilation time.
File size reduction: LTO often produces smaller binaries than -O3 without LTO because it eliminates unused functions globally:
gcc -O3 -o app a.c b.c c.c # ~5MB gcc -O3 -flto -o app a.c b.c c.c # ~3.5MB (dead code removed)
Performance trade-off: Sometimes LTO produces faster code (better inlining, dead code removal). Sometimes it produces slower code if aggressive inlining increases code size and hurts cache behavior. Measure both.
Incremental builds: With LTO, every link operation requires optimization. -flto=thin (thin LTO) speeds up this by doing parallel optimization:
gcc -O3 -flto=thin -o app a.c b.c c.c
Thin LTO is faster than full LTO but produces less optimal code. Good compromise for development builds.