Отключить все параметры оптимизации в GCC
Уровень оптимизации по умолчанию для компиляции программ на Си с использованием 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
предоставленный мною флаг не был переопределен чем-то другим.
Фактически, я пытаюсь реализовать инструмент с нуля, который генерирует случайные последовательности параметров оптимизации и сравнивает сгенерированные последовательности с уровнями по умолчанию 0-3. Так же, как "Acovea". Итак, я хотел бы сравнить мои сгенерированные последовательности с уровнем нулевой оптимизации (который должен быть -O0
)
Можете ли вы объяснить мне, почему 50 опций включены по умолчанию в -O0
?
Я имею в виду одну идею: -O0
и отключить оптимизацию по умолчанию в -O0
с помощью -fno-OPTIMIZATION_NAME
50 раз. Как вы думаете?
3 ответа
Stricto sensu, промежуточная часть компилятора GCC состоит из последовательности (фактически вложенного дерева, динамически изменяющегося во время компиляции) этапов оптимизации, поэтому, если GCC не выполнил оптимизацию, он не сможет генерировать какой-либо код.
Подумайте об этом по-другому: язык ввода в GCC довольно богат (даже для простого C, где у вас есть while
, for
,....) но промежуточный язык Gimple гораздо беднее (в частности, Gimple/SSA), поэтому вам нужно применить некоторые преобразования для перехода от исходного AST к Gimple. Эти преобразования являются этапами оптимизации, почти по определению.
Смотрите также фотографии из этого ответа и этого (изображение SVG) и прочитайте ссылки, упомянутые здесь.
Ты должен понимать -O0
как отключение любых дополнительных оптимизаций (например, предоставленных -O1
и т. д.) не требуется для создания некоторого исполняемого файла.
Что ж
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
отключит все опции (гадость).
Если говорить более серьезно, если вы охватываете все состояния оптимизации, составьте список флагов оптимизации (что вам нужно сделать в любом случае) и явно включите или выключите каждый из них с помощью -fmyflag
или же -fno-myflag
, По сути, это отвечает на ваш второй вопрос.
Вы можете, однако, считать, что это не стоит того, чтобы поиграть с отключением оптимизаций, которые включены для всех -O
уровни.
Что касается того, почему это так, то это где-то между "слишком широким" (то есть вы должны спросить, кто бы это ни написал) и "потому что это то, что https://github.com/gcc-mirror/gcc/blob/master/gcc/toplev.c делает '.
Обратите внимание, что в документации не сказано, что -O0
отключает оптимизацию Он говорит (со страницы руководства):
-O0
Сократите время компиляции и сделайте отладку ожидаемым результатом. Это по умолчанию.
Это может означать, что оптимизации не увеличивают время компиляции и не влияют на отладку, и они останутся включенными.
Чтобы ответить на мой вопрос, я сделал несколько выводов и предположений:
Итак, позвольте мне сказать, что компиляция с O0 не означает, что никакие оптимизации не будут применены. Опции, которые сокращают время компиляции и улучшают отладку, будут включены, как сказано выше @abligh.
Другими словами, O0 оптимизирует уровень компиляции. Производимые двоичные файлы не оптимизированы для упрощения процесса отладки.
Я приведу пример: эта опция включена на уровне O0
-faggressive-петля-оптимизация
В документации GCC:
Эта опция говорит оптимизатору цикла использовать языковые ограничения для получения границ для числа итераций цикла. Это предполагает, что код цикла не вызывает неопределенное поведение, например, вызывая целочисленные переполнения со знаком или обращения к массиву вне границ. Границы для числа итераций цикла используются для направления развертывания цикла и оптимизации процесса очистки и завершения цикла. Эта опция включена по умолчанию.
Таким образом, для GCC 4.8.x по умолчанию включено почти 50 параметров.