OSDN Git Service

* config/sparc/sparc.md (movdi_insn_sp64_novis): New pattern.
[pf3gnuchains/gcc-fork.git] / gcc / reload.c
index 46f29a0..3e5d277 100644 (file)
@@ -1,5 +1,6 @@
 /* Search an insn for pseudo regs that must be in hard regs and are not.
-   Copyright (C) 1987, 88, 89, 92-98, 1999 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
+   1999, 2000 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -237,42 +238,43 @@ static int output_reloadnum;
       : (type)))
 
 #ifdef HAVE_SECONDARY_RELOADS
-static int push_secondary_reload PROTO((int, rtx, int, int, enum reg_class,
+static int push_secondary_reload PARAMS ((int, rtx, int, int, enum reg_class,
                                        enum machine_mode, enum reload_type,
                                        enum insn_code *));
 #endif
-static enum reg_class find_valid_class PROTO((enum machine_mode, int));
-static int push_reload         PROTO((rtx, rtx, rtx *, rtx *, enum reg_class,
+static enum reg_class find_valid_class PARAMS ((enum machine_mode, int));
+static int push_reload         PARAMS ((rtx, rtx, rtx *, rtx *, enum reg_class,
                                       enum machine_mode, enum machine_mode,
                                       int, int, int, enum reload_type));
-static void push_replacement   PROTO((rtx *, int, enum machine_mode));
-static void combine_reloads    PROTO((void));
-static int find_reusable_reload        PROTO((rtx *, rtx, enum reg_class,
+static void push_replacement   PARAMS ((rtx *, int, enum machine_mode));
+static void combine_reloads    PARAMS ((void));
+static int find_reusable_reload        PARAMS ((rtx *, rtx, enum reg_class,
                                       enum reload_type, int, int));
-static rtx find_dummy_reload   PROTO((rtx, rtx, rtx *, rtx *,
+static rtx find_dummy_reload   PARAMS ((rtx, rtx, rtx *, rtx *,
                                       enum machine_mode, enum machine_mode,
                                       enum reg_class, int, int));
-static int hard_reg_set_here_p PROTO((int, int, rtx));
-static struct decomposition decompose PROTO((rtx));
-static int immune_p            PROTO((rtx, rtx, struct decomposition));
-static int alternative_allows_memconst PROTO((const char *, int));
-static rtx find_reloads_toplev PROTO((rtx, int, enum reload_type, int, int, rtx));
-static rtx make_memloc         PROTO((rtx, int));
-static int find_reloads_address        PROTO((enum machine_mode, rtx *, rtx, rtx *,
+static int hard_reg_set_here_p PARAMS ((unsigned int, unsigned int, rtx));
+static struct decomposition decompose PARAMS ((rtx));
+static int immune_p            PARAMS ((rtx, rtx, struct decomposition));
+static int alternative_allows_memconst PARAMS ((const char *, int));
+static rtx find_reloads_toplev PARAMS ((rtx, int, enum reload_type, int,
+                                        int, rtx));
+static rtx make_memloc         PARAMS ((rtx, int));
+static int find_reloads_address        PARAMS ((enum machine_mode, rtx *, rtx, rtx *,
                                       int, enum reload_type, int, rtx));
-static rtx subst_reg_equivs    PROTO((rtx, rtx));
-static rtx subst_indexed_address PROTO((rtx));
-static int find_reloads_address_1 PROTO((enum machine_mode, rtx, int, rtx *,
+static rtx subst_reg_equivs    PARAMS ((rtx, rtx));
+static rtx subst_indexed_address PARAMS ((rtx));
+static int find_reloads_address_1 PARAMS ((enum machine_mode, rtx, int, rtx *,
                                         int, enum reload_type,int, rtx));
-static void find_reloads_address_part PROTO((rtx, rtx *, enum reg_class,
+static void find_reloads_address_part PARAMS ((rtx, rtx *, enum reg_class,
                                             enum machine_mode, int,
                                             enum reload_type, int));
-static rtx find_reloads_subreg_address PROTO((rtx, int, int, enum reload_type,
+static rtx find_reloads_subreg_address PARAMS ((rtx, int, int, enum reload_type,
                                              int, rtx));
-static int find_inc_amount     PROTO((rtx, rtx));
-static int loc_mentioned_in_p  PROTO((rtx *, rtx));
-extern void debug_reload_to_stream PROTO((FILE *));
-extern void debug_reload PROTO((void));
+static int find_inc_amount     PARAMS ((rtx, rtx));
+static int loc_mentioned_in_p  PARAMS ((rtx *, rtx));
+extern void debug_reload_to_stream PARAMS ((FILE *));
+extern void debug_reload PARAMS ((void));
 \f
 #ifdef HAVE_SECONDARY_RELOADS
 
@@ -465,7 +467,6 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
          rld[t_reload].outmode = ! in_p ? t_mode : VOIDmode;
          rld[t_reload].reg_rtx = 0;
          rld[t_reload].optional = optional;
-         rld[t_reload].nongroup = 0;
          rld[t_reload].inc = 0;
          /* Maybe we could combine these, but it seems too tricky.  */
          rld[t_reload].nocombine = 1;
@@ -535,7 +536,6 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
       rld[s_reload].outmode = ! in_p ? mode : VOIDmode;
       rld[s_reload].reg_rtx = 0;
       rld[s_reload].optional = optional;
-      rld[s_reload].nongroup = 0;
       rld[s_reload].inc = 0;
       /* Maybe we could combine these, but it seems too tricky.  */
       rld[s_reload].nocombine = 1;
@@ -654,13 +654,13 @@ clear_secondary_mem ()
 
 static enum reg_class
 find_valid_class (m1, n)
-     enum machine_mode  m1;
+     enum machine_mode m1 ATTRIBUTE_UNUSED;
      int n;
 {
   int class;
   int regno;
   enum reg_class best_class = NO_REGS;
-  int best_size = 0;
+  unsigned int best_size = 0;
 
   for (class = 1; class < N_REG_CLASSES; class++)
     {
@@ -1246,7 +1246,6 @@ push_reload (in, out, inloc, outloc, class,
       rld[i].outmode = outmode;
       rld[i].reg_rtx = 0;
       rld[i].optional = optional;
-      rld[i].nongroup = 0;
       rld[i].inc = 0;
       rld[i].nocombine = 0;
       rld[i].in_reg = inloc ? *inloc : 0;
@@ -1460,12 +1459,21 @@ push_reload (in, out, inloc, outloc, class,
            && GET_MODE_SIZE (inmode) <= GET_MODE_SIZE (GET_MODE (XEXP (note, 0)))
            && HARD_REGNO_MODE_OK (regno, inmode)
            && GET_MODE_SIZE (outmode) <= GET_MODE_SIZE (GET_MODE (XEXP (note, 0)))
-           && HARD_REGNO_MODE_OK (regno, outmode)
-           && TEST_HARD_REG_BIT (reg_class_contents[(int) class], regno)
-           && !fixed_regs[regno])
+           && HARD_REGNO_MODE_OK (regno, outmode))
          {
-           rld[i].reg_rtx = gen_rtx_REG (inmode, regno);
-           break;
+           int offs;
+           int nregs = HARD_REGNO_NREGS (regno, inmode);
+           for (offs = 0; offs < nregs; offs++)
+             if (fixed_regs[regno + offs]
+                 || ! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
+                                         regno + offs))
+               break;
+
+           if (offs == nregs)
+             {
+               rld[i].reg_rtx = gen_rtx_REG (inmode, regno);
+               break;
+             }
          }
     }
 
@@ -1816,8 +1824,8 @@ find_dummy_reload (real_in, real_out, inloc, outloc,
   if (GET_CODE (out) == REG
       && REGNO (out) < FIRST_PSEUDO_REGISTER)
     {
-      register int regno = REGNO (out) + out_offset;
-      int nwords = HARD_REGNO_NREGS (regno, outmode);
+      unsigned int regno = REGNO (out) + out_offset;
+      unsigned int nwords = HARD_REGNO_NREGS (regno, outmode);
       rtx saved_rtx;
 
       /* When we consider whether the insn uses OUT,
@@ -1833,15 +1841,11 @@ find_dummy_reload (real_in, real_out, inloc, outloc,
       *inloc = const0_rtx;
 
       if (regno < FIRST_PSEUDO_REGISTER
-         /* A fixed reg that can overlap other regs better not be used
-            for reloading in any way.  */
-#ifdef OVERLAPPING_REGNO_P
-         && ! (fixed_regs[regno] && OVERLAPPING_REGNO_P (regno))
-#endif
          && ! refers_to_regno_for_reload_p (regno, regno + nwords,
                                             PATTERN (this_insn), outloc))
        {
-         int i;
+         unsigned int i;
+
          for (i = 0; i < nwords; i++)
            if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
                                     regno + i))
@@ -1880,8 +1884,8 @@ find_dummy_reload (real_in, real_out, inloc, outloc,
                             (GET_MODE (out) != VOIDmode
                              ? GET_MODE (out) : outmode)))
     {
-      register int regno = REGNO (in) + in_offset;
-      int nwords = HARD_REGNO_NREGS (regno, inmode);
+      unsigned int regno = REGNO (in) + in_offset;
+      unsigned int nwords = HARD_REGNO_NREGS (regno, inmode);
 
       if (! refers_to_regno_for_reload_p (regno, regno + nwords, out, NULL_PTR)
          && ! hard_reg_set_here_p (regno, regno + nwords,
@@ -1890,7 +1894,8 @@ find_dummy_reload (real_in, real_out, inloc, outloc,
              || ! refers_to_regno_for_reload_p (regno, regno + nwords,
                                                 PATTERN (this_insn), inloc)))
        {
-         int i;
+         unsigned int i;
+
          for (i = 0; i < nwords; i++)
            if (! TEST_HARD_REG_BIT (reg_class_contents[(int) class],
                                     regno + i))
@@ -1940,17 +1945,19 @@ earlyclobber_operand_p (x)
 
 static int
 hard_reg_set_here_p (beg_regno, end_regno, x)
-     register int beg_regno, end_regno;
+     unsigned int beg_regno, end_regno;
      rtx x;
 {
   if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)
     {
       register rtx op0 = SET_DEST (x);
+
       while (GET_CODE (op0) == SUBREG)
        op0 = SUBREG_REG (op0);
       if (GET_CODE (op0) == REG)
        {
-         register int r = REGNO (op0);
+         unsigned int r = REGNO (op0);
+
          /* See if this reg overlaps range under consideration.  */
          if (r < end_regno
              && r + HARD_REGNO_NREGS (r, GET_MODE (op0)) > beg_regno)
@@ -1960,6 +1967,7 @@ hard_reg_set_here_p (beg_regno, end_regno, x)
   else if (GET_CODE (x) == PARALLEL)
     {
       register int i = XVECLEN (x, 0) - 1;
+
       for (; i >= 0; i--)
        if (hard_reg_set_here_p (beg_regno, end_regno, XVECEXP (x, 0, i)))
          return 1;
@@ -1974,7 +1982,7 @@ hard_reg_set_here_p (beg_regno, end_regno, x)
 
 int
 strict_memory_address_p (mode, addr)
-     enum machine_mode mode;
+     enum machine_mode mode ATTRIBUTE_UNUSED;
      register rtx addr;
 {
   GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
@@ -2382,7 +2390,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
   int swapped;
   int goal_alternative[MAX_RECOG_OPERANDS];
   int this_alternative_number;
-  int goal_alternative_number;
+  int goal_alternative_number = 0;
   int operand_reloadnum[MAX_RECOG_OPERANDS];
   int goal_alternative_matches[MAX_RECOG_OPERANDS];
   int goal_alternative_matched[MAX_RECOG_OPERANDS];
@@ -2392,12 +2400,11 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
   int goal_alternative_swapped;
   int best;
   int commutative;
-  int changed;
   char operands_match[MAX_RECOG_OPERANDS][MAX_RECOG_OPERANDS];
   rtx substed_operand[MAX_RECOG_OPERANDS];
   rtx body = PATTERN (insn);
   rtx set = single_set (insn);
-  int goal_earlyclobber, this_earlyclobber;
+  int goal_earlyclobber = 0, this_earlyclobber;
   enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
   int retval = 0;
 
@@ -4037,7 +4044,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
       {
        for (i = 0; i < n_reloads; i++)
          {
-           int first_num, type;
+           int first_num;
+           enum reload_type type;
 
            switch (rld[i].when_needed)
              {
@@ -4115,67 +4123,6 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
        abort ();
 #endif
 
-  /* Set which reloads must use registers not used in any group.  Start
-     with those that conflict with a group and then include ones that
-     conflict with ones that are already known to conflict with a group.  */
-
-  changed = 0;
-  for (i = 0; i < n_reloads; i++)
-    {
-      enum machine_mode mode = rld[i].inmode;
-      enum reg_class class = rld[i].class;
-      int size;
-
-      if (GET_MODE_SIZE (rld[i].outmode) > GET_MODE_SIZE (mode))
-       mode = rld[i].outmode;
-      size = CLASS_MAX_NREGS (class, mode);
-
-      if (size == 1)
-       for (j = 0; j < n_reloads; j++)
-         if ((CLASS_MAX_NREGS (rld[j].class,
-                               (GET_MODE_SIZE (rld[j].outmode)
-                                > GET_MODE_SIZE (rld[j].inmode))
-                               ? rld[j].outmode : rld[j].inmode)
-              > 1)
-             && !rld[j].optional
-             && (rld[j].in != 0 || rld[j].out != 0
-                 || rld[j].secondary_p)
-             && reloads_conflict (i, j)
-             && reg_classes_intersect_p (class, rld[j].class))
-           {
-             rld[i].nongroup = 1;
-             changed = 1;
-             break;
-           }
-    }
-
-  while (changed)
-    {
-      changed = 0;
-
-      for (i = 0; i < n_reloads; i++)
-       {
-         enum machine_mode mode = rld[i].inmode;
-         enum reg_class class = rld[i].class;
-         int size;
-
-         if (GET_MODE_SIZE (rld[i].outmode) > GET_MODE_SIZE (mode))
-           mode = rld[i].outmode;
-         size = CLASS_MAX_NREGS (class, mode);
-
-         if (! rld[i].nongroup && size == 1)
-           for (j = 0; j < n_reloads; j++)
-             if (rld[j].nongroup
-                 && reloads_conflict (i, j)
-                 && reg_classes_intersect_p (class, rld[j].class))
-               {
-                 rld[i].nongroup = 1;
-                 changed = 1;
-                 break;
-               }
-       }
-    }
-
   /* Compute reload_mode and reload_nregs.  */
   for (i = 0; i < n_reloads; i++)
     {
@@ -5748,13 +5695,14 @@ find_replacement (loc)
 
 int
 refers_to_regno_for_reload_p (regno, endregno, x, loc)
-     int regno, endregno;
+     unsigned int regno, endregno;
      rtx x;
      rtx *loc;
 {
-  register int i;
-  register RTX_CODE code;
-  register const char *fmt;
+  int i;
+  unsigned int r;
+  RTX_CODE code;
+  const char *fmt;
 
   if (x == 0)
     return 0;
@@ -5765,26 +5713,26 @@ refers_to_regno_for_reload_p (regno, endregno, x, loc)
   switch (code)
     {
     case REG:
-      i = REGNO (x);
+      r = REGNO (x);
 
       /* If this is a pseudo, a hard register must not have been allocated.
         X must therefore either be a constant or be in memory.  */
-      if (i >= FIRST_PSEUDO_REGISTER)
+      if (r >= FIRST_PSEUDO_REGISTER)
        {
-         if (reg_equiv_memory_loc[i])
+         if (reg_equiv_memory_loc[r])
            return refers_to_regno_for_reload_p (regno, endregno,
-                                                reg_equiv_memory_loc[i],
+                                                reg_equiv_memory_loc[r],
                                                 NULL_PTR);
 
-         if (reg_equiv_constant[i])
+         if (reg_equiv_constant[r])
            return 0;
 
          abort ();
        }
 
-      return (endregno > i
-             && regno < i + (i < FIRST_PSEUDO_REGISTER
-                             ? HARD_REGNO_NREGS (i, GET_MODE (x))
+      return (endregno > r
+             && regno < r + (r < FIRST_PSEUDO_REGISTER
+                             ? HARD_REGNO_NREGS (r, GET_MODE (x))
                              : 1));
 
     case SUBREG:
@@ -5793,8 +5741,8 @@ refers_to_regno_for_reload_p (regno, endregno, x, loc)
       if (GET_CODE (SUBREG_REG (x)) == REG
          && REGNO (SUBREG_REG (x)) < FIRST_PSEUDO_REGISTER)
        {
-         int inner_regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
-         int inner_endregno
+         unsigned int inner_regno = REGNO (SUBREG_REG (x)) + SUBREG_WORD (x);
+         unsigned int inner_endregno
            = inner_regno + (inner_regno < FIRST_PSEUDO_REGISTER
                             ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
 
@@ -6033,15 +5981,6 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
   else
     return 0;
 
-  /* On some machines, certain regs must always be rejected
-     because they don't behave the way ordinary registers do.  */
-
-#ifdef OVERLAPPING_REGNO_P
-  if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER
-      && OVERLAPPING_REGNO_P (regno))
-    return 0;
-#endif
-
   /* Scan insns back from INSN, looking for one that copies
      a value into or out of GOAL.
      Stop and give up if we reach a label.  */
@@ -6051,21 +5990,24 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
       p = PREV_INSN (p);
       if (p == 0 || GET_CODE (p) == CODE_LABEL)
        return 0;
+
       if (GET_CODE (p) == INSN
          /* If we don't want spill regs ...  */
          && (! (reload_reg_p != 0
                 && reload_reg_p != (short *) (HOST_WIDE_INT) 1)
-             /* ... then ignore insns introduced by reload; they aren't useful
-                and can cause results in reload_as_needed to be different
-                from what they were when calculating the need for spills.
-                If we notice an input-reload insn here, we will reject it below,
-                but it might hide a usable equivalent.  That makes bad code.
-                It may even abort: perhaps no reg was spilled for this insn
-                because it was assumed we would find that equivalent.  */
+             /* ... then ignore insns introduced by reload; they aren't
+                useful and can cause results in reload_as_needed to be
+                different from what they were when calculating the need for
+                spills.  If we notice an input-reload insn here, we will
+                reject it below, but it might hide a usable equivalent.
+                That makes bad code.  It may even abort: perhaps no reg was
+                spilled for this insn because it was assumed we would find
+                that equivalent.  */
              || INSN_UID (p) < reload_first_uid))
        {
          rtx tem;
          pat = single_set (p);
+
          /* First check for something that sets some reg equal to GOAL.  */
          if (pat != 0
              && ((regno >= 0
@@ -6166,8 +6108,8 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
   /* Reject registers that overlap GOAL.  */
 
   if (!goal_mem && !goal_const
-      && regno + HARD_REGNO_NREGS (regno, mode) > valueno
-      && regno < valueno + HARD_REGNO_NREGS (valueno, mode))
+      && regno + (int) HARD_REGNO_NREGS (regno, mode) > valueno
+      && regno < valueno + (int) HARD_REGNO_NREGS (valueno, mode))
     return 0;
 
   /* Reject VALUE if it is one of the regs reserved for reloads.
@@ -6180,14 +6122,6 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
       && reload_reg_p[valueno] >= 0)
     return 0;
 
-  /* On some machines, certain regs must always be rejected
-     because they don't behave the way ordinary registers do.  */
-
-#ifdef OVERLAPPING_REGNO_P
-  if (OVERLAPPING_REGNO_P (valueno))
-    return 0;
-#endif
-
   nregs = HARD_REGNO_NREGS (regno, mode);
   valuenregs = HARD_REGNO_NREGS (valueno, mode);
 
@@ -6243,14 +6177,6 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
        return 0;
 #endif
 
-#ifdef INSN_CLOBBERS_REGNO_P
-      if ((valueno >= 0 && valueno < FIRST_PSEUDO_REGISTER
-          && INSN_CLOBBERS_REGNO_P (p, valueno))
-         || (regno >= 0 && regno < FIRST_PSEUDO_REGISTER
-             && INSN_CLOBBERS_REGNO_P (p, regno)))
-       return 0;
-#endif
-
       if (GET_RTX_CLASS (GET_CODE (p)) == 'i')
        {
          pat = PATTERN (p);
@@ -6472,7 +6398,7 @@ find_inc_amount (x, inced)
 
 int
 regno_clobbered_p (regno, insn)
-     int regno;
+     unsigned int regno;
      rtx insn;
 {
   if (GET_CODE (PATTERN (insn)) == CLOBBER