OSDN Git Service

fix TImode offset addres test
[pf3gnuchains/gcc-fork.git] / gcc / reload.c
index b64cb63..4f79b6e 100644 (file)
@@ -1,5 +1,5 @@
 /* Search an insn for pseudo regs that must be in hard regs and are not.
-   Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc.
+   Copyright (C) 1987, 88, 89, 92-5, 1996 Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -98,6 +98,7 @@ a register with any other reload.  */
 #include "hard-reg-set.h"
 #include "flags.h"
 #include "real.h"
+#include "output.h"
 
 #ifndef REGISTER_MOVE_COST
 #define REGISTER_MOVE_COST(x, y) 2
@@ -290,6 +291,7 @@ static int output_reloadnum;
 static int push_secondary_reload PROTO((int, rtx, int, int, enum reg_class,
                                        enum machine_mode, enum reload_type,
                                        enum insn_code *));
+static enum reg_class find_valid_class PROTO((enum machine_mode, int));
 static int push_reload         PROTO((rtx, rtx, rtx *, rtx *, enum reg_class,
                                       enum machine_mode, enum machine_mode,
                                       int, int, int, enum reload_type));
@@ -359,6 +361,9 @@ push_secondary_reload (in_p, x, opnum, optional, reload_class, reload_mode,
   /* If X is a paradoxical SUBREG, use the inner value to determine both the
      mode and object being reloaded.  */
   if (GET_CODE (x) == SUBREG
+#ifdef CLASS_CANNOT_CHANGE_SIZE
+      && reload_class != CLASS_CANNOT_CHANGE_SIZE
+#endif
       && (GET_MODE_SIZE (GET_MODE (x))
          > GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)))))
     {
@@ -687,6 +692,38 @@ clear_secondary_mem ()
 }
 #endif /* SECONDARY_MEMORY_NEEDED */
 \f
+/* Find the largest class for which every register number plus N is valid in
+   M1 (if in range).  Abort if no such class exists.  */
+
+static enum reg_class
+find_valid_class (m1, n)
+     enum machine_mode  m1;
+     int n;
+{
+  int class;
+  int regno;
+  enum reg_class best_class;
+  int best_size = 0;
+
+  for (class = 1; class < N_REG_CLASSES; class++)
+    {
+      int bad = 0;
+      for (regno = 0; regno < FIRST_PSEUDO_REGISTER && ! bad; regno++)
+       if (TEST_HARD_REG_BIT (reg_class_contents[class], regno)
+           && TEST_HARD_REG_BIT (reg_class_contents[class], regno + n)
+           && ! HARD_REGNO_MODE_OK (regno + n, m1))
+         bad = 1;
+
+      if (! bad && reg_class_size[class] > best_size)
+       best_class = class, best_size = reg_class_size[class];
+    }
+
+  if (best_size == 0)
+    abort ();
+
+  return best_class;
+}
+\f
 /* Record one reload that needs to be performed.
    IN is an rtx saying where the data are to be found before this instruction.
    OUT says where they must be stored after the instruction.
@@ -892,7 +929,8 @@ push_reload (in, out, inloc, outloc, class,
   if (in != 0 && GET_CODE (in) == SUBREG
       && GET_CODE (SUBREG_REG (in)) == REG
       && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
-      && (! HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (in)), inmode)
+      && (! HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (in)) + SUBREG_WORD (in),
+                               inmode)
          || (GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
              && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
                  > UNITS_PER_WORD)
@@ -901,8 +939,14 @@ push_reload (in, out, inloc, outloc, class,
                  != HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)),
                                       GET_MODE (SUBREG_REG (in)))))))
     {
+      /* This relies on the fact that emit_reload_insns outputs the
+        instructions for input reloads of type RELOAD_OTHER in the same
+        order as the reloads.  Thus if the outer reload is also of type
+        RELOAD_OTHER, we are guaranteed that this inner reload will be
+        output before the outer reload.  */
       push_reload (SUBREG_REG (in), NULL_RTX, &SUBREG_REG (in), NULL_PTR,
-                  GENERAL_REGS, VOIDmode, VOIDmode, 0, 0, opnum, type);
+                  find_valid_class (inmode, SUBREG_WORD (in)),
+                  VOIDmode, VOIDmode, 0, 0, opnum, type);
       dont_remove_subreg = 1;
     }
 
@@ -975,7 +1019,8 @@ push_reload (in, out, inloc, outloc, class,
   if (out != 0 && GET_CODE (out) == SUBREG
       && GET_CODE (SUBREG_REG (out)) == REG
       && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER
-      && (! HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (out)), outmode)
+      && (! HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (out)) + SUBREG_WORD (out),
+                               outmode)
          || (GET_MODE_SIZE (outmode) <= UNITS_PER_WORD
              && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))
                  > UNITS_PER_WORD)
@@ -984,16 +1029,19 @@ push_reload (in, out, inloc, outloc, class,
                  != HARD_REGNO_NREGS (REGNO (SUBREG_REG (out)),
                                       GET_MODE (SUBREG_REG (out)))))))
     {
-      if (type == RELOAD_OTHER)
-       abort ();
-
+      /* This relies on the fact that emit_reload_insns outputs the
+        instructions for output reloads of type RELOAD_OTHER in reverse
+        order of the reloads.  Thus if the outer reload is also of type
+        RELOAD_OTHER, we are guaranteed that this inner reload will be
+        output after the outer reload.  */
       dont_remove_subreg = 1;
       push_reload (SUBREG_REG (out), SUBREG_REG (out), &SUBREG_REG (out),
-                  &SUBREG_REG (out), ALL_REGS, VOIDmode, VOIDmode, 0, 0,
+                  &SUBREG_REG (out),
+                  find_valid_class (outmode, SUBREG_WORD (out)),
+                  VOIDmode, VOIDmode, 0, 0,
                   opnum, RELOAD_OTHER);
     }
 
-
   /* If IN appears in OUT, we can't share any input-only reload for IN.  */
   if (in != 0 && out != 0 && GET_CODE (out) == MEM
       && (GET_CODE (in) == REG || GET_CODE (in) == MEM)
@@ -5510,7 +5558,7 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
   /* Reject VALUE if it was loaded from GOAL
      and is also a register that appears in the address of GOAL.  */
 
-  if (goal_mem && value == SET_DEST (PATTERN (where))
+  if (goal_mem && value == SET_DEST (single_set (where))
       && refers_to_regno_for_reload_p (valueno,
                                       (valueno
                                        + HARD_REGNO_NREGS (valueno, mode)),
@@ -5591,6 +5639,12 @@ find_equiv_reg (goal, insn, class, other, reload_reg_p, goalreg, mode)
              || need_stable_sp))
        return 0;
 
+#ifdef NON_SAVING_SETJMP 
+      if (NON_SAVING_SETJMP && GET_CODE (p) == NOTE
+         && NOTE_LINE_NUMBER (p) == NOTE_INSN_SETJMP)
+       return 0;
+#endif
+
 #ifdef INSN_CLOBBERS_REGNO_P
       if ((valueno >= 0 && valueno < FIRST_PSEUDO_REGISTER
          && INSN_CLOBBERS_REGNO_P (p, valueno))
@@ -5886,7 +5940,7 @@ debug_reload()
        fprintf (stderr, ", inc by %d\n", reload_inc[r]);
 
       if (reload_nocombine[r])
-       fprintf (stderr, ", can combine", reload_nocombine[r]);
+       fprintf (stderr, ", can't combine", reload_nocombine[r]);
 
       if (reload_secondary_p[r])
        fprintf (stderr, ", secondary_reload_p");