Отключить все опции оптимизации в GCC

Уровень оптимизации по умолчанию для компиляции C-программ с использованием GCC -O0. который отключает все оптимизации в соответствии с документацией GCC. например:

    gcc -O0 test.c 

Однако, чтобы проверить, действительно ли -O0 отключить все оптимизации. Я выполнил эту команду:

    gcc -Q -O0 --help=optimizers 

И здесь я был немного удивлен. У меня включено 50 опций. Затем я проверил аргументы по умолчанию, переданные в gcc, используя это:

    gcc -v 

Я получил это:

Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-       
2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --      
enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --
program-suffix=-4.8 --enable-shared --enable-linker-build-id --
libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-
gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-
sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-
time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --
with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-
cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-
java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-
jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-
directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-
gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --
with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release 
--build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu

Thread model: posix

gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) 

Итак, я пришел к выводу, что флаг -O0, который я предоставил программе, не был переоценен чем-то другим.

Фактически я пытаюсь реализовать с нуля инструмент, который генерирует случайные последовательности опций оптимизации и сравнивает сгенерированные последовательности с уровнями O0-3 по умолчанию. Также как "acovea". Таким образом, я хотел бы сравнить мои сгенерированные последовательности с уровнем нулевой оптимизации (который должен быть O0)

Можете ли вы объяснить мне, почему 50 опций включены по умолчанию в -O0?

Одна идея, которую я имею в виду, - это скомпилировать с O0 + отключить оптимизацию по умолчанию в O0, используя -fno-OPTIMIZATION_NAME 50 раз. Как вы думаете?

Ответ 1

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

Подумайте об этом по-другому: язык ввода в GCC довольно богат (даже для обычного C, где у вас есть while, for,....), но промежуточный язык Gimple намного хуже (в конкретный Gimple/SSA), поэтому вам нужно применить некоторые преобразования, чтобы перейти от источника АСТ к Gimple. Эти преобразования являются прохождением оптимизации, почти по определению.

Смотрите также фотографии из и этот один (SVG изображение) и прочитайте ссылки, упомянутые здесь.

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

Ответ 2

Ну

gcc -O0 `gcc -Q -O0 --help=optimizers 2>&1 | perl -ane 'if ($F[1] =~/enabled/) {$F[0] =~ s/^\s*-f/-fno-/g;push @o,$F[0];}} END {print join(" ", @o)'` your args here

отключит все параметры (yuck).

Более серьезно, если вы охватываете все состояния оптимизации, создайте список флагов оптимизации (что вам нужно сделать в любом случае) и явно включите или выключите каждый из них с помощью -fmyflag или -fno-myflag. Это по существу отвечает на ваш второй вопрос.

Однако вы можете подумать, что вам не стоит играть, отключая оптимизацию, которая включена для всех уровней -O.

Что до этого так, что-то между "слишком широким" (т.е. вы должны спросить, кто бы это написал), и "потому что то, что https://github.com/gcc-mirror/gcc/blob/master/gcc/toplev.c does..

Обратите внимание, что в документации не указано, что -O0 отключает оптимизацию. В нем говорится (из справочная страница):

-O0 Сократите время компиляции и сделайте отладку ожидаемыми результатами. Это значение по умолчанию.

Подразумевается, что могут быть оптимизации, не увеличивающие время компиляции и не влияющие на отладку, и они будут оставлены.

Ответ 3

Чтобы ответить на мой вопрос, я сделал некоторые выводы и предположения:

Итак, позвольте мне сказать, что компиляция с O0 не означает, что никакие оптимизации не будут применены. Опции, которые сокращают время компиляции и делают отладку лучше, будут включены как @abligh, упомянутые выше.

Иными словами, O0 оптимизирует уровень компиляции. Выпущенные двоичные файлы не оптимизированы для упрощения процесса отладки.

Приведу пример: эта опция включена на уровне O0

-faggressive-петля-оптимизации

В документации GCC:

Этот параметр указывает оптимизатору цикла использовать языковые ограничения для получения оценок для числа итераций цикла. Это предполагает, что код цикла не вызывает поведение undefined, например, вызывая переполнение целых чисел со знаком или без доступа к массиву. Оценки для числа итераций цикла используются для управления оптимизацией циклов для разворачивания и пилинга и цикла. Эта опция включена по умолчанию.

Итак, для GCC 4.8.x по умолчанию включено почти 50 опций.