OSDN Git Service

* gcse.c (lookup_set): Remove unused argument PAT. Update
[pf3gnuchains/gcc-fork.git] / gcc / caller-save.c
index 787d45c..53f3aa5 100644 (file)
@@ -1,26 +1,28 @@
 /* Save and restore call-clobbered registers which are live across a call.
    Copyright (C) 1989, 1992, 1994, 1995, 1997, 1998,
-   1999, 2000 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+along with GCC; see the file COPYING.  If not, write to the Free
+Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+02111-1307, USA.  */
 
 #include "config.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "rtl.h"
 #include "insn-config.h"
 #include "flags.h"
@@ -64,9 +66,9 @@ static rtx
    when we emit them, the addresses might not be valid, so they might not
    be recognized.  */
 
-static enum insn_code 
+static int
   reg_save_code[FIRST_PSEUDO_REGISTER][MAX_MACHINE_MODE];
-static enum insn_code 
+static int 
   reg_restore_code[FIRST_PSEUDO_REGISTER][MAX_MACHINE_MODE];
 
 /* Set of hard regs currently residing in save area (during insn scan).  */
@@ -94,7 +96,7 @@ static int insert_save                        PARAMS ((struct insn_chain *, int, int,
 static int insert_restore              PARAMS ((struct insn_chain *, int, int,
                                                 int, enum machine_mode *));
 static struct insn_chain *insert_one_insn PARAMS ((struct insn_chain *, int,
-                                                  enum insn_code, rtx));
+                                                  int, rtx));
 static void add_stored_regs            PARAMS ((rtx, rtx, void *));
 \f
 /* Initialize for caller-save.
@@ -115,6 +117,9 @@ init_caller_save ()
   rtx address;
   int i, j;
   enum machine_mode mode;
+  rtx savepat, restpat;
+  rtx test_reg, test_mem;
+  rtx saveinsn, restinsn;
 
   /* 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,
@@ -151,7 +156,9 @@ init_caller_save ()
      that register in every mode we will use to save registers.  */
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
-    if (TEST_HARD_REG_BIT (reg_class_contents[(int) BASE_REG_CLASS], i))
+    if (TEST_HARD_REG_BIT
+       (reg_class_contents
+        [(int) MODE_BASE_REG_CLASS (regno_save_mode [i][1])], i))
       break;
 
   if (i == FIRST_PSEUDO_REGISTER)
@@ -177,29 +184,42 @@ init_caller_save ()
     address = addr_reg;
 
   /* Next we try to form an insn to save and restore the register.  We
-     see if such an insn is recognized and meets its constraints.  */
+     see if such an insn is recognized and meets its constraints. 
+
+     To avoid lots of unnecessary RTL allocation, we construct all the RTL
+     once, then modify the memory and register operands in-place.  */
+
+  test_reg = gen_rtx_REG (VOIDmode, 0);
+  test_mem = gen_rtx_MEM (VOIDmode, address);
+  savepat = gen_rtx_SET (VOIDmode, test_mem, test_reg);
+  restpat = gen_rtx_SET (VOIDmode, test_reg, test_mem);
 
-  start_sequence ();
+  saveinsn = gen_rtx_INSN (VOIDmode, 0, 0, 0, 0, 0, savepat, -1, 0, 0);
+  restinsn = gen_rtx_INSN (VOIDmode, 0, 0, 0, 0, 0, restpat, -1, 0, 0);
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     for (mode = 0 ; mode < MAX_MACHINE_MODE; mode++)
       if (HARD_REGNO_MODE_OK (i, mode))
         {
-         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;
 
+         /* Update the register number and modes of the register
+            and memory operand.  */
+         REGNO (test_reg) = i;
+         PUT_MODE (test_reg, mode);
+         PUT_MODE (test_mem, mode);
+
+         /* Force re-recognition of the modified insns.  */
+         INSN_CODE (saveinsn) = -1;
+         INSN_CODE (restinsn) = -1;
+
          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][mode] != (enum insn_code)-1
-               && reg_restore_code[i][mode] != (enum insn_code)-1);
+         ok = (reg_save_code[i][mode] != -1
+               && reg_restore_code[i][mode] != -1);
          if (ok)
            {
              extract_insn (saveinsn);
@@ -210,18 +230,19 @@ init_caller_save ()
 
          if (! ok)
            {
-             reg_save_code[i][mode] = (enum insn_code) -1;
-             reg_restore_code[i][mode] = (enum insn_code) -1;
+             reg_save_code[i][mode] = -1;
+             reg_restore_code[i][mode] = -1;
            }
         }
       else
        {
-         reg_save_code[i][mode] = (enum insn_code) -1;
-         reg_restore_code[i][mode] = (enum insn_code) -1;
+         reg_save_code[i][mode] = -1;
+         reg_restore_code[i][mode] = -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)
+      if (reg_save_code [i][regno_save_mode[i][j]] == -1)
        {
          regno_save_mode[i][j] = VOIDmode;
          if (j == 1)
@@ -230,8 +251,6 @@ init_caller_save ()
              SET_HARD_REG_BIT (call_fixed_reg_set, i);
            }
        }
-
-  end_sequence ();
 }
 \f
 /* Initialize save areas by showing that we haven't allocated any yet.  */
@@ -329,15 +348,12 @@ setup_save_areas ()
 
        /* Setup single word save area just in case...  */
        for (k = 0; k < j; k++)
-         {
-           /* This should not depend on WORDS_BIG_ENDIAN.
-              The order of words in regs is the same as in memory.  */
-           rtx temp = gen_rtx_MEM (regno_save_mode[i + k][1], 
-                                   XEXP (regno_save_mem[i][j], 0));
-
-           regno_save_mem[i + k][1] 
-             = adj_offsettable_operand (temp, k * UNITS_PER_WORD);
-         }
+         /* This should not depend on WORDS_BIG_ENDIAN.
+            The order of words in regs is the same as in memory.  */
+         regno_save_mem[i + k][1]
+           = adjust_address_nv (regno_save_mem[i][j],
+                                regno_save_mode[i + k][1],
+                                k * UNITS_PER_WORD);
       }
 
   /* Now loop again and set the alias set of any save areas we made to
@@ -345,7 +361,7 @@ setup_save_areas ()
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     for (j = MOVE_MAX_WORDS; j > 0; j--)
       if (regno_save_mem[i][j] != 0)
-       MEM_ALIAS_SET (regno_save_mem[i][j]) = get_frame_alias_set ();
+       set_mem_alias_set (regno_save_mem[i][j], get_frame_alias_set ());
 }
 \f
 /* Find the places where hard regs are live across calls and save them.  */
@@ -402,14 +418,14 @@ save_call_clobbered_regs ()
                 regs are live during the call.  */
              REG_SET_TO_HARD_REG_SET (hard_regs_to_save,
                                       &chain->live_throughout);
-             /* Save hard registers always in the widest mode availble.  */
+             /* Save hard registers always in the widest mode available.  */
              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
+             /* Look through 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,
@@ -485,20 +501,23 @@ mark_set_regs (reg, setter, data)
      rtx setter ATTRIBUTE_UNUSED;
      void *data ATTRIBUTE_UNUSED;
 {
-  register int regno, endregno, i;
+  int regno, endregno, i;
   enum machine_mode mode = GET_MODE (reg);
-  int word = 0;
 
   if (GET_CODE (reg) == SUBREG)
     {
-      word = SUBREG_WORD (reg);
-      reg = SUBREG_REG (reg);
-    }
+      rtx inner = SUBREG_REG (reg);
+      if (GET_CODE (inner) != REG || REGNO (inner) >= FIRST_PSEUDO_REGISTER)
+       return;
 
-  if (GET_CODE (reg) != REG || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
+      regno = subreg_hard_regno (reg, 1);
+    }
+  else if (GET_CODE (reg) == REG
+          && REGNO (reg) < FIRST_PSEUDO_REGISTER)
+    regno = REGNO (reg);
+  else
     return;
 
-  regno = REGNO (reg) + word;
   endregno = regno + HARD_REGNO_NREGS (regno, mode);
 
   for (i = regno; i < endregno; i++)
@@ -515,23 +534,26 @@ add_stored_regs (reg, setter, data)
      rtx setter;
      void *data;
 {
-  register int regno, endregno, i;
+  int regno, endregno, i;
   enum machine_mode mode = GET_MODE (reg);
-  int word = 0;
+  int offset = 0;
 
   if (GET_CODE (setter) == CLOBBER)
     return;
 
-  while (GET_CODE (reg) == SUBREG)
+  if (GET_CODE (reg) == SUBREG && GET_CODE (SUBREG_REG (reg)) == REG)
     {
-      word += SUBREG_WORD (reg);
+      offset = subreg_regno_offset (REGNO (SUBREG_REG (reg)),
+                                   GET_MODE (SUBREG_REG (reg)),
+                                   SUBREG_BYTE (reg),
+                                   GET_MODE (reg));
       reg = SUBREG_REG (reg);
     }
 
   if (GET_CODE (reg) != REG || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
     return;
 
-  regno = REGNO (reg) + word;
+  regno = REGNO (reg) + offset;
   endregno = regno + HARD_REGNO_NREGS (regno, mode);
 
   for (i = regno; i < endregno; i++)
@@ -626,7 +648,7 @@ insert_restore (chain, before_p, regno, maxrestore, save_mode)
 {
   int i, k;
   rtx pat = NULL_RTX;
-  enum insn_code code = CODE_FOR_nothing;
+  int code;
   unsigned int numregs = 0;
   struct insn_chain *new;
   rtx mem;
@@ -670,8 +692,8 @@ insert_restore (chain, before_p, regno, maxrestore, save_mode)
   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));
+      && numregs == (unsigned int) HARD_REGNO_NREGS (regno, save_mode [regno]))
+    mem = adjust_address (mem, save_mode[regno], 0);
   pat = gen_rtx_SET (VOIDmode,
                     gen_rtx_REG (GET_MODE (mem), 
                                  regno), mem);
@@ -686,13 +708,12 @@ insert_restore (chain, before_p, regno, maxrestore, save_mode)
       n_regs_saved--;
     }
 
-
-
   /* Tell our callers how many extra registers we saved/restored */
   return numregs - 1;
 }
 
 /* Like insert_restore above, but save registers instead.  */
+
 static int
 insert_save (chain, before_p, regno, to_save, save_mode)
      struct insn_chain *chain;
@@ -704,7 +725,7 @@ insert_save (chain, before_p, regno, to_save, save_mode)
   int i;
   unsigned int k;
   rtx pat = NULL_RTX;
-  enum insn_code code = CODE_FOR_nothing;
+  int code;
   unsigned int numregs = 0;
   struct insn_chain *new;
   rtx mem;
@@ -747,8 +768,8 @@ insert_save (chain, before_p, regno, to_save, save_mode)
   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));
+      && numregs == (unsigned int) HARD_REGNO_NREGS (regno, save_mode [regno]))
+    mem = adjust_address (mem, save_mode[regno], 0);
   pat = gen_rtx_SET (VOIDmode, mem,
                     gen_rtx_REG (GET_MODE (mem),
                                  regno));
@@ -772,7 +793,7 @@ static struct insn_chain *
 insert_one_insn (chain, before_p, code, pat)
      struct insn_chain *chain;
      int before_p;
-     enum insn_code code;
+     int code;
      rtx pat;
 {
   rtx insn = chain->insn;