2011-02-04 7 views
8

Sto compilando questo programma C e confrontando il codice assembly generato:Perché LLVM aggiunge due istruzioni aggiuntive per lo stesso programma?

int main(){ return 0; } 

GCC dà questa funzione main (cc hello.c -S):

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

LLVM dà questa funzione main (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: 

Cosa sono necessari per movl $0, -4(%rbp) e popq %rbp? Spostare qualcosa in pila e scoccarlo subito dopo sembra inutile per me.

+10

Sembra un po 'ingiusto confrontare l'output dell'assieme dei compilatori senza utilizzare l'ottimizzatore. –

risposta

9

In realtà, sono comparabili. Il congedo è un'istruzione di alto livello:

Dal manuale 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. 

in fondo, il congedo è equivalente a

movq %rbp, %rsp 
popq %rbp 
+1

A quanto ho capito, 'leave' non è più o meno costoso dell'identico' mov'/'pop', ma' enter' è ridicolmente più costoso di un semplice 'add "al puntatore dello stack. –

+0

Questo spiegherebbe perché non ho quasi mai visto un compilatore produrre istruzioni 'enter' ... –

2

Sembra LLVM sta usando una funzione tradizionale prologo/epilogo, mentre GCC sta approfittando del fatto che il punto di ingresso non ha bisogno di ripulire

+0

Ahah, quindi GCC presume sempre che la funzione principale sia il punto di partenza, ma LLVM no? –

+0

No, gcc sta sfruttando il fatto che il corpo della funzione era vuoto. –

+3

Non sono d'accordo su entrambi i fronti. 'eax' viene impostato, l'epilogo avviene ancora tramite' leave'. L'implementazione più efficiente è 'movl $ 0, $ eax' quindi' ret', senza preoccuparsi dello stack. Ecco cosa fa gcc su "-O3", che sta veramente sfruttando una funzione praticamente vuota. Come è, i due sono paragonabili, anche se non so quanto sia costoso il congedo rispetto a mov/pop. –

9

L'istruzione movl $0, -4(%rbp) è morto, perché questo è il codice non ottimizzato. Prova a passare -O in entrambi i compilatori per vedere quali modifiche.

+2

Chris cerca le citazioni" codice "quando scrivi bit di codice. –

Problemi correlati