Let's интерпретировать исходный код GCC 5.1, чтобы увидеть, что происходит на -O100
, так как на странице руководства не ясно.
Мы заключаем, что:
- что выше
-O3
до INT_MAX
такой же, как -O3
, но это может легко измениться в будущем, так что не полагаться на него.
- GCC 5.1 запускает неопределенное поведение, если вы вводите целые числа, превышающие
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
.
О в common.opt
common.opt является GCC конкретный вариант CLI описание формата описаны в internals documentation и переведен на С помощью 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 отступиться, чтобы увидеть, кто называет эту функцию, и мы видим, что единственный код путь:
main.c:main
toplev.c:toplev::main
opts-global.c:decode_opts
opts.c:default_options_optimization
и main.c
- это точка входа cc1
. Хорошо!
Первая часть этой функции:
- делает
integral_argument
, который вызывает atoi
на строке, соответствующей OPT_O
для разбора входного аргумента
- сохраняет значение внутри
opts->x_optimize
, где opts
является struct gcc_opts
.
структура gcc_opts
После оглавлению напрасными, мы замечаем, что это struct
также генерируется на options.h
:
struct gcc_options {
int x_optimize;
[...]
}
где x_optimize
происходит от линии:
Variable
int optimize
prese нт в common.opt
, и что options.c
:
struct gcc_options global_options;
так мы предполагаем, что это то, что содержит в себе всю конфигурацию глобального состояния, и int x_optimize
это значение оптимизации.
255 представляет собой внутренний максимальный
в 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: maybe_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_PLUS
в 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
для конкретного отображения оптимизации упоминается в docs закодирован. Ницца!
Убедите, что нет больше использует для x_optimize
Основное использование x_optimize
было установить другие конкретные варианты оптимизации как -fdefer_pop
как описано на странице человека. Есть ли еще?
We grep
, и найти еще несколько. Число мало, и при ручном осмотре мы видим, что каждое использование составляет не более 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
передать его вперед, поэтому мы должны быть в порядке.
@Jens: TFM имеет длину 15 000 строк и не имеет большого значения о '-O' :) – Ryan
@minitech На какой FM вы смотрите? Даже с 'man gcc' на Cygwin (12000 нечетных строк) вы можете искать' -O' и находить все ответы ниже состояния, а затем некоторые. – Jens
@minmaxavg после чтения источника, я не согласен с вами: что-то большее, чем '3', такое же, как' 3' (до тех пор, пока оно не переполняется 'int'). См. [Мой ответ] (http://stackoverflow.com/a/30308151/895245). –