5

(Using Apple LLVM version 8.1.0 (clang-802.0.42) Target: x86_64-apple-darwin16.6.0)

When disassembling some code compiled with -O2, I noticed that a lot of them have a seemingly unnecessary saving and restoring of the base pointer rbp, usually looking like the following

pushq %rbp
movq  %rsp, %rbp
...
popq  %rbp

I know what this would be for, but it seems to be used even in situations where it seems completely unnecessary, such as in the following disassembled convoluted identity function emited by objdump

__Z8identityI5arrayIiLm2EEET_S2_:
  60:   55  pushq   %rbp
  61:   48 89 e5    movq    %rsp, %rbp
  64:   48 89 f8    movq    %rdi, %rax
  67:   5d  popq    %rbp
  68:   c3  retq
  69:   0f 1f 80 00 00 00 00    nopl    (%rax)

where the only two meaningful instructions are the move from rdi to rax (first argument to return register) and the obviously necessary retq (I assume the nopl is for padding or alignment for whatever follows).

Is there a reason for this seemingly unnecessary context save?

Ross Ridge
  • 38,414
  • 7
  • 81
  • 112
Mona the Monad
  • 2,265
  • 3
  • 19
  • 30
  • 1
    It may be there to help debuggers/profilers/etc, since they need to be able to walk the call chain. Try [`-fomit-frame-pointer`](https://stackoverflow.com/q/14666665/253056) and see if the boilerplate code goes away. (Or it may just be that you have `-fno-omit-frame-pointer` in your build settings.) – Paul R Jun 15 '17 at 15:37
  • 2
    Maybe Apple ABI mandates the use of frames, e.g. for exception handling? PS: `-O2` should already enable `-fomit-frame-pointer` on any recent gcc version, but maybe not on clang. – Jester Jun 15 '17 at 15:38
  • @Jester: you're right, both gcc and clang default to `-fomit-frame-pointer` when compiling for x86-64 at `-O2` and above. I'm wondering if OP's code was compiled with `-fno-omit-frame-pointer` ? – Paul R Jun 15 '17 at 15:42
  • `-fomit-frame-pointer` does seem to remove the "unnecessary" frame pointer. Also, the only flags I used were `-m64 -std=c++1z -O2 -fno-inline`. – Mona the Monad Jun 15 '17 at 15:44
  • Also, it somewhat makes sense that the saved frame pointer could be for debuggers or exception handling and such, but why enable it even with `-O2` on? Shouldn't it be a thing for `-Og` or something? – Mona the Monad Jun 15 '17 at 15:52
  • @AliciaRose: profiling tools can have a hard time unwinding the stack without any stack frames, and you would normally use such tools with optimised code. Having said that, it may be a peculiarity of Apple's clang, since both gcc and clang normally default to omitting the frame pointer where possible, as noted above. – Paul R Jun 15 '17 at 15:54
  • 1
    This seems similar to this frame pointer OS/X question: https://stackoverflow.com/questions/43792447/assembled-c-appears-to-contain-superfluous-instructions – Michael Petch Jun 15 '17 at 17:11
  • 1
    @Jester If the use of frames is mandated for exception handling, that's even more reason to optimize this away without the heavy hammer of `-fomit-frame-pointer`. This is a leaf function that doesn't throw. No unwinding should be initiated from this function; the only exit path is the `retq` instruction. A profiling tool based on interrupting the code with a timer might have a hard time without the frame pointers. In the case of this type of leaf function, the tool will just see the original frame, since `%rbp` hasn't moved, so there is no real problem. – Kaz Jun 15 '17 at 17:46

0 Answers0