Различия между -O0 и -O1 в GCC
При компиляции некоторого кода я заметил большие различия в ассемблере, созданном между -O0 и -O1. Я хотел запустить оптимизацию с включением/отключением, пока не узнаю, что вызвало определенные изменения в ассемблере.
Если я использую -fverbose-asm, чтобы выяснить, какие флаги O1 разрешены по сравнению с O0, а затем отключить их вручную, почему ассемблер все еще так сильно отличается? Даже если я запустил gcc с помощью O0 и вручную добавлю все флаги, которые fverbose-asm сказали, были включены с O1, я не получаю тот же ассемблер, что и у меня, используя O1.
Есть ли что-нибудь помимо "-f..." и "-m...", которое можно изменить?
Или это просто, что "O1" имеет некоторую магию по сравнению с "O0", которую нельзя отключить.
Извините за загадочность - это было связано с Сокращение использования стека во время рекурсии с помощью GCC + ARM, однако упоминание об этом делало вопрос немного трудным для понимания.
Ответы
Ответ 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);