Вопрос по c++, c, g++, templates, gcc – Какой мертвый код может удалить GCC из окончательного результата?

16

Мне всегда говорили, что компилятор достаточно умен, чтобы устранить мертвый код. Большая часть кода, который я пишу, содержит много информации, известной во время компиляции, но код должен быть написан в наиболее общей форме. Я не знаю ни одной сборки, поэтому не могу просмотреть созданную сборку. Какой код может быть эффективно устранен в конечном исполняемом файле?

Несколько примеров, но не ограничиваясь

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

Вы должны прочитатьHow can I know which parts in the code are never used?. Jesse Good
@JesseGood Это полезно! Благодарю. Но мне не нужно знать, какой код мертв, я просто хочу убедиться, что они не скомпилированы в конечный исполняемый файл. На самом деле я специально знаю, какая часть кода мертва, когда я пишу код вызывающей стороны. leon

Ваш Ответ

3   ответа
25

-O flag на следующие флаги включены:

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

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

Читайте оразные проходы компилятора:

SSA Aggressive Dead Code Elimination. Turned on by the `-fssa-dce' option. This pass performs elimination of code considered unnecessary because it has no externally visible effects on the program. It operates in linear time.

Что касается помощи компоновщику в устранении мертвого кодаэта презентация, Два основных выноса:

Compile your modules with -ffunction-sections -fdata-sections – there are no downsides to it!

This includes static libraries, not just binaries – make it possible for users of your library to benefit from more efficient dead code removal. Link your binaries with --gc-sections, unless you have to link against nasty third-party static library which uses magic sections.

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

@ *: Как точно отключить & quot; -fdce & quot; явно когда -O включен?
Вопрос: В документах они используют аббревиатуру «RTL», что это означает?
Кроме того, так как--gc-sections и подобные флаги являются относительно новыми и широко не поддерживаются, разработчики библиотек (особенно разработчики стандартных библиотек C) обычно придерживаются одной библиотечной функции на исходный файл, достигая аналогичного эффекта.See glibc as an example.
К вашему сведению, если вашему коду или библиотеке нужны магические разделы, то скрипт компоновщика должен пометить эти разделы как KEEP. Такого рода вещи часто случаются во встроенной разработке (которой часто все равно требуются сценарии компоновщика для определения структуры памяти), поскольку такие вещи, как таблицы векторов исключений, никогда не вызываются или на которые не ссылается main, но они должны присутствовать для платформы. Кстати, если вы создаете встроенный код без-ffunction-sections, -fdata сечения, and --gc-section`, ты только делаешь себе больно.
@ *: RTL = Register Transfer Language - это низкоуровневый промежуточный язык на основе Lisp (один из трех, используемых GCC), используемый (наряду с другим, называемым GIMPLE) для целей оптимизации.
0

флаги компилятора dce (Dead Code Elmination) (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

как упоминалось в:Как удалить неиспользуемые символы C / C ++ с помощью GCC и ld?

Эти флаги не включены на различных уровнях GCC -O (-O1, -O2 и т. Д.)по умолчанию.

Похожие вопросы