Подтвердить что ты не робот

Различия между -O0 и -O1 в GCC

При компиляции некоторого кода я заметил большие различия в ассемблере, созданном между -O0 и -O1. Я хотел запустить оптимизацию с включением/отключением, пока не узнаю, что вызвало определенные изменения в ассемблере.

Если я использую -fverbose-asm, чтобы выяснить, какие флаги O1 разрешены по сравнению с O0, а затем отключить их вручную, почему ассемблер все еще так сильно отличается? Даже если я запустил gcc с помощью O0 и вручную добавлю все флаги, которые fverbose-asm сказали, были включены с O1, я не получаю тот же ассемблер, что и у меня, используя O1.

Есть ли что-нибудь помимо "-f..." и "-m...", которое можно изменить?

Или это просто, что "O1" имеет некоторую магию по сравнению с "O0", которую нельзя отключить.


Извините за загадочность - это было связано с Сокращение использования стека во время рекурсии с помощью GCC + ARM, однако упоминание об этом делало вопрос немного трудным для понимания.

4b9b3361

Ответ 1

Если вы хотите увидеть, какие пропуска включены в O1, которые не включены в O0, вы можете запустить что-то вроде:

gcc -O0 test.c -fdump-tree-all -da
ls > O0
rm -f test.c.*
gcc -O1 test.c -fdump-tree-all -da
ls > O1
diff O0 O1

Аналогичный процесс с использованием набора флагов, который вы обнаружили, позволит вам узнать, какие дополнительные магические проходы, не контролируемые флажками, выполняются GCC на O1.

EDIT:

Менее грязным способом может быть сравнение вывода -fdump-pass, в котором будут перечислены, какие проходы включены или выключены для stderr.

Так что-то вроде:

gcc -O0 test.c -fdump-passes |& grep ON > O0
gcc -O1 test.c -fdump-passes |& grep ON > O1
diff O0 O1

Ответ 2

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

  • Из http://gcc.gnu.org/ml/gcc-help/2007-11/msg00214.html:

    CAVEAT, не все оптимизаторы, включенные -O1, имеют флаг переключения командной строки, чтобы отключить их.

  • От Хагена "Окончательное руководство по GCC, 2-е изд.":

    Примечание. Не все оптимизации GCC можно контролировать с помощью флага. GCC автоматически выполняет некоторые оптимизации и, не изменяя исходный код, вы не можете отключить эти оптимизации при запросе оптимизации с помощью -O

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

Ответ 3

В дополнение ко многим параметрам вы также можете изменить параметры, например,

--param max-crossjump-edges=1

который влияет на генерацию кода. Проверьте исходный файл params.def на наличие всех доступных параметров.

Но нет способа переключиться с -O0 на -O1, или с -O1 на -O2, или с -Os, или на -Os, и т.п. путем добавления параметров без внесения исправлений в исходный код, поскольку существует несколько жестко закодированных местоположений, в которых уровень проверяется без обращения к параметру командной строки, например:

  return perform_tree_ssa_dce (/*aggressive=*/optimize >= 2);