C Mastery / LTO, PGO, Vectorization
Part 6 — Debugging and Optimization

LTO, PGO, Vectorization

This chapter covers three advanced optimization techniques: link-time optimization (LTO), profile-guided optimization (PGO), and auto-vectorization.

Why This Matters

Whole-program and profile-driven optimization can yield significant speedups beyond -O3. Vectorization uses SIMD to process multiple data elements at once. These are the tools that separate "correct" from "fast."

Prerequisites

Core Concept

Normally the compiler optimizes each translation unit separately; the linker just combines objects. LTO defers optimization until link time, allowing inlining and other passes across translation units.

gcc -flto -O2 -c a.c
gcc -flto -O2 -c b.c
gcc -flto -O2 a.o b.o -o app

Profile-guided optimization (PGO)

PGO runs the program on representative inputs to collect a profile, then recompiles using that profile to guide inlining, branch layout, and hot/cold code splitting.

gcc -O2 -fprofile-generate app.c -o app
./app < training-input        # produces .gcda files
gcc -O2 -fprofile-use app.c -o app-optimized

Auto-vectorization

The compiler transforms loops to use SIMD instructions (SSE/AVX/NEON) when it can prove the iterations are independent and the accesses are aligned or handled.

for (int i = 0; i < n; i++)
    c[i] = a[i] + b[i];   /* vectorizable */

Enable with -O3 (or -O2 with -ftree-vectorize on GCC), and inspect with -fopt-info-vec.

How It Works

LTO serializes the compiler's IR into the object file, then re-optimizes at link time. PGO instruments the binary to record branch/call frequencies, which a later compilation reads. Vectorization analyzes loop-carried dependencies and emits packed SIMD operations.

Variations

ThinLTO

Clang's ThinLTO scales LTO to large programs by partitioning the IR, trading a little optimization for much faster link times.

Explicit SIMD

When auto-vectorization fails, you can write intrinsics directly (c.perf.4).

Common Mistakes

Undefined Behavior

miscompiled vectorized code.

Portability

hardware-dependent (SSE/AVX/NEON).

Under the Hood

LTO stores GIMPLE/LLVM IR in object sections. PGO emits counters that update on each edge/call. The vectorizer uses SLP/loop vectorization on SSA form to find independent lanes.

Practical Usage

aliasing via restrict).

Exercises

1. Build a multi-file program with and without LTO and compare size/speed. 2. Run a PGO cycle and observe the profile files. 3. Write a vectorizable loop and confirm with -fopt-info-vec.

Deep Challenge

Take a loop that does not vectorize (due to possible aliasing) and make it vectorizable by adding restrict and restructuring. Explain each blocker you removed.

References

Verification

verified.`

Progress

Concept checkboxes

Mastery levels

ConceptCurrent level (0–8)Target level
c.opt.lto06
c.opt.pgo05
c.opt.vectorize06