As noted in fixed_reg_p comment

/* Return whether REG is a global user reg or has been specifed by
   -ffixed-REG.  We should not restore these, and so cannot use
   lmw or out-of-line restore functions if there are any.  We also
   can't save them (well, emit frame notes for them), because frame
   unwinding during exception handling will restore saved registers.  */

        * config/rs6000/rs6000.c (rs6000_savres_strategy): Don't restore
        fixed regs.

Bootstrapped and regression tested powerpc64-linux (-m32 too) and
powerpc64le-linux.  OK?

diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 74158cd..b628808 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -24309,6 +24309,7 @@ rs6000_savres_strategy (rs6000_stack_t *info,
                        bool using_static_chain_p)
 {
   int strategy = 0;
+  int i;
 
   /* Select between in-line and out-of-line save and restore of regs.
      First, all the obvious cases where we don't use out-of-line.  */
@@ -24383,6 +24384,17 @@ rs6000_savres_strategy (rs6000_stack_t *info,
                 | SAVE_INLINE_GPRS
                 | SAVE_INLINE_VRS);
 
+  /* Don't ever restore fixed regs.  That means we can't use the
+     out-of-line register restore functions if a fixed reg is in the
+     range of regs restored.   */
+  if (!(strategy & REST_INLINE_FPRS))
+    for (i = info->first_fp_reg_save; i < 64; i++)
+      if (fixed_regs[i])
+       {
+         strategy |= REST_INLINE_FPRS;
+         break;
+       }
+
   /* We can only use the out-of-line routines to restore fprs if we've
      saved all the registers from first_fp_reg_save in the prologue.
      Otherwise, we risk loading garbage.  Of course, if we have saved
@@ -24390,10 +24402,8 @@ rs6000_savres_strategy (rs6000_stack_t *info,
   if ((strategy & SAVE_INLINE_FPRS)
       && !(strategy & REST_INLINE_FPRS))
     {
-      int i;
-
       for (i = info->first_fp_reg_save; i < 64; i++)
-       if (fixed_regs[i] || !save_reg_p (i))
+       if (!save_reg_p (i))
          {
            strategy |= REST_INLINE_FPRS;
            break;
@@ -24401,13 +24411,19 @@ rs6000_savres_strategy (rs6000_stack_t *info,
     }
 
   /* Similarly, for altivec regs.  */
+  if (!(strategy & REST_INLINE_VRS))
+    for (i = info->first_altivec_reg_save; i < LAST_ALTIVEC_REGNO + 1; i++)
+      if (fixed_regs[i])
+       {
+         strategy |= REST_INLINE_VRS;
+         break;
+       }
+
   if ((strategy & SAVE_INLINE_VRS)
       && !(strategy & REST_INLINE_VRS))
     {
-      int i;
-
       for (i = info->first_altivec_reg_save; i < LAST_ALTIVEC_REGNO + 1; i++)
-       if (fixed_regs[i] || !save_reg_p (i))
+       if (!save_reg_p (i))
          {
            strategy |= REST_INLINE_VRS;
            break;
@@ -24467,6 +24483,16 @@ rs6000_savres_strategy (rs6000_stack_t *info,
          }
     }
 
+  /* Don't ever restore fixed regs.  */
+  if ((strategy & (REST_INLINE_GPRS | REST_MULTIPLE)) != REST_INLINE_GPRS)
+    for (i = info->first_gp_reg_save; i < 32; i++)
+      if (fixed_reg_p (i))
+       {
+         strategy |= REST_INLINE_GPRS;
+         strategy &= ~REST_MULTIPLE;
+         break;
+       }
+
   /* We can only use load multiple or the out-of-line routines to
      restore gprs if we've saved all the registers from
      first_gp_reg_save.  Otherwise, we risk loading garbage.
@@ -24475,10 +24501,8 @@ rs6000_savres_strategy (rs6000_stack_t *info,
   if ((strategy & (SAVE_INLINE_GPRS | SAVE_MULTIPLE)) == SAVE_INLINE_GPRS
       && (strategy & (REST_INLINE_GPRS | REST_MULTIPLE)) != REST_INLINE_GPRS)
     {
-      int i;
-
       for (i = info->first_gp_reg_save; i < 32; i++)
-       if (fixed_reg_p (i) || !save_reg_p (i))
+       if (!save_reg_p (i))
          {
            strategy |= REST_INLINE_GPRS;
            strategy &= ~REST_MULTIPLE;

-- 
Alan Modra
Australia Development Lab, IBM

Reply via email to