OSDN Git Service

2004-06-09 Benjamin Kosnik <bkoz@redhat.com>
[pf3gnuchains/gcc-fork.git] / gcc / reorg.c
index 46b6657..ff32162 100644 (file)
@@ -1,6 +1,6 @@
 /* Perform instruction reorganizations for delay slot filling.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
    Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu).
    Hacked by Michael Tiemann (tiemann@cygnus.com).
 
@@ -36,19 +36,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    cycle, and the Branch Penalty is 0.  Several RISC machines approach
    branch delays differently:
 
-   The MIPS and AMD 29000 have a single branch delay slot.  Most insns
+   The MIPS has a single branch delay slot.  Most insns
    (except other branches) can be used to fill this slot.  When the
    slot is filled, two insns execute in two cycles, reducing the
    branch penalty to zero.
 
-   The Motorola 88000 conditionally exposes its branch delay slot,
-   so code is shorter when it is turned off, but will run faster
-   when useful insns are scheduled there.
-
-   The IBM ROMP has two forms of branch and call insns, both with and
-   without a delay slot.  Much like the 88k, insns not using the delay
-   slot can be shorted (2 bytes vs. 4 bytes), but will run slowed.
-
    The SPARC always has a branch delay slot, but its effects can be
    annulled when the branch is not taken.  This means that failing to
    find other sources of insns, we can hoist an insn from the branch
@@ -84,8 +76,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
    `fill_eager_delay_slots' tries to guess the direction the branch
    will go; if it guesses right 100% of the time, it can reduce the
    branch penalty as much as `fill_simple_delay_slots' does.  If it
-   guesses wrong 100% of the time, it might as well schedule nops (or
-   on the m88k, unexpose the branch slot).  When
+   guesses wrong 100% of the time, it might as well schedule nops.  When
    `fill_eager_delay_slots' takes insns from the fall-through path of
    the jump, usually there is no code expansion; when it takes insns
    from the branch target, there is code expansion if it is not the
@@ -579,6 +570,7 @@ delete_from_delay_slot (rtx insn)
   rtx trial, seq_insn, seq, prev;
   rtx delay_list = 0;
   int i;
+  int had_barrier = 0;
 
   /* We first must find the insn containing the SEQUENCE with INSN in its
      delay slot.  Do this by finding an insn, TRIAL, where
@@ -592,6 +584,9 @@ delete_from_delay_slot (rtx insn)
   seq_insn = PREV_INSN (NEXT_INSN (trial));
   seq = PATTERN (seq_insn);
 
+  if (NEXT_INSN (seq_insn) && GET_CODE (NEXT_INSN (seq_insn)) == BARRIER)
+    had_barrier = 1;
+
   /* Create a delay list consisting of all the insns other than the one
      we are deleting (unless we were the only one).  */
   if (XVECLEN (seq, 0) > 2)
@@ -606,8 +601,8 @@ delete_from_delay_slot (rtx insn)
   delete_related_insns (seq_insn);
   add_insn_after (trial, prev);
 
-  if (GET_CODE (trial) == JUMP_INSN
-      && (simplejump_p (trial) || GET_CODE (PATTERN (trial)) == RETURN))
+  /* If there was a barrier after the old SEQUENCE, remit it.  */
+  if (had_barrier)
     emit_barrier_after (trial);
 
   /* If there are any delay insns, remit them.  Otherwise clear the
@@ -1621,7 +1616,7 @@ try_merge_delay_insns (rtx insn, rtx thread)
    If we are not careful, this routine can take up a significant fraction
    of the total compilation time (4%), but only wins rarely.  Hence we
    speed this routine up by making two passes.  The first pass goes back
-   until it hits a label and sees if it find an insn with an identical
+   until it hits a label and sees if it finds an insn with an identical
    pattern.  Only in this (relatively rare) event does it check for
    data conflicts.
 
@@ -2358,7 +2353,9 @@ fill_simple_delay_slots (int non_jumps_p)
              && eligible_for_delay (insn, slots_filled, next_trial, flags)
              && ! can_throw_internal (trial))
            {
-             rtx new_label = next_active_insn (next_trial);
+             /* See comment in relax_delay_slots about necessity of using
+                next_real_insn here.  */
+             rtx new_label = next_real_insn (next_trial);
 
              if (new_label != 0)
                new_label = get_label_before (new_label);
@@ -3082,9 +3079,7 @@ relax_delay_slots (rtx first)
          && (condjump_p (insn) || condjump_in_parallel_p (insn))
          && (target_label = JUMP_LABEL (insn)) != 0)
        {
-         target_label = follow_jumps (target_label);
-         target_label = prev_label (next_active_insn (target_label));
-
+         target_label = skip_consecutive_labels (follow_jumps (target_label));
          if (target_label == 0)
            target_label = find_end_label ();
 
@@ -3179,7 +3174,7 @@ relax_delay_slots (rtx first)
 
       /* See if we have a RETURN insn with a filled delay slot followed
         by a RETURN insn with an unfilled a delay slot.  If so, we can delete
-        the first RETURN (but not it's delay insn).  This gives the same
+        the first RETURN (but not its delay insn).  This gives the same
         effect in fewer instructions.
 
         Only do so if optimizing for size since this results in slower, but
@@ -3232,14 +3227,8 @@ relax_delay_slots (rtx first)
        {
          /* If this jump goes to another unconditional jump, thread it, but
             don't convert a jump into a RETURN here.  */
-         trial = follow_jumps (target_label);
-         /* We use next_real_insn instead of next_active_insn, so that
-            the special USE insns emitted by reorg won't be ignored.
-            If they are ignored, then they will get deleted if target_label
-            is now unreachable, and that would cause mark_target_live_regs
-            to fail.  */
-         trial = prev_label (next_real_insn (trial));
-         if (trial == 0 && target_label != 0)
+         trial = skip_consecutive_labels (follow_jumps (target_label));
+         if (trial == 0)
            trial = find_end_label ();
 
          if (trial != target_label
@@ -3622,7 +3611,7 @@ dbr_schedule (rtx first, FILE *file)
       if (GET_CODE (insn) == JUMP_INSN
          && (condjump_p (insn) || condjump_in_parallel_p (insn))
          && JUMP_LABEL (insn) != 0
-         && ((target = prev_label (next_active_insn (JUMP_LABEL (insn))))
+         && ((target = skip_consecutive_labels (JUMP_LABEL (insn)))
              != JUMP_LABEL (insn)))
        redirect_jump (insn, target, 1);
     }