OSDN Git Service

Added fixup for __STDC__ == 0 and __STDC__ == 1
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index ac8eaf6..c7ea46f 100644 (file)
@@ -1,5 +1,5 @@
 /* Reload pseudo regs into hard regs for insns that require hard regs.
-   Copyright (C) 1987, 1988, 1989, 1992 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1989, 1992, 1993 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -77,7 +77,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #endif
 \f
 /* During reload_as_needed, element N contains a REG rtx for the hard reg
-   into which pseudo reg N has been reloaded (perhaps for a previous insn). */
+   into which reg N has been reloaded (perhaps for a previous insn). */
 static rtx *reg_last_reload_reg;
 
 /* Elt N nonzero if reg_last_reload_reg[N] has been set in this insn
@@ -190,6 +190,12 @@ static HARD_REG_SET counted_for_groups;
    as part of a group, even if it seems to be otherwise ok.  */
 static HARD_REG_SET counted_for_nongroups;
 
+/* Indexed by pseudo reg number N,
+   says may not delete stores into the real (memory) home of pseudo N.
+   This is set if we already substituted a memory equivalent in some uses,
+   which happens when we have to eliminate the fp from it.  */
+static char *cannot_omit_stores;
+
 /* Nonzero if indirect addressing is supported on the machine; this means
    that spilling (REG n) does not require reloading it into a register in
    order to do (MEM (REG n)) or (MEM (PLUS (REG n) (CONST_INT c))).  The
@@ -330,6 +336,7 @@ static int new_spill_reg            PROTO((int, int, int *, int *, int,
                                               FILE *));
 static void delete_dead_insn           PROTO((rtx));
 static void alter_reg                          PROTO((int, int));
+static void mark_scratch_live          PROTO((rtx));
 static void set_label_offsets          PROTO((rtx, rtx, int));
 static int eliminate_regs_in_insn      PROTO((rtx, int));
 static void mark_not_eliminable                PROTO((rtx, rtx));
@@ -339,10 +346,12 @@ static int hard_reg_use_compare           PROTO((struct hard_reg_n_uses *,
                                               struct hard_reg_n_uses *));
 static void order_regs_for_reload      PROTO((void));
 static void reload_as_needed           PROTO((rtx, int));
-static void forget_old_reloads_1       PROTO((rtx));
+static void forget_old_reloads_1       PROTO((rtx, rtx));
 static int reload_reg_class_lower      PROTO((short *, short *));
 static void mark_reload_reg_in_use     PROTO((int, int, enum reload_type,
                                               enum machine_mode));
+static void clear_reload_reg_in_use    PROTO((int, int, enum reload_type,
+                                              enum machine_mode));
 static int reload_reg_free_p           PROTO((int, int, enum reload_type));
 static int reload_reg_free_before_p    PROTO((int, int, enum reload_type));
 static int reload_reg_reaches_end_p    PROTO((int, int, enum reload_type));
@@ -404,106 +413,6 @@ init_reload ()
   /* Initialize obstack for our rtl allocation. */
   gcc_obstack_init (&reload_obstack);
   reload_firstobj = (char *) obstack_alloc (&reload_obstack, 0);
-
-#ifdef HAVE_SECONDARY_RELOADS
-
-  /* Initialize the optabs for doing special input and output reloads.  */
-
-  for (i = 0; i < NUM_MACHINE_MODES; i++)
-    reload_in_optab[i] = reload_out_optab[i] = CODE_FOR_nothing;
-
-#ifdef HAVE_reload_inqi
-  if (HAVE_reload_inqi)
-    reload_in_optab[(int) QImode] = CODE_FOR_reload_inqi;
-#endif
-#ifdef HAVE_reload_inhi
-  if (HAVE_reload_inhi)
-    reload_in_optab[(int) HImode] = CODE_FOR_reload_inhi;
-#endif
-#ifdef HAVE_reload_insi
-  if (HAVE_reload_insi)
-    reload_in_optab[(int) SImode] = CODE_FOR_reload_insi;
-#endif
-#ifdef HAVE_reload_indi
-  if (HAVE_reload_indi)
-    reload_in_optab[(int) DImode] = CODE_FOR_reload_indi;
-#endif
-#ifdef HAVE_reload_inti
-  if (HAVE_reload_inti)
-    reload_in_optab[(int) TImode] = CODE_FOR_reload_inti;
-#endif
-#ifdef HAVE_reload_inqf
-  if (HAVE_reload_inqf)
-    reload_in_optab[(int) QFmode] = CODE_FOR_reload_inqf;
-#endif
-#ifdef HAVE_reload_inhf
-  if (HAVE_reload_inhf)
-    reload_in_optab[(int) HFmode] = CODE_FOR_reload_inhf;
-#endif
-#ifdef HAVE_reload_insf
-  if (HAVE_reload_insf)
-    reload_in_optab[(int) SFmode] = CODE_FOR_reload_insf;
-#endif
-#ifdef HAVE_reload_indf
-  if (HAVE_reload_indf)
-    reload_in_optab[(int) DFmode] = CODE_FOR_reload_indf;
-#endif
-#ifdef HAVE_reload_inxf
-  if (HAVE_reload_inxf)
-    reload_in_optab[(int) XFmode] = CODE_FOR_reload_inxf;
-#endif
-#ifdef HAVE_reload_intf
-  if (HAVE_reload_intf)
-    reload_in_optab[(int) TFmode] = CODE_FOR_reload_intf;
-#endif
-
-#ifdef HAVE_reload_outqi
-  if (HAVE_reload_outqi)
-    reload_out_optab[(int) QImode] = CODE_FOR_reload_outqi;
-#endif
-#ifdef HAVE_reload_outhi
-  if (HAVE_reload_outhi)
-    reload_out_optab[(int) HImode] = CODE_FOR_reload_outhi;
-#endif
-#ifdef HAVE_reload_outsi
-  if (HAVE_reload_outsi)
-    reload_out_optab[(int) SImode] = CODE_FOR_reload_outsi;
-#endif
-#ifdef HAVE_reload_outdi
-  if (HAVE_reload_outdi)
-    reload_out_optab[(int) DImode] = CODE_FOR_reload_outdi;
-#endif
-#ifdef HAVE_reload_outti
-  if (HAVE_reload_outti)
-    reload_out_optab[(int) TImode] = CODE_FOR_reload_outti;
-#endif
-#ifdef HAVE_reload_outqf
-  if (HAVE_reload_outqf)
-    reload_out_optab[(int) QFmode] = CODE_FOR_reload_outqf;
-#endif
-#ifdef HAVE_reload_outhf
-  if (HAVE_reload_outhf)
-    reload_out_optab[(int) HFmode] = CODE_FOR_reload_outhf;
-#endif
-#ifdef HAVE_reload_outsf
-  if (HAVE_reload_outsf)
-    reload_out_optab[(int) SFmode] = CODE_FOR_reload_outsf;
-#endif
-#ifdef HAVE_reload_outdf
-  if (HAVE_reload_outdf)
-    reload_out_optab[(int) DFmode] = CODE_FOR_reload_outdf;
-#endif
-#ifdef HAVE_reload_outxf
-  if (HAVE_reload_outxf)
-    reload_out_optab[(int) XFmode] = CODE_FOR_reload_outxf;
-#endif
-#ifdef HAVE_reload_outtf
-  if (HAVE_reload_outtf)
-    reload_out_optab[(int) TFmode] = CODE_FOR_reload_outtf;
-#endif
-
-#endif /* HAVE_SECONDARY_RELOADS */
-
 }
 
 /* Main entry point for the reload pass.
@@ -583,6 +492,10 @@ reload (first, global, dumpfile)
   for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
     mark_home_live (i);
 
+  for (i = 0; i < scratch_list_length; i++)
+    if (scratch_list[i])
+      mark_scratch_live (scratch_list[i]);
+
   /* Make sure that the last insn in the chain
      is not something that needs reloading.  */
   emit_note (NULL_PTR, NOTE_INSN_DELETED);
@@ -609,6 +522,8 @@ reload (first, global, dumpfile)
   bzero (reg_equiv_address, max_regno * sizeof (rtx));
   reg_max_ref_width = (int *) alloca (max_regno * sizeof (int));
   bzero (reg_max_ref_width, max_regno * sizeof (int));
+  cannot_omit_stores = (char *) alloca (max_regno);
+  bzero (cannot_omit_stores, max_regno);
 
   /* Look for REG_EQUIV notes; record what each pseudo is equivalent to.
      Also find all paradoxical subregs
@@ -904,7 +819,8 @@ reload (first, global, dumpfile)
         and constant, it is probably not addressable because the constant is
         out of range, in that case record the address; we will generate
         hairy code to compute the address in a register each time it is
-        needed.
+        needed.  Similarly if it is a hard register, but one that is not
+        valid as an address register.
 
         If the location is not addressable, but does not have one of the
         above forms, assign a stack slot.  We have to do this to avoid the
@@ -924,6 +840,8 @@ reload (first, global, dumpfile)
                                         XEXP (x, 0)))
              reg_equiv_mem[i] = x, reg_equiv_address[i] = 0;
            else if (CONSTANT_P (XEXP (x, 0))
+                    || (GET_CODE (XEXP (x, 0)) == REG
+                        && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)
                     || (GET_CODE (XEXP (x, 0)) == PLUS
                         && GET_CODE (XEXP (XEXP (x, 0), 0)) == REG
                         && (REGNO (XEXP (XEXP (x, 0), 0))
@@ -1778,14 +1696,21 @@ reload (first, global, dumpfile)
                  if (i == FIRST_PSEUDO_REGISTER)
                    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
                      {
+                       int k;
                        j = potential_reload_regs[i];
+                       /* Verify that J+1 is a potential reload reg.  */
+                       for (k = 0; k < FIRST_PSEUDO_REGISTER; k++)
+                         if (potential_reload_regs[k] == j + 1)
+                           break;
                        if (j >= 0 && j + 1 < FIRST_PSEUDO_REGISTER
+                           && k < FIRST_PSEUDO_REGISTER
                            && spill_reg_order[j] < 0 && spill_reg_order[j + 1] < 0
                            && TEST_HARD_REG_BIT (reg_class_contents[class], j)
                            && TEST_HARD_REG_BIT (reg_class_contents[class], j + 1)
                            && HARD_REGNO_MODE_OK (j, group_mode[class])
                            && ! TEST_HARD_REG_BIT (counted_for_nongroups,
-                                                   j + 1))
+                                                   j + 1)
+                           && ! TEST_HARD_REG_BIT (bad_spill_regs, j + 1))
                          break;
                      }
 
@@ -1868,6 +1793,35 @@ reload (first, global, dumpfile)
 
          while (max_needs[class] > 0 || max_nongroups[class] > 0)
            {
+#ifdef SMALL_REGISTER_CLASSES
+             /* This should be right for all machines, but only the 386
+                is known to need it, so this conditional plays safe.
+                ??? For 2.5, try making this unconditional.  */
+             /* If we spilled enough regs, but they weren't counted
+                against the non-group need, see if we can count them now.
+                If so, we can avoid some actual spilling.  */
+             if (max_needs[class] <= 0 && max_nongroups[class] > 0)
+               for (i = 0; i < n_spills; i++)
+                 if (TEST_HARD_REG_BIT (reg_class_contents[class],
+                                        spill_regs[i])
+                     && !TEST_HARD_REG_BIT (counted_for_groups,
+                                            spill_regs[i])
+                     && !TEST_HARD_REG_BIT (counted_for_nongroups,
+                                            spill_regs[i])
+                     && max_nongroups[class] > 0)
+                   {
+                     register enum reg_class *p;
+
+                     SET_HARD_REG_BIT (counted_for_nongroups, spill_regs[i]);
+                     max_nongroups[class]--;
+                     p = reg_class_superclasses[class];
+                     while (*p != LIM_REG_CLASSES)
+                       max_nongroups[(int) *p++]--;
+                   }
+             if (max_needs[class] <= 0 && max_nongroups[class] <= 0)
+               break;
+#endif
+
              /* Consider the potential reload regs that aren't
                 yet in use as reload regs, in order of preference.
                 Find the most preferred one that's in this class.  */
@@ -2046,6 +2000,11 @@ reload (first, global, dumpfile)
   reg_equiv_constant = 0;
   reg_equiv_memory_loc = 0;
 
+  free (scratch_list);
+  scratch_list = 0;
+  free (scratch_block);
+  scratch_block = 0;
+
   return failure;
 }
 \f
@@ -2448,6 +2407,20 @@ mark_home_live (regno)
   while (i < lim)
     regs_ever_live[i++] = 1;
 }
+
+/* Mark the registers used in SCRATCH as being live.  */
+
+static void
+mark_scratch_live (scratch)
+     rtx scratch;
+{
+  register int i;
+  int regno = REGNO (scratch);
+  int lim = regno + HARD_REGNO_NREGS (regno, GET_MODE (scratch));
+
+  for (i = regno; i < lim; i++)
+    regs_ever_live[i] = 1;
+}
 \f
 /* This function handles the tracking of elimination offsets around branches.
 
@@ -2692,7 +2665,10 @@ eliminate_regs (x, mem_mode, insn)
          new = eliminate_regs (reg_equiv_memory_loc[regno],
                                mem_mode, NULL_RTX);
          if (new != reg_equiv_memory_loc[regno])
-           return copy_rtx (new);
+           {
+             cannot_omit_stores[regno] = 1;
+             return copy_rtx (new);
+           }
        }
       return x;
 
@@ -2832,10 +2808,17 @@ eliminate_regs (x, mem_mode, insn)
       for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
        if (ep->to_rtx == XEXP (x, 0))
          {
+           int size = GET_MODE_SIZE (mem_mode);
+
+           /* If more bytes than MEM_MODE are pushed, account for them.  */
+#ifdef PUSH_ROUNDING
+           if (ep->to_rtx == stack_pointer_rtx)
+             size = PUSH_ROUNDING (size);
+#endif
            if (code == PRE_DEC || code == POST_DEC)
-             ep->offset += GET_MODE_SIZE (mem_mode);
+             ep->offset += size;
            else
-             ep->offset -= GET_MODE_SIZE (mem_mode);
+             ep->offset -= size;
          }
 
       /* Fall through to generic unary operation case.  */
@@ -2885,7 +2868,17 @@ eliminate_regs (x, mem_mode, insn)
        {
          if (GET_CODE (new) == MEM
              && (GET_MODE_SIZE (GET_MODE (x))
-                 <= GET_MODE_SIZE (GET_MODE (new))))
+                 <= GET_MODE_SIZE (GET_MODE (new)))
+#if defined(BYTE_LOADS_ZERO_EXTEND) || defined(BYTE_LOADS_SIGN_EXTEND)
+             /* On these machines we will be reloading what is
+                inside the SUBREG if it originally was a pseudo and
+                the inner and outer modes are both a word or
+                smaller.  So leave the SUBREG then.  */
+             && ! (GET_CODE (SUBREG_REG (x)) == REG
+                   && GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD
+                   && GET_MODE_SIZE (GET_MODE (new)) <= UNITS_PER_WORD)
+#endif
+             )
            {
              int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
              enum machine_mode mode = GET_MODE (x);
@@ -3141,14 +3134,22 @@ eliminate_regs_in_insn (insn, replace)
        for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
             ep++)
          if (ep->from_rtx == XEXP (SET_SRC (old_body), 0)
-             && ep->can_eliminate
-             && ep->offset == - INTVAL (XEXP (SET_SRC (old_body), 1)))
+             && ep->can_eliminate)
            {
-             PATTERN (insn) = gen_rtx (SET, VOIDmode,
-                                       SET_DEST (old_body), ep->to_rtx);
-             INSN_CODE (insn) = -1;
-             val = 1;
-             goto done;
+             /* We must stop at the first elimination that will be used.
+                If this one would replace the PLUS with a REG, do it
+                now.  Otherwise, quit the loop and let eliminate_regs
+                do its normal replacement.  */
+             if (ep->offset == - INTVAL (XEXP (SET_SRC (old_body), 1)))
+               {
+                 PATTERN (insn) = gen_rtx (SET, VOIDmode,
+                                           SET_DEST (old_body), ep->to_rtx);
+                 INSN_CODE (insn) = -1;
+                 val = 1;
+                 goto done;
+               }
+
+             break;
            }
     }
 
@@ -3305,6 +3306,7 @@ spill_hard_reg (regno, global, dumpfile, cant_eliminate)
      FILE *dumpfile;
      int cant_eliminate;
 {
+  enum reg_class class = REGNO_REG_CLASS (regno);
   int something_changed = 0;
   register int i;
 
@@ -3321,8 +3323,6 @@ spill_hard_reg (regno, global, dumpfile, cant_eliminate)
                                PSEUDO_REGNO_MODE (i))
            > regno))
       {
-       enum reg_class class = REGNO_REG_CLASS (regno);
-
        /* If this register belongs solely to a basic block which needed no
           spilling of any class that this register is contained in,
           leave it be, unless we are spilling this register because
@@ -3361,6 +3361,29 @@ spill_hard_reg (regno, global, dumpfile, cant_eliminate)
                       i, reg_renumber[i]);
          }
       }
+  for (i = 0; i < scratch_list_length; i++)
+    {
+      if (scratch_list[i] && REGNO (scratch_list[i]) == regno)
+       {
+         if (! cant_eliminate && basic_block_needs[0]
+             && ! basic_block_needs[(int) class][scratch_block[i]])
+           {
+             enum reg_class *p;
+
+             for (p = reg_class_superclasses[(int) class];
+                  *p != LIM_REG_CLASSES; p++)
+               if (basic_block_needs[(int) *p][scratch_block[i]] > 0)
+                 break;
+
+             if (*p == LIM_REG_CLASSES)
+               continue;
+           }
+         PUT_CODE (scratch_list[i], SCRATCH);
+         scratch_list[i] = 0;
+         something_changed = 1;
+         continue;
+       }
+    }
 
   return something_changed;
 }
@@ -3540,7 +3563,7 @@ order_regs_for_reload ()
    and perhaps store insns after insns that modify the reloaded pseudo reg.
 
    reg_last_reload_reg and reg_reloaded_contents keep track of
-   which pseudo-registers are already available in reload registers.
+   which registers are already available in reload registers.
    We update these for the reloads that we perform,
    as the insns are scanned.  */
 
@@ -3762,7 +3785,7 @@ reload_as_needed (first, live_known)
                    break;
 
                if (i == n_reloads)
-                 forget_old_reloads_1 (XEXP (x, 0));
+                 forget_old_reloads_1 (XEXP (x, 0), NULL_RTX);
              }
 #endif
        }
@@ -3812,8 +3835,9 @@ reload_as_needed (first, live_known)
    or it may be a pseudo reg that was reloaded from.  */
 
 static void
-forget_old_reloads_1 (x)
+forget_old_reloads_1 (x, ignored)
      rtx x;
+     rtx ignored;
 {
   register int regno;
   int nr;
@@ -3928,6 +3952,10 @@ static HARD_REG_SET reload_reg_used_in_other_addr;
 /* If reg is in use as a reload reg for any sort of reload.  */
 static HARD_REG_SET reload_reg_used_at_all;
 
+/* If reg is use as an inherited reload.  We just mark the first register
+   in the group.  */
+static HARD_REG_SET reload_reg_used_for_inherit;
+
 /* Mark reg REGNO as in use for a reload of the sort spec'd by OPNUM and
    TYPE. MODE is used to indicate how many consecutive regs are
    actually used.  */
@@ -3983,6 +4011,57 @@ mark_reload_reg_in_use (regno, opnum, type, mode)
     }
 }
 
+/* Similarly, but show REGNO is no longer in use for a reload.  */
+
+static void
+clear_reload_reg_in_use (regno, opnum, type, mode)
+     int regno;
+     int opnum;
+     enum reload_type type;
+     enum machine_mode mode;
+{
+  int nregs = HARD_REGNO_NREGS (regno, mode);
+  int i;
+
+  for (i = regno; i < nregs + regno; i++)
+    {
+      switch (type)
+       {
+       case RELOAD_OTHER:
+         CLEAR_HARD_REG_BIT (reload_reg_used, i);
+         break;
+
+       case RELOAD_FOR_INPUT_ADDRESS:
+         CLEAR_HARD_REG_BIT (reload_reg_used_in_input_addr[opnum], i);
+         break;
+
+       case RELOAD_FOR_OUTPUT_ADDRESS:
+         CLEAR_HARD_REG_BIT (reload_reg_used_in_output_addr[opnum], i);
+         break;
+
+       case RELOAD_FOR_OPERAND_ADDRESS:
+         CLEAR_HARD_REG_BIT (reload_reg_used_in_op_addr, i);
+         break;
+
+       case RELOAD_FOR_OTHER_ADDRESS:
+         CLEAR_HARD_REG_BIT (reload_reg_used_in_other_addr, i);
+         break;
+
+       case RELOAD_FOR_INPUT:
+         CLEAR_HARD_REG_BIT (reload_reg_used_in_input[opnum], i);
+         break;
+
+       case RELOAD_FOR_OUTPUT:
+         CLEAR_HARD_REG_BIT (reload_reg_used_in_output[opnum], i);
+         break;
+
+       case RELOAD_FOR_INSN:
+         CLEAR_HARD_REG_BIT (reload_reg_used_in_insn, i);
+         break;
+       }
+    }
+}
+
 /* 1 if reg REGNO is free as a reload reg for a reload of the sort
    specified by OPNUM and TYPE.  */
 
@@ -4332,7 +4411,7 @@ int reload_spill_index[MAX_RELOADS];
 /* Index of last register assigned as a spill register.  We allocate in
    a round-robin fashio.  */
 
-static last_spill_reg = 0;
+static int last_spill_reg = 0;
 
 /* Find a spill register to use as a reload register for reload R.
    LAST_RELOAD is non-zero if this is the last reload for the insn being
@@ -4400,9 +4479,14 @@ allocate_reload_reg (r, insn, last_reload, noerror)
                                 reload_when_needed[r])
              && TEST_HARD_REG_BIT (reg_class_contents[class], spill_regs[i])
              && HARD_REGNO_MODE_OK (spill_regs[i], reload_mode[r])
-             /* Look first for regs to share, then for unshared.  */
-             && (pass || TEST_HARD_REG_BIT (reload_reg_used_at_all,
-                                            spill_regs[i])))
+             /* Look first for regs to share, then for unshared.  But
+                don't share regs used for inherited reloads; they are
+                the ones we want to preserve.  */
+             && (pass
+                 || (TEST_HARD_REG_BIT (reload_reg_used_at_all,
+                                        spill_regs[i])
+                     && ! TEST_HARD_REG_BIT (reload_reg_used_for_inherit,
+                                             spill_regs[i]))))
            {
              int nr = HARD_REGNO_NREGS (spill_regs[i], reload_mode[r]);
              /* Avoid the problem where spilling a GENERAL_OR_FP_REG
@@ -4453,19 +4537,15 @@ allocate_reload_reg (r, insn, last_reload, noerror)
       goto failure;
     }
 
-  last_spill_reg = i;
-
-  /* Mark as in use for this insn the reload regs we use for this.  */
-  mark_reload_reg_in_use (spill_regs[i], reload_opnum[r],
-                         reload_when_needed[r], reload_mode[r]);
+  /* I is the index in SPILL_REG_RTX of the reload register we are to
+     allocate.  Get an rtx for it and find its register number.  */
 
   new = spill_reg_rtx[i];
 
   if (new == 0 || GET_MODE (new) != reload_mode[r])
-    spill_reg_rtx[i] = new = gen_rtx (REG, reload_mode[r], spill_regs[i]);
-
-  reload_reg_rtx[r] = new;
-  reload_spill_index[r] = i;
+    spill_reg_rtx[i] = new
+      = gen_rtx (REG, reload_mode[r], spill_regs[i]);
+           
   regno = true_regnum (new);
 
   /* Detect when the reload reg can't hold the reload mode.
@@ -4485,8 +4565,19 @@ allocate_reload_reg (r, insn, last_reload, noerror)
             && ! HARD_REGNO_MODE_OK (regno, test_mode)))
        if (! (reload_out[r] != 0
               && ! HARD_REGNO_MODE_OK (regno, GET_MODE (reload_out[r]))))
-         /* The reg is OK.  */
-         return 1;
+         {
+           /* The reg is OK.  */
+           last_spill_reg = i;
+
+           /* Mark as in use for this insn the reload regs we use
+              for this.  */
+           mark_reload_reg_in_use (spill_regs[i], reload_opnum[r],
+                                   reload_when_needed[r], reload_mode[r]);
+
+           reload_reg_rtx[r] = new;
+           reload_spill_index[r] = i;
+           return 1;
+         }
     }
 
   /* The reg is not OK.  */
@@ -4720,6 +4811,8 @@ choose_reload_regs (insn, avoid_return_reg)
         Then make a second pass over the reloads to allocate any reloads
         that haven't been given registers yet.  */
 
+      CLEAR_HARD_REG_SET (reload_reg_used_for_inherit);
+
       for (j = 0; j < n_reloads; j++)
        {
          register int r = reload_order[j];
@@ -4824,16 +4917,44 @@ choose_reload_regs (insn, avoid_return_reg)
 
                      if (k == nr)
                        {
-                         /* Mark the register as in use for this part of
-                            the insn.  */
-                         mark_reload_reg_in_use (spill_regs[i],
-                                                 reload_opnum[r],
-                                                 reload_when_needed[r],
-                                                 reload_mode[r]);
-                         reload_reg_rtx[r] = reg_last_reload_reg[regno];
-                         reload_inherited[r] = 1;
-                         reload_inheritance_insn[r] = reg_reloaded_insn[i];
-                         reload_spill_index[r] = i;
+                         int i1;
+
+                         /* We found a register that contains the
+                            value we need.  If this register is the
+                            same as an `earlyclobber' operand of the
+                            current insn, just mark it as a place to
+                            reload from since we can't use it as the
+                            reload register itself.  */
+
+                         for (i1 = 0; i1 < n_earlyclobbers; i1++)
+                           if (reg_overlap_mentioned_for_reload_p
+                               (reg_last_reload_reg[regno],
+                                reload_earlyclobbers[i1]))
+                             break;
+
+                         if (i1 != n_earlyclobbers
+                             /* Don't really use the inherited spill reg
+                                if we need it wider than we've got it.  */
+                             || (GET_MODE_SIZE (reload_mode[r])
+                                 > GET_MODE_SIZE (mode)))
+                           reload_override_in[r] = reg_last_reload_reg[regno];
+                         else
+                           {
+                             /* We can use this as a reload reg.  */
+                             /* Mark the register as in use for this part of
+                                the insn.  */
+                             mark_reload_reg_in_use (spill_regs[i],
+                                                     reload_opnum[r],
+                                                     reload_when_needed[r],
+                                                     reload_mode[r]);
+                             reload_reg_rtx[r] = reg_last_reload_reg[regno];
+                             reload_inherited[r] = 1;
+                             reload_inheritance_insn[r]
+                               = reg_reloaded_insn[i];
+                             reload_spill_index[r] = i;
+                             SET_HARD_REG_BIT (reload_reg_used_for_inherit,
+                                               spill_regs[i]);
+                           }
                        }
                    }
                }
@@ -4920,9 +5041,12 @@ choose_reload_regs (insn, avoid_return_reg)
                     mark the spill reg as in use for this insn.  */
                  i = spill_reg_order[regno];
                  if (i >= 0)
-                   mark_reload_reg_in_use (regno, reload_opnum[r],
-                                           reload_when_needed[r],
-                                           reload_mode[r]);
+                   {
+                     mark_reload_reg_in_use (regno, reload_opnum[r],
+                                             reload_when_needed[r],
+                                             reload_mode[r]);
+                     SET_HARD_REG_BIT (reload_reg_used_for_inherit, regno);
+                   }
                }
            }
 
@@ -5061,10 +5185,18 @@ choose_reload_regs (insn, avoid_return_reg)
      optional and not inherited, clear reload_reg_rtx so other
      routines (such as subst_reloads) don't get confused.  */
   for (j = 0; j < n_reloads; j++)
-    if ((reload_optional[j] && ! reload_inherited[j])
-       || (reload_in[j] == 0 && reload_out[j] == 0
-           && ! reload_secondary_p[j]))
-      reload_reg_rtx[j] = 0;
+    if (reload_reg_rtx[j] != 0
+       && ((reload_optional[j] && ! reload_inherited[j])
+           || (reload_in[j] == 0 && reload_out[j] == 0
+               && ! reload_secondary_p[j])))
+      {
+       int regno = true_regnum (reload_reg_rtx[j]);
+
+       if (spill_reg_order[regno] >= 0)
+         clear_reload_reg_in_use (regno, reload_opnum[j],
+                                  reload_when_needed[j], reload_mode[j]);
+       reload_reg_rtx[j] = 0;
+      }
 
   /* Record which pseudos and which spill regs have output reloads.  */
   for (j = 0; j < n_reloads; j++)
@@ -5225,14 +5357,14 @@ emit_reload_insns (insn)
           && GET_CODE (PATTERN (PREV_INSN (before_insn))) == USE)
       before_insn = PREV_INSN (before_insn);
 
-  /* If this insn is followed by any CLOBBER insns made by find_reloads,
+  /* If INSN is followed by any CLOBBER insns made by find_reloads,
      put our reloads after them since they may otherwise be 
      misinterpreted.  */
 
-  while (NEXT_INSN (following_insn) != 0
-        && GET_CODE (NEXT_INSN (following_insn)) == INSN
-        && GET_MODE (NEXT_INSN (following_insn)) == DImode
-        && GET_CODE (PATTERN (NEXT_INSN (following_insn))) == CLOBBER)
+  while (GET_CODE (following_insn) == INSN
+        && GET_MODE (following_insn) == DImode
+        && GET_CODE (PATTERN (following_insn)) == CLOBBER
+        && NEXT_INSN (following_insn) != 0)
     following_insn = NEXT_INSN (following_insn);
 
   /* Now output the instructions to copy the data into and out of the
@@ -5384,10 +5516,13 @@ emit_reload_insns (insn)
            oldequiv_reg = SUBREG_REG (oldequiv);
 
          /* Encapsulate both RELOADREG and OLDEQUIV into that mode,
-            then load RELOADREG from OLDEQUIV.  */
+            then load RELOADREG from OLDEQUIV.  Note that we cannot use
+            gen_lowpart_common since it can do the wrong thing when
+            RELOADREG has a multi-word mode.  Note that RELOADREG
+            must always be a REG here.  */
 
          if (GET_MODE (reloadreg) != mode)
-           reloadreg = gen_lowpart_common (mode, reloadreg);
+           reloadreg = gen_rtx (REG, mode, REGNO (reloadreg));
          while (GET_CODE (oldequiv) == SUBREG && GET_MODE (oldequiv) != mode)
            oldequiv = SUBREG_REG (oldequiv);
          if (GET_MODE (oldequiv) != VOIDmode
@@ -5557,7 +5692,7 @@ emit_reload_insns (insn)
                              if (new_icode == CODE_FOR_nothing)
                                new_mode = mode;
                              else
-                               new_mode = insn_operand_mode[new_icode][2];
+                               new_mode = insn_operand_mode[(int) new_icode][2];
 
                              if (GET_MODE (second_reload_reg) != new_mode)
                                {
@@ -5849,7 +5984,7 @@ emit_reload_insns (insn)
            }
 
          if (GET_MODE (reloadreg) != mode)
-           reloadreg = gen_lowpart_common (mode, reloadreg);
+           reloadreg = gen_rtx (REG, mode, REGNO (reloadreg));
 
 #ifdef SECONDARY_OUTPUT_RELOAD_CLASS
 
@@ -6134,32 +6269,67 @@ emit_reload_insns (insn)
          if (reload_out[r] != 0 && GET_CODE (reload_out[r]) == REG)
            {
              register int nregno = REGNO (reload_out[r]);
+             int nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1
+                        : HARD_REGNO_NREGS (nregno,
+                                            GET_MODE (reload_reg_rtx[r])));
 
              spill_reg_store[i] = new_spill_reg_store[i];
              reg_last_reload_reg[nregno] = reload_reg_rtx[r];
 
+             /* If NREGNO is a hard register, it may occupy more than
+                one register.  If it does, say what is in the 
+                rest of the registers assuming that both registers
+                agree on how many words the object takes.  If not,
+                invalidate the subsequent registers.  */
+
+             if (nregno < FIRST_PSEUDO_REGISTER)
+               for (k = 1; k < nnr; k++)
+                 reg_last_reload_reg[nregno + k]
+                   = (nr == nnr ? gen_rtx (REG, word_mode,
+                                           REGNO (reload_reg_rtx[r]) + k)
+                      : 0);
+
+             /* Now do the inverse operation.  */
              for (k = 0; k < nr; k++)
                {
                  reg_reloaded_contents[spill_reg_order[spill_regs[i] + k]]
-                   = nregno;
+                   = (nregno >= FIRST_PSEUDO_REGISTER || nr != nnr ? nregno
+                      : nregno + k);
                  reg_reloaded_insn[spill_reg_order[spill_regs[i] + k]] = insn;
                }
            }
 
-         /* Maybe the spill reg contains a copy of reload_in.  */
+         /* Maybe the spill reg contains a copy of reload_in.  Only do
+            something if there will not be an output reload for
+            the register being reloaded.  */
          else if (reload_out[r] == 0
                   && reload_in[r] != 0
-                  && (GET_CODE (reload_in[r]) == REG
-                      || GET_CODE (reload_in_reg[r]) == REG))
+                  && ((GET_CODE (reload_in[r]) == REG
+                       && ! reg_has_output_reload[REGNO (reload_in[r])]
+                      || (GET_CODE (reload_in_reg[r]) == REG
+                          && ! reg_has_output_reload[REGNO (reload_in_reg[r])]))))
            {
              register int nregno;
+             int nnr;
+
              if (GET_CODE (reload_in[r]) == REG)
                nregno = REGNO (reload_in[r]);
              else
                nregno = REGNO (reload_in_reg[r]);
 
+             nnr = (nregno >= FIRST_PSEUDO_REGISTER ? 1
+                    : HARD_REGNO_NREGS (nregno,
+                                        GET_MODE (reload_reg_rtx[r])));
+
              reg_last_reload_reg[nregno] = reload_reg_rtx[r];
 
+             if (nregno < FIRST_PSEUDO_REGISTER)
+               for (k = 1; k < nnr; k++)
+                 reg_last_reload_reg[nregno + k]
+                   = (nr == nnr ? gen_rtx (REG, word_mode,
+                                           REGNO (reload_reg_rtx[r]) + k)
+                      : 0);
+
              /* Unless we inherited this reload, show we haven't
                 recently done a store.  */
              if (! reload_inherited[r])
@@ -6168,7 +6338,8 @@ emit_reload_insns (insn)
              for (k = 0; k < nr; k++)
                {
                  reg_reloaded_contents[spill_reg_order[spill_regs[i] + k]]
-                   = nregno;
+                   = (nregno >= FIRST_PSEUDO_REGISTER || nr != nnr ? nregno
+                      : nregno + k);
                  reg_reloaded_insn[spill_reg_order[spill_regs[i] + k]]
                    = insn;
                }
@@ -6394,6 +6565,9 @@ delete_output_reload (insn, j, output_reload_insn)
        return;
     }
 
+  if (cannot_omit_stores[REGNO (reg)])
+    return;
+
   /* If this insn will store in the pseudo again,
      the previous store can be removed.  */
   if (reload_out[j] == reload_in[j])