2009-11-22 12 views
56

¿Cuántos niveles de optimización GCC hay?¿Cuántos niveles de optimización de GCC hay?

me trataron -O1 gcc, gcc -O2, -O3 gcc, y gcc -O4

Si uso un muy gran número, no funcionará.

Sin embargo, he tratado

gcc -O100 

y compilado.

¿Cuántos niveles de optimización hay?

+3

@Jens: TFM tiene 15,000 líneas y no tiene mucho que decir sobre '-O' :) – Ryan

+13

@minitech ¿Qué FM estás mirando? Incluso con 'man gcc' en Cygwin (12000 líneas impares) puede buscar' -O' y encontrar todo lo que las respuestas a continuación dicen, y algo más. – Jens

+1

@minmaxavg después de leer la fuente, no estoy de acuerdo con usted: cualquier cosa más grande que '3' es lo mismo que' 3' (siempre que no se sobrepase 'int'). Ver [mi respuesta] (http://stackoverflow.com/a/30308151/895245). –

Respuesta

82

Para ser pedantes, hay 8 opciones -O válidas diferentes que puedes dar a gcc, aunque hay algunas que significan lo mismo.

La versión original de esta respuesta indicó que había 7 opciones. desde GCC ha añadido -Og para llevar el total a 8

Desde el man page:

  • -O (Igual que -O1)
  • -O0 (no hacer la optimización, el valor por defecto si no se especifica el nivel de optimización)
  • -O1 (optimizar al mínimo)
  • -O2 (optimizar más)
  • -O3 (optimizar aún más)
  • -Ofast (optimizar de forma muy agresiva hasta el punto de romper el cumplimiento estándar)
  • -Og (Optimizar la experiencia de depuración. -Og habilita optimizaciones que no interfieren con la depuración. Debe ser el nivel optimización de elección para el ciclo de edición-compilación de depuración estándar, que ofrece un nivel razonable de optimización mientras se mantiene la compilación rápida y una buena experiencia de depuración.)
  • -Os (Optimizar para el tamaño. -Os permite todo -O2 . optimizaciones que típicamente no aumentan el tamaño del código también realiza otras optimizaciones diseñados para reducir el tamaño del código -Os desactiva los siguientes parámetros de optimización:. -falign-functions -falign-jumps -falign-loops -falign-labels -freorder-blocks -freorder-blocks-and-partition -fprefetch-loop-arrays -ftree-vect-loop-version)

también puede haber optimizaciones específicas de la plataforma, como @pauldoo notas, OS X tiene -Oz

+21

Si está desarrollando en Mac OS X, hay una configuración adicional '-Oz' que es' 'optimizar el tamaño de forma más agresiva que '-Os'": http://developer.apple.com/mac/library/DOCUMENTATION/DeveloperTools /gcc-4.0.1/gcc/Optimize-Options.html – pauldoo

+3

Nota: O3 no es necesariamente mejor que O2, incluso si el nombre lo sugiere. Prueba ambos. –

+1

página @pauldoo 404, reemplace con archive.org –

3

Cuatro (0-3): Ver el GCC 4.4.2 manual. Cualquier cosa más alta es solo -O3, pero en algún momento se desbordará el límite de tamaño variable.

+0

He explorado el código fuente [en mi respuesta] (http://stackoverflow.com/a/30308151/895245) y estoy de acuerdo con usted. Más pedante, GCC parece confiar en el comportamiento indefinido 'atoi', seguido por un límite interno' 255'. –

+0

Por favor, considere eliminar su respuesta, ya que es (al menos en estos días) incorrecta. – einpoklum

29

siete niveles distintos:

  • -O0 (por defecto): Sin optimización.

  • -O o -O1 (lo mismo): Optimice, pero no pase demasiado tiempo.

  • -O2: Optimizar de forma más agresiva

  • -O3: Optimizar la forma más agresiva

  • -Ofast: Equivalente a -O3 -ffast-math. -ffast-math desencadena optimizaciones de coma flotante no compatibles con los estándares. Esto le permite al compilador pretender que los números de punto flotante son infinitamente precisos, y que el álgebra en ellos sigue las reglas estándar del álgebra de números reales. También le dice al compilador que le diga al hardware que purgue los denormales a cero y trate los denormales como cero, al menos en algunos procesadores, incluidos x86 y x86-64. Los denormales desencadenan un camino lento en muchas FPU, por lo que tratarlos como cero (que no desencadena la ruta lenta) puede ser una gran ganancia de rendimiento.

  • -Os: Optimice el tamaño del código. Esto en realidad puede mejorar la velocidad en algunos casos, debido a un mejor comportamiento de I-caché.

  • -Og: Optimice, pero no interfiera con la depuración. Esto permite un rendimiento no embarazoso para las compilaciones de depuración y está destinado a reemplazar -O0 por compilaciones de depuración.

También hay otras opciones que no están habilitados por cualquiera de estos, y debe estar habilitado por separado. También es posible utilizar una opción de optimización, pero deshabilitar los indicadores específicos habilitados por esta optimización.

Para obtener más información, consulte el sitio web de GCC.

+0

De hecho, aunque para ser justos con las otras respuestas, ni -Ofast ni -Og existían cuando esas respuestas fueron escritas. – janneb

+0

¿Entonces por qué compila '-O100'? – einpoklum

+2

@einpoklum porque GCC considera que todo lo que está por encima de -O3 es igual a -O3. – Demi

25

Vamos a interpretar el código fuente de GCC 5.1 para ver qué pasa en -O100 ya que no está claro en la página de manual.

Vamos a la conclusión de que:

  • nada por encima de -O3 hasta INT_MAX es la misma que -O3, pero que fácilmente podría cambiar en el futuro, así que no confíe en él.
  • GCC 5.1 ejecuta un comportamiento indefinido si ingresa números enteros mayores que INT_MAX.
  • el argumento solo puede tener dígitos, o falla con elegancia. En particular, esto excluye enteros negativos como -O-1

Centrarse en subprogramas

En primer lugar recuerda que GCC es sólo un front-end para cpp, as, cc1, collect2. Un rápido ./XXX --help dice que solo collect2 y cc1 toman -O, así que centrémonos en ellos.

Y:

gcc -v -O100 main.c |& grep 100 

da:

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. 

por lo -O fue remitida a los dos cc1 y collect2.

O en common.opt

common.opt es una opción CLI formato de descripción específica GCC se describe en la internals documentation y traducido a C por opth-gen.awk y optc-gen.awk.

Contiene las siguientes líneas interesantes:

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 

que especifican todas las opciones O. Observe cómo -O<n> se encuentra en una familia separada de la otra Os, Ofast y Og.

Cuando construimos, esto genera un archivo options.h que contiene:

OPT_O = 139,        /* -O */ 
OPT_Ofast = 140,       /* -Ofast */ 
OPT_Og = 141,        /* -Og */ 
OPT_Os = 142,        /* -Os */ 

Como beneficio adicional, mientras que estamos grepping para \bO\n dentro common.opt nos damos cuenta de las líneas:

-optimize 
Common Alias(O) 

que nos enseña que --optimize (doble guión porque comienza con un guión -optimize en el archivo .opt) es un alias no documentado para -O que se puede utilizar como --optimize=3!

Cuando se utiliza OPT_O

Ahora GREP:

git grep -E '\bOPT_O\b' 

que nos señala dos archivos:

primera pista

Vamos hacia abajo opts.c

opts.c: default_options_optimization

Todos opts.c usos suceden en el interior: default_options_optimization.

Nos GrEP a retroceder para ver quién llama a esta función, y vemos que la única ruta de código es:

  • main.c:main
  • toplev.c:toplev::main
  • opts-global.c:decode_opts
  • opts.c:default_options_optimization

y main.c es el punto de entrada de cc1. ¡Bueno!

La primera parte de esta función:

  • hace integral_argument que exige atoi en la cuerda correspondiente a OPT_O para analizar el argumento de entrada
  • almacena el valor en el interior opts->x_optimize donde opts es una struct gcc_opts.

estructura gcc_opts

Después grepping en vano, nos damos cuenta de que este struct también se genera en options.h:

struct gcc_options { 
    int x_optimize; 
    [...] 
} 

donde x_optimize proviene de las líneas:

Variable 
int optimize 

prese nt de common.opt, y que options.c:

struct gcc_options global_options; 

así que supongo que esto es lo que contiene todo el estado de configuración global, y int x_optimize es el valor de optimización.

255 es una interna máxima

en opts.c:integral_argument, atoi se aplica al argumento de entrada, por lo INT_MAX es un límite superior. Y si pone algo más grande, parece que GCC ejecuta C comportamiento indefinido. ¿Ay?

integral_argument también envuelve delgadas atoi y rechaza el argumento si cualquier carácter no es un dígito. Entonces los valores negativos fallan con gracia.

Volver a opts.c:default_options_optimization, vemos la línea:

if ((unsigned int) opts->x_optimize > 255) 
    opts->x_optimize = 255; 

de manera que el nivel de optimización se trunca a 255.Durante la lectura de opth-gen.awk me había encontrado:

# All of the optimization switches gathered together so they can be saved and restored. 
# This will allow attribute((cold)) to turn on space optimization. 

y sobre la generada options.h:

struct GTY(()) cl_optimization 
{ 
    unsigned char x_optimize; 

que explica por qué el truncamiento: las opciones también deben enviarse a cl_optimization, que utiliza un char para ahorrar espacio . Entonces 255 es un máximo interno en realidad.

opts.c: maybe_default_options

Volver a opts.c:default_options_optimization, nos encontramos con maybe_default_options que suena interesante. Entramos en él, y luego maybe_default_option donde se llega a un gran cambio:

switch (default_opt->levels) 
    { 

    [...] 

    case OPT_LEVELS_1_PLUS: 
    enabled = (level >= 1); 
    break; 

    [...] 

    case OPT_LEVELS_3_PLUS: 
    enabled = (level >= 3); 
    break; 

No hay >= 4 cheques, lo que indica que 3 es la más grande posible.

Luego buscamos la definición de OPT_LEVELS_3_PLUS en 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. */ 
}; 

Ja! Este es un fuerte indicador de que solo hay 3 niveles.

opts.c: default_options_table

opt_levels es tan interesante, que GrEP OPT_LEVELS_3_PLUS, y encontramos 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 }, 
    [...] 
} 

por lo que este es el lugar donde el -On a la cartografía de optimización específica mencionada en el docs está codificado. ¡Bonito!

asegurar que no hay más usos para x_optimize

El uso principal de x_optimize era establecer otras opciones de optimización específicas como -fdefer_pop tal como se documenta en la página del manual. ¿Hay más?

We grep, y encuentre algunos más. El número es pequeño, y después de la inspección manual vemos que cada uso solo hace como máximo un x_optimize >= 3, por lo que nuestra conclusión es válida.

LTO-wrapper.c

Ahora vamos a por la segunda aparición de OPT_O, que estaba en lto-wrapper.c.

LTO significa Link Time Optimization, que como su nombre indica va a necesitar una opción -O, y se vinculará a collec2 (que básicamente es un enlazador).

De hecho, la primera línea de lto-wrapper.c dice:

/* Wrapper to call lto. Used by collect2 and the linker plugin. 

En este archivo, las ocurrencias OPT_O sólo parece normalizar el valor de O a pasarla hacia adelante, por lo que debe estar bien.

+1

Esta debería haber sido la respuesta aceptada. –

Cuestiones relacionadas