OSDN Git Service

* doc/install.texi (xtensa-*-elf): New target.
[pf3gnuchains/gcc-fork.git] / gcc / reload.c
index 9ed9cd0..9b8cdc9 100644 (file)
@@ -1,6 +1,6 @@
 /* Search an insn for pseudo regs that must be in hard regs and are not.
    Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -642,7 +642,7 @@ get_secondary_mem (x, mode, opnum, type)
               : type == RELOAD_FOR_OUTPUT ? RELOAD_FOR_OUTPUT_ADDRESS
               : RELOAD_OTHER);
 
-      find_reloads_address (mode, (rtx*)0, XEXP (loc, 0), &XEXP (loc, 0),
+      find_reloads_address (mode, (rtx*) 0, XEXP (loc, 0), &XEXP (loc, 0),
                            opnum, type, 0, 0);
     }
 
@@ -913,7 +913,7 @@ push_reload (in, out, inloc, outloc, class,
 
       default:
        break;
-    }
+      }
 
   /* If we are reloading a (SUBREG constant ...), really reload just the
      inside expression in its own mode.  Similarly for (SUBREG (PLUS ...)).
@@ -1047,7 +1047,7 @@ push_reload (in, out, inloc, outloc, class,
         order as the reloads.  Thus if the outer reload is also of type
         RELOAD_OTHER, we are guaranteed that this inner reload will be
         output before the outer reload.  */
-      push_reload (SUBREG_REG (in), NULL_RTX, &SUBREG_REG (in), (rtx *)0,
+      push_reload (SUBREG_REG (in), NULL_RTX, &SUBREG_REG (in), (rtx *) 0,
                   in_class, VOIDmode, VOIDmode, 0, 0, opnum, type);
       dont_remove_subreg = 1;
     }
@@ -1641,6 +1641,16 @@ combine_reloads ()
   if (earlyclobber_operand_p (rld[output_reload].out))
     return;
 
+  /* If there is a reload for part of the address of this operand, we would
+     need to chnage it to RELOAD_FOR_OTHER_ADDRESS.  But that would extend
+     its life to the point where doing this combine would not lower the
+     number of spill registers needed.  */
+  for (i = 0; i < n_reloads; i++)
+    if ((rld[i].when_needed == RELOAD_FOR_OUTPUT_ADDRESS
+        || rld[i].when_needed == RELOAD_FOR_OUTADDR_ADDRESS)
+       && rld[i].opnum == rld[output_reload].opnum)
+      return;
+
   /* Check each input reload; can we combine it?  */
 
   for (i = 0; i < n_reloads; i++)
@@ -1915,7 +1925,7 @@ find_dummy_reload (real_in, real_out, inloc, outloc,
       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, (rtx*)0)
+      if (! refers_to_regno_for_reload_p (regno, regno + nwords, out, (rtx*) 0)
          && ! hard_reg_set_here_p (regno, regno + nwords,
                                    PATTERN (this_insn))
          && (! earlyclobber
@@ -2334,7 +2344,7 @@ immune_p (x, y, ydata)
   struct decomposition xdata;
 
   if (ydata.reg_flag)
-    return !refers_to_regno_for_reload_p (ydata.start, ydata.end, x, (rtx*)0);
+    return !refers_to_regno_for_reload_p (ydata.start, ydata.end, x, (rtx*) 0);
   if (ydata.safe)
     return 1;
 
@@ -2613,7 +2623,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
        ;
       else if (constraints[i][0] == 'p')
        {
-         find_reloads_address (VOIDmode, (rtx*)0,
+         find_reloads_address (VOIDmode, (rtx*) 0,
                                recog_data.operand[i],
                                recog_data.operand_loc[i],
                                i, operand_type[i], ind_levels, insn);
@@ -3019,7 +3029,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
              case 'p':
                /* All necessary reloads for an address_operand
                   were handled in find_reloads_address.  */
-               this_alternative[i] = (int) BASE_REG_CLASS;
+               this_alternative[i] = (int) MODE_BASE_REG_CLASS (VOIDmode);
                win = 1;
                break;
 
@@ -3500,6 +3510,12 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
 
          recog_data.operand[commutative] = substed_operand[commutative + 1];
          recog_data.operand[commutative + 1] = substed_operand[commutative];
+         /* Swap the duplicates too.  */
+         for (i = 0; i < recog_data.n_dups; i++)
+           if (recog_data.dup_num[i] == commutative
+               || recog_data.dup_num[i] == commutative + 1)
+             *recog_data.dup_loc[i]
+                = recog_data.operand[(int) recog_data.dup_num[i]];
 
          tclass = preferred_class[commutative];
          preferred_class[commutative] = preferred_class[commutative + 1];
@@ -3518,6 +3534,12 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
          recog_data.operand[commutative] = substed_operand[commutative];
          recog_data.operand[commutative + 1]
            = substed_operand[commutative + 1];
+         /* Unswap the duplicates too.  */
+         for (i = 0; i < recog_data.n_dups; i++)
+           if (recog_data.dup_num[i] == commutative
+               || recog_data.dup_num[i] == commutative + 1)
+             *recog_data.dup_loc[i]
+                = recog_data.operand[(int) recog_data.dup_num[i]];
        }
     }
 
@@ -3530,7 +3552,7 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
     {
       /* No alternative works with reloads??  */
       if (insn_code_number >= 0)
-       fatal_insn ("Unable to generate reloads for:", insn);
+       fatal_insn ("unable to generate reloads for:", insn);
       error_for_asm (insn, "inconsistent operand constraints in an `asm'");
       /* Avoid further trouble with this insn.  */
       PATTERN (insn) = gen_rtx_USE (VOIDmode, const0_rtx);
@@ -3663,8 +3685,8 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
          {
            operand_reloadnum[i]
              = push_reload (XEXP (recog_data.operand[i], 0), NULL_RTX,
-                            &XEXP (recog_data.operand[i], 0), (rtx*)0,
-                            BASE_REG_CLASS,
+                            &XEXP (recog_data.operand[i], 0), (rtx*) 0,
+                            MODE_BASE_REG_CLASS (VOIDmode),
                             GET_MODE (XEXP (recog_data.operand[i], 0)),
                             VOIDmode, 0, 0, i, RELOAD_FOR_INPUT);
            rld[operand_reloadnum[i]].inc
@@ -4219,6 +4241,23 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p)
       rld[i].nregs = CLASS_MAX_NREGS (rld[i].class, rld[i].mode);
     }
 
+  /* Special case a simple move with an input reload and a
+     destination of a hard reg, if the hard reg is ok, use it.  */
+  for (i = 0; i < n_reloads; i++)
+    if (rld[i].when_needed == RELOAD_FOR_INPUT
+       && GET_CODE (PATTERN (insn)) == SET
+       && GET_CODE (SET_DEST (PATTERN (insn))) == REG
+       && SET_SRC (PATTERN (insn)) == rld[i].in)
+      {
+       rtx dest = SET_DEST (PATTERN (insn));
+       unsigned int regno = REGNO (dest);
+
+       if (regno < FIRST_PSEUDO_REGISTER
+           && TEST_HARD_REG_BIT (reg_class_contents[rld[i].class], regno)
+           && HARD_REGNO_MODE_OK (regno, rld[i].mode))
+         rld[i].reg_rtx = dest;
+      }
+
   return retval;
 }
 
@@ -4546,7 +4585,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
              tem = make_memloc (ad, regno);
              if (! strict_memory_address_p (GET_MODE (tem), XEXP (tem, 0)))
                {
-                 find_reloads_address (GET_MODE (tem), (rtx*)0, XEXP (tem, 0),
+                 find_reloads_address (GET_MODE (tem), (rtx*) 0, XEXP (tem, 0),
                                        &XEXP (tem, 0), opnum, ADDR_TYPE (type),
                                        ind_levels, insn);
                }
@@ -4595,7 +4634,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
        return 0;
 
       /* If we do not have one of the cases above, we must do the reload.  */
-      push_reload (ad, NULL_RTX, loc, (rtx*)0, BASE_REG_CLASS,
+      push_reload (ad, NULL_RTX, loc, (rtx*) 0, MODE_BASE_REG_CLASS (mode),
                   GET_MODE (ad), VOIDmode, 0, 0, opnum, type);
       return 1;
     }
@@ -4695,8 +4734,8 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
        {
          /* Must use TEM here, not AD, since it is the one that will
             have any subexpressions reloaded, if needed.  */
-         push_reload (tem, NULL_RTX, loc, (rtx*)0,
-                      BASE_REG_CLASS, GET_MODE (tem),
+         push_reload (tem, NULL_RTX, loc, (rtx*) 0,
+                      MODE_BASE_REG_CLASS (mode), GET_MODE (tem),
                       VOIDmode, 0,
                       0, opnum, type);
          return ! removed_and;
@@ -4742,7 +4781,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
          /* If the sum of two regs is not necessarily valid,
             reload the sum into a base reg.
             That will at least work.  */
-         find_reloads_address_part (ad, loc, BASE_REG_CLASS,
+         find_reloads_address_part (ad, loc, MODE_BASE_REG_CLASS (mode),
                                     Pmode, opnum, type, ind_levels);
        }
       return ! removed_and;
@@ -4785,7 +4824,8 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
                                plus_constant (XEXP (XEXP (ad, 0), 0),
                                               INTVAL (XEXP (ad, 1))),
                                XEXP (XEXP (ad, 0), 1));
-      find_reloads_address_part (XEXP (ad, 0), &XEXP (ad, 0), BASE_REG_CLASS,
+      find_reloads_address_part (XEXP (ad, 0), &XEXP (ad, 0),
+                                MODE_BASE_REG_CLASS (mode),
                                 GET_MODE (ad), opnum, type, ind_levels);
       find_reloads_address_1 (mode, XEXP (ad, 1), 1, &XEXP (ad, 1), opnum,
                              type, 0, insn);
@@ -4809,7 +4849,8 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
                                XEXP (XEXP (ad, 0), 0),
                                plus_constant (XEXP (XEXP (ad, 0), 1),
                                               INTVAL (XEXP (ad, 1))));
-      find_reloads_address_part (XEXP (ad, 1), &XEXP (ad, 1), BASE_REG_CLASS,
+      find_reloads_address_part (XEXP (ad, 1), &XEXP (ad, 1),
+                                MODE_BASE_REG_CLASS (mode),
                                 GET_MODE (ad), opnum, type, ind_levels);
       find_reloads_address_1 (mode, XEXP (ad, 0), 1, &XEXP (ad, 0), opnum,
                              type, 0, insn);
@@ -4855,8 +4896,8 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn)
            loc = &XEXP (*loc, 0);
        }
 
-      find_reloads_address_part (ad, loc, BASE_REG_CLASS, Pmode, opnum, type,
-                                ind_levels);
+      find_reloads_address_part (ad, loc, MODE_BASE_REG_CLASS (mode),
+                                Pmode, opnum, type, ind_levels);
       return ! removed_and;
     }
 
@@ -5281,7 +5322,8 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
                    /* Then reload the memory location into a base
                       register.  */
                    reloadnum = push_reload (tem, tem, &XEXP (x, 0),
-                                            &XEXP (op1, 0), BASE_REG_CLASS,
+                                            &XEXP (op1, 0),
+                                            MODE_BASE_REG_CLASS (mode),
                                             GET_MODE (x), GET_MODE (x), 0,
                                             0, opnum, RELOAD_OTHER);
 
@@ -5298,7 +5340,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
              {
                reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0),
                                         &XEXP (op1, 0), &XEXP (x, 0),
-                                        BASE_REG_CLASS,
+                                        MODE_BASE_REG_CLASS (mode),
                                         GET_MODE (x), GET_MODE (x), 0, 0,
                                         opnum, RELOAD_OTHER);
 
@@ -5399,15 +5441,17 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
                  x = XEXP (x, 0);
                  reloadnum
                    = push_reload (x, x, loc, loc,
-                                  (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
+                                  (context ? INDEX_REG_CLASS :
+                                   MODE_BASE_REG_CLASS (mode)),
                                   GET_MODE (x), GET_MODE (x), 0, 0,
                                   opnum, RELOAD_OTHER);
                }
              else
                {
                  reloadnum
-                   = push_reload (x, NULL_RTX, loc, (rtx*)0,
-                                  (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
+                   = push_reload (x, NULL_RTX, loc, (rtx*) 0,
+                                  (context ? INDEX_REG_CLASS :
+                                   MODE_BASE_REG_CLASS (mode)),
                                   GET_MODE (x), GET_MODE (x), 0, 0,
                                   opnum, type);
                  rld[reloadnum].inc
@@ -5446,8 +5490,9 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
                                XEXP (XEXP (x, 0), 0), &XEXP (XEXP (x, 0), 0),
                                opnum, type, ind_levels, insn);
 
-         reloadnum = push_reload (x, NULL_RTX, loc, (rtx*)0,
-                                  (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
+         reloadnum = push_reload (x, NULL_RTX, loc, (rtx*) 0,
+                                  (context ? INDEX_REG_CLASS :
+                                   MODE_BASE_REG_CLASS (mode)),
                                   GET_MODE (x), VOIDmode, 0, 0, opnum, type);
          rld[reloadnum].inc
            = find_inc_amount (PATTERN (this_insn), XEXP (x, 0));
@@ -5475,8 +5520,8 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
 
       find_reloads_address (GET_MODE (x), loc, XEXP (x, 0), &XEXP (x, 0),
                            opnum, ADDR_TYPE (type), ind_levels, insn);
-      push_reload (*loc, NULL_RTX, loc, (rtx*)0,
-                  (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
+      push_reload (*loc, NULL_RTX, loc, (rtx*) 0,
+                  (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
                   GET_MODE (x), VOIDmode, 0, 0, opnum, type);
       return 1;
 
@@ -5487,7 +5532,8 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
        if (reg_equiv_constant[regno] != 0)
          {
            find_reloads_address_part (reg_equiv_constant[regno], loc,
-                                      (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
+                                      (context ? INDEX_REG_CLASS :
+                                       MODE_BASE_REG_CLASS (mode)),
                                       GET_MODE (x), opnum, type, ind_levels);
            return 1;
          }
@@ -5496,8 +5542,9 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
         that feeds this insn.  */
        if (reg_equiv_mem[regno] != 0)
          {
-           push_reload (reg_equiv_mem[regno], NULL_RTX, loc, (rtx*)0,
-                        (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
+           push_reload (reg_equiv_mem[regno], NULL_RTX, loc, (rtx*) 0,
+                        (context ? INDEX_REG_CLASS :
+                         MODE_BASE_REG_CLASS (mode)),
                         GET_MODE (x), VOIDmode, 0, 0, opnum, type);
            return 1;
          }
@@ -5524,8 +5571,8 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
             || !(context ? REGNO_OK_FOR_INDEX_P (regno)
                  : REGNO_MODE_OK_FOR_BASE_P (regno, mode))))
          {
-           push_reload (x, NULL_RTX, loc, (rtx*)0,
-                        (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
+           push_reload (x, NULL_RTX, loc, (rtx*) 0,
+                        (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
                         GET_MODE (x), VOIDmode, 0, 0, opnum, type);
            return 1;
          }
@@ -5536,8 +5583,8 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
           from before this insn to after it.  */
        if (regno_clobbered_p (regno, this_insn, GET_MODE (x), 0))
          {
-           push_reload (x, NULL_RTX, loc, (rtx*)0,
-                        (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
+           push_reload (x, NULL_RTX, loc, (rtx*) 0,
+                        (context ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (mode)),
                         GET_MODE (x), VOIDmode, 0, 0, opnum, type);
            return 1;
          }
@@ -5557,8 +5604,9 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
              if (! (context ? REGNO_OK_FOR_INDEX_P (regno)
                     : REGNO_MODE_OK_FOR_BASE_P (regno, mode)))
                {
-                 push_reload (x, NULL_RTX, loc, (rtx*)0,
-                              (context ? INDEX_REG_CLASS : BASE_REG_CLASS),
+                 push_reload (x, NULL_RTX, loc, (rtx*) 0,
+                              (context ? INDEX_REG_CLASS :
+                               MODE_BASE_REG_CLASS (mode)),
                               GET_MODE (x), VOIDmode, 0, 0, opnum, type);
                  return 1;
                }
@@ -5568,13 +5616,13 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn)
          else
            {
              enum reg_class class = (context ? INDEX_REG_CLASS
-                                     : BASE_REG_CLASS);
+                                     : MODE_BASE_REG_CLASS (mode));
              if (CLASS_MAX_NREGS (class, GET_MODE (SUBREG_REG (x)))
                  > reg_class_size[class])
                {
                  x = find_reloads_subreg_address (x, 0, opnum, type,
                                                   ind_levels, insn);
-                 push_reload (x, NULL_RTX, loc, (rtx*)0, class,
+                 push_reload (x, NULL_RTX, loc, (rtx*) 0, class,
                               GET_MODE (x), VOIDmode, 0, 0, opnum, type);
                  return 1;
                }
@@ -5650,7 +5698,7 @@ find_reloads_address_part (x, loc, class, mode, opnum, type, ind_levels)
                            opnum, type, ind_levels, 0);
     }
 
-  push_reload (x, NULL_RTX, loc, (rtx*)0, class,
+  push_reload (x, NULL_RTX, loc, (rtx*) 0, class,
               mode, VOIDmode, 0, 0, opnum, type);
 }
 \f
@@ -6014,7 +6062,7 @@ refers_to_regno_for_reload_p (regno, endregno, x, loc)
          if (reg_equiv_memory_loc[r])
            return refers_to_regno_for_reload_p (regno, endregno,
                                                 reg_equiv_memory_loc[r],
-                                                (rtx*)0);
+                                                (rtx*) 0);
 
          if (reg_equiv_constant[r])
            return 0;
@@ -6118,7 +6166,8 @@ reg_overlap_mentioned_for_reload_p (x, in)
   int regno, endregno;
 
   /* Overly conservative.  */
-  if (GET_CODE (x) == STRICT_LOW_PART)
+  if (GET_CODE (x) == STRICT_LOW_PART
+      || GET_RTX_CLASS (GET_CODE (x)) == 'a')
     x = XEXP (x, 0);
 
   /* If either argument is a constant, then modifying X can not affect IN.  */
@@ -6154,13 +6203,16 @@ reg_overlap_mentioned_for_reload_p (x, in)
   else if (GET_CODE (x) == SCRATCH || GET_CODE (x) == PC
           || GET_CODE (x) == CC0)
     return reg_mentioned_p (x, in);
+  else if (GET_CODE (x) == PLUS)
+    return (reg_overlap_mentioned_for_reload_p (XEXP (x, 0), in)
+           || reg_overlap_mentioned_for_reload_p (XEXP (x, 1), in));
   else
     abort ();
 
   endregno = regno + (regno < FIRST_PSEUDO_REGISTER
                      ? HARD_REGNO_NREGS (regno, GET_MODE (x)) : 1);
 
-  return refers_to_regno_for_reload_p (regno, endregno, in, (rtx*)0);
+  return refers_to_regno_for_reload_p (regno, endregno, in, (rtx*) 0);
 }
 
 /* Return nonzero if anything in X contains a MEM.  Look also for pseudo
@@ -6415,7 +6467,7 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
       && refers_to_regno_for_reload_p (valueno,
                                       (valueno
                                        + HARD_REGNO_NREGS (valueno, mode)),
-                                      goal, (rtx*)0))
+                                      goal, (rtx*) 0))
     return 0;
 
   /* Reject registers that overlap GOAL.  */