OSDN Git Service

Added fixup for __STDC__ == 0 and __STDC__ == 1
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index bcbd68f..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.
 
@@ -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,7 +346,7 @@ 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));
@@ -485,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);
@@ -511,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
@@ -806,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
@@ -826,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))
@@ -1680,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;
                      }
 
@@ -1770,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.  */
@@ -1948,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
@@ -2350,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.
 
@@ -2594,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;
 
@@ -2734,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.  */
@@ -2787,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);
@@ -3043,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;
            }
     }
 
@@ -3207,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;
 
@@ -3223,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
@@ -3263,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;
 }
@@ -3664,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
        }
@@ -3714,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;
@@ -4289,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
@@ -4795,18 +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;
-                         SET_HARD_REG_BIT (reload_reg_used_for_inherit,
-                                           spill_regs[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]);
+                           }
                        }
                    }
                }
@@ -5209,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
@@ -5368,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
@@ -5541,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)
                                {
@@ -5833,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
 
@@ -6414,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])