2011-02-04 12 views
8

Estoy compilando este programa C y comparar el código de ensamblado generado:¿Por qué LLVM agrega dos instrucciones adicionales para el mismo programa?

int main(){ return 0; } 

GCC da esta función principal (cc hello.c -S):

_main: 
LFB2: 
    pushq %rbp 
LCFI0: 
    movq %rsp, %rbp 
LCFI1: 
    movl $0, %eax 
    leave 
    ret 

LLVM da esta función principal (clang hello.c -S):

_main: 
Leh_func_begin0: 
    pushq %rbp 
Ltmp0: 
    movq %rsp, %rbp 
Ltmp1: 
    movl $0, %eax 
    movl $0, -4(%rbp) 
    popq %rbp 
    ret 
Leh_func_end0: 

¿Para qué se necesitan movl $0, -4(%rbp) y popq %rbp? Mover algo en la pila y abrirlo directamente después me parece inútil.

+10

Parece un poco injusto comparar la salida del conjunto de compiladores sin usar el optimizador. –

Respuesta

9

En realidad, son comparables. Dejar es una instrucción de alto nivel:

Desde el manual de Intel:

16-bit: C9 LEAVE A Valid Valid Set SP to BP, then pop BP. 
32-bit: C9 LEAVE A N.E. Valid Set ESP to EBP, then pop EBP. 
64-bit: C9 LEAVE A Valid N.E. Set RSP to RBP, then pop RBP. 

básicamente, la licencia es equivalente a

movq %rbp, %rsp 
popq %rbp 
+1

Según tengo entendido, 'leave' no es más o menos costoso que el' mov'/'pop' idéntico, pero' enter' es ridículamente más caro que simplemente 'agregar' al puntero de la pila. –

+0

Eso explicaría por qué casi nunca he visto un compilador producir instrucciones 'enter' ... –

2

Parece que LLVM está utilizando una función tradicional prólogo/epílogo, mientras que GCC está tomando ventaja del hecho de que el punto de entrada no necesita limpiar

+0

Ahah, entonces GCC siempre asume que la función principal es el punto de partida, pero LLVM no? –

+0

No, gcc aprovecha el hecho de que el cuerpo de la función estaba vacío. –

+3

No estoy de acuerdo en ambos aspectos. 'eax' se está configurando, el epilog aún pasa por' leave'. La implementación más eficiente es 'movl $ 0, $ eax' y luego' ret', sin molestar en absoluto con la pila. Eso es lo que hace gcc en '-O3', que realmente se aprovecha de una función prácticamente vacía. Como es, los dos son comparables, aunque no sé qué tan caro es la licencia en comparación con mov/pop. –

9

La instrucción movl $0, -4(%rbp) está muerto, porque este es el código no optimizado. Intente pasar -O a ambos compiladores para ver qué cambios.

+2

Chris busca las citas de "código" cuando escribes bits de código. –

Cuestiones relacionadas