https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114097
Bug ID: 114097 Summary: Missed register optimization in _Noreturn functions Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c Assignee: unassigned at gcc dot gnu.org Reporter: pskocik at gmail dot com Target Milestone: --- Consider a never-returning functions such as this: #include<setjmp.h> #include<stdio.h> //_Noreturn void noret(unsigned A, unsigned B, unsigned C, unsigned D, unsigned E, jmp_buf Jb){ for(;A--;) puts("A"); for(;B--;) puts("B"); for(;C--;) puts("C"); for(;D--;) puts("D"); for(;E--;) puts("E"); longjmp(Jb,1); } https://godbolt.org/z/35YjrhjYq In its prologue, gcc saves the arguments in call-preserved registers to preserve them around the puts calls, and it does so the usual way: by (1) pushing the old values of the call-preserved registers to the stack and (2) actually moving the arguments into the call-preserved registers. pushq %r15 movq %r9, %r15 pushq %r14 movl %edi, %r14d pushq %r13 movl %esi, %r13d pushq %r12 movl %edx, %r12d pushq %rbp movl %ecx, %ebp pushq %rbx movl %r8d, %ebx pushq %rax //... Since this function demonstrably never returns, step 1 can be entirely elided as the old values of the call-preserved registers won't ever need to be restored (desirably, gcc does not generate the would-be-dead restoration code): movq %r9, %r15 movl %edi, %r14d movl %esi, %r13d movl %edx, %r12d movl %ecx, %ebp movl %r8d, %ebx pushq %rax //... (Also desirable would be the unrealized tailoptimization of the longjmp call in this case: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=10837)