Какой мертвый код может GCC устранить из окончательного вывода?
Мне всегда говорили, что компилятор достаточно умный, чтобы исключить мертвый код. Большая часть кода, который я пишу, имеет много информации, известную во время компиляции, но код должен быть написан в самой общей форме. Я не знаю сборки, поэтому я не могу проверить сгенерированную сборку. Какой код можно эффективно устранить в конечном исполняемом файле?
Несколько примеров, но не ограничиваясь этим
f(bool b){
if(b){
//some code
}else{
//some code
}
}
f(true);
//////////////////////////
template<bool b>
f(){
if(b){
//some code
}else{
//some code
}
}
f<true>();
///////////////////////////
Что делать, если определение f
находится в другом объектном коде, а основной f(true)
. Будет ли связывать оптимизацию времени эффективно устранять мертвый код? Что такое параметр/трюк стиля кодирования/компилятора для облегчения устранения мертвого кода?
Ответы
Ответ 1
Обычно, если вы компилируете флаг -O
, следующие флаги включаются:
-fauto-inc-dec
-fcompare-elim
-fcprop-registers
-fdce
[...]
-fdce
означает Dead Code Elimination. Я бы предложил вам скомпилировать ваши двоичные файлы с помощью и без (то есть, явно отключив) эту опцию, чтобы убедиться, что ваши двоичные файлы так же оптимизированы, как вам бы хотелось.
Прочитайте о разных проходах компилятора:
- SSA Агрессивное уничтожение мертвого кода. Включенный `-fssa-dce ' вариант. Этот проход выполняет исключение кода, считающегося ненужным потому что он не имеет внешне видимых эффектов для программы. Это работает в линейном времени.
Что касается того, чтобы помочь компоновщику с удалением мертвого кода пройти эту презентацию. Два основных вылета:
Скомпилируйте свои модули с разделами -ffunction-sections -fdata-sections - там это не минусы!
- Это включает в себя статические библиотеки, а не только двоичные файлы - позволяют пользователям вашей библиотеки извлекать выгоду из более эффективное удаление мертвого кода.
- Свяжите свои двоичные файлы с --gc-разделы, если только вам не нужно ссылаться на противную стороннюю статическую библиотеку, которая использует магические разделы.
Вы также можете взглянуть на эту ошибку GCC (чтобы увидеть, какие шансы на оптимизацию могут быть пропущены и почему).
Ответ 2
В вашем примере основное внимание уделяется устранению мертвого кода внутри функций.
Другой тип устранения мертвого кода - удаление целых неиспользуемых символов (функций или переменных), которые могут быть достигнуты с помощью:
-fdata-sections -ffunction-sections -Wl,--gc-sections
как указано в: Как удалить неиспользуемые символы C/С++ с помощью GCC и ld?
Эти флаги не включены в разных уровнях GCC -O (-O1, -O2 и т.д.) по умолчанию.
Ответ 3
Когда я использовал параметр параметра шаблона в таком выражении if, тогда компилятор dce (Dead Code Elimination) (GCC 4.8.1 на Linux) не помог, и оптимизация O2, O3 также не помогла.
Мне пришлось использовать обертку специализации шаблона:
template<bool b>
f();
template<>
f<true>(){
//some code on true condition
}
template<>
f<false>(){
//some code on false condition
}
Также можно использовать макросы, чтобы избежать компиляции неиспользуемой ветки кода, но это зависит от компилятора (независимо от того, обрабатываются ли они макросами по мере их возникновения в коде или на этапе предварительной компиляции):
template<bool b>
f(){
#if b
//some code
#elif
//some code
#endif // b
}