https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77904
Bug ID: 77904 Summary: [ARM Cortex-M0] Frame pointer thrashes registers if assembly statements with "sp" clobber are used Product: gcc Version: 6.2.0 Status: UNCONFIRMED Severity: critical Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: freddie_chopin at op dot pl Target Milestone: --- Target: arm-none-eabi In some very specific cases frame pointer can thrash caller's r7 (frame pointer) register. The following test case demonstrates the problem. ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- $ cat test.cpp void removeStackFrame(const void* const savedStackPointer) { __asm volatile ("MSR psp, %0\n" : : "r" (savedStackPointer) : "sp"); } $ arm-none-eabi-gcc -mcpu=cortex-m0 -mthumb -O2 test.cpp -c $ arm-none-eabi-objdump -S test.o test.o: file format elf32-littlearm Disassembly of section .text: 00000000 <_Z16removeStackFramePKv>: 0: af00 add r7, sp, #0 2: f380 8809 msr PSP, r0 6: 46bd mov sp, r7 8: 4770 bx lr a: 46c0 nop ; (mov r8, r8) ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- 8< ---- As you can see in this particular function the frame pointer thrashes caller's r7, which should be saved on stack and restored before returning. In this test case this seems to be caused by the "sp" clobber in the assembly statement (this particular line comes from CMSIS headers for ARM Cortex-M microcontrollers) - if I remove this clobber, then the frame pointer is omitted and the problem is gone, but this can hardly be considered a solution... This is somehow specific only to ARM Cortex-M0 - selecting ARM Cortex-M4 ("-mcpu=cortex-m4") causes r7 to be pushed to the stack. This is not related to optimization level, as the same behaviour can be observed on all optimization levels. Using "-fomit-frame-pointer" doesn't change anything, but doing the opposite "-fno-omit-frame-pointer" - causes r7 to be stacked. This problem was not present on GCC 5.3.1 (at least on the version with ARM patches) - with that version the frame pointer was omitted. Currently I'm observing this problem on almost clean GCC 6.2.0 - the only change is the multilib configuration.