2011-02-04 21 views
8

Mam kompilacji program C i porównując wygenerowany kod montaż:Dlaczego LLVM dodaje dwie dodatkowe instrukcje dla tego samego programu?

int main(){ return 0; } 

GCC daje tej funkcji main (cc hello.c -S):

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

LLVM daje tej funkcji 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: 

Do czego potrzebne są movl $0, -4(%rbp) i popq %rbp? Przeniesienie czegoś na stos i wyrzucenie go bezpośrednio potem wydaje mi się bezużyteczne.

+10

Wydaje się nieco niesprawiedliwe porównanie wydajności montażu kompilatorów bez korzystania z optymalizatora. –

Odpowiedz

9

Faktycznie, są one porównywalne. Urlop jest instrukcja wysoki poziom:

Z instrukcji 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. 

zasadzie urlopu odpowiada

movq %rbp, %rsp 
popq %rbp 
+1

Jak rozumiem, 'leave' nie jest ani droższy od identycznego' mov'/'pop', ale' enter' jest absurdalnie droższy niż "dodanie" do wskaźnika stosu. –

+0

To by wyjaśniało, dlaczego prawie nigdy nie widziałem, aby kompilator generował instrukcje 'enter' ... –

2

Wygląda LLVM jest przy użyciu tradycyjnych funkcji prolog/epilog, natomiast GCC jest wykorzystanie faktu, że punktem wyjścia nie musi oczyścić

+0

Ahah, więc GCC zawsze zakłada, że ​​główną funkcją jest punkt wyjścia, ale LLVM nie? –

+0

Nie, gcc wykorzystuje fakt, że treść funkcji była pusta. –

+3

Nie zgadzam się w obu przypadkach. 'eax' jest ustawiany, epilog nadal odbywa się przez' leave'. Najbardziej wydajną implementacją jest 'movl $ 0, $ eax' then' ret', nie zawracając sobie głowy stosem. Tak właśnie działa gcc na '-O3', który naprawdę korzysta z praktycznie pustej funkcji. Oba są porównywalne, choć nie wiem, jak drogie jest wyjście w porównaniu do mov/pop. –

9

Dyspozycja movl $0, -4(%rbp) jest martwy, bo to jest kod unoptimized. Spróbuj przekazać w obu kompilatorach: -O, aby zobaczyć, jakie zmiany.

+2

Chris szuka cytatów" kodu "podczas pisania bitów kodu. –

Powiązane problemy