caller-save.c (insert_save_restore): Break this function up into new functions insert...
authorJeff Law <law@gcc.gnu.org>
Fri, 2 Oct 1998 10:25:57 +0000 (04:25 -0600)
committerJeff Law <law@gcc.gnu.org>
Fri, 2 Oct 1998 10:25:57 +0000 (04:25 -0600)

* caller-save.c (insert_save_restore): Break this function up
into new functions insert_restore, insert_save and insert_one_insn.
All callers changed.
(insert_restore): New function, mostly broken out of
insert_save_restore.
(insert_save): Likewise.
(insert_one_insn): Likewise.
(restore_referenced_regs): New argument BLOCK.  All callers changed.
(save_call_clobbered_regs): Don't keep track of basic block boundaries
in this function, do it in insert_one_insn instead.

From-SVN: r22754

gcc/caller-save.c

index 60011f7..acb9ba4 100644 (file)
@@ -82,9 +82,14 @@ int n_regs_saved;
 
 static void set_reg_live               PROTO((rtx, rtx));
 static void clear_reg_live             PROTO((rtx));
-static void restore_referenced_regs    PROTO((rtx, rtx, enum machine_mode));
-static int insert_save_restore         PROTO((rtx, int, int,
+static void restore_referenced_regs    PROTO((rtx, rtx, enum machine_mode,
+                                              int));
+static int insert_restore              PROTO((rtx, int, int,
+                                              enum machine_mode, int, int));
+static int insert_save                 PROTO((rtx, int, int,
                                               enum machine_mode, int));
+static void insert_one_insn            PROTO((rtx, int, enum rtx_code,
+                                              enum machine_mode, rtx, int));
 \f
 /* Initialize for caller-save.
 
@@ -358,7 +363,6 @@ save_call_clobbered_regs (insn_mode)
   for (b = 0; b < n_basic_blocks; b++)
     {
       regset regs_live = basic_block_live_at_start[b];
-      rtx prev_block_last = PREV_INSN (basic_block_head[b]);
       int i, j;
       int regno;
 
@@ -399,7 +403,7 @@ save_call_clobbered_regs (insn_mode)
                 any of them.  We must restore them before the insn if so.  */
 
              if (n_regs_saved)
-               restore_referenced_regs (PATTERN (insn), insn, insn_mode);
+               restore_referenced_regs (PATTERN (insn), insn, insn_mode, b);
 
              /* NB: the normal procedure is to first enliven any
                 registers set by insn, then deaden any registers that
@@ -449,8 +453,7 @@ save_call_clobbered_regs (insn_mode)
                        /* It must not be set by this instruction.  */
                        && ! TEST_HARD_REG_BIT (this_call_sets, regno)
                        && ! TEST_HARD_REG_BIT (hard_regs_saved, regno))
-                     regno += insert_save_restore (insn, 1, regno, 
-                                                   insn_mode, 0);
+                     regno += insert_save (insn, 1, regno, insn_mode, b);
 
                  /* Put the information for this CALL_INSN on top of what
                     we already had.  */
@@ -489,13 +492,9 @@ save_call_clobbered_regs (insn_mode)
       if (n_regs_saved)
        for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
          if (TEST_HARD_REG_BIT (hard_regs_need_restore, regno))
-           regno += insert_save_restore ((GET_CODE (insn) == JUMP_INSN
-                                 ? insn : NEXT_INSN (insn)), 0,
-                                 regno, insn_mode, MOVE_MAX / UNITS_PER_WORD);
-
-      /* If we added any insns at the start of the block, update the start
-        of the block to point at those insns.  */
-      basic_block_head[b] = NEXT_INSN (prev_block_last);
+           regno += insert_restore (insn, GET_CODE (insn) == JUMP_INSN,
+                                    regno, insn_mode,
+                                    MOVE_MAX / UNITS_PER_WORD, b);
     }
 }
 
@@ -562,10 +561,11 @@ clear_reg_live (reg)
    INSN_MODE is the mode to assign to any insns that we add.  */
 
 static void
-restore_referenced_regs (x, insn, insn_mode)
+restore_referenced_regs (x, insn, insn_mode, block)
      rtx x;
      rtx insn;
      enum machine_mode insn_mode;
+     int block;
 {
   enum rtx_code code = GET_CODE (x);
   char *fmt;
@@ -584,11 +584,11 @@ restore_referenced_regs (x, insn, insn_mode)
       if (regno >= FIRST_PSEUDO_REGISTER
          && reg_equiv_mem[regno] != 0)
        restore_referenced_regs (XEXP (reg_equiv_mem[regno], 0),
-                                insn, insn_mode);
+                                insn, insn_mode, block);
       else if (regno >= FIRST_PSEUDO_REGISTER
               && reg_equiv_address[regno] != 0)
        restore_referenced_regs (reg_equiv_address[regno],
-                                insn, insn_mode);
+                                insn, insn_mode, block);
 
       /* Otherwise if this is a hard register, restore any piece of it that
         is currently saved.  */
@@ -597,13 +597,13 @@ restore_referenced_regs (x, insn, insn_mode)
        {
          int numregs = HARD_REGNO_NREGS (regno, GET_MODE (x));
          /* Save at most SAVEREGS at a time.  This can not be larger than
-            MOVE_MAX, because that causes insert_save_restore to fail.  */
+            MOVE_MAX, because that causes insert_restore to fail.  */
          int saveregs = MIN (numregs, MOVE_MAX / UNITS_PER_WORD);
          int endregno = regno + numregs;
 
          for (i = regno; i < endregno; i++)
            if (TEST_HARD_REG_BIT (hard_regs_need_restore, i))
-             i += insert_save_restore (insn, 0, i, insn_mode, saveregs);
+             i += insert_restore (insn, 1, i, insn_mode, saveregs, block);
        }
 
       return;
@@ -613,18 +613,18 @@ restore_referenced_regs (x, insn, insn_mode)
   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     {
       if (fmt[i] == 'e')
-       restore_referenced_regs (XEXP (x, i), insn, insn_mode);
+       restore_referenced_regs (XEXP (x, i), insn, insn_mode, block);
       else if (fmt[i] == 'E')
        for (j = XVECLEN (x, i) - 1; j >= 0; j--)
-         restore_referenced_regs (XVECEXP (x, i, j), insn, insn_mode);
+         restore_referenced_regs (XVECEXP (x, i, j), insn, insn_mode, block);
     }
 }
 \f
-/* Insert a sequence of insns to save or restore, SAVE_P says which,
-   REGNO.  Place these insns in front of INSN.  INSN_MODE is the mode
+/* Insert a sequence of insns to restore REGNO.  Place these insns in front
+   of or after INSN (determined by BEFORE_P).  INSN_MODE is the mode
    to assign to these insns.   MAXRESTORE is the maximum number of registers
-   which should be restored during this call (when SAVE_P == 0).  It should
-   never be less than 1 since we only work with entire registers.
+   which should be restored during this call.  It should never be less than
+   1 since we only work with entire registers.
 
    Note that we have verified in init_caller_save that we can do this
    with a simple SET, so use it.  Set INSN_CODE to what we save there
@@ -635,16 +635,19 @@ restore_referenced_regs (x, insn, insn_mode)
    Return the extra number of registers saved.  */
 
 static int
-insert_save_restore (insn, save_p, regno, insn_mode, maxrestore)
+insert_restore (insn, before_p, regno, insn_mode, maxrestore, block)
      rtx insn;
-     int save_p;
+     int before_p;
      int regno;
      enum machine_mode insn_mode;
      int maxrestore;
+     int block;
 {
   rtx pat = NULL_RTX;
   enum insn_code code = CODE_FOR_nothing;
   int numregs = 0;
+  int i, j, k;
+  int ok;
 
   /* A common failure mode if register status is not correct in the RTL
      is for this routine to be called with a REGNO we didn't expect to
@@ -656,108 +659,159 @@ insert_save_restore (insn, save_p, regno, insn_mode, maxrestore)
   if (regno_save_mem[regno][1] == 0)
     abort ();
 
-#ifdef HAVE_cc0
-  /* If INSN references CC0, put our insns in front of the insn that sets
-     CC0.  This is always safe, since the only way we could be passed an
-     insn that references CC0 is for a restore, and doing a restore earlier
-     isn't a problem.  We do, however, assume here that CALL_INSNs don't
-     reference CC0.  Guard against non-INSN's like CODE_LABEL.  */
-
-  if ((GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
-      && reg_referenced_p (cc0_rtx, PATTERN (insn)))
-    insn = prev_nonnote_insn (insn);
-#endif
-
   /* Get the pattern to emit and update our status.  */
-  if (save_p)
+
+  /* See if we can restore `maxrestore' registers at once.  Work
+     backwards to the single register case.  */
+  for (i = maxrestore; i > 0; i--)
     {
-      int i, j, k;
-      int ok;
+      ok = 1;
+      if (regno_save_mem[regno][i])
+       for (j = 0; j < i; j++)
+         {
+           if (! TEST_HARD_REG_BIT (hard_regs_need_restore, regno + j))
+             ok = 0;
+         }
+      else
+       continue;
+
+      /* Must do this one restore at a time */
+      if (! ok)
+       continue;
+           
+      pat = gen_rtx_SET (VOIDmode,
+                        gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]), 
+                                     regno), 
+                        regno_save_mem[regno][i]);
+      code = reg_restore_code[regno][i];
+
 
-      /* See if we can save several registers with a single instruction.  
-        Work backwards to the single register case.  */
-      for (i = MOVE_MAX / UNITS_PER_WORD; i > 0; i--)
+      /* Clear status for all registers we restored.  */
+      for (k = 0; k < i; k++)
        {
-         ok = 1;
-         if (regno_save_mem[regno][i] != 0)
-           for (j = 0; j < i; j++)
-             {
-               if (! call_used_regs[regno + j] || call_fixed_regs[regno + j]
-                   || ! TEST_HARD_REG_BIT (hard_regs_live, regno + j)
-                   || TEST_HARD_REG_BIT (hard_regs_saved, regno + j))
-                 ok = 0;
-             }
-         else 
-           continue;
+         CLEAR_HARD_REG_BIT (hard_regs_need_restore, regno + k);
+         n_regs_saved--;
+       }
 
-         /* Must do this one save at a time */
-         if (! ok)
-           continue;
+      numregs = i;
+      break;
+    }
 
-          pat = gen_rtx_SET (VOIDmode, regno_save_mem[regno][i],
-                            gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]),
-                                         regno));
-          code = reg_save_code[regno][i];
+  insert_one_insn (insn, before_p, code, insn_mode, pat, block);
 
-         /* Set hard_regs_saved for all the registers we saved.  */
-         for (k = 0; k < i; k++)
-           {
-             SET_HARD_REG_BIT (hard_regs_saved, regno + k);
-             SET_HARD_REG_BIT (hard_regs_need_restore, regno + k);
-             n_regs_saved++;
-           }
+  /* Tell our callers how many extra registers we saved/restored */
+  return numregs - 1;
+}
 
-         numregs = i;
-         break;
-        }
-    }
-  else
-    {
-      int i, j, k;
-      int ok;
+/* Like insert_restore, but emit code to save REGNO.  */
+static int
+insert_save (insn, before_p, regno, insn_mode, block)
+     rtx insn;
+     int before_p;
+     int regno;
+     enum machine_mode insn_mode;
+     int block;
+{
+  rtx pat = NULL_RTX;
+  enum insn_code code = CODE_FOR_nothing;
+  int numregs = 0;
+  int i, j, k;
+  int ok;
 
-      /* See if we can restore `maxrestore' registers at once.  Work
-        backwards to the single register case.  */
-      for (i = maxrestore; i > 0; i--)
-       {
-         ok = 1;
-         if (regno_save_mem[regno][i])
-           for (j = 0; j < i; j++)
-             {
-               if (! TEST_HARD_REG_BIT (hard_regs_need_restore, regno + j))
-                 ok = 0;
-             }
-         else
-           continue;
+  /* A common failure mode if register status is not correct in the RTL
+     is for this routine to be called with a REGNO we didn't expect to
+     save.  That will cause us to write an insn with a (nil) SET_DEST
+     or SET_SRC.  Instead of doing so and causing a crash later, check
+     for this common case and abort here instead.  This will remove one
+     step in debugging such problems.  */
 
-         /* Must do this one restore at a time */
-         if (! ok)
-           continue;
-           
-          pat = gen_rtx_SET (VOIDmode,
-                            gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]), 
-                                         regno), 
-                        regno_save_mem[regno][i]);
-          code = reg_restore_code[regno][i];
+  if (regno_save_mem[regno][1] == 0)
+    abort ();
 
+  /* Get the pattern to emit and update our status.  */
 
-         /* Clear status for all registers we restored.  */
-         for (k = 0; k < i; k++)
-           {
-             CLEAR_HARD_REG_BIT (hard_regs_need_restore, regno + k);
-             n_regs_saved--;
-           }
+  /* See if we can save several registers with a single instruction.  
+     Work backwards to the single register case.  */
+  for (i = MOVE_MAX / UNITS_PER_WORD; i > 0; i--)
+    {
+      ok = 1;
+      if (regno_save_mem[regno][i] != 0)
+       for (j = 0; j < i; j++)
+         {
+           if (! call_used_regs[regno + j] || call_fixed_regs[regno + j]
+               || ! TEST_HARD_REG_BIT (hard_regs_live, regno + j)
+               || TEST_HARD_REG_BIT (hard_regs_saved, regno + j))
+             ok = 0;
+         }
+      else 
+       continue;
 
-         numregs = i;
-         break;
-        }
+      /* Must do this one save at a time */
+      if (! ok)
+       continue;
+
+      pat = gen_rtx_SET (VOIDmode, regno_save_mem[regno][i],
+                        gen_rtx_REG (GET_MODE (regno_save_mem[regno][i]),
+                                     regno));
+      code = reg_save_code[regno][i];
+
+      /* Set hard_regs_saved for all the registers we saved.  */
+      for (k = 0; k < i; k++)
+       {
+         SET_HARD_REG_BIT (hard_regs_saved, regno + k);
+         SET_HARD_REG_BIT (hard_regs_need_restore, regno + k);
+         n_regs_saved++;
+       }
+
+      numregs = i;
+      break;
     }
-  /* Emit the insn and set the code and mode.  */
 
-  insn = emit_insn_before (pat, insn);
-  PUT_MODE (insn, insn_mode);
-  INSN_CODE (insn) = code;
+  insert_one_insn (insn, before_p, code, insn_mode, pat, block);
 
   /* Tell our callers how many extra registers we saved/restored */
   return numregs - 1;
 }
+
+/* Emit one insn, set the code and mode, and update basic block
+   boundaries.  */
+static void
+insert_one_insn (insn, before_p, code, mode, pat, block)
+     rtx insn;
+     int before_p;
+     enum rtx_code code;
+     enum machine_mode mode;
+     rtx pat;
+     int block;
+{
+  rtx insert_point = insn;
+  rtx new;
+#ifdef HAVE_cc0
+  /* If INSN references CC0, put our insns in front of the insn that sets
+     CC0.  This is always safe, since the only way we could be passed an
+     insn that references CC0 is for a restore, and doing a restore earlier
+     isn't a problem.  We do, however, assume here that CALL_INSNs don't
+     reference CC0.  Guard against non-INSN's like CODE_LABEL.  */
+
+  if ((GET_CODE (insn) == INSN || GET_CODE (insn) == JUMP_INSN)
+      && before_p
+      && reg_referenced_p (cc0_rtx, PATTERN (insn)))
+    insert_point = prev_nonnote_insn (insn);
+#endif
+
+  if (before_p)
+    {
+      new = emit_insn_before (pat, insert_point);
+      if (insert_point == basic_block_head[block])
+       basic_block_head[block] = new;
+    }
+  else
+    {
+      new = emit_insn_after (pat, insert_point);
+      if (insert_point == basic_block_end[block])
+       basic_block_end[block] = new;
+    }
+    
+  PUT_MODE (new, mode);
+  INSN_CODE (new) = code;
+}