diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 592ca9bfd319..fb7ee99fa28f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2020-05-15 Christophe Lyon + + * config/arm/arm.c (reg_needs_saving_p): Add support for interrupt + routines. + (arm_compute_save_reg0_reg12_mask): Use reg_needs_saving_p. + 2020-05-15 Tobias Burnus PR middle-end/94635 diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 3dab61459873..349918a9bfa6 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -4188,14 +4188,29 @@ arm_trampoline_adjust_address (rtx addr) return addr; } -/* Return 1 if REG needs to be saved. */ +/* Return 1 if REG needs to be saved. For interrupt handlers, this + includes call-clobbered registers too. If this is a leaf function + we can just examine the registers used by the RTL, but otherwise we + have to assume that whatever function is called might clobber + anything, and so we have to save all the call-clobbered registers + as well. */ static inline bool reg_needs_saving_p (unsigned reg) { - if (!df_regs_ever_live_p (reg) - || call_used_or_fixed_reg_p (reg)) - return false; + unsigned long func_type = arm_current_func_type (); + + if (IS_INTERRUPT (func_type)) + if (df_regs_ever_live_p (reg) + /* Save call-clobbered core registers. */ + || (! crtl->is_leaf && call_used_or_fixed_reg_p (reg) && reg < FIRST_VFP_REGNUM)) + return true; + else + return false; else - return true; + if (!df_regs_ever_live_p (reg) + || call_used_or_fixed_reg_p (reg)) + return false; + else + return true; } /* Return 1 if it is possible to return using a single instruction. @@ -20677,8 +20692,7 @@ arm_compute_save_reg0_reg12_mask (void) max_reg = 12; for (reg = 0; reg <= max_reg; reg++) - if (df_regs_ever_live_p (reg) - || (! crtl->is_leaf && call_used_or_fixed_reg_p (reg))) + if (reg_needs_saving_p (reg)) save_reg_mask |= (1 << reg); /* Also save the pic base register if necessary. */