https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115853
Bug ID: 115853 Summary: Unnecessary push to stack in __attribute((noreturn)) Reset_Handler(), leading to permanent wasted SRAM Product: gcc Version: 13.3.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: rlcamp.pdx at gmail dot com Target Milestone: --- The following code: extern int main(void); __attribute__((noreturn)) static void Reset_Handler(void) { /* usual setup stuff omitted */ main(); while (1) asm volatile("wfi" :::); __builtin_unreachable(); } void (* exception_table[])(void) = { Reset_Handler }; when compiled with (version 13.3.1, or any other version afaict) arm-none-eabi-gcc -Os -mcpu=cortex-m4, produces the following instructions (copied and pasted from https://c.godbolt.org/z/dPGWe1jKf, but initially observed in the wild): Reset_Handler: push {r3, lr} bl main .L2: wfi b .L2 exception_table: .word Reset_Handler The push of two registers to the stack causes the call stack to be 8 bytes deeper than necessary, forever, which in some use cases on chips with small SRAM can be significant. There doesn't seem to be any valid code path which would lead to use of those values, and they are likely to be garbage values anyway. Notably, in more complicated Reset_Handler code, the absence of __attribute((noreturn)) DOES result in more registers being pushed to the stack vs when it is present, so the compiler is definitely acknowledging the attribute, but it is not applying all of the optimization it is entitled to do.