2011-10-06 11 views
18

Dado el siguiente código C++:Strange GCC Comportamiento

struct vertex_type { 
    float x, y, z; 

    //vertex_type() {} 
    //vertex_type(float x, float y, float z) : x(x), y(y), z(z) {} 
}; 

typedef struct { 
    vertex_type vertex[10000]; 
} obj_type; 

obj_type cube = { 
    { 
     {-1, -1, -1}, 
     {1, -1, -1}, 
     {-1, 1, -1}, 
     {1, 1, -1}, 

     {-1, -1, 1}, 
     {1, -1, 1}, 
     {-1, 1, 1}, 
     {1, 1, 1} 
    } 
}; 

int main() { 
    return 0; 
} 

Cuando añadí la (actualmente comentado) constructores en el vertex_type struct, abruptamente 10-15 segundos aumento en tiempo de compilación. Stumped, miré al ensamblado generado por gcc (usando -S) y noté que el tamaño del código gen era varios cientos de veces más grande que antes.

... 
movl $0x3f800000, cube+84(%rip) 
movl $0x3f800000, cube+88(%rip) 
movl $0x3f800000, cube+92(%rip) 
movl $0x00000000, cube+96(%rip) 
... 
movl $0x00000000, cube+119996(%rip) 
... 

Al omitir la definición del constructor, el ensamblaje generado fue completamente diferente.

.globl cube 
    .data 
    .align 32 
    .type cube, @object 
    .size cube, 120 
cube: 
    .long 3212836864 
    .long 3212836864 
    .long 3212836864 
    .long 1065353216 
    .long 3212836864 
    .long 3212836864 
    .long 3212836864 
    .long 1065353216 
    .long 3212836864 
    .long 1065353216 
    .long 1065353216 
    .long 3212836864 
    .long 3212836864 
    .long 3212836864 
    .long 1065353216 
    .long 1065353216 
    .long 3212836864 
    .long 1065353216 
    .long 3212836864 
    .long 1065353216 
    .long 1065353216 
    .long 1065353216 
    .long 1065353216 
    .long 1065353216 
    .zero 24 
    .text 

Obviamente, hay una diferencia significativa en el código generado por el compilador. ¿Por qué es eso? Además, ¿por qué gcc pone a cero todos los elementos en una situación y no en la otra?

edición: estoy usando las siguientes opciones del compilador: -std=c++0x con g ++ 4.5.2.

+0

Esto es una suposición descabellada, pero intente esto: tipo_vertex(): x(), y(), z() {} – Pubby

+4

@ AlfP.Steinbach Esto es EXACTAMENTE el código que tengo en mi archivo. No hay nada más. ¿Alguno de ustedes revisó el código? Tiene {}. Está en línea ... – dcousens

+3

@Alf los constructores en cuestión están comentados. – zwol

Respuesta

14

Esto es un antiguo missing optimization in GCC. Es debería ser capaz de generar el mismo código para ambos casos, pero no puede.

Sin los constructores, su vertex_type es una estructura POD, que GCC puede inicializar instancias estáticas/globales en tiempo de compilación. Con los constructores, lo mejor que puede hacer es generar código para inicializar el global al inicio del programa.

+1

Gracias por la información y el enlace, pero también ¿por qué pone a cero los elementos restantes en un caso y no en el otro? – dcousens

+0

Esta respuesta no es correcta. El código con el constructor ni siquiera debería compilarse. Ver mi respuesta – Nawaz

+0

@ Daniel que podría ser un error (no relacionado). Mi copia de g ++ 4.6.1 pone a cero los elementos restantes en ambos casos (y también las instrucciones * not * generate 9976 'movl' para completar los ceros - usa' .bss' para hacerlo implícitamente). No tengo gcc 4.5 a mano. – zwol

0

Si tiene un constructor personalizado, el compilador debe llamarlo para todos los vectores que cree. Si no escribes el tuyo propio, es un constructor generado por defecto. Pero como ningún tipo es complejo, simplemente no necesita llamarlo. Y la matriz se almacena como una tabla constante en el binario.

Intente alinear su constructor predeterminado y déjelo vacío. Por supuesto, solo puede funcionar con la optimización habilitada

+1

No es posible en línea un constructor predeterminado hasta donde yo sé. El código que publicó los constructores está implícitamente en línea. – Pubby

+0

Es posible usar la extensión del compilador como __forceinline en MSVC – crazyjul

Cuestiones relacionadas