Как изменить уровень оптимизации одной функции?

Это связано с Определить причину segfault при использовании -O3? В этом вопросе я поймаю segfault в определенной функции при компиляции с помощью -O3 используя определенную версию GCC. В -O3 используются инструкции векторизации (в -O2 они не используются).

Я хочу обернуть одну функцию на более низком уровне оптимизации. Согласно Отключение оптимизации для конкретной функции в GCC 4.2.2, я могу это сделать. Однако, следуя различным ссылкам в вопросе и ответах, я не нахожу ответа на вопрос "как именно это сделать".

Как отметить одну функцию для использования другого уровня оптимизации?


Связанный, я не хочу переместить эту функцию в отдельный файл, а затем предоставить другой рецепт файла makefile для него. Это открывает еще одну возможность червей, например, применять ее к GCC 4.9 только на некоторых платформах.

Ответ 2

Я знаю, что этот вопрос помечен как GCC, но я просто хотел сделать это мобильно и подумал, что результаты могут кому-то пригодиться, поэтому:

  • GCC имеет атрибут функции optimize(X)
  • Clang имеет optnone функций optnone и minsize (используйте __has_attribute для проверки поддержки). Так как я верю, что 3.5 также имеет #pragma clang optimize on|off.
  • Компилятор Intel C/C++ имеет #pragma intel optimization_level 0 Optimization_level #pragma intel optimization_level 0 который применяется к следующей функции после прагмы
  • В MSVC есть #pragma optimize, которая применяется к первой функции после прагмы
  • В IBM XL есть #pragma option_override(funcname, "opt(level,X)"). Обратите внимание, что 13.1.6 (по крайней мере) возвращает true для __has_attribute(optnone) но фактически не поддерживает его.
  • В ARM есть #pragma Onum, который может быть связан с #pragma push/pop
  • ODS имеет #pragma opt X (funcname)
  • У Cray есть #pragma _CRI [no]opt
  • У TI есть #pragma FUNCTION_OPTIONS(func,"…") (C) и #pragma FUNCTION_OPTIONS("…") (C++)
  • В IAR есть #pragma optimize=...
  • Pelles C имеет #pragma optimize time/size/none

Таким образом, для GCC/ICC/MSVC/clang/IAR/Pelles и TI C++ вы можете определить макрос, который вы только что поместили перед функцией. Если вы хотите поддерживать XL, ODS и TI C, вы можете добавить имя функции в качестве аргумента. ARM потребует другой макрос после функции, чтобы вытолкнуть настройку. Для Cray AFAIK вы не можете восстановить предыдущее значение, только отключить оптимизацию и включить.

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

Редактировать: Стоит также отметить, что довольно часто отключают оптимизации, потому что код, который работал раньше, больше не работает. Хотя возможно, что в компиляторе есть ошибка, гораздо более вероятно, что ваш код полагается на неопределенное поведение, а более новые, более умные компиляторы могут и будут исключать неопределенный случай. Правильный ответ в подобных ситуациях - не отключать оптимизацию, а исправить код. UBsan на Clang и GCC может помочь здесь; скомпилируйте с -fsanitize=undefined и много неопределенного поведения начнут выдавать предупреждения во время выполнения. Кроме того, попробуйте скомпилировать все возможные варианты предупреждений; для GCC это означает -Wall -Wextra, для броска лязга в -Weverything.

Ответ 3

Вот как это сделать с помощью прагм:

#pragma GCC push_options
#pragma GCC optimize ("-O2")
void xorbuf(byte *buf, const byte *mask, size_t count)
{
   ...
}
#pragma GCC pop_options

Сделать это переносным, что-то вроде следующего.

#define GCC_OPTIMIZE_AWARE (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7)) || defined(__clang__)

#if GCC_OPTIMIZE_AWARE
# pragma GCC push_options
# pragma GCC optimize ("-O2")
#endif

Его нужно обернуть, потому что с -Wall более старая версия GCC не понимает -Wno-unknown-pragma, и они вызовут шумную компиляцию. Старая версия будет встречена в поле, например, GCC 4.2.1 на OpenBSD.

Но в соответствии с Маркусом Триппельсдорфом на Когда в списке рассылки GCC появилась опция "pragma optimize" ,

Это плохая идея в целом, потому что "оптимизация прагмы GCC" означает только отладочная помощь компилятора. Он не должен использоваться в производстве код.