OSDN Git Service

(pred): Fix additional typo in `comparison_operator'.
[pf3gnuchains/gcc-fork.git] / gcc / local-alloc.c
index 5f48a88..00c06e8 100644 (file)
@@ -1,5 +1,5 @@
 /* Allocate registers within a basic block, for GNU compiler.
-   Copyright (C) 1987, 1988, 1991 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1991, 1993 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -65,6 +65,17 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "recog.h"
 #include "output.h"
 \f
+/* Pseudos allocated here cannot be reallocated by global.c if the hard
+   register is used as a spill register.  So we don't allocate such pseudos
+   here if their preferred class is likely to be used by spills.
+
+   On most machines, the appropriate test is if the class has one
+   register, so we default to that.  */
+
+#ifndef CLASS_LIKELY_SPILLED_P
+#define CLASS_LIKELY_SPILLED_P(CLASS) (reg_class_size[(int) (CLASS)] == 1)
+#endif
+
 /* Next quantity number available for allocation.  */
 
 static int next_qty;
@@ -105,7 +116,7 @@ static char *qty_phys_has_sugg;
 
 /* Element Q is the number of refs to quantity Q.  */
 
-static short *qty_n_refs;
+static int *qty_n_refs;
 
 /* Element Q is a reg class contained in (smaller than) the
    preferred classes of all the pseudo regs that are tied in quantity Q.
@@ -145,9 +156,10 @@ static enum machine_mode *qty_mode;
 
 static int *qty_n_calls_crossed;
 
-/* Nonzero means don't allocate qty Q if we can't get its preferred class.  */
+/* Register class within which we allocate qty Q if we can't get
+   its preferred class.  */
 
-static char *qty_preferred_or_nothing;
+static enum reg_class *qty_alternate_class;
 
 /* Element Q is the SCRATCH expression for which this quantity is being
    allocated or 0 if this quantity is allocating registers.  */
@@ -158,13 +170,13 @@ static rtx *qty_scratch_rtx;
    reg_qty value is Q, or -1 is this quantity is for a SCRATCH.  This
    register should be the head of the chain maintained in reg_next_in_qty.  */
 
-static short *qty_first_reg;
+static int *qty_first_reg;
 
 /* If (REG N) has been assigned a quantity number, is a register number
    of another register assigned the same quantity number, or -1 for the
    end of the chain.  qty_first_reg point to the head of this chain.  */
 
-static short *reg_next_in_qty;
+static int *reg_next_in_qty;
 
 /* reg_qty[N] (where N is a pseudo reg number) is the qty number of that reg
    if it is >= 0,
@@ -215,6 +227,11 @@ static HARD_REG_SET regs_live;
 
 static HARD_REG_SET *regs_live_at;
 
+int *scratch_block;
+rtx *scratch_list;
+int scratch_list_length;
+static int scratch_index;
+
 /* Communicate local vars `insn_number' and `insn'
    from `block_alloc' to `reg_is_set', `wipe_dead_reg', and `alloc_qty'.  */
 static int this_insn_number;
@@ -258,7 +275,7 @@ alloc_qty (regno, mode, size, birth)
   qty_birth[qty] = birth;
   qty_n_calls_crossed[qty] = reg_n_calls_crossed[regno];
   qty_min_class[qty] = reg_preferred_class (regno);
-  qty_preferred_or_nothing[qty] = reg_preferred_or_nothing (regno);
+  qty_alternate_class[qty] = reg_alternate_class (regno);
   qty_n_refs[qty] = reg_n_refs[regno];
 }
 \f
@@ -278,6 +295,7 @@ alloc_qty_for_scratch (scratch, n, insn, insn_code_num, insn_number)
   char *p, c;
   int i;
 
+#ifdef REGISTER_CONSTRAINTS
   /* If we haven't yet computed which alternative will be used, do so now.
      Then set P to the constraints for that alternative.  */
   if (which_alternative == -1)
@@ -327,13 +345,15 @@ alloc_qty_for_scratch (scratch, n, insn, insn_code_num, insn_number)
        break;
       }
 
-  /* If CLASS has only one register, don't allocate the SCRATCH here since
-     it will prevent that register from being used as a spill register.
-     reload will do the allocation.  */
-
-  if (class == NO_REGS || reg_class_size[(int) class] == 1)
+  if (class == NO_REGS)
     return;
 
+#else /* REGISTER_CONSTRAINTS */
+
+  class = GENERAL_REGS;
+#endif
+  
+
   qty = next_qty++;
 
   qty_first_reg[qty] = -1;
@@ -344,7 +364,7 @@ alloc_qty_for_scratch (scratch, n, insn, insn_code_num, insn_number)
   qty_death[qty] = 2 * insn_number + 1;
   qty_n_calls_crossed[qty] = 0;
   qty_min_class[qty] = class;
-  qty_preferred_or_nothing[qty] = 1;
+  qty_alternate_class[qty] = NO_REGS;
   qty_n_refs[qty] = 1;
 }
 \f
@@ -368,14 +388,26 @@ local_alloc ()
   update_equiv_regs ();
 
   /* This sets the maximum number of quantities we can have.  Quantity
-     numbers start at zero and we can have one for each psuedo plus the
-     number of SCRATCHs in the largest block, in the worst case.  */
+     numbers start at zero and we can have one for each pseudo plus the
+     number of SCRATCHes in the largest block, in the worst case.  */
   max_qty = (max_regno - FIRST_PSEUDO_REGISTER) + max_scratch;
 
   /* Allocate vectors of temporary data.
      See the declarations of these variables, above,
      for what they mean.  */
 
+  /* There can be up to MAX_SCRATCH * N_BASIC_BLOCKS SCRATCHes to allocate.
+     Instead of allocating this much memory from now until the end of
+     reload, only allocate space for MAX_QTY SCRATCHes.  If there are more
+     reload will allocate them.  */
+
+  scratch_list_length = max_qty;
+  scratch_list = (rtx *) xmalloc (scratch_list_length * sizeof (rtx));
+  bzero (scratch_list, scratch_list_length * sizeof (rtx));
+  scratch_block = (int *) xmalloc (scratch_list_length * sizeof (int));
+  bzero (scratch_block, scratch_list_length * sizeof (int));
+  scratch_index = 0;
+
   qty_phys_reg = (short *) alloca (max_qty * sizeof (short));
   qty_phys_copy_sugg = (HARD_REG_SET *) alloca (max_qty * sizeof (HARD_REG_SET));
   qty_phys_has_copy_sugg = (char *) alloca (max_qty * sizeof (char));
@@ -384,17 +416,17 @@ local_alloc ()
   qty_birth = (int *) alloca (max_qty * sizeof (int));
   qty_death = (int *) alloca (max_qty * sizeof (int));
   qty_scratch_rtx = (rtx *) alloca (max_qty * sizeof (rtx));
-  qty_first_reg = (short *) alloca (max_qty * sizeof (short));
+  qty_first_reg = (int *) alloca (max_qty * sizeof (int));
   qty_size = (int *) alloca (max_qty * sizeof (int));
   qty_mode = (enum machine_mode *) alloca (max_qty * sizeof (enum machine_mode));
   qty_n_calls_crossed = (int *) alloca (max_qty * sizeof (int));
   qty_min_class = (enum reg_class *) alloca (max_qty * sizeof (enum reg_class));
-  qty_preferred_or_nothing = (char *) alloca (max_qty);
-  qty_n_refs = (short *) alloca (max_qty * sizeof (short));
+  qty_alternate_class = (enum reg_class *) alloca (max_qty * sizeof (enum reg_class));
+  qty_n_refs = (int *) alloca (max_qty * sizeof (int));
 
   reg_qty = (int *) alloca (max_regno * sizeof (int));
   reg_offset = (char *) alloca (max_regno * sizeof (char));
-  reg_next_in_qty = (short *) alloca (max_regno * sizeof (short));
+  reg_next_in_qty = (int *) alloca (max_regno * sizeof (int));
 
   reg_renumber = (short *) oballoc (max_regno * sizeof (short));
   for (i = 0; i < max_regno; i++)
@@ -403,7 +435,7 @@ local_alloc ()
   /* Determine which pseudo-registers can be allocated by local-alloc.
      In general, these are the registers used only in a single block and
      which only die once.  However, if a register's preferred class has only
-     one entry, don't allocate this register here unless it is preferred
+     a few entries, don't allocate this register here unless it is preferred
      or nothing since retry_global_alloc won't be able to move it to
      GENERAL_REGS if a reload register of this class is needed.
 
@@ -413,8 +445,8 @@ local_alloc ()
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     {
       if (reg_basic_block[i] >= 0 && reg_n_deaths[i] == 1
-         && (reg_preferred_or_nothing (i)
-             || reg_class_size[(int) reg_preferred_class (i)] > 1))
+         && (reg_alternate_class (i) == NO_REGS
+             || ! CLASS_LIKELY_SPILLED_P (reg_preferred_class (i))))
        reg_qty[i] = -2;
       else
        reg_qty[i] = -1;
@@ -640,7 +672,7 @@ memref_used_between_p (memref, start, end)
    register-register copy.  */
 
 static void
-optimize_reg_copy (insn, dest, src)
+optimize_reg_copy_1 (insn, dest, src)
      rtx insn;
      rtx dest;
      rtx src;
@@ -678,11 +710,16 @@ optimize_reg_copy (insn, dest, src)
              && reg_overlap_mentioned_p (src, XEXP (PATTERN (p), 0))))
        break;
 
-      if ((note = find_regno_note (p, REG_DEAD, sregno)) != 0)
+      /* See if all of SRC dies in P.  This test is slightly more
+        conservative than it needs to be. */
+      if ((note = find_regno_note (p, REG_DEAD, sregno)) != 0
+         && GET_MODE (XEXP (note, 0)) == GET_MODE (src))
        {
          int failed = 0;
          int length = 0;
+         int d_length = 0;
          int n_calls = 0;
+         int d_n_calls = 0;
 
          /* We can do the optimization.  Scan forward from INSN again,
             replacing regs as we go.  Set FAILED if a replacement can't
@@ -694,9 +731,23 @@ optimize_reg_copy (insn, dest, src)
               q != next_real_insn (p);
               q = next_real_insn (q))
            {
-             if (reg_mentioned_p (src, PATTERN (q)))
+             if (reg_overlap_mentioned_p (src, PATTERN (q)))
                {
-                 if (validate_replace_rtx (src, dest, q))
+                 /* If SRC is a hard register, we might miss some
+                    overlapping registers with validate_replace_rtx,
+                    so we would have to undo it.  We can't if DEST is
+                    present in the insn, so fail in that combination
+                    of cases.  */
+                 if (sregno < FIRST_PSEUDO_REGISTER
+                     && reg_mentioned_p (dest, PATTERN (q)))
+                   failed = 1;
+
+                 /* Replace all uses and make sure that the register
+                    isn't still present.  */
+                 else if (validate_replace_rtx (src, dest, q)
+                          && (sregno >= FIRST_PSEUDO_REGISTER
+                              || ! reg_overlap_mentioned_p (src,
+                                                            PATTERN (q))))
                    {
                      /* We assume that a register is used exactly once per
                         insn in the updates below.  If this is not correct,
@@ -707,26 +758,31 @@ optimize_reg_copy (insn, dest, src)
                        reg_n_refs[dregno] += loop_depth;
                    }
                  else
-                   failed = 1;
+                   {
+                     validate_replace_rtx (dest, src, q);
+                     failed = 1;
+                   }
                }
 
              /* Count the insns and CALL_INSNs passed.  If we passed the
                 death note of DEST, show increased live length.  */
              length++;
              if (dest_death)
-               reg_live_length[dregno]++;
+               d_length++;
 
              if (GET_CODE (q) == CALL_INSN)
                {
                  n_calls++;
                  if (dest_death)
-                   reg_n_calls_crossed[dregno]++;
+                   d_n_calls++;
                }
 
              /* If DEST dies here, remove the death note and save it for
-                later.  */
+                later.  Make sure ALL of DEST dies here; again, this is
+                overly conservative.  */
              if (dest_death == 0
-                 && (dest_death = find_regno_note (q, REG_DEAD, dregno)) != 0)
+                 && (dest_death = find_regno_note (q, REG_DEAD, dregno)) != 0
+                 && GET_MODE (XEXP (dest_death, 0)) == GET_MODE (dest))
                remove_note (q, dest_death);
            }
 
@@ -738,6 +794,12 @@ optimize_reg_copy (insn, dest, src)
                  reg_n_calls_crossed[sregno] -= n_calls;
                }
 
+             if (dregno >= FIRST_PSEUDO_REGISTER)
+               {
+                 reg_live_length[dregno] += d_length;
+                 reg_n_calls_crossed[dregno] += d_n_calls;
+               }
+
              /* Move death note of SRC from P to INSN.  */
              remove_note (p, note);
              XEXP (note, 1) = REG_NOTES (insn);
@@ -753,6 +815,91 @@ optimize_reg_copy (insn, dest, src)
 
          return;
        }
+
+      /* If SRC is a hard register which is set or killed in some other
+        way, we can't do this optimization.  */
+      else if (sregno < FIRST_PSEUDO_REGISTER
+              && dead_or_set_p (p, src))
+       break;
+    }
+}
+\f
+/* INSN is a copy of SRC to DEST, in which SRC dies.  See if we now have
+   a sequence of insns that modify DEST followed by an insn that sets
+   SRC to DEST in which DEST dies, with no prior modification of DEST.
+   (There is no need to check if the insns in between actually modify
+   DEST.  We should not have cases where DEST is not modified, but
+   the optimization is safe if no such modification is detected.)
+   In that case, we can replace all uses of DEST, starting with INSN and
+   ending with the set of SRC to DEST, with SRC.  We do not do this
+   optimization if a CALL_INSN is crossed unless SRC already crosses a
+   call.
+
+   It is assumed that DEST and SRC are pseudos; it is too complicated to do
+   this for hard registers since the substitutions we may make might fail.  */
+
+static void
+optimize_reg_copy_2 (insn, dest, src)
+     rtx insn;
+     rtx dest;
+     rtx src;
+{
+  rtx p, q;
+  rtx set;
+  int sregno = REGNO (src);
+  int dregno = REGNO (dest);
+
+  for (p = NEXT_INSN (insn); p; p = NEXT_INSN (p))
+    {
+      if (GET_CODE (p) == CODE_LABEL || GET_CODE (p) == JUMP_INSN
+         || (GET_CODE (p) == NOTE
+             && (NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_BEG
+                 || NOTE_LINE_NUMBER (p) == NOTE_INSN_LOOP_END)))
+       break;
+
+      if (GET_RTX_CLASS (GET_CODE (p)) != 'i')
+       continue;
+
+      set = single_set (p);
+      if (set && SET_SRC (set) == dest && SET_DEST (set) == src
+         && find_reg_note (p, REG_DEAD, dest))
+       {
+         /* We can do the optimization.  Scan forward from INSN again,
+            replacing regs as we go.  */
+
+         /* Set to stop at next insn.  */
+         for (q = insn; q != NEXT_INSN (p); q = NEXT_INSN (q))
+           if (GET_RTX_CLASS (GET_CODE (q)) == 'i')
+             {
+               if (reg_mentioned_p (dest, PATTERN (q)))
+                 {
+                   PATTERN (q) = replace_rtx (PATTERN (q), dest, src);
+
+                   /* We assume that a register is used exactly once per
+                      insn in the updates below.  If this is not correct,
+                      no great harm is done.  */
+                   reg_n_refs[dregno] -= loop_depth;
+                   reg_n_refs[sregno] += loop_depth;
+                 }
+
+
+             if (GET_CODE (q) == CALL_INSN)
+               {
+                 reg_n_calls_crossed[dregno]--;
+                 reg_n_calls_crossed[sregno]++;
+               }
+             }
+
+         remove_note (p, find_reg_note (p, REG_DEAD, dest));
+         reg_n_deaths[dregno]--;
+         remove_note (insn, find_reg_note (insn, REG_DEAD, src));
+         reg_n_deaths[sregno]--;
+         return;
+       }
+
+      if (reg_set_p (src, p)
+         || (GET_CODE (p) == CALL_INSN && reg_n_calls_crossed[sregno] == 0))
+       break;
     }
 }
 \f            
@@ -825,7 +972,15 @@ update_equiv_regs ()
       if (flag_expensive_optimizations && GET_CODE (dest) == REG
          && GET_CODE (SET_SRC (set)) == REG
          && ! find_reg_note (insn, REG_DEAD, SET_SRC (set)))
-       optimize_reg_copy (insn, dest, SET_SRC (set));
+       optimize_reg_copy_1 (insn, dest, SET_SRC (set));
+
+      /* Similarly for a pseudo-pseudo copy when SRC is dead.  */
+      else if (flag_expensive_optimizations && GET_CODE (dest) == REG
+              && REGNO (dest) >= FIRST_PSEUDO_REGISTER
+              && GET_CODE (SET_SRC (set)) == REG
+              && REGNO (SET_SRC (set)) >= FIRST_PSEUDO_REGISTER
+              && find_reg_note (insn, REG_DEAD, SET_SRC (set)))
+       optimize_reg_copy_2 (insn, dest, SET_SRC (set));
 
       /* Otherwise, we only handle the case of a pseudo register being set
         once.  */
@@ -834,7 +989,7 @@ update_equiv_regs ()
          || reg_n_sets[regno] != 1)
        continue;
 
-      note = find_reg_note (insn, REG_EQUAL, 0);
+      note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
 
       /* Record this insn as initializing this register.  */
       reg_equiv_init_insn[regno] = insn;
@@ -859,7 +1014,7 @@ update_equiv_regs ()
         MEM remains unchanged for the life of the register, add a REG_EQUIV
         note.  */
         
-      note = find_reg_note (insn, REG_EQUIV, 0);
+      note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
 
       if (note == 0 && reg_basic_block[regno] >= 0
          && GET_CODE (SET_SRC (set)) == MEM
@@ -942,8 +1097,11 @@ block_alloc (b)
   int insn_number = 0;
   int insn_count = 0;
   int max_uid = get_max_uid ();
-  short *qty_order;
+  int *qty_order;
   int no_conflict_combined_regno = -1;
+  /* Counter to prevent allocating more SCRATCHes than can be stored
+     in SCRATCH_LIST.  */
+  int scratches_allocated = scratch_index;
 
   /* Count the instructions in the basic block.  */
 
@@ -1005,48 +1163,88 @@ block_alloc (b)
             Suitable insns are those with at least two operands and where
             operand 0 is an output that is a register that is not
             earlyclobber.
-            For a commutative operation, try (set reg0 (arithop ... reg1)).
+
+            We can tie operand 0 with some operand that dies in this insn.
+            First look for operands that are required to be in the same
+            register as operand 0.  If we find such, only try tying that
+            operand or one that can be put into that operand if the
+            operation is commutative.  If we don't find an operand
+            that is required to be in the same register as operand 0,
+            we can tie with any operand.
+
             Subregs in place of regs are also ok.
 
             If tying is done, WIN is set nonzero.  */
 
          if (insn_code_number >= 0
+#ifdef REGISTER_CONSTRAINTS
              && insn_n_operands[insn_code_number] > 1
              && insn_operand_constraint[insn_code_number][0][0] == '='
-             && insn_operand_constraint[insn_code_number][0][1] != '&')
+             && insn_operand_constraint[insn_code_number][0][1] != '&'
+#else
+             && GET_CODE (PATTERN (insn)) == SET
+             && rtx_equal_p (SET_DEST (PATTERN (insn)), recog_operand[0])
+#endif
+             )
            {
-             r0 = recog_operand[0];
-             r1 = recog_operand[1];
+#ifdef REGISTER_CONSTRAINTS
+             int must_match_0 = -1;
+
 
-             /* If the first operand is an address, find a register in it.
-                There may be more than one register, but we only try one of
-                them.  */
-             if (insn_operand_constraint[insn_code_number][1][0] == 'p')
-               while (GET_CODE (r1) == PLUS || GET_CODE (r1) == MULT)
-                 r1 = XEXP (r1, 0);
+             for (i = 1; i < insn_n_operands[insn_code_number]; i++)
+               if (requires_inout_p
+                   (insn_operand_constraint[insn_code_number][i]))
+                 must_match_0 = i;
+#endif
 
-             if (GET_CODE (r0) == REG || GET_CODE (r0) == SUBREG)
+             r0 = recog_operand[0];
+             for (i = 1; i < insn_n_operands[insn_code_number]; i++)
                {
-                 /* We have two priorities for hard register preferrences.
-                    If we have a move insn or an insn whose first input can
-                    only be in the same register as the output, give
-                    priority to an equivalence found from that insn.  */
-                 int may_save_copy
-                   = ((SET_DEST (body) == r0 && SET_SRC (body) == r1)
-                      || (r1 == recog_operand[1]
-                          && (requires_inout_p (insn_operand_constraint[insn_code_number][1]))));
-
-                 if (GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG)
-                   win = combine_regs (r1, r0, may_save_copy,
-                                       insn_number, insn, 0);
-
-                 if (win == 0
-                     && insn_n_operands[insn_code_number] > 2
-                     && insn_operand_constraint[insn_code_number][1][0] == '%'
-                     && (r1 = recog_operand[2],
-                         GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG))
-                   win = combine_regs (r1, r0, may_save_copy,
-                                       insn_number, insn, 0);
+#ifdef REGISTER_CONSTRAINTS
+                 /* Skip this operand if we found an operand that
+                    must match operand 0 and this operand isn't it
+                    and can't be made to be it by commutativity.  */
+
+                 if (must_match_0 >= 0 && i != must_match_0
+                     && ! (i == must_match_0 + 1
+                           && insn_operand_constraint[insn_code_number][i-1][0] == '%')
+                     && ! (i == must_match_0 - 1
+                           && insn_operand_constraint[insn_code_number][i][0] == '%'))
+                   continue;
+#endif
+
+                 r1 = recog_operand[i];
+
+                 /* If the operand is an address, find a register in it.
+                    There may be more than one register, but we only try one
+                    of them.  */
+                 if (
+#ifdef REGISTER_CONSTRAINTS
+                     insn_operand_constraint[insn_code_number][i][0] == 'p'
+#else
+                     insn_operand_address_p[insn_code_number][i]
+#endif
+                     )
+                   while (GET_CODE (r1) == PLUS || GET_CODE (r1) == MULT)
+                     r1 = XEXP (r1, 0);
+
+                 if (GET_CODE (r0) == REG || GET_CODE (r0) == SUBREG)
+                   {
+                     /* We have two priorities for hard register preferences.
+                        If we have a move insn or an insn whose first input
+                        can only be in the same register as the output, give
+                        priority to an equivalence found from that insn.  */
+                     int may_save_copy
+                       = ((SET_DEST (body) == r0 && SET_SRC (body) == r1)
+#ifdef REGISTER_CONSTRAINTS
+                          || (r1 == recog_operand[i] && must_match_0 >= 0)
+#endif
+                          );
+                     
+                     if (GET_CODE (r1) == REG || GET_CODE (r1) == SUBREG)
+                       win = combine_regs (r1, r0, may_save_copy,
+                                           insn_number, insn, 0);
+                   }
                }
            }
 
@@ -1067,11 +1265,13 @@ block_alloc (b)
          if (GET_CODE (PATTERN (insn)) == CLOBBER
              && (r0 = XEXP (PATTERN (insn), 0),
                  GET_CODE (r0) == REG)
-             && (link = find_reg_note (insn, REG_LIBCALL, 0)) != 0
+             && (link = find_reg_note (insn, REG_LIBCALL, NULL_RTX)) != 0
+             && XEXP (link, 0) != 0
              && GET_CODE (XEXP (link, 0)) == INSN
              && (set = single_set (XEXP (link, 0))) != 0
              && SET_DEST (set) == r0 && SET_SRC (set) == r0
-             && (note = find_reg_note (XEXP (link, 0), REG_EQUAL, 0)) != 0)
+             && (note = find_reg_note (XEXP (link, 0), REG_EQUAL,
+                                       NULL_RTX)) != 0)
            {
              if (r1 = XEXP (note, 0), GET_CODE (r1) == REG
                  /* Check that we have such a sequence.  */
@@ -1139,25 +1339,19 @@ block_alloc (b)
                && GET_CODE (XEXP (link, 0)) == REG)
              wipe_dead_reg (XEXP (link, 0), 1);
 
-#ifndef SMALL_REGISTER_CLASSES
-         /* Allocate quantities for any SCRATCH operands of this insn.  We
-            don't do this for machines with small register classes because
-            those machines can use registers explicitly mentioned in the
-            RTL as spill registers and our usage of hard registers
-            explicitly for SCRATCH operands will conflict.  On those machines,
-            reload will allocate the SCRATCH.  */
+         /* Allocate quantities for any SCRATCH operands of this insn.  */
 
          if (insn_code_number >= 0)
            for (i = 0; i < insn_n_operands[insn_code_number]; i++)
-             if (GET_CODE (recog_operand[i]) == SCRATCH)
+             if (GET_CODE (recog_operand[i]) == SCRATCH
+                 && scratches_allocated++ < scratch_list_length)
                alloc_qty_for_scratch (recog_operand[i], i, insn,
                                       insn_code_number, insn_number);
-#endif
 
          /* If this is an insn that has a REG_RETVAL note pointing at a 
             CLOBBER insn, we have reached the end of a REG_NO_CONFLICT
             block, so clear any register number that combined within it.  */
-         if ((note = find_reg_note (insn, REG_RETVAL, 0)) != 0
+         if ((note = find_reg_note (insn, REG_RETVAL, NULL_RTX)) != 0
              && GET_CODE (XEXP (note, 0)) == INSN
              && GET_CODE (PATTERN (XEXP (note, 0))) == CLOBBER)
            no_conflict_combined_regno = -1;
@@ -1184,7 +1378,7 @@ block_alloc (b)
      decreasing length of life.  Normally call qsort, but if we 
      have only a very small number of quantities, sort them ourselves.  */
 
-  qty_order = (short *) alloca (next_qty * sizeof (short));
+  qty_order = (int *) alloca (next_qty * sizeof (int));
   for (i = 0; i < next_qty; i++)
     qty_order[i] = i;
 
@@ -1214,7 +1408,7 @@ block_alloc (b)
       break;
 
     default:
-      qsort (qty_order, next_qty, sizeof (short), qty_compare_1);
+      qsort (qty_order, next_qty, sizeof (int), qty_compare_1);
     }
 
   /* Try to put each quantity in a suggested physical register, if it has one.
@@ -1249,8 +1443,8 @@ block_alloc (b)
                continue;
            }
 
-         if (!qty_preferred_or_nothing[q])
-           qty_phys_reg[q] = find_free_reg (ALL_REGS, 
+         if (qty_alternate_class[q] != NO_REGS)
+           qty_phys_reg[q] = find_free_reg (qty_alternate_class[q],
                                             qty_mode[q], q, 0, 0,
                                             qty_birth[q], qty_death[q]);
        }
@@ -1266,13 +1460,13 @@ block_alloc (b)
          reg_renumber[i] = qty_phys_reg[q] + reg_offset[i];
        if (qty_scratch_rtx[q])
          {
+           if (GET_CODE (qty_scratch_rtx[q]) == REG)
+             abort ();
            PUT_CODE (qty_scratch_rtx[q], REG);
            REGNO (qty_scratch_rtx[q]) = qty_phys_reg[q];
 
-           for (i = HARD_REGNO_NREGS (qty_phys_reg[q],
-                                      GET_MODE (qty_scratch_rtx[q])) - 1;
-                i >= 0; i--)
-             regs_ever_live[qty_phys_reg[q] + i] = 1;
+           scratch_block[scratch_index] = b;
+           scratch_list[scratch_index++] = qty_scratch_rtx[q];
 
            /* Must clear the USED field, because it will have been set by
               copy_rtx_if_shared, but the leaf_register code expects that
@@ -1285,8 +1479,8 @@ block_alloc (b)
 \f
 /* Compare two quantities' priority for getting real registers.
    We give shorter-lived quantities higher priority.
-   Quantities with more references are also preferred, as are quanties that
-   require multiple registers.  This is the identical prioritorization as
+   Quantities with more references are also preferred, as are quantities that
+   require multiple registers.  This is the identical prioritization as
    done by global-alloc.
 
    We used to give preference to registers with *longer* lives, but using
@@ -1314,7 +1508,7 @@ qty_compare (q1, q2)
 
 static int
 qty_compare_1 (q1, q2)
-     short *q1, *q2;
+     int *q1, *q2;
 {
   register int tem;
 
@@ -1375,7 +1569,7 @@ combine_regs (usedreg, setreg, may_save_copy, insn_number, insn, already_dead)
   register int sqty;
 
   /* Determine the numbers and sizes of registers being used.  If a subreg
-     is present that does not change the entire register, don't conside
+     is present that does not change the entire register, don't consider
      this a copy insn.  */
 
   while (GET_CODE (usedreg) == SUBREG)
@@ -1509,8 +1703,6 @@ combine_regs (usedreg, setreg, may_save_copy, insn_number, insn, already_dead)
       /* Update info about quantity SQTY.  */
       qty_n_calls_crossed[sqty] += reg_n_calls_crossed[sreg];
       qty_n_refs[sqty] += reg_n_refs[sreg];
-      if (! reg_preferred_or_nothing (sreg))
-       qty_preferred_or_nothing[sqty] = 0;
       if (usize < ssize)
        {
          register int i;
@@ -1575,6 +1767,10 @@ update_qty_class (qty, reg)
   enum reg_class rclass = reg_preferred_class (reg);
   if (reg_class_subset_p (rclass, qty_min_class[qty]))
     qty_min_class[qty] = rclass;
+
+  rclass = reg_alternate_class (reg);
+  if (reg_class_subset_p (rclass, qty_alternate_class[qty]))
+    qty_alternate_class[qty] = rclass;
 }
 \f
 /* Handle something which alters the value of an rtx REG.
@@ -1642,7 +1838,8 @@ reg_is_born (reg, birth)
 
 /* Record the death of REG in the current insn.  If OUTPUT_P is non-zero,
    REG is an output that is dying (i.e., it is never used), otherwise it
-   is an input (the normal case).  */
+   is an input (the normal case).
+   If OUTPUT_P is 1, then we extend the life past the end of this insn.  */
 
 static void
 wipe_dead_reg (reg, output_p)
@@ -1651,6 +1848,25 @@ wipe_dead_reg (reg, output_p)
 {
   register int regno = REGNO (reg);
 
+  /* If this insn has multiple results,
+     and the dead reg is used in one of the results,
+     extend its life to after this insn,
+     so it won't get allocated together with any other result of this insn.  */
+  if (GET_CODE (PATTERN (this_insn)) == PARALLEL
+      && !single_set (this_insn))
+    {
+      int i;
+      for (i = XVECLEN (PATTERN (this_insn), 0) - 1; i >= 0; i--)
+       {
+         rtx set = XVECEXP (PATTERN (this_insn), 0, i);
+         if (GET_CODE (set) == SET
+             && GET_CODE (SET_DEST (set)) != REG
+             && !rtx_equal_p (reg, SET_DEST (set))
+             && reg_overlap_mentioned_p (reg, SET_DEST (set)))
+           output_p = 1;
+       }
+    }
+
   if (regno < FIRST_PSEUDO_REGISTER)
     {
       mark_life (regno, GET_MODE (reg), 0);
@@ -1797,6 +2013,10 @@ find_free_reg (class, mode, qty, accept_call_clobbered, just_try_suggested,
                            born_index, dead_index);
     }
 
+  /* We need not check to see if the current function has nonlocal
+     labels because we don't put any pseudos that are live over calls in
+     registers in that case.  */
+
   if (! accept_call_clobbered
       && flag_caller_saves
       && ! just_try_suggested
@@ -1878,7 +2098,7 @@ no_conflict_p (insn, r0, r1)
      rtx insn, r0, r1;
 {
   int ok = 0;
-  rtx note = find_reg_note (insn, REG_LIBCALL, 0);
+  rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX);
   rtx p, last;
 
   /* If R1 is a hard register, return 0 since we handle this case
@@ -1906,6 +2126,8 @@ no_conflict_p (insn, r0, r1)
   return ok;
 }
 \f
+#ifdef REGISTER_CONSTRAINTS
+
 /* Return 1 if the constraint string P indicates that the a the operand
    must be equal to operand 0 and that no register is acceptable.  */
 
@@ -1948,6 +2170,7 @@ requires_inout_p (p)
 
   return found_zero;
 }
+#endif /* REGISTER_CONSTRAINTS */
 \f
 void
 dump_local_alloc (file)