OSDN Git Service

* config/xtensa/xtensa.h (TRAMPOLINE_TEMPLATE): Use "no-transform"
[pf3gnuchains/gcc-fork.git] / gcc / sched-ebb.c
index 0e316b5..560faf3 100644 (file)
@@ -1,6 +1,6 @@
 /* Instruction scheduling pass.
    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 Michael Tiemann (tiemann@cygnus.com) Enhanced by,
    and currently maintained by, Jim Wilson (wilson@cygnus.com)
 
@@ -29,7 +29,6 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "rtl.h"
 #include "tm_p.h"
 #include "hard-reg-set.h"
-#include "basic-block.h"
 #include "regs.h"
 #include "function.h"
 #include "flags.h"
@@ -39,6 +38,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "toplev.h"
 #include "recog.h"
 #include "cfglayout.h"
+#include "params.h"
 #include "sched-int.h"
 #include "target.h"
 \f
@@ -55,7 +55,7 @@ static int schedule_more_p (void);
 static const char *ebb_print_insn (rtx, int);
 static int rank (rtx, rtx);
 static int contributes_to_priority (rtx, rtx);
-static void compute_jump_reg_dependencies (rtx, regset);
+static void compute_jump_reg_dependencies (rtx, regset, regset, regset);
 static basic_block earliest_block_with_similiar_load (basic_block, rtx);
 static void add_deps_for_risky_insns (rtx, rtx);
 static basic_block schedule_ebb (rtx, rtx);
@@ -163,20 +163,29 @@ contributes_to_priority (rtx next ATTRIBUTE_UNUSED,
   return 1;
 }
 
-/* INSN is a JUMP_INSN.  Store the set of registers that must be considered
-   to be set by this jump in SET.  */
+ /* INSN is a JUMP_INSN, COND_SET is the set of registers that are
+    conditionally set before INSN.  Store the set of registers that
+    must be considered as used by this jump in USED and that of
+    registers that must be considered as set in SET.  */
 
 static void
-compute_jump_reg_dependencies (rtx insn, regset set)
+compute_jump_reg_dependencies (rtx insn, regset cond_set, regset used,
+                              regset set)
 {
   basic_block b = BLOCK_FOR_INSN (insn);
   edge e;
-  for (e = b->succ; e; e = e->succ_next)
-    if ((e->flags & EDGE_FALLTHRU) == 0)
-      {
-       bitmap_operation (set, set, e->dest->global_live_at_start,
-                         BITMAP_IOR);
-      }
+  edge_iterator ei;
+
+  FOR_EACH_EDGE (e, ei, b->succs)
+    if (e->flags & EDGE_FALLTHRU)
+      /* The jump may be a by-product of a branch that has been merged
+        in the main codepath after being conditionalized.  Therefore
+        it may guard the fallthrough block from using a value that has
+        conditionally overwritten that of the main codepath.  So we
+        consider that it restores the value of the main codepath.  */
+      bitmap_and (set, e->dest->global_live_at_start, cond_set);
+    else
+      bitmap_ior_into (used, e->dest->global_live_at_start);
 }
 
 /* Used in schedule_insns to initialize current_sched_info for scheduling
@@ -195,7 +204,7 @@ static struct sched_info ebb_sched_info =
 
   NULL, NULL,
   NULL, NULL,
-  0, 1
+  0, 1, 0
 };
 \f
 /* It is possible that ebb scheduling eliminated some blocks.
@@ -208,8 +217,8 @@ add_missing_bbs (rtx before, basic_block first, basic_block last)
     {
       before = emit_note_before (NOTE_INSN_BASIC_BLOCK, before);
       NOTE_BASIC_BLOCK (before) = last;
-      last->head = before;
-      last->end = before;
+      BB_HEAD (last) = before;
+      BB_END (last) = before;
       update_bb_for_insn (last);
     }
 }
@@ -223,15 +232,14 @@ fix_basic_block_boundaries (basic_block bb, basic_block last, rtx head,
                            rtx tail)
 {
   rtx insn = head;
-  rtx last_inside = bb->head;
+  rtx last_inside = BB_HEAD (bb);
   rtx aftertail = NEXT_INSN (tail);
 
-  head = bb->head;
+  head = BB_HEAD (bb);
 
   for (; insn != aftertail; insn = NEXT_INSN (insn))
     {
-      if (GET_CODE (insn) == CODE_LABEL)
-       abort ();
+      gcc_assert (!LABEL_P (insn));
       /* Create new basic blocks just before first insn.  */
       if (inside_basic_block_p (insn))
        {
@@ -240,7 +248,7 @@ fix_basic_block_boundaries (basic_block bb, basic_block last, rtx head,
              rtx note;
 
              /* Re-emit the basic block note for newly found BB header.  */
-             if (GET_CODE (insn) == CODE_LABEL)
+             if (LABEL_P (insn))
                {
                  note = emit_note_after (NOTE_INSN_BASIC_BLOCK, insn);
                  head = insn;
@@ -271,6 +279,7 @@ fix_basic_block_boundaries (basic_block bb, basic_block last, rtx head,
            {
              edge f;
              rtx h;
+             edge_iterator ei;
 
              /* An obscure special case, where we do have partially dead
                 instruction scheduled after last control flow instruction.
@@ -282,16 +291,17 @@ fix_basic_block_boundaries (basic_block bb, basic_block last, rtx head,
                 A safer solution can be to bring the code into sequence,
                 do the split and re-emit it back in case this will ever
                 trigger problem.  */
-             f = bb->prev_bb->succ;
-             while (f && !(f->flags & EDGE_FALLTHRU))
-               f = f->succ_next;
+
+             FOR_EACH_EDGE (f, ei, bb->prev_bb->succs)
+               if (f->flags & EDGE_FALLTHRU)
+                 break;
 
              if (f)
                {
                  last = curr_bb = split_edge (f);
-                 h = curr_bb->head;
-                 curr_bb->head = head;
-                 curr_bb->end = insn;
+                 h = BB_HEAD (curr_bb);
+                 BB_HEAD (curr_bb) = head;
+                 BB_END (curr_bb) = insn;
                  /* Edge splitting created misplaced BASIC_BLOCK note, kill
                     it.  */
                  delete_insn (h);
@@ -304,7 +314,7 @@ fix_basic_block_boundaries (basic_block bb, basic_block last, rtx head,
                  delete_insn_chain (head, insn);
                  /* We keep some notes in the way that may split barrier from the
                     jump.  */
-                 if (GET_CODE (next) == BARRIER)
+                 if (BARRIER_P (next))
                     {
                       emit_barrier_after (prev_nonnote_insn (head));
                       delete_insn (next);
@@ -314,11 +324,11 @@ fix_basic_block_boundaries (basic_block bb, basic_block last, rtx head,
            }
          else
            {
-             curr_bb->head = head;
-             curr_bb->end = insn;
-             add_missing_bbs (curr_bb->head, bb, curr_bb->prev_bb);
+             BB_HEAD (curr_bb) = head;
+             BB_END (curr_bb) = insn;
+             add_missing_bbs (BB_HEAD (curr_bb), bb, curr_bb->prev_bb);
            }
-         note = GET_CODE (head) == CODE_LABEL ? NEXT_INSN (head) : head;
+         note = LABEL_P (head) ? NEXT_INSN (head) : head;
          NOTE_BASIC_BLOCK (note) = curr_bb;
          update_bb_for_insn (curr_bb);
          bb = curr_bb->next_bb;
@@ -327,7 +337,7 @@ fix_basic_block_boundaries (basic_block bb, basic_block last, rtx head,
             break;
        }
     }
-  add_missing_bbs (last->next_bb->head, bb, last);
+  add_missing_bbs (BB_HEAD (last->next_bb), bb, last);
   return bb->prev_bb;
 }
 
@@ -410,7 +420,7 @@ add_deps_for_risky_insns (rtx head, rtx tail)
   basic_block last_block = NULL, bb;
 
   for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
-    if (GET_CODE (insn) == JUMP_INSN)
+    if (JUMP_P (insn))
       {
        bb = BLOCK_FOR_INSN (insn);
        bb->aux = last_block;
@@ -432,10 +442,10 @@ add_deps_for_risky_insns (rtx head, rtx tail)
                    bb = bb->aux;
                    if (!bb)
                      break;
-                   prev = bb->end;
+                   prev = BB_END (bb);
                  }
              }
-           /* FALLTHRU */
+           /* Fall through.  */
          case TRAP_RISKY:
          case IRISKY:
          case PRISKY_CANDIDATE:
@@ -515,11 +525,7 @@ schedule_ebb (rtx head, rtx tail)
 
       for (note = REG_NOTES (head); note; note = XEXP (note, 1))
        if (REG_NOTE_KIND (note) == REG_SAVE_NOTE)
-         {
-           remove_note (head, note);
-           note = XEXP (note, 1);
-           remove_note (head, note);
-         }
+         remove_note (head, note);
     }
 
   /* Remove remaining note insns from the block, save them in
@@ -532,8 +538,7 @@ schedule_ebb (rtx head, rtx tail)
   schedule_block (-1, n_insns);
 
   /* Sanity check: verify that all region insns were scheduled.  */
-  if (sched_n_insns != n_insns)
-    abort ();
+  gcc_assert (sched_n_insns == n_insns);
   head = current_sched_info->head;
   tail = current_sched_info->tail;
 
@@ -552,6 +557,13 @@ void
 schedule_ebbs (FILE *dump_file)
 {
   basic_block bb;
+  int probability_cutoff;
+
+  if (profile_info && flag_branch_probabilities)
+    probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY_FEEDBACK);
+  else
+    probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY);
+  probability_cutoff = REG_BR_PROB_BASE / 100 * probability_cutoff;
 
   /* Taking care of this degenerate case makes the rest of
      this code simpler.  */
@@ -562,28 +574,28 @@ schedule_ebbs (FILE *dump_file)
 
   current_sched_info = &ebb_sched_info;
 
-  allocate_reg_life_data ();
   compute_bb_for_insn ();
 
   /* Schedule every region in the subroutine.  */
   FOR_EACH_BB (bb)
     {
-      rtx head = bb->head;
+      rtx head = BB_HEAD (bb);
       rtx tail;
 
       for (;;)
        {
          edge e;
-         tail = bb->end;
+         edge_iterator ei;
+         tail = BB_END (bb);
          if (bb->next_bb == EXIT_BLOCK_PTR
-             || GET_CODE (bb->next_bb->head) == CODE_LABEL)
+             || LABEL_P (BB_HEAD (bb->next_bb)))
            break;
-         for (e = bb->succ; e; e = e->succ_next)
+         FOR_EACH_EDGE (e, ei, bb->succs)
            if ((e->flags & EDGE_FALLTHRU) != 0)
              break;
          if (! e)
            break;
-         if (e->probability < REG_BR_PROB_BASE / 2)
+         if (e->probability <= probability_cutoff)
            break;
          bb = bb->next_bb;
        }
@@ -592,11 +604,11 @@ schedule_ebbs (FILE *dump_file)
         a note or two.  */
       while (head != tail)
        {
-         if (GET_CODE (head) == NOTE)
+         if (NOTE_P (head))
            head = NEXT_INSN (head);
-         else if (GET_CODE (tail) == NOTE)
+         else if (NOTE_P (tail))
            tail = PREV_INSN (tail);
-         else if (GET_CODE (head) == CODE_LABEL)
+         else if (LABEL_P (head))
            head = NEXT_INSN (head);
          else
            break;