OSDN Git Service

../svn-commit.tmp
[pf3gnuchains/gcc-fork.git] / gcc / sched-deps.c
index a408fab..0cde4f2 100644 (file)
@@ -715,6 +715,78 @@ flush_pending_lists (struct deps *deps, rtx insn, int for_read,
   deps->pending_flush_length = 1;
 }
 \f
+/* Analyze a single reference to register (reg:MODE REGNO) in INSN.
+   The type of the reference is specified by REF and can be SET,
+   CLOBBER, PRE_DEC, POST_DEC, PRE_INC, POST_INC or USE.  */
+
+static void
+sched_analyze_reg (struct deps *deps, int regno, enum machine_mode mode,
+                  enum rtx_code ref, rtx insn)
+{
+  /* A hard reg in a wide mode may really be multiple registers.
+     If so, mark all of them just like the first.  */
+  if (regno < FIRST_PSEUDO_REGISTER)
+    {
+      int i = hard_regno_nregs[regno][mode];
+      if (ref == SET)
+       {
+         while (--i >= 0)
+           SET_REGNO_REG_SET (reg_pending_sets, regno + i);
+       }
+      else if (ref == USE)
+       {
+         while (--i >= 0)
+           SET_REGNO_REG_SET (reg_pending_uses, regno + i);
+       }
+      else
+       {
+         while (--i >= 0)
+           SET_REGNO_REG_SET (reg_pending_clobbers, regno + i);
+       }
+    }
+
+  /* ??? Reload sometimes emits USEs and CLOBBERs of pseudos that
+     it does not reload.  Ignore these as they have served their
+     purpose already.  */
+  else if (regno >= deps->max_reg)
+    {
+      enum rtx_code code = GET_CODE (PATTERN (insn));
+      gcc_assert (code == USE || code == CLOBBER);
+    }
+
+  else
+    {
+      if (ref == SET)
+       SET_REGNO_REG_SET (reg_pending_sets, regno);
+      else if (ref == USE)
+       SET_REGNO_REG_SET (reg_pending_uses, regno);
+      else
+       SET_REGNO_REG_SET (reg_pending_clobbers, regno);
+
+      /* Pseudos that are REG_EQUIV to something may be replaced
+        by that during reloading.  We need only add dependencies for
+       the address in the REG_EQUIV note.  */
+      if (!reload_completed && get_reg_known_equiv_p (regno))
+       {
+         rtx t = get_reg_known_value (regno);
+         if (MEM_P (t))
+           sched_analyze_2 (deps, XEXP (t, 0), insn);
+       }
+
+      /* Don't let it cross a call after scheduling if it doesn't
+        already cross one.  */
+      if (REG_N_CALLS_CROSSED (regno) == 0)
+       {
+         if (ref == USE)
+           deps->sched_before_next_call
+             = alloc_INSN_LIST (insn, deps->sched_before_next_call);
+         else
+           add_dependence_list (insn, deps->last_function_call, 1,
+                                REG_DEP_ANTI);
+       }
+    }
+}
+
 /* Analyze a single SET, CLOBBER, PRE_DEC, POST_DEC, PRE_INC or POST_INC
    rtx, X, creating all dependencies generated by the write to the
    destination of X, and reads of everything mentioned.  */
@@ -722,7 +794,6 @@ flush_pending_lists (struct deps *deps, rtx insn, int for_read,
 static void
 sched_analyze_1 (struct deps *deps, rtx x, rtx insn)
 {
-  int regno;
   rtx dest = XEXP (x, 0);
   enum rtx_code code = GET_CODE (x);
 
@@ -771,64 +842,21 @@ sched_analyze_1 (struct deps *deps, rtx x, rtx insn)
 
   if (REG_P (dest))
     {
-      regno = REGNO (dest);
+      int regno = REGNO (dest);
+      enum machine_mode mode = GET_MODE (dest);
+
+      sched_analyze_reg (deps, regno, mode, code, insn);
 
 #ifdef STACK_REGS
       /* Treat all writes to a stack register as modifying the TOS.  */
       if (regno >= FIRST_STACK_REG && regno <= LAST_STACK_REG)
        {
-         SET_REGNO_REG_SET (reg_pending_uses, FIRST_STACK_REG);
-         regno = FIRST_STACK_REG;
+         /* Avoid analyzing the same register twice.  */
+         if (regno != FIRST_STACK_REG)
+           sched_analyze_reg (deps, FIRST_STACK_REG, mode, code, insn);
+         sched_analyze_reg (deps, FIRST_STACK_REG, mode, USE, insn);
        }
 #endif
-
-      /* A hard reg in a wide mode may really be multiple registers.
-         If so, mark all of them just like the first.  */
-      if (regno < FIRST_PSEUDO_REGISTER)
-       {
-         int i = hard_regno_nregs[regno][GET_MODE (dest)];
-         if (code == SET)
-           {
-             while (--i >= 0)
-               SET_REGNO_REG_SET (reg_pending_sets, regno + i);
-           }
-         else
-           {
-             while (--i >= 0)
-               SET_REGNO_REG_SET (reg_pending_clobbers, regno + i);
-           }
-       }
-      /* ??? Reload sometimes emits USEs and CLOBBERs of pseudos that
-        it does not reload.  Ignore these as they have served their
-        purpose already.  */
-      else if (regno >= deps->max_reg)
-       {
-         gcc_assert (GET_CODE (PATTERN (insn)) == USE
-                     || GET_CODE (PATTERN (insn)) == CLOBBER);
-       }
-      else
-       {
-         if (code == SET)
-           SET_REGNO_REG_SET (reg_pending_sets, regno);
-         else
-           SET_REGNO_REG_SET (reg_pending_clobbers, regno);
-
-         /* Pseudos that are REG_EQUIV to something may be replaced
-            by that during reloading.  We need only add dependencies for
-            the address in the REG_EQUIV note.  */
-         if (!reload_completed && get_reg_known_equiv_p (regno))
-           {
-             rtx t = get_reg_known_value (regno);
-             if (MEM_P (t))
-               sched_analyze_2 (deps, XEXP (t, 0), insn);
-           }
-
-         /* Don't let it cross a call after scheduling if it doesn't
-            already cross one.  */
-         if (REG_N_CALLS_CROSSED (regno) == 0)
-           add_dependence_list (insn, deps->last_function_call, 1,
-                                REG_DEP_ANTI);
-       }
     }
   else if (MEM_P (dest))
     {
@@ -935,51 +963,20 @@ sched_analyze_2 (struct deps *deps, rtx x, rtx insn)
     case REG:
       {
        int regno = REGNO (x);
+       enum machine_mode mode = GET_MODE (x);
+
+       sched_analyze_reg (deps, regno, mode, USE, insn);
 
 #ifdef STACK_REGS
       /* Treat all reads of a stack register as modifying the TOS.  */
       if (regno >= FIRST_STACK_REG && regno <= LAST_STACK_REG)
        {
-         SET_REGNO_REG_SET (reg_pending_sets, FIRST_STACK_REG);
-         regno = FIRST_STACK_REG;
+         /* Avoid analyzing the same register twice.  */
+         if (regno != FIRST_STACK_REG)
+           sched_analyze_reg (deps, FIRST_STACK_REG, mode, USE, insn);
+         sched_analyze_reg (deps, FIRST_STACK_REG, mode, SET, insn);
        }
 #endif
-
-       if (regno < FIRST_PSEUDO_REGISTER)
-         {
-           int i = hard_regno_nregs[regno][GET_MODE (x)];
-           while (--i >= 0)
-             SET_REGNO_REG_SET (reg_pending_uses, regno + i);
-         }
-       /* ??? Reload sometimes emits USEs and CLOBBERs of pseudos that
-          it does not reload.  Ignore these as they have served their
-          purpose already.  */
-       else if (regno >= deps->max_reg)
-         {
-           gcc_assert (GET_CODE (PATTERN (insn)) == USE
-                       || GET_CODE (PATTERN (insn)) == CLOBBER);
-         }
-       else
-         {
-           SET_REGNO_REG_SET (reg_pending_uses, regno);
-
-           /* Pseudos that are REG_EQUIV to something may be replaced
-              by that during reloading.  We need only add dependencies for
-              the address in the REG_EQUIV note.  */
-           if (!reload_completed && get_reg_known_equiv_p (regno))
-             {
-               rtx t = get_reg_known_value (regno);
-               if (MEM_P (t))
-                 sched_analyze_2 (deps, XEXP (t, 0), insn);
-             }
-
-           /* If the register does not already cross any calls, then add this
-              insn to the sched_before_next_call list so that it will still
-              not cross calls after scheduling.  */
-           if (REG_N_CALLS_CROSSED (regno) == 0)
-             deps->sched_before_next_call
-               = alloc_INSN_LIST (insn, deps->sched_before_next_call);
-         }
        return;
       }