OSDN Git Service

Fix sh-elf linker relaxation:
[pf3gnuchains/gcc-fork.git] / gcc / regclass.c
index 94744a3..01c08f3 100644 (file)
@@ -43,6 +43,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "toplev.h"
 #include "output.h"
 #include "ggc.h"
+#include "timevar.h"
 
 #ifndef REGISTER_MOVE_COST
 #define REGISTER_MOVE_COST(m, x, y) 2
@@ -50,6 +51,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 
 static void init_reg_sets_1    PARAMS ((void));
 static void init_reg_modes     PARAMS ((void));
+static void init_reg_autoinc   PARAMS ((void));
 
 /* If we have auto-increment or auto-decrement and we can have secondary
    reloads, we are not allowed to use classes requiring secondary
@@ -230,9 +232,9 @@ static char *in_inc_dec;
 #endif /* FORBIDDEN_INC_DEC_CLASSES */
 
 #ifdef CANNOT_CHANGE_MODE_CLASS
-/* All registers that have been subreged.  Indexed by mode, where each
-   entry is a regset of registers.  */
-regset_head subregs_of_mode [NUM_MACHINE_MODES];
+/* All registers that have been subreged.  Indexed by regno * MAX_MACHINE_MODE
+   + mode.  */
+bitmap_head subregs_of_mode;
 #endif
 
 /* Sample MEM values for use by memory_move_secondary_cost.  */
@@ -459,7 +461,7 @@ init_reg_sets_1 ()
        ;
 #endif
 #ifndef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
-      else if (i == PIC_OFFSET_TABLE_REGNUM && fixed_regs[i])
+      else if (i == (unsigned) PIC_OFFSET_TABLE_REGNUM && fixed_regs[i])
        ;
 #endif
       else if (0
@@ -578,6 +580,8 @@ init_regs ()
   init_reg_sets_1 ();
 
   init_reg_modes ();
+
+  init_reg_autoinc ();
 }
 
 /* Initialize some fake stack-frame MEM references for use in
@@ -1143,37 +1147,18 @@ scan_one_insn (insn, pass)
   return insn;
 }
 
-/* This is a pass of the compiler that scans all instructions
-   and calculates the preferred class for each pseudo-register.
-   This information can be accessed later by calling `reg_preferred_class'.
-   This pass comes just before local register allocation.  */
+/* Initialize information about which register classes can be used for
+   pseudos that are auto-incremented or auto-decremented.  */
 
-void
-regclass (f, nregs, dump)
-     rtx f;
-     int nregs;
-     FILE *dump;
+static void
+init_reg_autoinc ()
 {
-  rtx insn;
-  int i;
-  int pass;
-
-  init_recog ();
-
-  costs = (struct costs *) xmalloc (nregs * sizeof (struct costs));
-
 #ifdef FORBIDDEN_INC_DEC_CLASSES
-
-  in_inc_dec = (char *) xmalloc (nregs);
-
-  /* Initialize information about which register classes can be used for
-     pseudos that are auto-incremented or auto-decremented.  It would
-     seem better to put this in init_reg_sets, but we need to be able
-     to allocate rtx, which we can't do that early.  */
+  int i;
 
   for (i = 0; i < N_REG_CLASSES; i++)
     {
-      rtx r = gen_rtx_REG (VOIDmode, 0);
+      rtx r = gen_rtx_raw_REG (VOIDmode, 0);
       enum machine_mode m;
       int j;
 
@@ -1214,6 +1199,32 @@ regclass (f, nregs, dump)
          }
     }
 #endif /* FORBIDDEN_INC_DEC_CLASSES */
+}
+
+/* This is a pass of the compiler that scans all instructions
+   and calculates the preferred class for each pseudo-register.
+   This information can be accessed later by calling `reg_preferred_class'.
+   This pass comes just before local register allocation.  */
+
+void
+regclass (f, nregs, dump)
+     rtx f;
+     int nregs;
+     FILE *dump;
+{
+  rtx insn;
+  int i;
+  int pass;
+
+  init_recog ();
+
+  costs = (struct costs *) xmalloc (nregs * sizeof (struct costs));
+
+#ifdef FORBIDDEN_INC_DEC_CLASSES
+
+  in_inc_dec = (char *) xmalloc (nregs);
+
+#endif /* FORBIDDEN_INC_DEC_CLASSES */
 
   /* Normally we scan the insns once and determine the best class to use for
      each register.  However, if -fexpensive_optimizations are on, we do so
@@ -2328,6 +2339,8 @@ reg_scan (f, nregs, repeat)
   max_parallel = 3;
   max_set_parallel = 0;
 
+  timevar_push (TV_REG_SCAN);
+
   for (insn = f; insn; insn = NEXT_INSN (insn))
     if (GET_CODE (insn) == INSN
        || GET_CODE (insn) == CALL_INSN
@@ -2343,6 +2356,8 @@ reg_scan (f, nregs, repeat)
       }
 
   max_parallel += max_set_parallel;
+
+  timevar_pop (TV_REG_SCAN);
 }
 
 /* Update 'regscan' information by looking at the insns
@@ -2520,7 +2535,7 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
        REG_POINTER (SET_DEST (x)) = 1;
 
       /* If this is setting a register from a register or from a simple
-        conversion of a register, propagate REG_DECL.  */
+        conversion of a register, propagate REG_EXPR.  */
       if (GET_CODE (dest) == REG)
        {
          rtx src = SET_SRC (x);
@@ -2531,10 +2546,10 @@ reg_scan_mark_refs (x, insn, note_flag, min_regno)
                 || (GET_CODE (src) == SUBREG && subreg_lowpart_p (src)))
            src = XEXP (src, 0);
 
-         if (GET_CODE (src) == REG && REGNO_DECL (REGNO (src)) == 0)
-           REGNO_DECL (REGNO (src)) = REGNO_DECL (REGNO (dest));
-         else if (GET_CODE (src) == REG && REGNO_DECL (REGNO (dest)) == 0)
-           REGNO_DECL (REGNO (dest)) = REGNO_DECL (REGNO (src));
+         if (!REG_ATTRS (dest) && REG_P (src))
+           REG_ATTRS (dest) = REG_ATTRS (src);
+         if (!REG_ATTRS (dest) && GET_CODE (src) == MEM)
+           set_reg_attrs_from_mem (dest, src);
        }
 
       /* ... fall through ...  */
@@ -2623,15 +2638,18 @@ cannot_change_mode_set_regs (used, from, regno)
      unsigned int regno;
 {
   enum machine_mode to;
-  enum reg_class class;
+  int n, i;
+  int start = regno * MAX_MACHINE_MODE;
 
-  for (to = VOIDmode; to < MAX_MACHINE_MODE; ++to)
-    if (REGNO_REG_SET_P (&subregs_of_mode[to], regno))
-      {
-        class = CANNOT_CHANGE_MODE_CLASS (from, to);
-        if (class != NO_REGS)
-          IOR_HARD_REG_SET (*used, reg_class_contents [(int) class]);
-      }
+  EXECUTE_IF_SET_IN_BITMAP (&subregs_of_mode, start, n,
+    if (n >= MAX_MACHINE_MODE + start)
+      return;
+    to = n - start;
+    for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+      if (! TEST_HARD_REG_BIT (*used, i)
+         && REG_CANNOT_CHANGE_MODE_P (i, from, to))
+       SET_HARD_REG_BIT (*used, i);
+  );
 }
 
 /* Return 1 if REGNO has had an invalid mode change in CLASS from FROM
@@ -2644,12 +2662,16 @@ invalid_mode_change_p (regno, class, from_mode)
      enum machine_mode from_mode;
 {
   enum machine_mode to_mode;
-
-  for (to_mode = 0; to_mode < NUM_MACHINE_MODES; ++to_mode)
-    if (REGNO_REG_SET_P (&subregs_of_mode[(int) to_mode], regno)
-       && reg_classes_intersect_p 
-            (class, CANNOT_CHANGE_MODE_CLASS (from_mode, to_mode)))
+  int n;
+  int start = regno * MAX_MACHINE_MODE;
+
+  EXECUTE_IF_SET_IN_BITMAP (&subregs_of_mode, start, n,
+    if (n >= MAX_MACHINE_MODE + start)
+      return 0;
+    to_mode = n - start;
+    if (CANNOT_CHANGE_MODE_CLASS (from_mode, to_mode, class))
       return 1;
+  );
   return 0;
 }
 #endif /* CANNOT_CHANGE_MODE_CLASS */