OSDN Git Service

More of previous change.
[pf3gnuchains/gcc-fork.git] / gcc / caller-save.c
index f77eda9..db49610 100644 (file)
@@ -28,8 +28,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "reload.h"
 #include "expr.h"
 
-#define CEIL(x,y) (((x) + (y) - 1) / (y))
-
 /* Modes for each hard register that we can save.  The smallest mode is wide
    enough to save the entire contents of the register.  When saving the
    register because it is live we first try to save in multi-register modes.
@@ -71,10 +69,12 @@ static HARD_REG_SET hard_regs_need_restore;
 
 int n_regs_saved;
 
-static void set_reg_live ();
-static void clear_reg_live ();
-static void restore_referenced_regs ();
-static int insert_save_restore ();
+static enum machine_mode choose_hard_reg_mode PROTO((int, int));
+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,
+                                              enum machine_mode, int));
 \f
 /* Return a machine mode that is legitimate for hard reg REGNO and large
    enough to save nregs.  If we can't find one, return VOIDmode.  */
@@ -82,6 +82,7 @@ static int insert_save_restore ();
 static enum machine_mode
 choose_hard_reg_mode (regno, nregs)
      int regno;
+     int nregs;
 {
   enum machine_mode found_mode = VOIDmode, mode;
 
@@ -314,12 +315,24 @@ setup_save_areas (pchanged)
     for (j = MOVE_MAX / UNITS_PER_WORD; j > 0; j--)
       {
        int ok = 1;
+       int do_save;
 
        /* If no mode exists for this size, try another.  Also break out
           if we have already saved this hard register.  */
        if (regno_save_mode[i][j] == VOIDmode || regno_save_mem[i][1] != 0)
          continue;
 
+       /* See if any register in this group has been saved.  */
+       do_save = 1;
+       for (k = 0; k < j; k++)
+         if (regno_save_mem[i + k][1])
+           {
+             do_save = 0;
+             break;
+           }
+       if (! do_save)
+         continue;
+
        for (k = 0; k < j; k++)
            {
              int regno = i + k;
@@ -592,12 +605,13 @@ restore_referenced_regs (x, insn, insn_mode)
 
       else if (regno < FIRST_PSEUDO_REGISTER)
        {
-         int endregno = regno + HARD_REGNO_NREGS (regno, GET_MODE (x));
+         int numregs = MIN (HARD_REGNO_NREGS (regno, GET_MODE (x)),
+                            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, 
-                  CEIL (GET_MODE_SIZE (GET_MODE (x)), UNITS_PER_WORD));
+             i += insert_save_restore (insn, 0, i, insn_mode, numregs);
        }
 
       return;