Сколько существует уровней оптимизации GCC ?
Я пробовал gcc -O1, gcc -O2, gcc -O3 и gcc -O4
Если я использую очень большое число, это не сработает.
Однако я пробовал
gcc -O100
и он скомпилирован.
Сколько существует уровней оптимизации?
Сколько существует уровней оптимизации GCC ?
Я пробовал gcc -O1, gcc -O2, gcc -O3 и gcc -O4
Если я использую очень большое число, это не сработает.
Однако я пробовал
gcc -O100
и он скомпилирован.
Сколько существует уровней оптимизации?
3то же самое 3(при условии, что оно не intпереполняется). Смотрите мой ответ .
-fomit-stack-pointer изменит сгенерированный код.
Ответы:
Чтобы быть педантичным, есть 8 различных допустимых опций -O, которые вы можете передать gcc, хотя есть некоторые, которые означают то же самое.
В исходной версии этого ответа говорилось, что существует 7 вариантов. GCC с тех пор добавил, -Ogчтобы довести общее количество до 8
-O (То же, что -O1)-O0 (без оптимизации, по умолчанию, если не указан уровень оптимизации)-O1 (оптимизировать минимально)-O2 (оптимизировать больше)-O3 (оптимизировать еще больше)-Ofast (очень агрессивно оптимизируйте, чтобы нарушить соответствие стандартам)-Og (Оптимизация процесса отладки. -Og обеспечивает оптимизацию, которая не мешает отладке. Это должен быть выбранный уровень оптимизации для стандартного цикла редактирования-компиляции-отладки, предлагающий разумный уровень оптимизации при сохранении быстрой компиляции и хорошего опыта отладки. )-Os(. Оптимизировать для размера -Osпозволяет использовать все -O2оптимизации , которые обычно не увеличивают размер кода Он также выполняет дополнительные оптимизации , предназначенные для уменьшения размера кода..
-OsОтключает следующие параметры оптимизации: -falign-functions -falign-jumps -falign-loops -falign-labels -freorder-blocks -freorder-blocks-and-partition -fprefetch-loop-arrays -ftree-vect-loop-version)Также могут быть оптимизации для конкретной платформы, как отмечает @pauldoo, OS X имеет -Oz
-Ozпараметр, который «оптимизирует размер более агрессивно, чем -Os»: developer.apple.com/mac/library/DOCUMENTATION/DeveloperTools/…
-Ogесть все параметры оптимизации, которые не мешают отладке
Давайте интерпретируем исходный код GCC 5.1
Постараемся разобраться, что происходит дальше -O100, поскольку на странице руководства это неясно.
Сделаем вывод, что:
-O3, INT_MAXто же самое -O3, но это может легко измениться в будущем, поэтому не полагайтесь на это.INT_MAX.-O-1Сосредоточьтесь на подпрограммах
Во- первых помните , что НКУ просто передний конец для cpp, as, cc1, collect2. Быстрый ./XXX --helpговорит, что только collect2и cc1бери -O, поэтому давайте сосредоточимся на них.
И:
gcc -v -O100 main.c |& grep 100
дает:
COLLECT_GCC_OPTIONS='-O100' '-v' '-mtune=generic' '-march=x86-64'
/usr/local/libexec/gcc/x86_64-unknown-linux-gnu/5.1.0/cc1 [[noise]] hello_world.c -O100 -o /tmp/ccetECB5.
поэтому -Oбыл перенаправлен на оба cc1и collect2.
O в общем. Опт
common.opt - это формат описания опций интерфейса командной строки для GCC, описанный во внутренней документации и переведенный на C с помощью opth-gen.awk и optc-gen.awk .
Он содержит следующие интересные строки:
O
Common JoinedOrMissing Optimization
-O<number> Set optimization level to <number>
Os
Common Optimization
Optimize for space rather than speed
Ofast
Common Optimization
Optimize for speed disregarding exact standards compliance
Og
Common Optimization
Optimize for debugging experience rather than speed or size
в которых указаны все Oпараметры. Обратите внимание, как -O<n>находится в отдельной от другой семье Os, Ofastи Og.
При сборке создается options.hфайл, содержащий:
OPT_O = 139, /* -O */
OPT_Ofast = 140, /* -Ofast */
OPT_Og = 141, /* -Og */
OPT_Os = 142, /* -Os */
В качестве бонуса, пока мы ищем \bO\nвнутри, common.optмы замечаем строки:
-optimize
Common Alias(O)
который учит нас тому, что --optimize(двойное тире, потому что оно начинается с тире -optimizeв .optфайле) является недокументированным псевдонимом, для -Oкоторого можно использовать --optimize=3!
Где используется OPT_O
Теперь мы grep:
git grep -E '\bOPT_O\b'
что указывает нам на два файла:
Давайте сначала отследим opts.c
opts.c: default_options_optimization
Все opts.c обычаи случаются внутри: default_options_optimization.
Мы используем команду grep backtrack, чтобы увидеть, кто вызывает эту функцию, и видим, что единственный путь кода:
main.c:maintoplev.c:toplev::mainopts-global.c:decode_optsopts.c:default_options_optimizationи main.c является точкой входа cc1. Хорошо!
Первая часть этой функции:
integral_argumentкоторый звонитatoi строку, соответствующую OPT_Oдля анализа входного аргументаopts->x_optimizeгде opts- struct gcc_opts.struct gcc_opts
После тщетного поиска мы замечаем, что это structтакже генерируется по адресу options.h:
struct gcc_options {
int x_optimize;
[...]
}
откуда x_optimizeвзято строки:
Variable
int optimize
присутствует в common.opt, и это options.c:
struct gcc_options global_options;
поэтому мы предполагаем, что это то, что содержит все глобальное состояние конфигурации и int x_optimizeявляется значением оптимизации.
255 - это внутренний максимум
in opts.c:integral_argument, atoiприменяется к входному аргументу, так INT_MAXже как и верхняя граница. И если вы поставите что-то большее, кажется, что GCC выполняет неопределенное поведение C. Ой?
integral_argumentтакже тонко обертывает atoiи отклоняет аргумент, если какой-либо символ не является цифрой. Так что отрицательные значения изящно терпят неудачу.
Вернувшись opts.c:default_options_optimization, мы видим строку:
if ((unsigned int) opts->x_optimize > 255)
opts->x_optimize = 255;
так что уровень оптимизации усечен до 255. Читая, opth-gen.awkя наткнулся на:
# All of the optimization switches gathered together so they can be saved and restored.
# This will allow attribute((cold)) to turn on space optimization.
и на сгенерированных options.h:
struct GTY(()) cl_optimization
{
unsigned char x_optimize;
что объясняет, почему усечение: параметры также должны быть перенаправлены на cl_optimization, который использует charдля экономии места. Так что 255 на самом деле является внутренним максимумом.
opts.c: возможно_default_options
Вернемся к тому opts.c:default_options_optimization, maybe_default_optionsчто звучит интересно. Входим в него, а потом maybe_default_optionдоходим до большого переключателя:
switch (default_opt->levels)
{
[...]
case OPT_LEVELS_1_PLUS:
enabled = (level >= 1);
break;
[...]
case OPT_LEVELS_3_PLUS:
enabled = (level >= 3);
break;
Проверок нет >= 4, что говорит о том, что3 это максимально возможное количество.
Затем ищем определение OPT_LEVELS_3_PLUSin common-target.h:
enum opt_levels
{
OPT_LEVELS_NONE, /* No levels (mark end of array). */
OPT_LEVELS_ALL, /* All levels (used by targets to disable options
enabled in target-independent code). */
OPT_LEVELS_0_ONLY, /* -O0 only. */
OPT_LEVELS_1_PLUS, /* -O1 and above, including -Os and -Og. */
OPT_LEVELS_1_PLUS_SPEED_ONLY, /* -O1 and above, but not -Os or -Og. */
OPT_LEVELS_1_PLUS_NOT_DEBUG, /* -O1 and above, but not -Og. */
OPT_LEVELS_2_PLUS, /* -O2 and above, including -Os. */
OPT_LEVELS_2_PLUS_SPEED_ONLY, /* -O2 and above, but not -Os or -Og. */
OPT_LEVELS_3_PLUS, /* -O3 and above. */
OPT_LEVELS_3_PLUS_AND_SIZE, /* -O3 and above and -Os. */
OPT_LEVELS_SIZE, /* -Os only. */
OPT_LEVELS_FAST /* -Ofast only. */
};
Ха! Это сильный показатель того, что уровней всего 3.
opts.c: default_options_table
opt_levelsнастолько интересно, что мы grep OPT_LEVELS_3_PLUSи встречаем opts.c:default_options_table:
static const struct default_options default_options_table[] = {
/* -O1 optimizations. */
{ OPT_LEVELS_1_PLUS, OPT_fdefer_pop, NULL, 1 },
[...]
/* -O3 optimizations. */
{ OPT_LEVELS_3_PLUS, OPT_ftree_loop_distribute_patterns, NULL, 1 },
[...]
}
так -Onчто здесь кодируется конкретное отображение оптимизации, упомянутое в документации. Ницца!
Убедитесь, что x_optimize больше не используется
Основное использование x_optimizeзаключалось в установке других конкретных параметров оптимизации, таких как-fdefer_pop как описано на странице руководства. Есть еще?
Мы grep, и найдем еще несколько. Число невелико, и при проверке вручную мы видим, что при каждом использовании происходит не более a x_optimize >= 3, поэтому наш вывод остается верным.
lto-wrapper.c
Теперь перейдем ко второму вхождению OPT_O, которое было вlto-wrapper.c .
LTO означает оптимизацию времени связи, для которой, как следует из названия, потребуется -Oопция, и она будет связана сcollec2 (который в основном является компоновщиком).
Фактически, первая строка lto-wrapper.cговорит:
/* Wrapper to call lto. Used by collect2 and the linker plugin.
В этом файле OPT_Oвхождения, кажется, только нормализуют значение, Oчтобы передать его вперед, так что все должно быть в порядке.
Семь различных уровней:
-O0 (по умолчанию): без оптимизации.
-Oили -O1(то же самое): оптимизируйте, но не тратьте слишком много времени.
-O2: Более агрессивная оптимизация
-O3: Оптимизировать наиболее агрессивно
-Ofast: Эквивалентно -O3 -ffast-math. -ffast-mathзапускает оптимизацию с плавающей запятой, не соответствующую стандартам. Это позволяет компилятору делать вид, что числа с плавающей запятой бесконечно точны, и что их алгебра следует стандартным правилам алгебры действительных чисел. Он также сообщает компилятору, чтобы оборудование сбрасывало денормальные значения до нуля и обрабатывало денормальные значения как ноль, по крайней мере, на некоторых процессорах, включая x86 и x86-64. Денормальные значения запускают медленный путь для многих FPU, поэтому рассмотрение их как нуля (которое не запускает медленный путь) может быть большим выигрышем в производительности.
-Os: Оптимизировать под размер кода. В некоторых случаях это действительно может улучшить скорость из-за лучшего поведения I-кеша.
-Og: Оптимизировать, но не мешать отладке. Это обеспечивает отличную производительность отладочных сборок и предназначено для замены -O0отладочных сборок.
Есть также другие параметры, которые не активируются ни одним из них, и их нужно включать отдельно. Также можно использовать параметр оптимизации, но отключить определенные флаги, включенные этой оптимизацией.
Для получения дополнительной информации см. Веб-сайт GCC.
-O100тогда компилируется?
Четыре (0-3): см. Руководство GCC 4.4.2 . Все, что выше, просто -O3, но в какой-то момент вы превысите ограничение на размер переменной.
atoiнеопределенное поведение, за которым следует 255внутреннее ограничение.
man gccCygwin (12000 нечетных строк) вы можете искать-Oи находить все, что указано в ответах ниже, а также некоторые.