Сейчас - без LTO грусть. Раньше, неиспользуемые секции выбрасывались линкером без LTO. Знаете, а давайте я расскажу как было раньше?
За базу возьмем JPI TopSpeed Modula-2 ver.1.17
Это 1997 год. Моя юность :-)
Так вот.
Компилятор, в те славные времена был сосредоточен на компиляции процедур (функций)
и отлично отлавливал мёртвый код внутри них.
Также он умел отлавливать неиспользуемые в пределах единицы компиляции как локальные, так и глобальные переменные.
И тоже об этом предупреждал.
Предполагалось что программисты предупреждения компилятора читают, долго стоят у окна с сигаретой, думают и ненужный текст удаляют.
После этого, внутри функций всё оптимально и неиспользуемых переменных в единицах компиляции нету.
Линкеру компилятор отдавал объектник, в котором каждая функция и каждая глобальная переменная
единицы компиляции сидела в отдельном блоке. Большинство блоков были релоцируемыми и линкеру для них передавалась
специальная таблица - куда вписать фактические адреса размещения.
Там же передавалась таблица внешних ссылок - какому модулю что нужно от других.
Линкер получал объектники, отлавливал в них неискользуемые блоки, молча их выкидывал,
прописывал по таблицам релокации что куда положил и в принципе это и было его работой.
Если сравнивать именно с этим LTO ни в жизнь не даст 30% экономиии.
Но сравнивают, естественно не с этим.
Потому что гладиолус.