1

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)

1201ProgramAlarm
  • 32,384
  • 7
  • 42
  • 56
Saksham Jain
  • 537
  • 3
  • 14
  • So, what is your question? Looks like you already figured out everything by yourself. – Anton Korobeynikov Dec 23 '20 at 10:00
  • My question is, this is not the behavior I expect. Why is llc not removing the frame pointer code when it says it has optimization to remove it? And what are other optimizations which llc can't do but clang can? I am not very familiar with compiler optimizations. – Saksham Jain Dec 23 '20 at 15:58
  • @SakshamJain It is possible that the LLVM byte code has a flag somewhere that says if the FP may be eliminated if possible. – fuz Dec 23 '20 at 17:21

1 Answers1

3

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.

Saksham Jain
  • 537
  • 3
  • 14