OSDN Git Service

* config/mips/mips.c (save_restore_insns): Don't mark any register
[pf3gnuchains/gcc-fork.git] / gcc / bb-reorder.c
index 93b2034..72d3902 100644 (file)
@@ -1,22 +1,22 @@
 /* Basic block reordering routines for the GNU compiler.
    Copyright (C) 2000 Free Software Foundation, Inc.
 
-   This file is part of GNU CC.
+   This file is part of GCC.
 
-   GNU CC is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2, or (at your option)
    any later version.
 
-   GNU CC is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with GNU CC; see the file COPYING.  If not, write to
-   the Free Software Foundation, 59 Temple Place - Suite 330,
-   Boston, MA 02111-1307, USA.  */
+   along with GCC; see the file COPYING.  If not, write to the Free
+   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
 
 /* References:
 
@@ -92,7 +92,6 @@
 #include "flags.h"
 #include "output.h"
 #include "function.h"
-#include "except.h"
 #include "toplev.h"
 #include "recog.h"
 #include "expr.h"
@@ -172,6 +171,9 @@ typedef struct reorder_block_def
 
 #define RBI(BB)        ((reorder_block_def) (BB)->aux)
 
+/* Holds the interesting trailing notes for the function.  */
+static rtx function_tail_eff_head;
+
 
 /* Local function prototypes.  */
 static rtx skip_insns_after_block      PARAMS ((basic_block));
@@ -206,13 +208,13 @@ static rtx
 skip_insns_after_block (bb)
      basic_block bb;
 {
-  rtx insn, last_insn, next_head;
+  rtx insn, last_insn, next_head, prev;
 
   next_head = NULL_RTX;
   if (bb->index + 1 != n_basic_blocks)
     next_head = BASIC_BLOCK (bb->index + 1)->head;
 
-  for (last_insn = bb->end; (insn = NEXT_INSN (last_insn)); last_insn = insn)
+  for (last_insn = insn = bb->end; (insn = NEXT_INSN (insn)); )
     {
       if (insn == next_head)
        break;
@@ -220,6 +222,7 @@ skip_insns_after_block (bb)
       switch (GET_CODE (insn))
        {
        case BARRIER:
+         last_insn = insn;
          continue;
 
        case NOTE:
@@ -227,11 +230,14 @@ skip_insns_after_block (bb)
            {
            case NOTE_INSN_LOOP_END:
            case NOTE_INSN_BLOCK_END:
+             last_insn = insn;
+             continue;
            case NOTE_INSN_DELETED:
            case NOTE_INSN_DELETED_LABEL:
              continue;
 
            default:
+             continue;
              break;
            }
          break;
@@ -243,6 +249,7 @@ skip_insns_after_block (bb)
                  || GET_CODE (PATTERN (NEXT_INSN (insn))) == ADDR_DIFF_VEC))
            {
              insn = NEXT_INSN (insn);
+             last_insn = insn;
              continue;
            }
           break;
@@ -253,6 +260,32 @@ skip_insns_after_block (bb)
 
       break;
     }
+  /* It is possible to hit contradicting sequence.  For instance:
+    
+     jump_insn
+     NOTE_INSN_LOOP_BEG
+     barrier
+
+     Where barrier belongs to jump_insn, but the note does not.
+     This can be created by removing the basic block originally
+     following NOTE_INSN_LOOP_BEG.
+
+     In such case reorder the notes.  */
+  for (insn = last_insn; insn != bb->end; insn = prev)
+    {
+    prev = PREV_INSN (insn);
+    if (GET_CODE (insn) == NOTE)
+      switch (NOTE_LINE_NUMBER (insn))
+        {
+          case NOTE_INSN_LOOP_END:
+          case NOTE_INSN_BLOCK_END:
+          case NOTE_INSN_DELETED:
+          case NOTE_INSN_DELETED_LABEL:
+       continue;
+          default:
+       reorder_insns (insn, insn, last_insn);
+        }
+    }
 
   return last_insn;
 }
@@ -277,6 +310,7 @@ record_effective_endpoints ()
       RBI (bb)->eff_end = end;
       next_insn = NEXT_INSN (end);
     }
+  function_tail_eff_head = next_insn;
 }
 
 
@@ -395,8 +429,6 @@ make_reorder_chain_1 (bb, prev)
       taken = probability > REG_BR_PROB_BASE / 2;
 
       /* Find the normal taken edge and the normal fallthru edge.
-         Note that there may in fact be other edges due to
-        flag_non_call_exceptions. 
 
         Note, conditional jumps with other side effects may not
         be fully optimized.  In this case it is possible for
@@ -412,7 +444,7 @@ make_reorder_chain_1 (bb, prev)
        {
          if (e->flags & EDGE_FALLTHRU)
            e_fall = e;
-         if (! (e->flags & EDGE_EH))
+         else if (! (e->flags & EDGE_EH))
            e_taken = e;
        }
 
@@ -504,6 +536,8 @@ emit_jump_to_block_after (bb, after)
       jump = emit_jump_insn_after (gen_jump (label), after);
       JUMP_LABEL (jump) = label;
       LABEL_NUSES (label) += 1;
+      if (basic_block_for_insn)
+       set_block_for_new_insns (jump, bb);
 
       if (rtl_dump_file)
        fprintf (rtl_dump_file, "Emitting jump to block %d (%d)\n",
@@ -550,8 +584,18 @@ fixup_reorder_chain ()
       last_bb = bb;
       bb = RBI (bb)->next;
     }
-  NEXT_INSN (RBI (last_bb)->eff_end) = NULL_RTX;
-  set_last_insn (RBI (last_bb)->eff_end);
+
+  {
+    rtx insn = RBI (last_bb)->eff_end;
+
+    NEXT_INSN (insn) = function_tail_eff_head;
+    if (function_tail_eff_head)
+      PREV_INSN (function_tail_eff_head) = insn;
+
+    while (NEXT_INSN (insn))
+      insn = NEXT_INSN (insn);
+    set_last_insn (insn);
+  }
 
   /* Now add jumps and labels as needed to match the blocks new
      outgoing edges.  */
@@ -689,6 +733,8 @@ fixup_reorder_chain ()
       nb->global_live_at_start = OBSTACK_ALLOC_REG_SET (&flow_obstack);
       nb->global_live_at_end = OBSTACK_ALLOC_REG_SET (&flow_obstack);
       nb->local_set = 0;
+      nb->count = e_fall->count;
+      nb->frequency = EDGE_FREQUENCY (e_fall);
 
       COPY_REG_SET (nb->global_live_at_start, bb->global_live_at_start);
       COPY_REG_SET (nb->global_live_at_end, bb->global_live_at_start);
@@ -705,6 +751,8 @@ fixup_reorder_chain ()
       /* Link to new block.  */
       make_edge (NULL, nb, e_fall->dest, 0);
       redirect_edge_succ (e_fall, nb);
+      nb->succ->count = e_fall->count;
+      nb->succ->probability = REG_BR_PROB_BASE;
 
       /* Don't process this new block.  */
       bb = nb;
@@ -1356,17 +1404,6 @@ reorder_basic_blocks ()
   if (n_basic_blocks <= 1)
     return;
 
-  /* We do not currently handle correct re-placement of EH notes.
-     But that does not matter unless we intend to use them.  */
-  if (flag_exceptions)
-    for (i = 0; i < n_basic_blocks; i++)
-      {
-       edge e;
-       for (e = BASIC_BLOCK (i)->succ; e ; e = e->succ_next)
-         if (e->flags & EDGE_EH)
-           return;
-      }
-
   for (i = 0; i < n_basic_blocks; i++)
     BASIC_BLOCK (i)->aux = xcalloc (1, sizeof (struct reorder_block_def));