OSDN Git Service

* cpppch.c (cpp_valid_state): Unconditionally initialize nl.
[pf3gnuchains/gcc-fork.git] / gcc / caller-save.c
index 2cf2cf0..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, 2001 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"
@@ -31,7 +33,6 @@ Boston, MA 02111-1307, USA.  */
 #include "reload.h"
 #include "function.h"
 #include "expr.h"
-#include "insn-codes.h"
 #include "toplev.h"
 #include "tm_p.h"
 
@@ -65,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).  */
@@ -95,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.
@@ -116,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,
@@ -152,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)
@@ -178,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);
@@ -211,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)
@@ -231,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.  */
@@ -400,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,
@@ -483,7 +501,7 @@ 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);
 
   if (GET_CODE (reg) == SUBREG)
@@ -516,7 +534,7 @@ 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 offset = 0;
 
@@ -630,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;
@@ -674,7 +692,7 @@ 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]))
+      && 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), 
@@ -690,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;
@@ -708,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;
@@ -751,7 +768,7 @@ 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]))
+      && 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),
@@ -776,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;