Why does LLVM add two extra instructions for the same program?
Asked Answered
D

3

7

I am compiling this C program and comparing the generated assembly code:

int main(){ return 0; }

GCC gives this main function (cc hello.c -S):

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

LLVM gives this main function (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:

What are movl $0, -4(%rbp) and popq %rbp needed for? Moving something on the stack and popping it directly afterwards seems useless to me.

Daughtry answered 4/2, 2011 at 23:25 Comment(1)
It seems a little unfair to compare compilers' assembly output without using the optimizer.Tremann
P
8

Actually, they're comparable. Leave is a high level instruction:

From the Intel manual:

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.

basically, leave is equivalent to

movq %rbp, %rsp
popq %rbp
Ptosis answered 4/2, 2011 at 23:52 Comment(2)
As I understand it, leave isn't more or less expensive than the identical mov/pop, but enter is ridiculously more expensive than just add ing to the stack pointer.Sottish
That would explain why I've almost never seen a compiler produce enter instructions...Ptosis
F
9

The movl $0, -4(%rbp) instruction is dead, because this is unoptimized code. Try passing in -O to both compilers to see what changes.

Fabrication answered 5/2, 2011 at 15:9 Comment(1)
Chris look for the "code" quotations when you write bits of code.Hive
P
8

Actually, they're comparable. Leave is a high level instruction:

From the Intel manual:

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.

basically, leave is equivalent to

movq %rbp, %rsp
popq %rbp
Ptosis answered 4/2, 2011 at 23:52 Comment(2)
As I understand it, leave isn't more or less expensive than the identical mov/pop, but enter is ridiculously more expensive than just add ing to the stack pointer.Sottish
That would explain why I've almost never seen a compiler produce enter instructions...Ptosis
D
2

It looks like LLVM is using a traditional function prolog/epilog, whereas GCC is taking advantage of the fact that the entry point doesn't need to clean up

Disincline answered 4/2, 2011 at 23:31 Comment(6)
Ahah, so GCC always assumes my the main function is the starting point, but LLVM does not?Daughtry
No, gcc is taking advantage of the fact that the function body was empty.Pidgin
I disagree on both counts. eax is being set, the epilog still happens via leave. The most efficient implementation is movl $0, $eax then ret, not bothering with the stack at all. That's what gcc does on -O3, which is truly taking advantage of a practically empty function. As is, the two are comparable, although I don't know how expensive leave is compared to mov/pop.Ptosis
leave used to be much more expensive than mov/pop. I'm not sure what the status is now -- I imagine it has a lot to do with which specific core you're dealing with. To be fair enter/leave also does more than mov/push/pop/etc. will. Specifically they cover nested procedures with a single high-level instruction (something not needed for the C blight).Bibb
@Matt Joiner: I'm not a huge fan of the BCPL-descended branch of the computer language tree. ;)Bibb
The only notable derivative of BCPL is C, so I presume you don't like anything derived from C? C++, Java, C#, PHP etc.?Hive

© 2022 - 2024 — McMap. All rights reserved.