A stack register keeps track of the top of the call stack. The value stored in the stack register is called the stack pointer.
Frame Register
Since the stack pointer may change during execution (e.g., due to push/pop operations), a separate register is used to refer to a stable location on the stack. The frame register (whose value is called the frame pointer or base pointer) always points to the start of the current function frame.
Frame Pointer Omission (FPO)
Some compiler backends can generate code that omits the frame pointer (a technique known as frame pointer omission), reducing code size for function calls and freeing up an additional register for general-purpose use.
Omitting the frame pointer can hinder debugging, so it is typically enabled only in optimized builds.
Recently, there has been a trend to re-enable frame pointers even in release mode:
- the ABI on macOS requires maintaining frame pointers
- certain popular Linux distributions like Ubuntu, Fedora and Arch are reenabling frame pointers in recent distributions 1 2 3
The performance impact of re-enabling frame pointers is generally minimal on modern platforms, partly due to modern CPUs having much more registers than 32-bit x86 (which only has 4 general purpose registers). 3
Enabled frame pointers has the benefit of better tooling. In particular, tools like perf
uses frame pointers to unwind the stack and get an accurate stack trace, so enable frame pointers can also help performance tuning. 2