Возможны такие оптимизации, как постоянное распространение через функции в одной единице компиляции (т. е.тот же файл).
Например:
int f(int x)
{
return 3 + x;
}
int main(void)
{
printf("%d\n", 1 + f(4));
return 0;
}
В этом примере я думаю, что достаточно умный компилятор может передать константу '4' функции 'f', решая целочисленную арифметику с другой константой '3' , и возвращает полученное значение, сворачивая все до конечного значения «8».
(Что ж, поправьте меня, если я ошибаюсь ..)
Однако что происходит, если функция 'f' находится в другом модуле компиляции. Поскольку оба модуля компилируются отдельно, компилятор не может оптимизировать таким образом.
Означает ли это, что оптимизации возможны только в пределах одного и того же модуля компиляции, или есть какая-то форма поздних оптимизаций, выполняемых во время компоновки?
И MSVC (начиная с версии 8.0: VS2005), и GCC (начиная с версии 4.5) поддерживают эту концепцию.
MSVC использует переключатель компилятора /GL
и переключатель компоновщика /LTCG
. Документация
У GCC он должен быть включен и использует -flto
, -fwhole-program
, -fwhopr
, и/или -combine
для того же эффекта. Документация (ищите опции в браузере)
Проблема в том, что каждая единица компиляции (исходный файл) (а в случае MSVC - каждая библиотека) должна быть скомпилирована с этим, поэтому вы не можете использовать старые двоичные объектные файлы, скомпилированные без этого. Это также затрудняет отладку, потому что оптимизатор становится намного более агрессивным и непредсказуемым.
GCC 4.5 представил оптимизацию времени компоновки. AFAIK, он работает только с целями x86 и x64.
Microsoft Visual Studio поддерживает WPO (оптимизацию всей программы), включенную переключателем ltcg (генерация кода во время компоновки).
Это вызывает несколько других проблем, о которых я сейчас не помню, и многие разработчики предпочитают их отключать.
Clang компилирует в LLVM IR, и компоновщик LLVM выполняет оптимизацию всей программы, когда производит родной двоичный файл.
Да, для компилятора Visual C ++ в Visual Studio это известно как Оптимизация всей программы :
Оптимизация всей программы позволяет компилятор для выполнения оптимизаций с информация обо всех модулях в программа. Без целой программы оптимизация, оптимизации выполняется на каждом модуле (компиляции) база
С информацией обо всех модулях, компилятор может:
Оптимизировать использование регистров в границы функций.
Лучше отслеживайте модификации глобальных данных, позволяющие уменьшение количества нагрузок и магазины.
Лучше отслеживайте возможный набор элементов, измененных разыменование указателя, уменьшая количества грузов и магазинов.
Встроить функцию в модуль даже когда функция определена в другой модуль.