See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117366 where it was suggested I send this bug fix as a patch to gcc-patches. I have never submitted to this alias so I apologize if I am not "doing it right", but here is the diff, and the Bugzilla ticket has an example written up with good/bad assembler code output. As the ticket notes, it has been a problem for years and should be backported to the latest bugfix releases of older supported versions as well. This patch reference is for master as of today, but the base code is the same since gcc 10. index bde06f3fa86..d6d8d720b67 100644 --- a/gcc/config/arm/arm.cc +++ b/gcc/config/arm/arm.cc @@ -26747,7 +26747,7 @@ thumb1_extra_regs_pushed (arm_stack_offsets *offsets, bool for_prologue) } while (reg_base + n_free < 8 && !(live_regs_mask & 1) - && (for_prologue || call_used_or_fixed_reg_p (reg_base + n_free))) + && (for_prologue || (call_used_or_fixed_reg_p (reg_base + n_free) && !fixed_reg[reg_base + n_free]))) { live_regs_mask >>= 1; n_free++;