Can LLC -O=3 not omit frame pointers from unoptimized llvm bytecode produced by clang -O0?

331 Views Asked by At

I have a simple c code:

// main.c
#include <stdio.h>
void foo()
{ 
}

int main()
{
    return 0;
}

Output of following command

clang -O3 -emit-llvm -c main.c -o main.bc; llc main.bc -o main.S; cat main.S;

I get:

...
foo:                                    # @foo
        .cfi_startproc
# %bb.0:
        retq
...

This is what is expected. The foo() function has been converted to retq instruction.

But if I run the following command:

clang -emit-llvm -c main.c -o main.bc; llc -O=3 main.bc -o main.S; cat main.S;

I get:

...
foo:                                    # @foo
        .cfi_startproc
# %bb.0:
        pushq   %rbp
        .cfi_def_cfa_offset 16
        .cfi_offset %rbp, -16
        movq    %rsp, %rbp
        .cfi_def_cfa_register %rbp
        popq    %rbp
        .cfi_def_cfa %rsp, 8
        retq
...

Functionally this is okay but foo() in this case is unnecessary dealing with frame-pointer for an empty function. The difference between first case and second case is that in first case, we used -O3 for clang whereas in second case we used -O3 for llc. I would thought these two to be equivalent.

I also tried the following:

clang -emit-llvm -fomit-frame-pointer -c main.c -o main.bc ; llc -O=3 main.bc -o main.S; cat main.S;

And I get:

...
foo:                                    # @foo
        .cfi_startproc
# %bb.0:
        retq
...

So, does this means if clang decides to emit frame pointers into the LLVM bytecode, llc is not smart enough to remove them? (llc doesn't seem to have a -fomit-frame-pointer option though it does have -disable-fp-elim option which Disable frame pointer elimination optimization so I would think llc is capable to eliminating frame pointers)

1

There are 1 best solutions below

0
Saksham Jain On

Thanks to @fuz

It seems clang adds attributes in the bitcode which disables/enables frame pointer elimination

When compiled with -O0, these are the attributes in the bitcode:

attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }

When compiled with -O3, these are the attributes:

attributes #0 = { norecurse nounwind readnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }

See that the value of no-frame-pointer-elim differs in both.