Created attachment 28939 [details] preprocessed test program On x86_64 linux, with -fno-omit-frame-pointer and -O1, gcc 4.7.x (verified for 4.7.0 and 4.7.2) allow the frame pointer (rbp) push instruction to wander away from the beginning of a function. As a result, profiling tools including perf and OProfile determine incorrect call chains, and subsequent calculations of call graphs and total time are wrong. The problem does not occur if any of the following are true: -O0 instead of -O1 -m32 instead of -m64 gcc 4.6.3 instead of 4.7.x The preprocessed source of a small program to demonstrate the problem is attached. Example output from the profiling tools and various versions of gcc, as well as the original small program, was sent to the oprofile-list at 2012-12-12 13:45 EST, but the list archive is presently unreachable, so email me for a copy if needed.
Created attachment 28940 [details] log of build of test program
N.B., in the test program, the problem occurs in fn2 but not fn1.
It's a feature. Unwind information is now correctly produced for the prologue which means we can (finally) schedule it freely. You can try -fno-schedule-insns2.
Realize this is a very old thread, but I came across it via https://news.ycombinator.com/item?id=34803759 (Frame pointers vs. DWARF) and wanted to chime in. There's been ongoing interest in compact unwind information, with relevant discussions like: https://discourse.llvm.org/t/rfc-improving-compact-x86-64-compact-unwind-descriptors/47471/23 https://sourceware.org/pipermail/binutils/2025-November/145523.html (Regarding "More compact SFrames through deduplication") Regularizing prologue and epilogue code seems key to making unwind format smaller (better deduplication or amenable to be described by a small opcode) Once GCC implements a compact unwind format, instruction rescheduling in the prologue should ideally not be necessary, even without specifying -fno-schedule-insns2. --- Simplified "Created attachment 28939 [details]" in #c0 #include <stdio.h> #include <stdint.h> uint64_t accumulator=1; double adder=0; void fn2() __attribute__((noinline,optimize("no-optimize-sibling-calls"))); void fn2() { for (uint64_t looper=0; looper<100000000; ++looper) adder += 3.14159265358979323846*3, accumulator = accumulator*3 + adder; } int main() { fn2(); printf ("%" "l" "u" " %f\n", accumulator, adder); return 0; } gcc -O2 -fno-omit-frame-pointer output contains "main": push rbp mov edi, OFFSET FLAT:.LC2 mov rbp, rsp
I still don't see why a compact unwind format can't handle this. Plus I am not sure the ABI will/can be changed to support a new unwind format. It would require a flag day which which will not happen any time soon. And then all distros need to support it all the same time etc.
(In reply to Fangrui Song from comment #4) > > https://sourceware.org/pipermail/binutils/2025-November/145523.html > (Regarding "More compact SFrames through deduplication") > > Regularizing prologue and epilogue code seems key to making unwind format > smaller (better deduplication or amenable to be described by a small opcode) > SFrame does not track all callee-saved registers. So this is not required for SFrame or further compact derivatives thereof.