LTO vs PGO

That they are two names for "the aggressive build". They answer different questions: LTO gives the optimizer more code to look at, PGO gives it evidence about what that code does. They compose, and neither substitutes for the other — LTO without a profile still guesses which calls are hot.

Link-time optimization

When the program is split across many translation units and the interesting call sites cross them.

Profile-guided optimization

When you have a workload representative enough to measure, and the wins you need are in layout, branch direction and inlining decisions.

AspectLink-time optimizationProfile-guided optimization
What it addsScope — the optimizer sees across translation-unit boundaries.Evidence — measured branch and call frequencies.
When it happensAt link time, on IR the compiler deferred instead of lowering.On a second compilation, reading counters from an instrumented or sampled run.
Main winsCross-module inlining, better alias facts, dead code across the whole program.Hot/cold splitting, block layout, more selective inlining, better register priorities.
Main costLink time and memory; the link step becomes the build bottleneck.The workflow — building twice and keeping the profile current.
How it goes wrongLonger builds and harder debugging for a win that was never measured.An unrepresentative profile optimizes for the benchmark and pessimises production.
PrerequisiteEvery input object must be compiled with it enabled.A workload someone is willing to defend as representative.