Вы имеете в виду объединение модулей трансляции до этапа генерации промежуточного представления? Такая техника называется Single Compilation Unit, SCU и, судя по всему, сейчас почти нигде не применяется из-за плохой масштабируемости. Кроме того, используя SCU вы теряете возможность осуществлять параллельную/инкрементальную сборку программы.
Даже если вы используете объединение модулей, у вас все равно могут остаться неразрешенные внешние символы (то есть функции и глобальные переменные), например, если компилируемая программа использует библиотеки с закрытым исходным кодом.
Но вы правы в главном: объединение модулей для анализа всей программы целиком используется для осуществления оптимизаций на этапе линковки (Link Time Optimization, LTO). Обычный подход предполагает трансляцию каждого модуля компиляции во внутреннее представление (например, .class файлы для Java, .bc файлы для Clang и других LLVM-based компиляторов) и объединение таких модулей байткода в один большой модуль. После оптимизации такого большого модуля генерируется код для целевой платформы. Ничего умнее пока, насколько мне известно, придумано не было (за исключением может быть ThinLTO).
Даже если вы используете объединение модулей, у вас все равно могут остаться неразрешенные внешние символы (то есть функции и глобальные переменные), например, если компилируемая программа использует библиотеки с закрытым исходным кодом.
Но вы правы в главном: объединение модулей для анализа всей программы целиком используется для осуществления оптимизаций на этапе линковки (Link Time Optimization, LTO). Обычный подход предполагает трансляцию каждого модуля компиляции во внутреннее представление (например, .class файлы для Java, .bc файлы для Clang и других LLVM-based компиляторов) и объединение таких модулей байткода в один большой модуль. После оптимизации такого большого модуля генерируется код для целевой платформы. Ничего умнее пока, насколько мне известно, придумано не было (за исключением может быть ThinLTO).