arm: Add support for interrupt routines to reg_needs_saving_p
authorChristophe Lyon <christophe.lyon@linaro.org>
Mon, 4 May 2020 13:42:03 +0000 (13:42 +0000)
committerChristophe Lyon <christophe.lyon@linaro.org>
Fri, 15 May 2020 09:57:57 +0000 (09:57 +0000)
reg_needs_saving_p is only used when dealing with non-interrupt
routines, but it makes sense to extend it to support that context too,
and make arm_compute_save_reg0_reg12_mask use it.

Save only live registers for non-leaf functions, but assume a callee
could clobber any register.

2020-05-15  Christophe Lyon  <christophe.lyon@linaro.org>

gcc/
* config/arm/arm.c (reg_needs_saving_p): Add support for interrupt
routines.
(arm_compute_save_reg0_reg12_mask): Use reg_needs_saving_p.

gcc/ChangeLog
gcc/config/arm/arm.c

index 592ca9bfd31919ec0b26dd9fd161cd4d22682fd0..fb7ee99fa28f9313645711d3ebe0afbaed4c9fb3 100644 (file)
@@ -1,3 +1,9 @@
+2020-05-15  Christophe Lyon  <christophe.lyon@linaro.org>
+
+        * 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  <tobias@codesourcery.com>
 
        PR middle-end/94635
index 3dab6145987395817bac42b7ebf4dc745a99cae2..349918a9bfa60bb8fbba7e3b4a213a1aa83e997e 100644 (file)
@@ -4188,14 +4188,29 @@ arm_trampoline_adjust_address (rtx addr)
   return addr;
 }
 \f
-/* 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.  */