OSDN Git Service

Add -mabi=n32 support.
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index 999b5e3..09922ce 100644 (file)
@@ -1,5 +1,5 @@
 /* Reload pseudo regs into hard regs for insns that require hard regs.
-   Copyright (C) 1987, 88, 89, 92, 93, 1994 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 89, 92-5, 1996 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -15,7 +15,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 
 #include <stdio.h>
@@ -33,6 +34,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "recog.h"
 #include "basic-block.h"
 #include "output.h"
+#include "real.h"
 
 /* This file contains the reload pass of the compiler, which is
    run after register allocation has been done.  It checks that
@@ -168,6 +170,18 @@ static HARD_REG_SET bad_spill_regs;
    elements that are actually valid; new ones are added at the end.  */
 static short spill_regs[FIRST_PSEUDO_REGISTER];
 
+/* This reg set indicates those registers that have been used a spill
+   registers.  This information is used in reorg.c, to help figure out
+   what registers are live at any point.  It is assumed that all spill_regs
+   are dead at every CODE_LABEL.  */
+
+HARD_REG_SET used_spill_regs;
+
+/* Index of last register assigned as a spill register.  We allocate in
+   a round-robin fashion.  */
+
+static int last_spill_reg;
+
 /* Describes order of preference for putting regs into spill_regs.
    Contains the numbers of all the hard regs, in order most preferred first.
    This order is different for each function.
@@ -263,6 +277,9 @@ char *reload_firstobj;
 
 /* List of labels that must never be deleted.  */
 extern rtx forced_labels;
+
+/* Allocation number table from global register allocation.  */
+extern int *reg_allocno;
 \f
 /* This structure is used to record information about register eliminations.
    Each array entry describes one possible way of eliminating a register
@@ -344,7 +361,7 @@ static int spill_hard_reg           PROTO((int, int, FILE *, int));
 static void scan_paradoxical_subregs   PROTO((rtx));
 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 order_regs_for_reload      PROTO((int));
 static int compare_spill_regs          PROTO((short *, short *));
 static void reload_as_needed           PROTO((rtx, int));
 static void forget_old_reloads_1       PROTO((rtx, rtx));
@@ -534,12 +551,20 @@ reload (first, global, dumpfile)
   /* Look for REG_EQUIV notes; record what each pseudo is equivalent to.
      Also find all paradoxical subregs and find largest such for each pseudo.
      On machines with small register classes, record hard registers that
-     are used for user variables.  These can never be used for spills.  */
+     are used for user variables.  These can never be used for spills. 
+     Also look for a "constant" NOTE_INSN_SETJMP.  This means that all
+     caller-saved registers must be marked live.  */
 
   for (insn = first; insn; insn = NEXT_INSN (insn))
     {
       rtx set = single_set (insn);
 
+      if (GET_CODE (insn) == NOTE && CONST_CALL_P (insn)
+         && NOTE_LINE_NUMBER (insn) == NOTE_INSN_SETJMP)
+       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+         if (! call_used_regs[i])
+           regs_ever_live[i] = 1;
+
       if (set != 0 && GET_CODE (SET_DEST (set)) == REG)
        {
          rtx note = find_reg_note (insn, REG_EQUIV, NULL_RTX);
@@ -684,13 +709,16 @@ reload (first, global, dumpfile)
   /* Compute the order of preference for hard registers to spill.
      Store them by decreasing preference in potential_reload_regs.  */
 
-  order_regs_for_reload ();
+  order_regs_for_reload (global);
 
   /* So far, no hard regs have been spilled.  */
   n_spills = 0;
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     spill_reg_order[i] = -1;
 
+  /* Initialize to -1, which means take the first spill register.  */
+  last_spill_reg = -1;
+
   /* On most machines, we can't use any register explicitly used in the
      rtl as a spill register.  But on some, we have to.  Those will have
      taken care to keep the life of hard regs as short as possible.  */
@@ -915,7 +943,7 @@ reload (first, global, dumpfile)
              int did_elimination = 0;
 
              /* To compute the number of reload registers of each class 
-                needed for an insn, we must similate what choose_reload_regs
+                needed for an insn, we must simulate what choose_reload_regs
                 can do.  We do this by splitting an insn into an "input" and
                 an "output" part.  RELOAD_OTHER reloads are used in both. 
                 The input part uses those reloads, RELOAD_FOR_INPUT reloads,
@@ -1153,7 +1181,8 @@ reload (first, global, dumpfile)
                      if (other_mode != VOIDmode && other_mode != allocate_mode
                          && ! modes_equiv_for_class_p (allocate_mode,
                                                        other_mode, class))
-                       abort ();
+                       fatal_insn ("Two dissimilar machine modes both need groups of consecutive regs of the same class",
+                                   insn);
                    }
                  else if (size == 1)
                    {
@@ -1328,10 +1357,10 @@ reload (first, global, dumpfile)
                     need only in the smallest class in which it
                     is required.  */
 
-                 bcopy (insn_needs.other.regs[0], basic_needs,
-                        sizeof basic_needs);
-                 bcopy (insn_needs.other.groups, basic_groups,
-                        sizeof basic_groups);
+                 bcopy ((char *) insn_needs.other.regs[0],
+                        (char *) basic_needs, sizeof basic_needs);
+                 bcopy ((char *) insn_needs.other.groups,
+                        (char *) basic_groups, sizeof basic_groups);
 
                  for (i = 0; i < N_REG_CLASSES; i++)
                    {
@@ -1349,19 +1378,14 @@ reload (first, global, dumpfile)
                    }
 
                  /* Now count extra regs if there might be a conflict with
-                    the return value register.
+                    the return value register. */
 
-                    ??? This is not quite correct because we don't properly
-                    handle the case of groups, but if we end up doing
-                    something wrong, it either will end up not mattering or
-                    we will abort elsewhere.  */
-                  
                  for (r = regno; r < regno + nregs; r++)
                    if (spill_reg_order[r] >= 0)
                      for (i = 0; i < N_REG_CLASSES; i++)
                        if (TEST_HARD_REG_BIT (reg_class_contents[i], r))
                          {
-                           if (basic_needs[i] > 0 || basic_groups[i] > 0)
+                           if (basic_needs[i] > 0)
                              {
                                enum reg_class *p;
 
@@ -1370,6 +1394,15 @@ reload (first, global, dumpfile)
                                while (*p != LIM_REG_CLASSES)
                                  insn_needs.other.regs[0][(int) *p++]++;
                              }
+                           if (basic_groups[i] > 0)
+                             {
+                               enum reg_class *p;
+
+                               insn_needs.other.groups[i]++;
+                               p = reg_class_superclasses[i];
+                               while (*p != LIM_REG_CLASSES)
+                                 insn_needs.other.groups[(int) *p++]++;
+                             }
                          }
                }
 #endif /* SMALL_REGISTER_CLASSES */
@@ -1533,7 +1566,7 @@ reload (first, global, dumpfile)
 
       /* Put all registers spilled so far back in potential_reload_regs, but
         put them at the front, since we've already spilled most of the
-        psuedos in them (we might have left some pseudos unspilled if they
+        pseudos in them (we might have left some pseudos unspilled if they
         were in a block that didn't need any spill registers of a conflicting
         class.  We used to try to mark off the need for those registers,
         but doing so properly is very complex and reallocating them is the
@@ -1648,7 +1681,11 @@ reload (first, global, dumpfile)
                          max_groups[class]--;
                          p = reg_class_superclasses[class];
                          while (*p != LIM_REG_CLASSES)
-                           max_groups[(int) *p++]--;
+                           {
+                             if (group_size [(int) *p] <= group_size [class])
+                               max_groups[(int) *p]--;
+                             p++;
+                           }
 
                          /* Indicate both these regs are part of a group.  */
                          SET_HARD_REG_BIT (counted_for_groups, j);
@@ -1763,8 +1800,12 @@ reload (first, global, dumpfile)
                              max_groups[class]--;
                              p = reg_class_superclasses[class];
                              while (*p != LIM_REG_CLASSES)
-                               max_groups[(int) *p++]--;
-
+                               {
+                                 if (group_size [(int) *p]
+                                     <= group_size [class])
+                                   max_groups[(int) *p]--;
+                                 p++;
+                               }
                              break;
                            }
                        }
@@ -1785,10 +1826,6 @@ 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.  */
@@ -1812,7 +1849,6 @@ reload (first, global, dumpfile)
                    }
              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.
@@ -2000,6 +2036,10 @@ reload (first, global, dumpfile)
     free (scratch_block);
   scratch_block = 0;
 
+  CLEAR_HARD_REG_SET (used_spill_regs);
+  for (i = 0; i < n_spills; i++)
+    SET_HARD_REG_BIT (used_spill_regs, spill_regs[i]);
+
   return failure;
 }
 \f
@@ -2112,10 +2152,14 @@ count_possible_groups (group_size, group_mode, max_groups, class)
            max_groups[class]--;
            p = reg_class_superclasses[class];
            while (*p != LIM_REG_CLASSES)
-             max_groups[(int) *p++]--;
+             {
+               if (group_size [(int) *p] <= group_size [class])
+                 max_groups[(int) *p]--;
+               p++;
+             }
 
            /* Don't count these registers again.  */
-           for (j = 0; j < group_size[j]; j++)
+           for (j = 0; j < group_size[class]; j++)
              SET_HARD_REG_BIT (counted_for_groups, i + j);
          }
 
@@ -2163,7 +2207,7 @@ spill_failure (insn)
   if (asm_noperands (PATTERN (insn)) >= 0)
     error_for_asm (insn, "`asm' needs too many reloads");
   else
-    abort ();
+    fatal_insn ("Unable to find a register to spill.", insn);
 }
 
 /* Add a new register to the tables of available spill-registers
@@ -2323,13 +2367,14 @@ alter_reg (i, from_reg)
        {
          /* No known place to spill from => no slot to reuse.  */
          x = assign_stack_local (GET_MODE (regno_reg_rtx[i]), total_size, -1);
-#if BYTES_BIG_ENDIAN
-         /* Cancel the  big-endian correction done in assign_stack_local.
-            Get the address of the beginning of the slot.
-            This is so we can do a big-endian correction unconditionally
-            below.  */
-         adjust = inherent_size - total_size;
-#endif
+         if (BYTES_BIG_ENDIAN)
+           /* Cancel the  big-endian correction done in assign_stack_local.
+              Get the address of the beginning of the slot.
+              This is so we can do a big-endian correction unconditionally
+              below.  */
+           adjust = inherent_size - total_size;
+
+         RTX_UNCHANGING_P (x) = RTX_UNCHANGING_P (regno_reg_rtx[i]);
        }
       /* Reuse a stack slot if possible.  */
       else if (spill_stack_slot[from_reg] != 0
@@ -2343,6 +2388,7 @@ alter_reg (i, from_reg)
          /* Compute maximum size needed, both for inherent size
             and for total size.  */
          enum machine_mode mode = GET_MODE (regno_reg_rtx[i]);
+         rtx stack_slot;
          if (spill_stack_slot[from_reg])
            {
              if (GET_MODE_SIZE (GET_MODE (spill_stack_slot[from_reg]))
@@ -2353,23 +2399,28 @@ alter_reg (i, from_reg)
            }
          /* Make a slot with that size.  */
          x = assign_stack_local (mode, total_size, -1);
-#if BYTES_BIG_ENDIAN
-         /* Cancel the  big-endian correction done in assign_stack_local.
-            Get the address of the beginning of the slot.
-            This is so we can do a big-endian correction unconditionally
-            below.  */
-         adjust = GET_MODE_SIZE (mode) - total_size;
-#endif
-         spill_stack_slot[from_reg] = x;
+         stack_slot = x;
+         if (BYTES_BIG_ENDIAN)
+           {
+             /* Cancel the  big-endian correction done in assign_stack_local.
+                Get the address of the beginning of the slot.
+                This is so we can do a big-endian correction unconditionally
+                below.  */
+             adjust = GET_MODE_SIZE (mode) - total_size;
+             if (adjust)
+               stack_slot = gen_rtx (MEM, mode_for_size (total_size
+                                                         * BITS_PER_UNIT,
+                                                         MODE_INT, 1),
+                                     plus_constant (XEXP (x, 0), adjust));
+           }
+         spill_stack_slot[from_reg] = stack_slot;
          spill_stack_slot_width[from_reg] = total_size;
        }
 
-#if BYTES_BIG_ENDIAN
       /* On a big endian machine, the "address" of the slot
         is the address of the low part that fits its inherent mode.  */
-      if (inherent_size < total_size)
+      if (BYTES_BIG_ENDIAN && inherent_size < total_size)
        adjust += (total_size - inherent_size);
-#endif /* BYTES_BIG_ENDIAN */
 
       /* If we have any adjustment to make, or if the stack slot is the
         wrong mode, make a new stack slot.  */
@@ -2764,7 +2815,7 @@ eliminate_regs (x, mem_mode, insn)
       /* If this is the product of an eliminable register and a 
         constant, apply the distribute law and move the constant out
         so that we have (plus (mult ..) ..).  This is needed in order
-        to keep load-address insns valid.   This case is pathalogical.
+        to keep load-address insns valid.   This case is pathological.
         We ignore the possibility of overflow here.  */
       if (GET_CODE (XEXP (x, 0)) == REG
          && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER
@@ -2851,7 +2902,6 @@ eliminate_regs (x, mem_mode, insn)
          }
 
       /* Fall through to generic unary operation case.  */
-    case USE:
     case STRICT_LOW_PART:
     case NEG:          case NOT:
     case SIGN_EXTEND:  case ZERO_EXTEND:
@@ -2914,18 +2964,21 @@ eliminate_regs (x, mem_mode, insn)
                 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)
+                   && GET_MODE_SIZE (GET_MODE (new)) <= UNITS_PER_WORD
+                   && (GET_MODE_SIZE (GET_MODE (x))
+                       > GET_MODE_SIZE (GET_MODE (new)))
+                   && INTEGRAL_MODE_P (GET_MODE (new))
+                   && LOAD_EXTEND_OP (GET_MODE (new)) != NIL)
 #endif
              )
            {
              int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
              enum machine_mode mode = GET_MODE (x);
 
-#if BYTES_BIG_ENDIAN
-             offset += (MIN (UNITS_PER_WORD,
-                             GET_MODE_SIZE (GET_MODE (new)))
-                        - MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)));
-#endif
+             if (BYTES_BIG_ENDIAN)
+               offset += (MIN (UNITS_PER_WORD,
+                               GET_MODE_SIZE (GET_MODE (new)))
+                          - MIN (UNITS_PER_WORD, GET_MODE_SIZE (mode)));
 
              PUT_MODE (new, mode);
              XEXP (new, 0) = plus_constant (XEXP (new, 0), offset);
@@ -2937,6 +2990,19 @@ eliminate_regs (x, mem_mode, insn)
 
       return x;
 
+    case USE:
+      /* If using a register that is the source of an eliminate we still
+        think can be performed, note it cannot be performed since we don't
+        know how this register is used.  */
+      for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+       if (ep->from_rtx == XEXP (x, 0))
+         ep->can_eliminate = 0;
+
+      new = eliminate_regs (XEXP (x, 0), mem_mode, insn);
+      if (new != XEXP (x, 0))
+       return gen_rtx (code, GET_MODE (x), new);
+      return x;
+
     case CLOBBER:
       /* If clobbering a register that is the replacement register for an
         elimination we still think can be performed, note that it cannot
@@ -3199,7 +3265,7 @@ eliminate_regs_in_insn (insn, replace)
               will delete it in reload_as_needed once we know that this
               elimination is, in fact, being done.
 
-              If REPLACE isn't set, we can't delete this insn, but neededn't
+              If REPLACE isn't set, we can't delete this insn, but needn't
               process it since it won't be used unless something changes.  */
            if (replace)
              delete_dead_insn (insn);
@@ -3335,7 +3401,7 @@ eliminate_regs_in_insn (insn, replace)
     }
 
  done:
-  /* If we changed something, perform elmination in REG_NOTES.  This is
+  /* If we changed something, perform elimination in REG_NOTES.  This is
      needed even when REPLACE is zero because a REG_DEAD note might refer
      to a register that we eliminate and could cause a different number
      of spill registers to be needed in the final reload pass than in
@@ -3457,7 +3523,7 @@ spill_hard_reg (regno, global, dumpfile, cant_eliminate)
        /* We will need to scan everything again.  */
        something_changed = 1;
        if (global)
-           retry_global_alloc (i, forbidden_regs);
+         retry_global_alloc (i, forbidden_regs);
 
        alter_reg (i, regno);
        if (dumpfile)
@@ -3566,7 +3632,8 @@ hard_reg_use_compare (p1, p2)
    Store them in order of decreasing preference in potential_reload_regs.  */
 
 static void
-order_regs_for_reload ()
+order_regs_for_reload (global)
+     int global;
 {
   register int i;
   register int o = 0;
@@ -3595,7 +3662,15 @@ order_regs_for_reload ()
        {
          int lim = regno + HARD_REGNO_NREGS (regno, PSEUDO_REGNO_MODE (i));
          while (regno < lim)
-           hard_reg_n_uses[regno++].uses += reg_n_refs[i];
+           {
+             /* If allocated by local-alloc, show more uses since
+                we're not going to be able to reallocate it, but
+                we might if allocated by global alloc.  */
+             if (global && reg_allocno[i] < 0)
+               hard_reg_n_uses[regno].uses += (reg_n_refs[i] + 1) / 2;
+
+             hard_reg_n_uses[regno++].uses += reg_n_refs[i];
+           }
        }
       large += reg_n_refs[i];
     }
@@ -3768,6 +3843,7 @@ reload_as_needed (first, live_known)
       else if (GET_RTX_CLASS (GET_CODE (insn)) == 'i')
        {
          rtx avoid_return_reg = 0;
+         rtx oldpat = PATTERN (insn);
 
 #ifdef SMALL_REGISTER_CLASSES
          /* Set avoid_return_reg if this is an insn
@@ -3848,7 +3924,7 @@ reload_as_needed (first, live_known)
                        && ! reload_optional[i]
                        && (reload_in[i] != 0 || reload_out[i] != 0
                            || reload_secondary_p[i] != 0))
-                     abort ();
+                     fatal_insn ("Non-optional registers need a spill register", insn);
 
              /* Now compute which reload regs to reload them into.  Perhaps
                 reusing reload regs from previous insns, or else output
@@ -3897,7 +3973,7 @@ reload_as_needed (first, live_known)
             for this insn in order to be stored in
             (obeying register constraints).  That is correct; such reload
             registers ARE still valid.  */
-         note_stores (PATTERN (insn), forget_old_reloads_1);
+         note_stores (oldpat, forget_old_reloads_1);
 
          /* There may have been CLOBBER insns placed after INSN.  So scan
             between INSN and NEXT and use them to forget old reloads.  */
@@ -4655,11 +4731,6 @@ rtx reload_override_in[MAX_RELOADS];
    or -1 if we did not need one of the spill registers for this reload.  */
 int reload_spill_index[MAX_RELOADS];
 
-/* Index of last register assigned as a spill register.  We allocate in
-   a round-robin fashio.  */
-
-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
    processed.
@@ -4844,7 +4915,7 @@ allocate_reload_reg (r, insn, last_reload, noerror)
  failure:
   if (asm_noperands (PATTERN (insn)) < 0)
     /* It's the compiler's fault.  */
-    abort ();
+    fatal_insn ("Could not find a spill register", insn);
 
   /* It's the user's fault; the operand's mode and constraint
      don't match.  Disable this reload so we don't crash in final.  */
@@ -5617,6 +5688,7 @@ emit_reload_insns (insn)
   rtx output_address_reload_insns[MAX_RECOG_OPERANDS];
   rtx operand_reload_insns = 0;
   rtx other_operand_reload_insns = 0;
+  rtx other_output_reload_insns = 0;
   rtx following_insn = NEXT_INSN (insn);
   rtx before_insn = insn;
   int special;
@@ -5999,50 +6071,8 @@ emit_reload_insns (insn)
                    {
                      if (icode != CODE_FOR_nothing)
                        {
-                         rtx pat;
-#ifdef SECONDARY_MEMORY_NEEDED
-                         /* If we need a memory location to do the move, do
-                            it that way.  */
-                         if (GET_CODE (real_oldequiv) == REG
-                             && REGNO (real_oldequiv) < FIRST_PSEUDO_REGISTER
-                             && SECONDARY_MEMORY_NEEDED
-                             (REGNO_REG_CLASS (REGNO (real_oldequiv)),
-                              REGNO_REG_CLASS (REGNO (second_reload_reg)),
-                              GET_MODE (second_reload_reg)))
-                           {
-                             /* Get the memory to use and rewrite both
-                                registers to its mode.  */
-                             rtx loc
-                               = get_secondary_mem (real_oldequiv,
-                                                    GET_MODE (second_reload_reg),
-                                                    reload_opnum[j],
-                                                    reload_when_needed[j]);
-                             rtx tmp_reloadreg;
-
-                             if (GET_MODE (loc)
-                                 != GET_MODE (second_reload_reg))
-                               second_reload_reg
-                                 = gen_rtx (REG,
-                                            GET_MODE (loc),
-                                            REGNO (second_reload_reg));
-                         
-                             if (GET_MODE (loc) != GET_MODE (real_oldequiv))
-                               tmp_reloadreg = gen_rtx (REG, GET_MODE (loc),
-                                                        REGNO (real_oldequiv));
-                             else
-                               tmp_reloadreg = real_oldequiv;
-                             
-                             emit_move_insn (loc, tmp_reloadreg);
-                             emit_move_insn (second_reload_reg, loc);
-                             pat = gen_move_insn (reloadreg, second_reload_reg);
-                             
-                           }
-                         else
-#endif
-                           pat = GEN_FCN (icode) (reloadreg,
-                                                  real_oldequiv,
-                                                  second_reload_reg);
-                         emit_insn (pat);
+                         emit_insn (GEN_FCN (icode) (reloadreg, real_oldequiv,
+                                                     second_reload_reg));
                          special = 1;
                        }
                      else
@@ -6062,9 +6092,9 @@ emit_reload_insns (insn)
                                           third_reload_reg)));
                            }
                          else
-                           gen_input_reload (second_reload_reg, oldequiv,
-                                             reload_opnum[j],
-                                             reload_when_needed[j]);
+                           gen_reload (second_reload_reg, oldequiv,
+                                       reload_opnum[j],
+                                       reload_when_needed[j]);
 
                          oldequiv = second_reload_reg;
                        }
@@ -6073,8 +6103,8 @@ emit_reload_insns (insn)
 #endif
 
              if (! special && ! rtx_equal_p (reloadreg, oldequiv))
-               gen_input_reload (reloadreg, oldequiv, reload_opnum[j],
-                                 reload_when_needed[j]);
+               gen_reload (reloadreg, oldequiv, reload_opnum[j],
+                           reload_when_needed[j]);
 
 #if defined(SECONDARY_INPUT_RELOAD_CLASS) && defined(PRESERVE_DEATH_INFO_REGNO_P)
              /* We may have to make a REG_DEAD note for the secondary reload
@@ -6268,6 +6298,16 @@ emit_reload_insns (insn)
              XEXP (note, 0) = reload_reg_rtx[j];
              continue;
            }
+         /* Likewise for a SUBREG of an operand that dies.  */
+         else if (GET_CODE (old) == SUBREG
+                  && GET_CODE (SUBREG_REG (old)) == REG
+                  && 0 != (note = find_reg_note (insn, REG_UNUSED,
+                                                 SUBREG_REG (old))))
+           {
+             XEXP (note, 0) = gen_lowpart_common (GET_MODE (old),
+                                                  reload_reg_rtx[j]);
+             continue;
+           }
          else if (GET_CODE (old) == SCRATCH)
            /* If we aren't optimizing, there won't be a REG_UNUSED note,
               but we don't want to make an output reload.  */
@@ -6287,7 +6327,10 @@ emit_reload_insns (insn)
          if (GET_CODE (insn) == JUMP_INSN)
            abort ();
 
-         push_to_sequence (output_reload_insns[reload_opnum[j]]);
+         if (reload_when_needed[j] == RELOAD_OTHER)
+           start_sequence ();
+         else
+           push_to_sequence (output_reload_insns[reload_opnum[j]]);
 
          /* Determine the mode to reload in.
             See comments above (for input reloading).  */
@@ -6298,7 +6341,7 @@ emit_reload_insns (insn)
              /* VOIDmode should never happen for an output.  */
              if (asm_noperands (PATTERN (insn)) < 0)
                /* It's the compiler's fault.  */
-               abort ();
+               fatal_insn ("VOIDmode on an output", insn);
              error_for_asm (insn, "output operand is constant in `asm'");
              /* Prevent crash--use something we know is valid.  */
              mode = word_mode;
@@ -6311,7 +6354,7 @@ emit_reload_insns (insn)
 #ifdef SECONDARY_OUTPUT_RELOAD_CLASS
 
          /* If we need two reload regs, set RELOADREG to the intermediate
-            one, since it will be stored into OUT.  We might need a secondary
+            one, since it will be stored into OLD.  We might need a secondary
             register only for an input reload, so check again here.  */
 
          if (reload_secondary_out_reload[j] >= 0)
@@ -6341,10 +6384,10 @@ emit_reload_insns (insn)
                    {
                      /* See if we need both a scratch and intermediate reload
                         register.  */
+
                      int secondary_reload = reload_secondary_out_reload[j];
                      enum insn_code tertiary_icode
                        = reload_secondary_out_icode[secondary_reload];
-                     rtx pat;
 
                      if (GET_MODE (reloadreg) != mode)
                        reloadreg = gen_rtx (REG, mode, REGNO (reloadreg));
@@ -6353,44 +6396,36 @@ emit_reload_insns (insn)
                        {
                          rtx third_reloadreg
                            = reload_reg_rtx[reload_secondary_out_reload[secondary_reload]];
-                         pat = (GEN_FCN (tertiary_icode)
-                                (reloadreg, second_reloadreg, third_reloadreg));
-                       }
-#ifdef SECONDARY_MEMORY_NEEDED
-                     /* If we need a memory location to do the move, do it that way.  */
-                     else if (GET_CODE (reloadreg) == REG
-                              && REGNO (reloadreg) < FIRST_PSEUDO_REGISTER
-                              && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (reloadreg)),
-                                          REGNO_REG_CLASS (REGNO (second_reloadreg)),
-                                          GET_MODE (second_reloadreg)))
-                       {
-                         /* Get the memory to use and rewrite both registers
-                            to its mode.  */
-                         rtx loc
-                           = get_secondary_mem (reloadreg,
-                                                GET_MODE (second_reloadreg),
-                                                reload_opnum[j],
-                                                reload_when_needed[j]);
-                         rtx tmp_reloadreg;
-                           
-                         if (GET_MODE (loc) != GET_MODE (second_reloadreg))
-                           second_reloadreg = gen_rtx (REG, GET_MODE (loc),
-                                                       REGNO (second_reloadreg));
-                         
-                         if (GET_MODE (loc) != GET_MODE (reloadreg))
-                           tmp_reloadreg = gen_rtx (REG, GET_MODE (loc),
-                                                    REGNO (reloadreg));
-                         else
-                           tmp_reloadreg = reloadreg;
-                         
-                         emit_move_insn (loc, second_reloadreg);
-                         pat = gen_move_insn (tmp_reloadreg, loc);
+                         rtx tem;
+
+                         /* Copy primary reload reg to secondary reload reg.
+                            (Note that these have been swapped above, then
+                            secondary reload reg to OLD using our insn.  */
+
+                         /* If REAL_OLD is a paradoxical SUBREG, remove it
+                            and try to put the opposite SUBREG on
+                            RELOADREG.  */
+                         if (GET_CODE (real_old) == SUBREG
+                             && (GET_MODE_SIZE (GET_MODE (real_old))
+                                 > GET_MODE_SIZE (GET_MODE (SUBREG_REG (real_old))))
+                             && 0 != (tem = gen_lowpart_common
+                                      (GET_MODE (SUBREG_REG (real_old)),
+                                       reloadreg)))
+                           real_old = SUBREG_REG (real_old), reloadreg = tem;
+
+                         gen_reload (reloadreg, second_reloadreg,
+                                     reload_opnum[j], reload_when_needed[j]);
+                         emit_insn ((GEN_FCN (tertiary_icode)
+                                     (real_old, reloadreg, third_reloadreg)));
+                         special = 1;
                        }
-#endif
+
                      else
-                       pat = gen_move_insn (reloadreg, second_reloadreg);
+                       /* Copy between the reload regs here and then to
+                          OUT later.  */
 
-                     emit_insn (pat);
+                       gen_reload (reloadreg, second_reloadreg,
+                                   reload_opnum[j], reload_when_needed[j]);
                    }
                }
            }
@@ -6398,34 +6433,8 @@ emit_reload_insns (insn)
 
          /* Output the last reload insn.  */
          if (! special)
-           {
-#ifdef SECONDARY_MEMORY_NEEDED
-             /* If we need a memory location to do the move, do it that way.  */
-             if (GET_CODE (old) == REG && REGNO (old) < FIRST_PSEUDO_REGISTER
-                 && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (old)),
-                                             REGNO_REG_CLASS (REGNO (reloadreg)),
-                                             GET_MODE (reloadreg)))
-               {
-                 /* Get the memory to use and rewrite both registers to
-                    its mode.  */
-                 rtx loc = get_secondary_mem (old, GET_MODE (reloadreg),
-                                              reload_opnum[j],
-                                              reload_when_needed[j]);
-
-                 if (GET_MODE (loc) != GET_MODE (reloadreg))
-                   reloadreg = gen_rtx (REG, GET_MODE (loc),
-                                        REGNO (reloadreg));
-
-                 if (GET_MODE (loc) != GET_MODE (old))
-                   old = gen_rtx (REG, GET_MODE (loc), REGNO (old));
-
-                 emit_insn (gen_move_insn (loc, reloadreg));
-                 emit_insn (gen_move_insn (old, loc));
-               }
-             else
-#endif
-               emit_insn (gen_move_insn (old, reloadreg));
-           }
+           gen_reload (old, reloadreg, reload_opnum[j],
+                       reload_when_needed[j]);
 
 #ifdef PRESERVE_DEATH_INFO_REGNO_P
          /* If final will look at death notes for this reg,
@@ -6465,7 +6474,15 @@ emit_reload_insns (insn)
                  new_spill_reg_store[reload_spill_index[j]] = p;
              }
 
-         output_reload_insns[reload_opnum[j]] = get_insns ();
+         if (reload_when_needed[j] == RELOAD_OTHER)
+           {
+             if (other_output_reload_insns)
+               emit_insns (other_output_reload_insns);
+             other_output_reload_insns = get_insns ();
+           }
+         else
+           output_reload_insns[reload_opnum[j]] = get_insns ();
+
          end_sequence ();
        }
     }
@@ -6476,7 +6493,7 @@ emit_reload_insns (insn)
 
      RELOAD_FOR_OTHER_ADDRESS reloads for input addresses.
 
-     RELOAD_OTHER reloads.
+     RELOAD_OTHER reloads, output in ascending order by reload number.
 
      For each operand, any RELOAD_FOR_INPUT_ADDRESS reloads followed by
      the RELOAD_FOR_INPUT reload for the operand.
@@ -6488,7 +6505,10 @@ emit_reload_insns (insn)
      After the insn being reloaded, we write the following:
 
      For each operand, any RELOAD_FOR_OUTPUT_ADDRESS reload followed by
-     the RELOAD_FOR_OUTPUT reload for that operand.  */
+     the RELOAD_FOR_OUTPUT reload for that operand.
+
+     Any RELOAD_OTHER output reloads, output in descending order by
+     reload number.  */
 
   emit_insns_before (other_input_address_reload_insns, before_insn);
   emit_insns_before (other_input_reload_insns, before_insn);
@@ -6508,6 +6528,8 @@ emit_reload_insns (insn)
       emit_insns_before (output_reload_insns[j], following_insn);
     }
 
+  emit_insns_before (other_output_reload_insns, following_insn);
+
   /* Move death notes from INSN
      to output-operand-address and output reload insns.  */
 #ifdef PRESERVE_DEATH_INFO_REGNO_P
@@ -6566,107 +6588,139 @@ emit_reload_insns (insn)
 
       /* I is nonneg if this reload used one of the spill regs.
         If reload_reg_rtx[r] is 0, this is an optional reload
-        that we opted to ignore.
-
-        Also ignore reloads that don't reach the end of the insn,
-        since we will eventually see the one that does.  */
+        that we opted to ignore.  */
 
-      if (i >= 0 && reload_reg_rtx[r] != 0
-         && reload_reg_reaches_end_p (spill_regs[i], reload_opnum[r],
-                                      reload_when_needed[r]))
+      if (i >= 0 && reload_reg_rtx[r] != 0)
        {
-         /* First, clear out memory of what used to be in this spill reg.
-            If consecutive registers are used, clear them all.  */
          int nr
            = HARD_REGNO_NREGS (spill_regs[i], GET_MODE (reload_reg_rtx[r]));
          int k;
+         int part_reaches_end = 0;
+         int all_reaches_end = 1;
 
+         /* For a multi register reload, we need to check if all or part
+            of the value lives to the end.  */
          for (k = 0; k < nr; k++)
            {
-             reg_reloaded_contents[spill_reg_order[spill_regs[i] + k]] = -1;
-             reg_reloaded_insn[spill_reg_order[spill_regs[i] + k]] = 0;
+             if (reload_reg_reaches_end_p (spill_regs[i] + k, reload_opnum[r],
+                                           reload_when_needed[r]))
+               part_reaches_end = 1;
+             else
+               all_reaches_end = 0;
            }
 
-         /* Maybe the spill reg contains a copy of reload_out.  */
-         if (reload_out[r] != 0 && GET_CODE (reload_out[r]) == REG)
+         /* Ignore reloads that don't reach the end of the insn in
+            entirety.  */
+         if (all_reaches_end)
            {
-             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];
+             /* First, clear out memory of what used to be in this spill reg.
+                If consecutive registers are used, clear them all.  */
 
-             /* 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,
-                                           reg_raw_mode[REGNO (reload_reg_rtx[r]) + k],
-                                           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 >= FIRST_PSEUDO_REGISTER || nr != nnr ? nregno
-                      : nregno + k);
-                 reg_reloaded_insn[spill_reg_order[spill_regs[i] + k]] = insn;
+                 reg_reloaded_contents[spill_reg_order[spill_regs[i] + k]] = -1;
+                 reg_reloaded_insn[spill_reg_order[spill_regs[i] + k]] = 0;
                }
-           }
-
-         /* 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
-                       && ! 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])));
+             /* Maybe the spill reg contains a copy of reload_out.  */
+             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,
+                                     reg_raw_mode[REGNO (reload_reg_rtx[r]) + k],
+                                     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 >= FIRST_PSEUDO_REGISTER || nr != nnr
+                          ? nregno
+                          : nregno + k);
+                     reg_reloaded_insn[spill_reg_order[spill_regs[i] + k]] = insn;
+                   }
+               }
 
-             reg_last_reload_reg[nregno] = reload_reg_rtx[r];
+             /* 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
+                           && ! 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 (nregno < FIRST_PSEUDO_REGISTER)
-               for (k = 1; k < nnr; k++)
-                 reg_last_reload_reg[nregno + k]
-                   = (nr == nnr ? gen_rtx (REG,
-                                           reg_raw_mode[REGNO (reload_reg_rtx[r]) + k],
-                                           REGNO (reload_reg_rtx[r]) + k)
-                      : 0);
+                 if (GET_CODE (reload_in[r]) == REG)
+                   nregno = REGNO (reload_in[r]);
+                 else
+                   nregno = REGNO (reload_in_reg[r]);
 
-             /* Unless we inherited this reload, show we haven't
-                recently done a store.  */
-             if (! reload_inherited[r])
-               spill_reg_store[i] = 0;
+                 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,
+                                     reg_raw_mode[REGNO (reload_reg_rtx[r]) + k],
+                                     REGNO (reload_reg_rtx[r]) + k)
+                          : 0);
+
+                 /* Unless we inherited this reload, show we haven't
+                    recently done a store.  */
+                 if (! reload_inherited[r])
+                   spill_reg_store[i] = 0;
+
+                 for (k = 0; k < nr; k++)
+                   {
+                     reg_reloaded_contents[spill_reg_order[spill_regs[i] + k]]
+                       = (nregno >= FIRST_PSEUDO_REGISTER || nr != nnr
+                          ? nregno
+                          : nregno + k);
+                     reg_reloaded_insn[spill_reg_order[spill_regs[i] + k]]
+                       = insn;
+                   }
+               }
+           }
 
+         /* However, if part of the reload reaches the end, then we must
+            invalidate the old info for the part that survives to the end.  */
+         else if (part_reaches_end)
+           {
              for (k = 0; k < nr; k++)
-               {
-                 reg_reloaded_contents[spill_reg_order[spill_regs[i] + k]]
-                   = (nregno >= FIRST_PSEUDO_REGISTER || nr != nnr ? nregno
-                      : nregno + k);
-                 reg_reloaded_insn[spill_reg_order[spill_regs[i] + k]]
-                   = insn;
-               }
+               if (reload_reg_reaches_end_p (spill_regs[i] + k,
+                                             reload_opnum[r],
+                                             reload_when_needed[r]))
+                 {
+                   reg_reloaded_contents[spill_reg_order[spill_regs[i] + k]] = -1;
+                   reg_reloaded_insn[spill_reg_order[spill_regs[i] + k]] = 0;
+                 }
            }
        }
 
@@ -6681,27 +6735,47 @@ emit_reload_insns (insn)
       if (i < 0 && reload_out[r] != 0 && GET_CODE (reload_out[r]) == REG)
        {
          register int nregno = REGNO (reload_out[r]);
-         int num_regs = HARD_REGNO_NREGS (nregno, GET_MODE (reload_out[r]));
+         if (nregno >= FIRST_PSEUDO_REGISTER)
+           reg_last_reload_reg[nregno] = 0;
+         else
+           {
+             int num_regs = HARD_REGNO_NREGS (nregno,GET_MODE (reload_out[r]));
 
-         while (num_regs-- > 0)
-           reg_last_reload_reg[nregno + num_regs] = 0;
+             while (num_regs-- > 0)
+               reg_last_reload_reg[nregno + num_regs] = 0;
+           }
        }
     }
 }
 \f
-/* Emit code to perform an input reload of IN to RELOADREG.  IN is from
-   operand OPNUM with reload type TYPE. 
+/* Emit code to perform a reload from IN (which may be a reload register) to
+   OUT (which may also be a reload register).  IN or OUT is from operand
+   OPNUM with reload type TYPE. 
 
    Returns first insn emitted.  */
 
 rtx
-gen_input_reload (reloadreg, in, opnum, type)
-     rtx reloadreg;
+gen_reload (out, in, opnum, type)
+     rtx out;
      rtx in;
      int opnum;
      enum reload_type type;
 {
   rtx last = get_last_insn ();
+  rtx tem;
+
+  /* If IN is a paradoxical SUBREG, remove it and try to put the
+     opposite SUBREG on OUT.  Likewise for a paradoxical SUBREG on OUT.  */
+  if (GET_CODE (in) == SUBREG
+      && (GET_MODE_SIZE (GET_MODE (in))
+         > GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))))
+      && (tem = gen_lowpart_common (GET_MODE (SUBREG_REG (in)), out)) != 0)
+    in = SUBREG_REG (in), out = tem;
+  else if (GET_CODE (out) == SUBREG
+      && (GET_MODE_SIZE (GET_MODE (out))
+         > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))))
+      && (tem = gen_lowpart_common (GET_MODE (SUBREG_REG (out)), in)) != 0)
+    out = SUBREG_REG (out), in = tem;
 
   /* How to do this reload can get quite tricky.  Normally, we are being
      asked to reload a simple operand, such as a MEM, a constant, or a pseudo
@@ -6763,13 +6837,13 @@ gen_input_reload (reloadreg, in, opnum, type)
         it will be A = A + B as constrain_operands expects. */
 
       if (GET_CODE (XEXP (in, 1)) == REG
-         && REGNO (reloadreg) == REGNO (XEXP (in, 1)))
+         && REGNO (out) == REGNO (XEXP (in, 1)))
        tem = op0, op0 = op1, op1 = tem;
 
       if (op0 != XEXP (in, 0) || op1 != XEXP (in, 1))
        in = gen_rtx (PLUS, GET_MODE (in), op0, op1);
 
-      insn = emit_insn (gen_rtx (SET, VOIDmode, reloadreg, in));
+      insn = emit_insn (gen_rtx (SET, VOIDmode, out, in));
       code = recog_memoized (insn);
 
       if (code >= 0)
@@ -6798,16 +6872,16 @@ gen_input_reload (reloadreg, in, opnum, type)
              && REGNO (op1) >= FIRST_PSEUDO_REGISTER))
        tem = op0, op0 = op1, op1 = tem;
 
-      emit_insn (gen_move_insn (reloadreg, op0));
+      emit_insn (gen_move_insn (out, op0));
 
-      /* If OP0 and OP1 are the same, we can use RELOADREG for OP1.
+      /* If OP0 and OP1 are the same, we can use OUT for OP1.
         This fixes a problem on the 32K where the stack pointer cannot
         be used as an operand of an add insn.  */
 
       if (rtx_equal_p (op0, op1))
-       op1 = reloadreg;
+       op1 = out;
 
-      insn = emit_insn (gen_add2_insn (reloadreg, op1));
+      insn = emit_insn (gen_add2_insn (out, op1));
 
       /* If that failed, copy the address register to the reload register.
         Then add the constant to the reload register. */
@@ -6826,43 +6900,44 @@ gen_input_reload (reloadreg, in, opnum, type)
 
       delete_insns_since (last);
 
-      emit_insn (gen_move_insn (reloadreg, op1));
-      emit_insn (gen_add2_insn (reloadreg, op0));
+      emit_insn (gen_move_insn (out, op1));
+      emit_insn (gen_add2_insn (out, op0));
     }
 
 #ifdef SECONDARY_MEMORY_NEEDED
   /* If we need a memory location to do the move, do it that way.  */
   else if (GET_CODE (in) == REG && REGNO (in) < FIRST_PSEUDO_REGISTER
+          && GET_CODE (out) == REG && REGNO (out) < FIRST_PSEUDO_REGISTER
           && SECONDARY_MEMORY_NEEDED (REGNO_REG_CLASS (REGNO (in)),
-                                      REGNO_REG_CLASS (REGNO (reloadreg)),
-                                      GET_MODE (reloadreg)))
+                                      REGNO_REG_CLASS (REGNO (out)),
+                                      GET_MODE (out)))
     {
       /* Get the memory to use and rewrite both registers to its mode.  */
-      rtx loc = get_secondary_mem (in, GET_MODE (reloadreg), opnum, type);
+      rtx loc = get_secondary_mem (in, GET_MODE (out), opnum, type);
 
-      if (GET_MODE (loc) != GET_MODE (reloadreg))
-       reloadreg = gen_rtx (REG, GET_MODE (loc), REGNO (reloadreg));
+      if (GET_MODE (loc) != GET_MODE (out))
+       out = gen_rtx (REG, GET_MODE (loc), REGNO (out));
 
       if (GET_MODE (loc) != GET_MODE (in))
        in = gen_rtx (REG, GET_MODE (loc), REGNO (in));
 
       emit_insn (gen_move_insn (loc, in));
-      emit_insn (gen_move_insn (reloadreg, loc));
+      emit_insn (gen_move_insn (out, loc));
     }
 #endif
 
   /* If IN is a simple operand, use gen_move_insn.  */
   else if (GET_RTX_CLASS (GET_CODE (in)) == 'o' || GET_CODE (in) == SUBREG)
-    emit_insn (gen_move_insn (reloadreg, in));
+    emit_insn (gen_move_insn (out, in));
 
 #ifdef HAVE_reload_load_address
   else if (HAVE_reload_load_address)
-    emit_insn (gen_reload_load_address (reloadreg, in));
+    emit_insn (gen_reload_load_address (out, in));
 #endif
 
-  /* Otherwise, just write (set REGLOADREG IN) and hope for the best.  */
+  /* Otherwise, just write (set OUT IN) and hope for the best.  */
   else
-    emit_insn (gen_rtx (SET, VOIDmode, reloadreg, in));
+    emit_insn (gen_rtx (SET, VOIDmode, out, in));
 
   /* Return the first insn emitted.
      We can not just return get_last_insn, because there may have
@@ -7009,7 +7084,7 @@ inc_for_reload (reloadreg, value, inc_amount)
     emit_insn (gen_move_insn (reloadreg, incloc));
 
   /* See if we can directly increment INCLOC.  Use a method similar to that
-     in gen_input_reload.  */
+     in gen_reload.  */
 
   last = get_last_insn ();
   add_insn = emit_insn (gen_rtx (SET, VOIDmode, incloc,