2012-05-30 2 views
15

Мне всегда говорили, что компилятор достаточно умный, чтобы исключить мертвый код. Большая часть кода, который я пишу, имеет много информации, известную во время компиляции, но код должен быть написан в самой общей форме. Я не знаю сборки, поэтому я не могу проверить сгенерированную сборку. Какой код можно эффективно устранить в конечном исполняемом файле?Какой мертвый код может 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) в основном. Будет ли связывать оптимизацию времени эффективно устранять мертвый код? Что такое вариант/трюк стиля кодирования/компилятора для облегчения устранения мертвого кода?

+2

Вы должны прочитать [Как я могу узнать, какие части кода никогда не используются?] (Http://stackoverflow.com/questions/4813947/how-can-i-know-which-parts-in-the- кода не-никогда используется /). –

+0

@JesseGood Это полезно! Благодарю. Но мне не нужно знать, какой код мертв, я просто хочу убедиться, что они не скомпилированы в окончательный исполняемый файл. На самом деле я специально знаю, какая часть кода мертва по дизайну, когда я пишу код вызывающего абонента. – leon

ответ

24

Как правило, если вы компилируете с the -O flag на следующие флаги включены:

 -fauto-inc-dec 
     -fcompare-elim 
     -fcprop-registers 
     -fdce 
     [...] 

-fdce стендами для Dead Code ликвидации. Я бы посоветовал вам скомпилировать ваши двоичные файлы с помощью и без (то есть, явно отключив) эту опцию, чтобы убедиться, что ваши двоичные файлы так же оптимизированы, как вам бы хотелось.

Читайте о different passes компилятора:

  • SSA Агрессивное Мертвый код ликвидации. Включен опцией `-fssa-dce ' . Этот проход выполняет отмену кода, который считается ненужным , потому что он не имеет внешне видимых эффектов для программы. Он работает в линейном режиме.

Что касается оказания помощи линкера с устранением мёртвого кода пройти через this presentation. Два основных вынос являются:

компилирование модулей с -ffunction-секций -fdata сечений - там нет минусов этого!

  • Это включает в себя статические библиотеки, а не только двоичных файлов - сделать возможной для пользователей вашей библиотеки, чтобы извлечь выгоду из более эффективного удаления мертвого кода.
  • Свяжите свои двоичные файлы с --gc-sections, если только вам не нужно ссылаться на противную стороннюю статическую библиотеку, которая использует магические разделы.

Вы также можете взглянуть на this GCC bug (чтобы увидеть, что шансы оптимизации могут быть упущены и почему).

+0

Вопрос: В документах используется аббревиатура «RTL», что это значит? –

+3

@ *: RTL = Register Transfer Language - это язык промежуточного языка, основанный на Lisp, один из трех, используемый GCC (используется вместе с другим именем GIMPLE) для целей оптимизации. – dirkgently

+0

FYI, если вашему коду или библиотеке нужны магические разделы, тогда скрипт компоновщика должен маркировать эти разделы как KEEP. Такие вещи случаются во встроенной разработке (для чего часто требуется компоновщик скриптов для определения макета памяти), поскольку такие вещи, как таблицы векторов исключений, никогда не вызываются или не ссылаются по основным причинам, а должны быть там для платформы. Кстати, если вы строите встроенный код без '-ffunction-sections',' -fdata-sections' и '-gc-sections', вы только вредите себе. –

0

Когда я использовал параметр параметра шаблона в таком выражении 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 
} 
1

Ваш пример фокусируется на устранении недостающих кодов внутри функций.

Другой тип устранения мёртвого кода, является удаление целых неиспользуемых символов (функций или переменных), которые могут быть достигнуты с:

-fdata-sections -ffunction-sections -Wl,--gc-sections 

как упомянуто в: How to remove unused C/C++ symbols with GCC and ld?

Эти флаги не включены в различные уровни GCC -O (-O1, -O2 и т. д.) by default.