OSDN Git Service

Added fixup for __STDC__ == 0 and __STDC__ == 1
[pf3gnuchains/gcc-fork.git] / gcc / reload1.c
index 32f6bf5..c7ea46f 100644 (file)
@@ -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));
@@ -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))
@@ -1693,7 +1709,8 @@ reload (first, global, dumpfile)
                            && 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;
                      }
 
@@ -1776,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.  */
@@ -1954,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
@@ -2356,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.
 
@@ -2600,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;
 
@@ -2801,7 +2869,7 @@ eliminate_regs (x, mem_mode, insn)
          if (GET_CODE (new) == MEM
              && (GET_MODE_SIZE (GET_MODE (x))
                  <= GET_MODE_SIZE (GET_MODE (new)))
-#if defined(BYTES_LOADS_ZERO_EXTEND) || defined(BYTE_LOADS_SIGN_EXTEND)
+#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
@@ -3066,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;
            }
     }
 
@@ -3230,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;
 
@@ -3246,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
@@ -3286,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;
 }
@@ -4819,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]);
+                           }
                        }
                    }
                }
@@ -5392,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
@@ -5857,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
 
@@ -6438,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])