* caller-save.c (reg_save_code, reg_restore_code): Index by mode, not
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 28 Feb 2001 16:24:00 +0000 (16:24 +0000)
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>
Wed, 28 Feb 2001 16:24:00 +0000 (16:24 +0000)
NREGS.
(insert_save, insert_restore): New parameter save_mode.
(init_caller_save): Update initialization of reg_save_code
and reg_restore_code.
(save_call_clobbered_regs):  Compute save_modes and update calls to
reg_save_code and reg_restore_code.
(insert_restore):  Unsignetize numbers; use save_modes to choose mode
of spill; update use of reg_restore_code.
(insert_save):  Likewise.
* i386.h (HARD_REGNO_CALLER_SAVE_MODE): Update.
* c4x.h (HARD_REGNO_CALLER_SAVE_MODE): Update.
* regs.h (HARD_REGNO_CALLER_SAVE_MODE): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@40120 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/caller-save.c
gcc/config/c4x/c4x.h
gcc/config/i386/i386.h
gcc/regs.h

index 9517123..b4ac8bc 100644 (file)
@@ -1,4 +1,20 @@
-Wed Feb 28 17:19:28 CET 2001  Jan Hubicka  <jh@suse.cz.
+Wed Feb 28 17:22:35 CET 2001  Jan Hubicka  <jh@suse.cz>
+
+       * caller-save.c (reg_save_code, reg_restore_code):  Index by mode, not
+       NREGS.
+       (insert_save, insert_restore): New parameter save_mode.
+       (init_caller_save): Update initialization of reg_save_code
+       and reg_restore_code.
+       (save_call_clobbered_regs):  Compute save_modes and update calls to
+       reg_save_code and reg_restore_code.
+       (insert_restore):  Unsignetize numbers; use save_modes to choose mode
+       of spill; update use of reg_restore_code.
+       (insert_save):  Likewise.
+       * i386.h (HARD_REGNO_CALLER_SAVE_MODE): Update.
+       * c4x.h (HARD_REGNO_CALLER_SAVE_MODE): Update.
+       * regs.h (HARD_REGNO_CALLER_SAVE_MODE): Likewise.
+
+Wed Feb 28 17:19:28 CET 2001  Jan Hubicka  <jh@suse.cz>
 
        * ifcvt.c (noce_emit_store_flag, noce_try_store_flag_constants,
        noce_try_store_flag_inc, noce_try_store_flag_mask,
index c8302ae..445de2c 100644 (file)
@@ -65,9 +65,9 @@ static rtx
    be recognized.  */
 
 static enum insn_code 
-  reg_save_code[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MIN_UNITS_PER_WORD + 1];
+  reg_save_code[FIRST_PSEUDO_REGISTER][MAX_MACHINE_MODE];
 static enum insn_code 
-  reg_restore_code[FIRST_PSEUDO_REGISTER][MAX_MOVE_MAX / MIN_UNITS_PER_WORD + 1];
+  reg_restore_code[FIRST_PSEUDO_REGISTER][MAX_MACHINE_MODE];
 
 /* Set of hard regs currently residing in save area (during insn scan).  */
 
@@ -89,9 +89,10 @@ static HARD_REG_SET this_insn_sets;
 static void mark_set_regs              PARAMS ((rtx, rtx, void *));
 static void mark_referenced_regs       PARAMS ((rtx));
 static int insert_save                 PARAMS ((struct insn_chain *, int, int,
-                                                HARD_REG_SET *));
+                                                HARD_REG_SET *,
+                                                enum machine_mode *));
 static int insert_restore              PARAMS ((struct insn_chain *, int, int,
-                                                int));
+                                                int, enum machine_mode *));
 static struct insn_chain *insert_one_insn PARAMS ((struct insn_chain *, int,
                                                   enum insn_code, rtx));
 static void add_stored_regs            PARAMS ((rtx, rtx, void *));
@@ -113,6 +114,7 @@ init_caller_save ()
   int offset;
   rtx address;
   int i, j;
+  enum machine_mode mode;
 
   /* First find all the registers that we need to deal with and all
      the modes that they can have.  If we can't find a mode to use,
@@ -124,7 +126,8 @@ init_caller_save ()
        {
          for (j = 1; j <= MOVE_MAX_WORDS; j++)
            {
-             regno_save_mode[i][j] = HARD_REGNO_CALLER_SAVE_MODE (i, j);
+             regno_save_mode[i][j] = HARD_REGNO_CALLER_SAVE_MODE (i, j,
+                                                                  VOIDmode);
              if (regno_save_mode[i][j] == VOIDmode && j == 1)
                {
                  call_fixed_regs[i] = 1;
@@ -179,24 +182,24 @@ init_caller_save ()
   start_sequence ();
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    for (j = 1; j <= MOVE_MAX_WORDS; j++)
-      if (regno_save_mode[i][j] != VOIDmode)
+    for (mode = 0 ; mode < MAX_MACHINE_MODE; mode++)
+      if (HARD_REGNO_MODE_OK (i, mode))
         {
-         rtx mem = gen_rtx_MEM (regno_save_mode[i][j], address);
-         rtx reg = gen_rtx_REG (regno_save_mode[i][j], i);
+         rtx mem = gen_rtx_MEM (mode, address);
+         rtx reg = gen_rtx_REG (mode, i);
          rtx savepat = gen_rtx_SET (VOIDmode, mem, reg);
          rtx restpat = gen_rtx_SET (VOIDmode, reg, mem);
          rtx saveinsn = emit_insn (savepat);
          rtx restinsn = emit_insn (restpat);
          int ok;
 
-         reg_save_code[i][j] = recog_memoized (saveinsn);
-         reg_restore_code[i][j] = recog_memoized (restinsn);
+         reg_save_code[i][mode] = recog_memoized (saveinsn);
+         reg_restore_code[i][mode] = recog_memoized (restinsn);
 
          /* Now extract both insns and see if we can meet their
              constraints.  */
-         ok = (reg_save_code[i][j] != (enum insn_code)-1
-               && reg_restore_code[i][j] != (enum insn_code)-1);
+         ok = (reg_save_code[i][mode] != (enum insn_code)-1
+               && reg_restore_code[i][mode] != (enum insn_code)-1);
          if (ok)
            {
              extract_insn (saveinsn);
@@ -207,14 +210,26 @@ init_caller_save ()
 
          if (! ok)
            {
-             regno_save_mode[i][j] = VOIDmode;
-             if (j == 1)
-               {
-                 call_fixed_regs[i] = 1;
-                 SET_HARD_REG_BIT (call_fixed_reg_set, i);
-               }
+             reg_save_code[i][mode] = (enum insn_code) -1;
+             reg_restore_code[i][mode] = (enum insn_code) -1;
            }
-      }
+        }
+      else
+       {
+         reg_save_code[i][mode] = (enum insn_code) -1;
+         reg_restore_code[i][mode] = (enum insn_code) -1;
+       }
+  for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+    for (j = 1; j <= MOVE_MAX_WORDS; j++)
+      if (reg_save_code [i][regno_save_mode[i][j]] == (enum insn_code) -1)
+       {
+         regno_save_mode[i][j] = VOIDmode;
+         if (j == 1)
+           {
+             call_fixed_regs[i] = 1;
+             SET_HARD_REG_BIT (call_fixed_reg_set, i);
+           }
+       }
 
   end_sequence ();
 }
@@ -339,6 +354,7 @@ void
 save_call_clobbered_regs ()
 {
   struct insn_chain *chain, *next;
+  enum machine_mode save_mode [FIRST_PSEUDO_REGISTER];
 
   CLEAR_HARD_REG_SET (hard_regs_saved);
   n_regs_saved = 0;
@@ -374,7 +390,7 @@ save_call_clobbered_regs ()
 
              for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
                if (TEST_HARD_REG_BIT (referenced_regs, regno))
-                 regno += insert_restore (chain, 1, regno, MOVE_MAX_WORDS);
+                 regno += insert_restore (chain, 1, regno, MOVE_MAX_WORDS, save_mode);
            }
 
          if (code == CALL_INSN)
@@ -386,8 +402,37 @@ save_call_clobbered_regs ()
                 regs are live during the call.  */
              REG_SET_TO_HARD_REG_SET (hard_regs_to_save,
                                       &chain->live_throughout);
-             compute_use_by_pseudos (&hard_regs_to_save,
-                                     &chain->live_throughout);
+             /* Save hard registers always in the widest mode availble.  */
+             for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
+               if (TEST_HARD_REG_BIT (hard_regs_to_save, regno))
+                 save_mode [regno] = regno_save_mode [regno][1];
+               else
+                 save_mode [regno] = VOIDmode;
+
+             /* Look trought all live pseudos, mark their hard registers
+                and choose proper mode for saving.  */
+             EXECUTE_IF_SET_IN_REG_SET
+               (&chain->live_throughout, FIRST_PSEUDO_REGISTER, regno,
+                {
+                  int r = reg_renumber[regno];
+                  int nregs;
+
+                  if (r > 0)
+                    {
+                      enum machine_mode mode;
+
+                      nregs = HARD_REGNO_NREGS (r, PSEUDO_REGNO_MODE (regno));
+                      mode = HARD_REGNO_CALLER_SAVE_MODE
+                               (r, nregs, PSEUDO_REGNO_MODE (regno));
+                      if (GET_MODE_BITSIZE (mode)
+                          > GET_MODE_BITSIZE (save_mode[r]))
+                        save_mode[r] = mode;
+                      while (nregs-- > 0)
+                        SET_HARD_REG_BIT (hard_regs_to_save, r + nregs);
+                    }
+                  else
+                    abort ();
+                });
 
              /* Record all registers set in this call insn.  These don't need
                 to be saved.  N.B. the call insn might set a subreg of a
@@ -404,7 +449,7 @@ save_call_clobbered_regs ()
 
              for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
                if (TEST_HARD_REG_BIT (hard_regs_to_save, regno))
-                 regno += insert_save (chain, 1, regno, &hard_regs_to_save);
+                 regno += insert_save (chain, 1, regno, &hard_regs_to_save, save_mode);
 
              /* Must recompute n_regs_saved.  */
              n_regs_saved = 0;
@@ -425,7 +470,7 @@ save_call_clobbered_regs ()
            for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
              if (TEST_HARD_REG_BIT (hard_regs_saved, regno))
                regno += insert_restore (chain, GET_CODE (insn) == JUMP_INSN,
-                                        regno, MOVE_MAX_WORDS);
+                                        regno, MOVE_MAX_WORDS, save_mode);
        }
     }  
 }
@@ -572,17 +617,19 @@ mark_referenced_regs (x)
    Return the extra number of registers saved.  */
 
 static int
-insert_restore (chain, before_p, regno, maxrestore)
+insert_restore (chain, before_p, regno, maxrestore, save_mode)
      struct insn_chain *chain;
      int before_p;
      int regno;
      int maxrestore;
+     enum machine_mode *save_mode;
 {
   int i, k;
   rtx pat = NULL_RTX;
   enum insn_code code = CODE_FOR_nothing;
-  int numregs = 0;
+  unsigned int numregs = 0;
   struct insn_chain *new;
+  rtx mem;
 
   /* 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
@@ -620,11 +667,15 @@ insert_restore (chain, before_p, regno, maxrestore)
       break;
     }
 
+  mem = regno_save_mem [regno][numregs];
+  if (save_mode [regno] != VOIDmode
+      && save_mode [regno] != GET_MODE (mem)
+      && numregs == HARD_REGNO_NREGS (regno, save_mode [regno]))
+    mem = change_address (mem, save_mode[regno], XEXP (mem, 0));
   pat = gen_rtx_SET (VOIDmode,
-                    gen_rtx_REG (GET_MODE (regno_save_mem[regno][numregs]), 
-                                 regno), 
-                    regno_save_mem[regno][numregs]);
-  code = reg_restore_code[regno][numregs];
+                    gen_rtx_REG (GET_MODE (mem), 
+                                 regno), mem);
+  code = reg_restore_code[regno][GET_MODE (mem)];
   new = insert_one_insn (chain, before_p, code, pat);
 
   /* Clear status for all registers we restored.  */
@@ -643,17 +694,20 @@ insert_restore (chain, before_p, regno, maxrestore)
 
 /* Like insert_restore above, but save registers instead.  */
 static int
-insert_save (chain, before_p, regno, to_save)
+insert_save (chain, before_p, regno, to_save, save_mode)
      struct insn_chain *chain;
      int before_p;
      int regno;
      HARD_REG_SET *to_save;
+     enum machine_mode *save_mode;
 {
-  int i, k;
+  int i;
+  unsigned int k;
   rtx pat = NULL_RTX;
   enum insn_code code = CODE_FOR_nothing;
-  int numregs = 0;
+  unsigned int numregs = 0;
   struct insn_chain *new;
+  rtx mem;
 
   /* 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
@@ -690,10 +744,15 @@ insert_save (chain, before_p, regno, to_save)
       break;
     }
 
-  pat = gen_rtx_SET (VOIDmode, regno_save_mem[regno][numregs],
-                    gen_rtx_REG (GET_MODE (regno_save_mem[regno][numregs]),
+  mem = regno_save_mem [regno][numregs];
+  if (save_mode [regno] != VOIDmode
+      && save_mode [regno] != GET_MODE (mem)
+      && numregs == HARD_REGNO_NREGS (regno, save_mode [regno]))
+    mem = change_address (mem, save_mode[regno], XEXP (mem, 0));
+  pat = gen_rtx_SET (VOIDmode, mem,
+                    gen_rtx_REG (GET_MODE (mem),
                                  regno));
-  code = reg_save_code[regno][numregs];
+  code = reg_save_code[regno][GET_MODE (mem)];
   new = insert_one_insn (chain, before_p, code, pat);
 
   /* Set hard_regs_saved and dead_or_set for all the registers we saved.  */
index 72ffb37..4250bf5 100644 (file)
@@ -648,7 +648,7 @@ extern const char *c4x_rpts_cycles_string, *c4x_cpu_version_string;
 
 /* Specify the modes required to caller save a given hard regno.  */
 
-#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS) (c4x_caller_save_map[REGNO])
+#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) (c4x_caller_save_map[REGNO])
 
 #define HARD_REGNO_MODE_OK(REGNO, MODE) c4x_hard_regno_mode_ok(REGNO, MODE)
 
index b4f7d30..1ba6118 100644 (file)
@@ -819,11 +819,16 @@ extern int ix86_arch;
    || ((MODE1) == HImode && (MODE2) == SImode))
 
 /* Specify the modes required to caller save a given hard regno.
-   We do this on i386 to prevent flags from being saved at all.  */
+   We do this on i386 to prevent flags from being saved at all.
 
-#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS)              \
+   Kill any attempts to combine saving of modes.  */
+
+#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE)                \
   (CC_REGNO_P (REGNO) ? VOIDmode                               \
-   : choose_hard_reg_mode ((REGNO), (NREGS)))
+   : (MODE) == VOIDmode && (NREGS) != 1 ? VOIDmode             \
+   : (MODE) == VOIDmode ? choose_hard_reg_mode ((REGNO), (NREGS)) \
+   : (MODE) == HImode && !TARGET_PARTIAL_REG_STALL ? SImode    \
+   : (MODE) == QImode && (REGNO) >= 4 ? SImode : (MODE))
 
 /* Specify the registers used for certain standard purposes.
    The values of these macros are register numbers.  */
index c219ecc..0822966 100644 (file)
@@ -192,7 +192,7 @@ extern int caller_save_needed;
 
 /* Select a register mode required for caller save of hard regno REGNO.  */
 #ifndef HARD_REGNO_CALLER_SAVE_MODE
-#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS) \
+#define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
   choose_hard_reg_mode (REGNO, NREGS)
 #endif