OSDN Git Service

Reverted:
[pf3gnuchains/gcc-fork.git] / gcc / haifa-sched.c
index bc947fa..bd3b84c 100644 (file)
@@ -1,6 +1,6 @@
 /* Instruction scheduling pass.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
    and currently maintained by, Jim Wilson (wilson@cygnus.com)
@@ -128,7 +128,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "toplev.h"
+#include "diagnostic-core.h"
 #include "rtl.h"
 #include "tm_p.h"
 #include "hard-reg-set.h"
@@ -138,7 +138,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "insn-config.h"
 #include "insn-attr.h"
 #include "except.h"
-#include "toplev.h"
 #include "recog.h"
 #include "sched-int.h"
 #include "target.h"
@@ -148,6 +147,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "dbgcnt.h"
 #include "cfgloop.h"
 #include "ira.h"
+#include "emit-rtl.h"  /* FIXME: Can go away once crtl is moved to rtl.h.  */
 
 #ifdef INSN_SCHEDULING
 
@@ -166,26 +166,13 @@ int issue_rate;
    N=3: rtl at abort point, control-flow, regions info.
    N=5: dependences info.  */
 
-static int sched_verbose_param = 0;
 int sched_verbose = 0;
 
 /* Debugging file.  All printouts are sent to dump, which is always set,
    either to stderr, or to the dump listing file (-dRS).  */
 FILE *sched_dump = 0;
 
-/* fix_sched_param() is called from toplev.c upon detection
-   of the -fsched-verbose=N option.  */
-
-void
-fix_sched_param (const char *param, const char *val)
-{
-  if (!strcmp (param, "verbose"))
-    sched_verbose_param = atoi (val);
-  else
-    warning (0, "fix_sched_param: unknown param: %s", param);
-}
-
-/* This is a placeholder for the scheduler parameters common 
+/* This is a placeholder for the scheduler parameters common
    to all schedulers.  */
 struct common_sched_info_def *common_sched_info;
 
@@ -198,10 +185,6 @@ struct common_sched_info_def *common_sched_info;
 /* The minimal value of the INSN_TICK of an instruction.  */
 #define MIN_TICK (-max_insn_queue_index)
 
-/* Issue points are used to distinguish between instructions in max_issue ().
-   For now, all instructions are equally good.  */
-#define ISSUE_POINTS(INSN) 1
-
 /* List of important notes we must keep around.  This is a pointer to the
    last element in the list.  */
 rtx note_list;
@@ -295,7 +278,7 @@ static int q_size = 0;
    queue or ready list.
    QUEUE_READY     - INSN is in ready list.
    N >= 0 - INSN queued for X [where NEXT_Q_AFTER (q_ptr, X) == N] cycles.  */
-   
+
 #define QUEUE_INDEX(INSN) (HID (INSN)->queue_index)
 
 /* The following variable value refers for all current and future
@@ -336,7 +319,7 @@ static int may_trap_exp (const_rtx, int);
 static int haifa_luid_for_non_insn (rtx x);
 
 /* Haifa version of sched_info hooks common to all headers.  */
-const struct common_sched_info_def haifa_common_sched_info = 
+const struct common_sched_info_def haifa_common_sched_info =
   {
     NULL, /* fix_recovery_cfg */
     NULL, /* add_block */
@@ -531,6 +514,7 @@ static void extend_h_i_d (void);
 
 static void ready_add (struct ready_list *, rtx, bool);
 static rtx ready_remove_first (struct ready_list *);
+static rtx ready_remove_first_dispatch (struct ready_list *ready);
 
 static void queue_to_ready (struct ready_list *);
 static int early_queue_to_ready (state_t, struct ready_list *);
@@ -542,8 +526,6 @@ static void debug_ready_list (struct ready_list *);
 static rtx ready_remove (struct ready_list *, int);
 static void ready_remove_insn (rtx);
 
-static int choose_ready (struct ready_list *, rtx *);
-
 static void fix_inter_tick (rtx, rtx);
 static int fix_tick_ready (rtx);
 static void change_queue_index (rtx, int);
@@ -713,12 +695,12 @@ setup_ref_regs (rtx x)
 static void
 initiate_bb_reg_pressure_info (basic_block bb)
 {
-  unsigned int i;
+  unsigned int i ATTRIBUTE_UNUSED;
   rtx insn;
 
   if (current_nr_blocks > 1)
     FOR_BB_INSNS (bb, insn)
-      if (INSN_P (insn))
+      if (NONDEBUG_INSN_P (insn))
        setup_ref_regs (PATTERN (insn));
   initiate_reg_pressure_info (df_get_live_in (bb));
 #ifdef EH_RETURN_DATA_REGNO
@@ -726,7 +708,7 @@ initiate_bb_reg_pressure_info (basic_block bb)
     for (i = 0; ; ++i)
       {
        unsigned int regno = EH_RETURN_DATA_REGNO (i);
-       
+
        if (regno == INVALID_REGNUM)
          break;
        if (! bitmap_bit_p (df_get_live_in (bb), regno))
@@ -740,7 +722,7 @@ static void
 save_reg_pressure (void)
 {
   int i;
-  
+
   for (i = 0; i < ira_reg_class_cover_size; i++)
     saved_reg_pressure[ira_reg_class_cover[i]]
       = curr_reg_pressure[ira_reg_class_cover[i]];
@@ -752,7 +734,7 @@ static void
 restore_reg_pressure (void)
 {
   int i;
-  
+
   for (i = 0; i < ira_reg_class_cover_size; i++)
     curr_reg_pressure[ira_reg_class_cover[i]]
       = saved_reg_pressure[ira_reg_class_cover[i]];
@@ -766,7 +748,8 @@ dying_use_p (struct reg_use_data *use)
   struct reg_use_data *next;
 
   for (next = use->next_regno_use; next != use; next = next->next_regno_use)
-    if (QUEUE_INDEX (next->insn) != QUEUE_SCHEDULED)
+    if (NONDEBUG_INSN_P (next->insn)
+       && QUEUE_INDEX (next->insn) != QUEUE_SCHEDULED)
       return false;
   return true;
 }
@@ -887,7 +870,7 @@ dep_cost_1 (dep_t link, dw_t dw)
          else if (bypass_p (insn))
            cost = insn_latency (insn, used);
        }
-       
+
 
       if (targetm.sched.adjust_cost_2)
        cost = targetm.sched.adjust_cost_2 (used, (int) dep_type, insn, cost,
@@ -940,7 +923,7 @@ increase_insn_priority (rtx insn, int amount)
     }
   else
     {
-      /* In sel-sched.c INSN_PRIORITY is not kept up to date.  
+      /* In sel-sched.c INSN_PRIORITY is not kept up to date.
         Use EXPR_PRIORITY instead. */
       sel_add_to_insn_priority (insn, amount);
     }
@@ -1027,7 +1010,7 @@ priority (rtx insn)
             different than that of normal instructions.  Instead of walking
             through INSN_FORW_DEPS (check) list, we walk through
             INSN_FORW_DEPS list of each instruction in the corresponding
-            recovery block.  */ 
+            recovery block.  */
 
           /* Selective scheduling does not define RECOVERY_BLOCK macro.  */
          rec = sel_sched_p () ? NULL : RECOVERY_BLOCK (insn);
@@ -1078,7 +1061,7 @@ priority (rtx insn)
                        this_priority = next_priority;
                    }
                }
-             
+
              twin = PREV_INSN (twin);
            }
          while (twin != prev_first);
@@ -1122,6 +1105,8 @@ setup_insn_reg_pressure_info (rtx insn)
   struct reg_use_data *use;
   static int death[N_REG_CLASSES];
 
+  gcc_checking_assert (!DEBUG_INSN_P (insn));
+
   excess_cost_change = 0;
   for (i = 0; i < ira_reg_class_cover_size; i++)
     death[ira_reg_class_cover[i]] = 0;
@@ -1178,7 +1163,7 @@ rank_for_schedule (const void *x, const void *y)
     }
 
   /* The insn in a schedule group should be issued the first.  */
-  if (flag_sched_group_heuristic && 
+  if (flag_sched_group_heuristic &&
       SCHED_GROUP_P (tmp) != SCHED_GROUP_P (tmp2))
     return SCHED_GROUP_P (tmp2) ? 1 : -1;
 
@@ -1216,7 +1201,7 @@ rank_for_schedule (const void *x, const void *y)
 
   if (flag_sched_critical_path_heuristic && priority_val)
     return priority_val;
-    
+
   /* Prefer speculative insn with greater dependencies weakness.  */
   if (flag_sched_spec_insn_heuristic && spec_info)
     {
@@ -1229,7 +1214,7 @@ rank_for_schedule (const void *x, const void *y)
        dw1 = ds_weak (ds1);
       else
        dw1 = NO_DEP_WEAK;
-      
+
       ds2 = TODO_SPEC (tmp2) & SPECULATIVE;
       if (ds2)
        dw2 = ds_weak (ds2);
@@ -1416,7 +1401,7 @@ HAIFA_INLINE static rtx
 ready_remove_first (struct ready_list *ready)
 {
   rtx t;
-  
+
   gcc_assert (ready->n_ready);
   t = ready->vec[ready->first--];
   ready->n_ready--;
@@ -1444,7 +1429,7 @@ rtx
 ready_element (struct ready_list *ready, int index)
 {
   gcc_assert (ready->n_ready && index < ready->n_ready);
-  
+
   return ready->vec[ready->first - index];
 }
 
@@ -1498,7 +1483,8 @@ ready_sort (struct ready_list *ready)
   if (sched_pressure_p)
     {
       for (i = 0; i < ready->n_ready; i++)
-       setup_insn_reg_pressure_info (first[i]);
+       if (!DEBUG_INSN_P (first[i]))
+         setup_insn_reg_pressure_info (first[i]);
     }
   SCHED_SORT (first, ready->n_ready);
 }
@@ -1534,7 +1520,7 @@ advance_state (state_t state)
                      targetm.sched.dfa_pre_cycle_insn ());
 
   state_transition (state, NULL);
-  
+
   if (targetm.sched.dfa_post_cycle_insn)
     state_transition (state,
                      targetm.sched.dfa_post_cycle_insn ());
@@ -1562,6 +1548,8 @@ update_register_pressure (rtx insn)
   struct reg_use_data *use;
   struct reg_set_data *set;
 
+  gcc_checking_assert (!DEBUG_INSN_P (insn));
+
   for (use = INSN_REG_USE_LIST (insn); use != NULL; use = use->next_insn_use)
     if (dying_use_p (use) && bitmap_bit_p (curr_reg_live, use->regno))
       mark_regno_birth_or_death (use->regno, false);
@@ -1585,7 +1573,8 @@ setup_insn_max_reg_pressure (rtx after, bool update_p)
     max_reg_pressure[ira_reg_class_cover[i]]
       = curr_reg_pressure[ira_reg_class_cover[i]];
   for (insn = NEXT_INSN (after);
-       insn != NULL_RTX && BLOCK_FOR_INSN (insn) == BLOCK_FOR_INSN (after);
+       insn != NULL_RTX && ! BARRIER_P (insn)
+        && BLOCK_FOR_INSN (insn) == BLOCK_FOR_INSN (after);
        insn = NEXT_INSN (insn))
     if (NONDEBUG_INSN_P (insn))
       {
@@ -1681,7 +1670,7 @@ schedule_insn (rtx insn)
       fputc ('\n', sched_dump);
     }
 
-  if (sched_pressure_p)
+  if (sched_pressure_p && !DEBUG_INSN_P (insn))
     update_reg_and_insn_max_reg_pressure (insn);
 
   /* Scheduling instruction should have all its dependencies resolved and
@@ -1694,6 +1683,7 @@ schedule_insn (rtx insn)
         sd_iterator_cond (&sd_it, &dep);)
       {
        rtx dbg = DEP_PRO (dep);
+       struct reg_use_data *use, *next;
 
        gcc_assert (DEBUG_INSN_P (dbg));
 
@@ -1715,6 +1705,20 @@ schedule_insn (rtx insn)
        INSN_VAR_LOCATION_LOC (dbg) = gen_rtx_UNKNOWN_VAR_LOC ();
        df_insn_rescan (dbg);
 
+       /* Unknown location doesn't use any registers.  */
+       for (use = INSN_REG_USE_LIST (dbg); use != NULL; use = next)
+         {
+           struct reg_use_data *prev = use;
+
+           /* Remove use from the cyclic next_regno_use chain first.  */
+           while (prev->next_regno_use != use)
+             prev = prev->next_regno_use;
+           prev->next_regno_use = use->next_regno_use;
+           next = use->next_insn_use;
+           free (use);
+         }
+       INSN_REG_USE_LIST (dbg) = NULL;
+
        /* We delete rather than resolve these deps, otherwise we
           crash in sched_free_deps(), because forward deps are
           expected to be released before backward deps.  */
@@ -1728,7 +1732,7 @@ schedule_insn (rtx insn)
   if (INSN_TICK (insn) > clock_var)
     /* INSN has been prematurely moved from the queue to the ready list.
        This is possible only if following flag is set.  */
-    gcc_assert (flag_sched_stalled_insns);    
+    gcc_assert (flag_sched_stalled_insns);
 
   /* ??? Probably, if INSN is scheduled prematurely, we should leave
      INSN_TICK untouched.  This is a machine-dependent issue, actually.  */
@@ -1753,10 +1757,10 @@ schedule_insn (rtx insn)
 
       if (!IS_SPECULATION_BRANCHY_CHECK_P (insn))
        {
-         int effective_cost;      
-         
+         int effective_cost;
+
          effective_cost = try_ready (next);
-         
+
          if (effective_cost >= 0
              && SCHED_GROUP_P (next)
              && advance < effective_cost)
@@ -1775,7 +1779,7 @@ schedule_insn (rtx insn)
      forward dependencies for INSN anymore.  Nevertheless they are used in
      heuristics in rank_for_schedule (), early_queue_to_ready () and in
      some targets (e.g. rs6000).  Thus the earliest place where we *can*
-     remove dependencies is after targetm.sched.md_finish () call in
+     remove dependencies is after targetm.sched.finish () call in
      schedule_block ().  But, on the other side, the safest place to remove
      dependencies is when we are finishing scheduling entire region.  As we
      don't generate [many] dependencies during scheduling itself, we won't
@@ -1803,89 +1807,82 @@ schedule_insn (rtx insn)
 
 /* Functions for handling of notes.  */
 
-/* Insert the INSN note at the end of the notes list.  */
-static void 
-add_to_note_list (rtx insn, rtx *note_list_end_p)
-{
-  PREV_INSN (insn) = *note_list_end_p;
-  if (*note_list_end_p)
-    NEXT_INSN (*note_list_end_p) = insn;
-  *note_list_end_p = insn;
-}
-
 /* Add note list that ends on FROM_END to the end of TO_ENDP.  */
 void
 concat_note_lists (rtx from_end, rtx *to_endp)
 {
   rtx from_start;
 
+  /* It's easy when have nothing to concat.  */
   if (from_end == NULL)
-    /* It's easy when have nothing to concat.  */
     return;
 
+  /* It's also easy when destination is empty.  */
   if (*to_endp == NULL)
-    /* It's also easy when destination is empty.  */
     {
       *to_endp = from_end;
       return;
     }
 
   from_start = from_end;
-  /* A note list should be traversed via PREV_INSN.  */
-  while (PREV_INSN (from_start) != NULL) 
+  while (PREV_INSN (from_start) != NULL)
     from_start = PREV_INSN (from_start);
 
-  add_to_note_list (from_start, to_endp);
+  PREV_INSN (from_start) = *to_endp;
+  NEXT_INSN (*to_endp) = from_start;
   *to_endp = from_end;
 }
 
-/* Delete notes beginning with INSN and put them in the chain
-   of notes ended by NOTE_LIST.
-   Returns the insn following the notes.  */
-static rtx
-unlink_other_notes (rtx insn, rtx tail)
+/* Delete notes between HEAD and TAIL and put them in the chain
+   of notes ended by NOTE_LIST.  */
+void
+remove_notes (rtx head, rtx tail)
 {
-  rtx prev = PREV_INSN (insn);
+  rtx next_tail, insn, next;
 
-  while (insn != tail && NOTE_NOT_BB_P (insn))
-    {
-      rtx next = NEXT_INSN (insn);
-      basic_block bb = BLOCK_FOR_INSN (insn);
-
-      /* Delete the note from its current position.  */
-      if (prev)
-       NEXT_INSN (prev) = next;
-      if (next)
-       PREV_INSN (next) = prev;
+  note_list = 0;
+  if (head == tail && !INSN_P (head))
+    return;
 
-      if (bb)
-        {
-          /* Basic block can begin with either LABEL or
-             NOTE_INSN_BASIC_BLOCK.  */
-          gcc_assert (BB_HEAD (bb) != insn);
+  next_tail = NEXT_INSN (tail);
+  for (insn = head; insn != next_tail; insn = next)
+    {
+      next = NEXT_INSN (insn);
+      if (!NOTE_P (insn))
+       continue;
 
-          /* Check if we are removing last insn in the BB.  */
-          if (BB_END (bb) == insn)
-            BB_END (bb) = prev;
-        }
+      switch (NOTE_KIND (insn))
+       {
+       case NOTE_INSN_BASIC_BLOCK:
+         continue;
 
-      /* See sched_analyze to see how these are handled.  */
-      if (NOTE_KIND (insn) != NOTE_INSN_EH_REGION_BEG
-         && NOTE_KIND (insn) != NOTE_INSN_EH_REGION_END)
-        add_to_note_list (insn, &note_list);
+       case NOTE_INSN_EPILOGUE_BEG:
+         if (insn != tail)
+           {
+             remove_insn (insn);
+             add_reg_note (next, REG_SAVE_NOTE,
+                           GEN_INT (NOTE_INSN_EPILOGUE_BEG));
+             break;
+           }
+         /* FALLTHRU */
 
-      insn = next;
-    }
+       default:
+         remove_insn (insn);
+
+         /* Add the note to list that ends at NOTE_LIST.  */
+         PREV_INSN (insn) = note_list;
+         NEXT_INSN (insn) = NULL_RTX;
+         if (note_list)
+           NEXT_INSN (note_list) = insn;
+         note_list = insn;
+         break;
+       }
 
-  if (insn == tail)
-    {
-      gcc_assert (sel_sched_p ());
-      return prev;
+      gcc_assert ((sel_sched_p () || insn != tail) && insn != head);
     }
-
-  return insn;
 }
 
+
 /* Return the head and tail pointers of ebb starting at BEG and ending
    at END.  */
 void
@@ -1939,62 +1936,6 @@ no_real_insns_p (const_rtx head, const_rtx tail)
   return 1;
 }
 
-/* Delete notes between HEAD and TAIL and put them in the chain
-   of notes ended by NOTE_LIST.  */
-static void
-rm_other_notes (rtx head, rtx tail)
-{
-  rtx next_tail;
-  rtx insn;
-
-  note_list = 0;
-  if (head == tail && (! INSN_P (head)))
-    return;
-
-  next_tail = NEXT_INSN (tail);
-  for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
-    {
-      rtx prev;
-
-      /* Farm out notes, and maybe save them in NOTE_LIST.
-         This is needed to keep the debugger from
-         getting completely deranged.  */
-      if (NOTE_NOT_BB_P (insn))
-       {
-         prev = insn;
-         insn = unlink_other_notes (insn, next_tail);
-
-         gcc_assert ((sel_sched_p ()
-                      || prev != tail) && prev != head && insn != next_tail);
-       }
-    }
-}
-
-/* Same as above, but also process REG_SAVE_NOTEs of HEAD.  */
-void
-remove_notes (rtx head, rtx tail)
-{
-  /* rm_other_notes only removes notes which are _inside_ the
-     block---that is, it won't remove notes before the first real insn
-     or after the last real insn of the block.  So if the first insn
-     has a REG_SAVE_NOTE which would otherwise be emitted before the
-     insn, it is redundant with the note before the start of the
-     block, and so we have to take it out.  */
-  if (INSN_P (head))
-    {
-      rtx note;
-
-      for (note = REG_NOTES (head); note; note = XEXP (note, 1))
-       if (REG_NOTE_KIND (note) == REG_SAVE_NOTE)
-         remove_note (head, note);
-    }
-
-  /* Remove remaining note insns from the block, save them in
-     note_list.  These notes are restored at the end of
-     schedule_block ().  */
-  rm_other_notes (head, tail);
-}
-
 /* Restore-other-notes: NOTE_LIST is the end of a chain of notes
    previously found among the insns.  Insert them just before HEAD.  */
 rtx
@@ -2043,13 +1984,9 @@ queue_to_ready (struct ready_list *ready)
   q_ptr = NEXT_Q (q_ptr);
 
   if (dbg_cnt (sched_insn) == false)
-    {
-      /* If debug counter is activated do not requeue insn next after
-        last_scheduled_insn.  */
-      skip_insn = next_nonnote_insn (last_scheduled_insn);
-      while (skip_insn && DEBUG_INSN_P (skip_insn))
-       skip_insn = next_nonnote_insn (skip_insn);
-    }
+    /* If debug counter is activated do not requeue insn next after
+       last_scheduled_insn.  */
+    skip_insn = next_nonnote_nondebug_insn (last_scheduled_insn);
   else
     skip_insn = NULL_RTX;
 
@@ -2123,17 +2060,17 @@ queue_to_ready (struct ready_list *ready)
 }
 
 /* Used by early_queue_to_ready.  Determines whether it is "ok" to
-   prematurely move INSN from the queue to the ready list.  Currently, 
-   if a target defines the hook 'is_costly_dependence', this function 
+   prematurely move INSN from the queue to the ready list.  Currently,
+   if a target defines the hook 'is_costly_dependence', this function
    uses the hook to check whether there exist any dependences which are
-   considered costly by the target, between INSN and other insns that 
+   considered costly by the target, between INSN and other insns that
    have already been scheduled.  Dependences are checked up to Y cycles
    back, with default Y=1; The flag -fsched-stalled-insns-dep=Y allows
-   controlling this value. 
-   (Other considerations could be taken into account instead (or in 
+   controlling this value.
+   (Other considerations could be taken into account instead (or in
    addition) depending on user flags and target hooks.  */
 
-static bool 
+static bool
 ok_for_early_queue_removal (rtx insn)
 {
   int n_cycles;
@@ -2173,9 +2110,9 @@ ok_for_early_queue_removal (rtx insn)
                break;
            }
 
-         if (!prev_insn) 
+         if (!prev_insn)
            break;
-         prev_insn = PREV_INSN (prev_insn);     
+         prev_insn = PREV_INSN (prev_insn);
        }
     }
 
@@ -2186,7 +2123,7 @@ ok_for_early_queue_removal (rtx insn)
 /* Remove insns from the queue, before they become "ready" with respect
    to FU latency considerations.  */
 
-static int 
+static int
 early_queue_to_ready (state_t state, struct ready_list *ready)
 {
   rtx insn;
@@ -2200,20 +2137,20 @@ early_queue_to_ready (state_t state, struct ready_list *ready)
   int insns_removed = 0;
 
   /*
-     Flag '-fsched-stalled-insns=X' determines the aggressiveness of this 
-     function: 
+     Flag '-fsched-stalled-insns=X' determines the aggressiveness of this
+     function:
 
-     X == 0: There is no limit on how many queued insns can be removed          
+     X == 0: There is no limit on how many queued insns can be removed
              prematurely.  (flag_sched_stalled_insns = -1).
 
-     X >= 1: Only X queued insns can be removed prematurely in each 
+     X >= 1: Only X queued insns can be removed prematurely in each
             invocation.  (flag_sched_stalled_insns = X).
 
      Otherwise: Early queue removal is disabled.
          (flag_sched_stalled_insns = 0)
   */
 
-  if (! flag_sched_stalled_insns)   
+  if (! flag_sched_stalled_insns)
     return 0;
 
   for (stalls = 0; stalls <= max_insn_queue_index; stalls++)
@@ -2232,7 +2169,7 @@ early_queue_to_ready (state_t state, struct ready_list *ready)
                print_rtl_single (sched_dump, insn);
 
              memcpy (temp_state, state, dfa_state_size);
-             if (recog_memoized (insn) < 0) 
+             if (recog_memoized (insn) < 0)
                /* non-negative to indicate that it's not ready
                   to avoid infinite Q->R->Q->R... */
                cost = 0;
@@ -2243,7 +2180,7 @@ early_queue_to_ready (state_t state, struct ready_list *ready)
                fprintf (sched_dump, "transition cost = %d\n", cost);
 
              move_to_ready = false;
-             if (cost < 0) 
+             if (cost < 0)
                {
                  move_to_ready = ok_for_early_queue_removal (insn);
                  if (move_to_ready == true)
@@ -2252,7 +2189,7 @@ early_queue_to_ready (state_t state, struct ready_list *ready)
                      q_size -= 1;
                      ready_add (ready, insn, false);
 
-                     if (prev_link)   
+                     if (prev_link)
                        XEXP (prev_link, 1) = next_link;
                      else
                        insn_queue[NEXT_Q_AFTER (q_ptr, stalls)] = next_link;
@@ -2276,11 +2213,11 @@ early_queue_to_ready (state_t state, struct ready_list *ready)
 
              link = next_link;
            } /* while link */
-       } /* if link */    
+       } /* if link */
 
     } /* for stalls.. */
 
-  return insns_removed; 
+  return insns_removed;
 }
 
 
@@ -2315,11 +2252,9 @@ debug_ready_list (struct ready_list *ready)
   fprintf (sched_dump, "\n");
 }
 
-/* Search INSN for REG_SAVE_NOTE note pairs for
-   NOTE_INSN_EHREGION_{BEG,END}; and convert them back into
-   NOTEs.  The REG_SAVE_NOTE note following first one is contains the
-   saved value for NOTE_BLOCK_NUMBER which is useful for
-   NOTE_INSN_EH_REGION_{BEG,END} NOTEs.  */
+/* Search INSN for REG_SAVE_NOTE notes and convert them back into insn
+   NOTEs.  This is used for NOTE_INSN_EPILOGUE_BEG, so that sched-ebb
+   replaces the epilogue note in the correct basic block.  */
 void
 reemit_notes (rtx insn)
 {
@@ -2348,9 +2283,9 @@ move_insn (rtx insn, rtx last, rtx nt)
       int jump_p = 0;
 
       bb = BLOCK_FOR_INSN (insn);
+
       /* BB_HEAD is either LABEL or NOTE.  */
-      gcc_assert (BB_HEAD (bb) != insn);      
+      gcc_assert (BB_HEAD (bb) != insn);
 
       if (BB_END (bb) == insn)
        /* If this is last instruction in BB, move end marker one
@@ -2364,7 +2299,7 @@ move_insn (rtx insn, rtx last, rtx nt)
                          && IS_SPECULATION_BRANCHY_CHECK_P (insn))
                      || (common_sched_info->sched_pass_id
                          == SCHED_EBB_PASS));
-         
+
          gcc_assert (BLOCK_FOR_INSN (PREV_INSN (insn)) == bb);
 
          BB_END (bb) = PREV_INSN (insn);
@@ -2385,7 +2320,7 @@ move_insn (rtx insn, rtx last, rtx nt)
              && (LABEL_P (note)
                  || BARRIER_P (note)))
            note = NEXT_INSN (note);
-      
+
          gcc_assert (NOTE_INSN_BASIC_BLOCK_P (note));
        }
       else
@@ -2413,13 +2348,13 @@ move_insn (rtx insn, rtx last, rtx nt)
        }
 
       df_insn_change_bb (insn, bb);
-  
+
       /* Update BB_END, if needed.  */
       if (BB_END (bb) == last)
-       BB_END (bb) = insn;  
+       BB_END (bb) = insn;
     }
 
-  SCHED_GROUP_P (insn) = 0;  
+  SCHED_GROUP_P (insn) = 0;
 }
 
 /* Return true if scheduling INSN will finish current clock cycle.  */
@@ -2439,6 +2374,12 @@ insn_finishes_cycle_p (rtx insn)
   return false;
 }
 
+/* Define type for target data used in multipass scheduling.  */
+#ifndef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T
+# define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T int
+#endif
+typedef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T first_cycle_multipass_data_t;
+
 /* The following structure describe an entry of the stack of choices.  */
 struct choice_entry
 {
@@ -2450,6 +2391,8 @@ struct choice_entry
   int n;
   /* State after issuing the insn.  */
   state_t state;
+  /* Target-specific data.  */
+  first_cycle_multipass_data_t target_data;
 };
 
 /* The following array is used to implement a stack of choices used in
@@ -2489,8 +2432,7 @@ static int cached_issue_rate = 0;
    insns is insns with the best rank (the first insn in READY).  To
    make this function tries different samples of ready insns.  READY
    is current queue `ready'.  Global array READY_TRY reflects what
-   insns are already issued in this try.  MAX_POINTS is the sum of points
-   of all instructions in READY.  The function stops immediately,
+   insns are already issued in this try.  The function stops immediately,
    if it reached the such a solution, that all instruction can be issued.
    INDEX will contain index of the best insn in READY.  The following
    function is used only for first cycle multipass scheduling.
@@ -2501,9 +2443,9 @@ static int cached_issue_rate = 0;
    CLOBBERs, etc must be filtered elsewhere.  */
 int
 max_issue (struct ready_list *ready, int privileged_n, state_t state,
-          int *index)
+          bool first_cycle_insn_p, int *index)
 {
-  int n, i, all, n_ready, best, delay, tries_num, points = -1, max_points;
+  int n, i, all, n_ready, best, delay, tries_num;
   int more_issue;
   struct choice_entry *top;
   rtx insn;
@@ -2522,25 +2464,8 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
     }
 
   /* Init max_points.  */
-  max_points = 0;
   more_issue = issue_rate - cycle_issued_insns;
-
-  /* ??? We used to assert here that we never issue more insns than issue_rate.
-     However, some targets (e.g. MIPS/SB1) claim lower issue rate than can be
-     achieved to get better performance.  Until these targets are fixed to use
-     scheduler hooks to manipulate insns priority instead, the assert should 
-     be disabled.  
-
-     gcc_assert (more_issue >= 0);  */
-
-  for (i = 0; i < n_ready; i++)
-    if (!ready_try [i])
-      {
-       if (more_issue-- > 0)
-         max_points += ISSUE_POINTS (ready_element (ready, i));
-       else
-         break;
-      }
+  gcc_assert (more_issue >= 0);
 
   /* The number of the issued insns in the best solution.  */
   best = 0;
@@ -2551,6 +2476,10 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
   memcpy (top->state, state, dfa_state_size);
   top->rest = dfa_lookahead;
   top->n = 0;
+  if (targetm.sched.first_cycle_multipass_begin)
+    targetm.sched.first_cycle_multipass_begin (&top->target_data,
+                                              ready_try, n_ready,
+                                              first_cycle_insn_p);
 
   /* Count the number of the insns to search among.  */
   for (all = i = 0; i < n_ready; i++)
@@ -2565,12 +2494,17 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
       if (/* If we've reached a dead end or searched enough of what we have
             been asked...  */
          top->rest == 0
-         /* Or have nothing else to try.  */
-         || i >= n_ready)
+         /* or have nothing else to try...  */
+         || i >= n_ready
+         /* or should not issue more.  */
+         || top->n >= more_issue)
        {
          /* ??? (... || i == n_ready).  */
          gcc_assert (i <= n_ready);
 
+         /* We should not issue more than issue_rate instructions.  */
+         gcc_assert (top->n <= more_issue);
+
          if (top == choice_stack)
            break;
 
@@ -2593,8 +2527,7 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
                  /* This is the index of the insn issued first in this
                     solution.  */
                  *index = choice_stack [1].index;
-                 points = top->n;
-                 if (top->n == max_points || best == all)
+                 if (top->n == more_issue || best == all)
                    break;
                }
            }
@@ -2605,6 +2538,11 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
 
          /* Backtrack.  */
          ready_try [i] = 0;
+
+         if (targetm.sched.first_cycle_multipass_backtrack)
+           targetm.sched.first_cycle_multipass_backtrack (&top->target_data,
+                                                          ready_try, n_ready);
+
          top--;
          memcpy (state, top->state, dfa_state_size);
        }
@@ -2627,7 +2565,7 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
 
              n = top->n;
              if (memcmp (top->state, state, dfa_state_size) != 0)
-               n += ISSUE_POINTS (insn);
+               n++;
 
              /* Advance to the next choice_entry.  */
              top++;
@@ -2636,8 +2574,15 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
              top->index = i;
              top->n = n;
              memcpy (top->state, state, dfa_state_size);
-
              ready_try [i] = 1;
+
+             if (targetm.sched.first_cycle_multipass_issue)
+               targetm.sched.first_cycle_multipass_issue (&top->target_data,
+                                                          ready_try, n_ready,
+                                                          insn,
+                                                          &((top - 1)
+                                                            ->target_data));
+
              i = -1;
            }
        }
@@ -2646,8 +2591,13 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
       i++;
     }
 
+  if (targetm.sched.first_cycle_multipass_end)
+    targetm.sched.first_cycle_multipass_end (best != 0
+                                            ? &choice_stack[1].target_data
+                                            : NULL);
+
   /* Restore the original state of the DFA.  */
-  memcpy (state, choice_stack->state, dfa_state_size);  
+  memcpy (state, choice_stack->state, dfa_state_size);
 
   return best;
 }
@@ -2660,7 +2610,8 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
    0 if INSN_PTR is set to point to the desirable insn,
    1 if choose_ready () should be restarted without advancing the cycle.  */
 static int
-choose_ready (struct ready_list *ready, rtx *insn_ptr)
+choose_ready (struct ready_list *ready, bool first_cycle_insn_p,
+             rtx *insn_ptr)
 {
   int lookahead;
 
@@ -2689,7 +2640,11 @@ choose_ready (struct ready_list *ready, rtx *insn_ptr)
   if (lookahead <= 0 || SCHED_GROUP_P (ready_element (ready, 0))
       || DEBUG_INSN_P (ready_element (ready, 0)))
     {
-      *insn_ptr = ready_remove_first (ready);
+      if (targetm.sched.dispatch (NULL_RTX, IS_DISPATCH_ON))
+       *insn_ptr = ready_remove_first_dispatch (ready);
+      else
+       *insn_ptr = ready_remove_first (ready);
+
       return 0;
     }
   else
@@ -2699,7 +2654,7 @@ choose_ready (struct ready_list *ready, rtx *insn_ptr)
       rtx insn;
       int try_data = 1, try_control = 1;
       ds_t ts;
-      
+
       insn = ready_element (ready, 0);
       if (INSN_CODE (insn) < 0)
        {
@@ -2718,16 +2673,16 @@ choose_ready (struct ready_list *ready, rtx *insn_ptr)
 
              x = ready_element (ready, i);
              s = TODO_SPEC (x);
-             
+
              if (spec_info->flags & PREFER_NON_DATA_SPEC
                  && !(s & DATA_SPEC))
-               {                 
+               {
                  try_data = 0;
                  if (!(spec_info->flags & PREFER_NON_CONTROL_SPEC)
                      || !try_control)
                    break;
                }
-             
+
              if (spec_info->flags & PREFER_NON_CONTROL_SPEC
                  && !(s & CONTROL_SPEC))
                {
@@ -2769,14 +2724,12 @@ choose_ready (struct ready_list *ready, rtx *insn_ptr)
          {
            insn = ready_element (ready, i);
 
-#ifdef ENABLE_CHECKING
            /* If this insn is recognizable we should have already
               recognized it earlier.
               ??? Not very clear where this is supposed to be done.
               See dep_cost_1.  */
-           gcc_assert (INSN_CODE (insn) >= 0
-                       || recog_memoized (insn) < 0);
-#endif
+           gcc_checking_assert (INSN_CODE (insn) >= 0
+                                || recog_memoized (insn) < 0);
 
            ready_try [i]
              = (/* INSN_CODE check can be omitted here as it is also done later
@@ -2787,21 +2740,21 @@ choose_ready (struct ready_list *ready, rtx *insn_ptr)
                     (insn)));
          }
 
-      if (max_issue (ready, 1, curr_state, &index) == 0)
+      if (max_issue (ready, 1, curr_state, first_cycle_insn_p, &index) == 0)
        {
          *insn_ptr = ready_remove_first (ready);
          if (sched_verbose >= 4)
-           fprintf (sched_dump, ";;\t\tChosen insn (but can't issue) : %s \n", 
+           fprintf (sched_dump, ";;\t\tChosen insn (but can't issue) : %s \n",
                      (*current_sched_info->print_insn) (*insn_ptr, 0));
          return 0;
        }
       else
        {
-         if (sched_verbose >= 4)    
+         if (sched_verbose >= 4)
            fprintf (sched_dump, ";;\t\tChosen insn : %s\n",
                     (*current_sched_info->print_insn)
                     (ready_element (ready, index), 0));
-          
+
          *insn_ptr = ready_remove (ready, index);
          return 0;
        }
@@ -2815,7 +2768,8 @@ choose_ready (struct ready_list *ready, rtx *insn_ptr)
 void
 schedule_block (basic_block *target_bb)
 {
-  int i, first_cycle_insn_p;
+  int i;
+  bool first_cycle_insn_p;
   int can_issue_more;
   state_t temp_state = NULL;  /* It is used for multipass scheduling.  */
   int sort_p, advance, start_clock_var;
@@ -2851,8 +2805,8 @@ schedule_block (basic_block *target_bb)
   /* It is used for first cycle multipass scheduling.  */
   temp_state = alloca (dfa_state_size);
 
-  if (targetm.sched.md_init)
-    targetm.sched.md_init (sched_dump, sched_verbose, ready.veclen);
+  if (targetm.sched.init)
+    targetm.sched.init (sched_dump, sched_verbose, ready.veclen);
 
   /* We start inserting insns after PREV_HEAD.  */
   last_scheduled_insn = prev_head;
@@ -2872,7 +2826,7 @@ schedule_block (basic_block *target_bb)
   /* Start just before the beginning of time.  */
   clock_var = -1;
 
-  /* We need queue and ready lists and clock_var be initialized 
+  /* We need queue and ready lists and clock_var be initialized
      in try_ready () (which is called through init_ready_list ()).  */
   (*current_sched_info->init_ready_list) ();
 
@@ -3021,7 +2975,7 @@ schedule_block (basic_block *target_bb)
       else
        can_issue_more = issue_rate;
 
-      first_cycle_insn_p = 1;
+      first_cycle_insn_p = true;
       cycle_issued_insns = 0;
       for (;;)
        {
@@ -3038,9 +2992,9 @@ schedule_block (basic_block *target_bb)
                print_curr_reg_pressure ();
            }
 
-         if (ready.n_ready == 0 
-             && can_issue_more 
-             && reload_completed) 
+         if (ready.n_ready == 0
+             && can_issue_more
+             && reload_completed)
            {
              /* Allow scheduling insns directly from the queue in case
                 there's nothing better to do (ready list is empty) but
@@ -3064,7 +3018,7 @@ schedule_block (basic_block *target_bb)
              int res;
 
              insn = NULL_RTX;
-             res = choose_ready (&ready, &insn);
+             res = choose_ready (&ready, first_cycle_insn_p, &insn);
 
              if (res < 0)
                /* Finish cycle.  */
@@ -3096,10 +3050,10 @@ schedule_block (basic_block *target_bb)
               to have the highest priority (so it will be returned by
               the ready_remove_first call above), we invoke
               ready_add (&ready, insn, true).
-              But, still, there is one issue: INSN can be later 
-              discarded by scheduler's front end through 
+              But, still, there is one issue: INSN can be later
+              discarded by scheduler's front end through
               current_sched_info->can_schedule_ready_p, hence, won't
-              be issued next.  */ 
+              be issued next.  */
            {
              ready_add (&ready, insn, true);
               break;
@@ -3141,7 +3095,7 @@ schedule_block (basic_block *target_bb)
                  advance = cost;
                  break;
                }
+
              continue;
            }
 
@@ -3154,12 +3108,12 @@ schedule_block (basic_block *target_bb)
              continue;
            }
 
-         /* DECISION is made.  */      
-  
+         /* DECISION is made.  */
+
           if (TODO_SPEC (insn) & SPECULATIVE)
             generate_recovery_code (insn);
 
-         if (control_flow_insn_p (last_scheduled_insn)      
+         if (control_flow_insn_p (last_scheduled_insn)
              /* This is used to switch basic blocks by request
                 from scheduler front-end (actually, sched-ebb.c only).
                 This is used to process blocks with single fallthru
@@ -3169,7 +3123,7 @@ schedule_block (basic_block *target_bb)
            {
              *target_bb = current_sched_info->advance_target_bb
                (*target_bb, 0);
-             
+
              if (sched_verbose)
                {
                  rtx x;
@@ -3181,15 +3135,19 @@ schedule_block (basic_block *target_bb)
 
              last_scheduled_insn = bb_note (*target_bb);
            }
+
          /* Update counters, etc in the scheduler's front end.  */
          (*current_sched_info->begin_schedule_ready) (insn,
                                                       last_scheduled_insn);
+
          move_insn (insn, last_scheduled_insn, current_sched_info->next_tail);
+
+         if (targetm.sched.dispatch (NULL_RTX, IS_DISPATCH_ON))
+           targetm.sched.dispatch_do (insn, ADD_TO_DISPATCH_WINDOW);
+
          reemit_notes (insn);
          last_scheduled_insn = insn;
-         
+
          if (memcmp (curr_state, temp_state, dfa_state_size) != 0)
             {
               cycle_issued_insns++;
@@ -3213,7 +3171,7 @@ schedule_block (basic_block *target_bb)
          if (advance != 0)
            break;
 
-         first_cycle_insn_p = 0;
+         first_cycle_insn_p = false;
 
          /* Sort the ready list based on priority.  This must be
             redone here, as schedule_insn may have readied additional
@@ -3283,19 +3241,19 @@ schedule_block (basic_block *target_bb)
     /* Sanity check -- queue must be empty now.  Meaningless if region has
        multiple bbs.  */
     gcc_assert (!q_size && !ready.n_ready && !ready.n_debug);
-  else 
+  else
     {
       /* We must maintain QUEUE_INDEX between blocks in region.  */
       for (i = ready.n_ready - 1; i >= 0; i--)
        {
          rtx x;
-         
+
          x = ready_element (&ready, i);
          QUEUE_INDEX (x) = QUEUE_NOWHERE;
          TODO_SPEC (x) = (TODO_SPEC (x) & ~SPECULATIVE) | HARD_DEP;
        }
 
-      if (q_size)   
+      if (q_size)
        for (i = 0; i <= max_insn_queue_index; i++)
          {
            rtx link;
@@ -3326,9 +3284,9 @@ schedule_block (basic_block *target_bb)
       fix_inter_tick (NEXT_INSN (prev_head), last_scheduled_insn);
     }
 
-  if (targetm.sched.md_finish)
+  if (targetm.sched.finish)
     {
-      targetm.sched.md_finish (sched_dump, sched_verbose);
+      targetm.sched.finish (sched_dump, sched_verbose);
       /* Target might have added some instructions to the scheduled block
         in its md_finish () hook.  These new insns don't have any data
         initialized and to identify them we extend h_i_d so that they'll
@@ -3357,7 +3315,7 @@ set_priorities (rtx head, rtx tail)
 {
   rtx insn;
   int n_insn;
-  int sched_max_insns_priority = 
+  int sched_max_insns_priority =
        current_sched_info->sched_max_insns_priority;
   rtx prev_head;
 
@@ -3399,7 +3357,7 @@ setup_sched_dump (void)
                ? stderr : dump_file);
 }
 
-/* Initialize some global state for the scheduler.  This function works 
+/* Initialize some global state for the scheduler.  This function works
    with the common data shared between all the schedulers.  It is called
    from the scheduler specific initialization routine.  */
 
@@ -3411,8 +3369,12 @@ sched_init (void)
   flag_schedule_speculative_load = 0;
 #endif
 
+  if (targetm.sched.dispatch (NULL_RTX, IS_DISPATCH_ON))
+    targetm.sched.dispatch_do (NULL_RTX, DISPATCH_INIT);
+
   sched_pressure_p = (flag_sched_pressure && ! reload_completed
                      && common_sched_info->sched_pass_id == SCHED_RGN_PASS);
+
   if (sched_pressure_p)
     ira_setup_eliminable_regset ();
 
@@ -3479,17 +3441,16 @@ sched_init (void)
     }
 
   df_analyze ();
-  
-  /* Do not run DCE after reload, as this can kill nops inserted 
+
+  /* Do not run DCE after reload, as this can kill nops inserted
      by bundling.  */
   if (reload_completed)
     df_clear_flags (DF_LR_RUN_DCE);
 
   regstat_compute_calls_crossed ();
 
-  if (targetm.sched.md_init_global)
-    targetm.sched.md_init_global (sched_dump, sched_verbose,
-                                 get_max_uid () + 1);
+  if (targetm.sched.init_global)
+    targetm.sched.init_global (sched_dump, sched_verbose, get_max_uid () + 1);
 
   if (sched_pressure_p)
     {
@@ -3507,7 +3468,7 @@ sched_init (void)
       saved_reg_live = BITMAP_ALLOC (NULL);
       region_ref_regs = BITMAP_ALLOC (NULL);
     }
-  
+
   curr_state = xmalloc (dfa_state_size);
 }
 
@@ -3598,7 +3559,7 @@ haifa_sched_finish (void)
   sched_finish ();
 }
 
-/* Free global data used during insn scheduling.  This function works with 
+/* Free global data used during insn scheduling.  This function works with
    the common data shared between the schedulers.  */
 
 void
@@ -3614,8 +3575,8 @@ sched_finish (void)
     }
   free (curr_state);
 
-  if (targetm.sched.md_finish_global)
-    targetm.sched.md_finish_global (sched_dump, sched_verbose);
+  if (targetm.sched.finish_global)
+    targetm.sched.finish_global (sched_dump, sched_verbose);
 
   end_alias_analysis ();
 
@@ -3645,7 +3606,7 @@ fix_inter_tick (rtx head, rtx tail)
   int next_clock = clock_var + 1;
 
   bitmap_initialize (&processed, 0);
-  
+
   /* Iterates over scheduled instructions and fix their INSN_TICKs and
      INSN_TICKs of dependent instructions, so that INSN_TICKs are consistent
      across different blocks.  */
@@ -3656,26 +3617,25 @@ fix_inter_tick (rtx head, rtx tail)
          int tick;
          sd_iterator_def sd_it;
          dep_t dep;
-                  
+
          tick = INSN_TICK (head);
          gcc_assert (tick >= MIN_TICK);
-         
+
          /* Fix INSN_TICK of instruction from just scheduled block.  */
-         if (!bitmap_bit_p (&processed, INSN_LUID (head)))
+         if (bitmap_set_bit (&processed, INSN_LUID (head)))
            {
-             bitmap_set_bit (&processed, INSN_LUID (head));
              tick -= next_clock;
-             
+
              if (tick < MIN_TICK)
                tick = MIN_TICK;
-             
-             INSN_TICK (head) = tick;           
+
+             INSN_TICK (head) = tick;
            }
-         
+
          FOR_EACH_DEP (head, SD_LIST_RES_FORW, sd_it, dep)
            {
              rtx next;
-             
+
              next = DEP_CON (dep);
              tick = INSN_TICK (next);
 
@@ -3683,14 +3643,13 @@ fix_inter_tick (rtx head, rtx tail)
                  /* If NEXT has its INSN_TICK calculated, fix it.
                     If not - it will be properly calculated from
                     scratch later in fix_tick_ready.  */
-                 && !bitmap_bit_p (&processed, INSN_LUID (next)))
+                 && bitmap_set_bit (&processed, INSN_LUID (next)))
                {
-                 bitmap_set_bit (&processed, INSN_LUID (next));
                  tick -= next_clock;
-                 
+
                  if (tick < MIN_TICK)
                    tick = MIN_TICK;
-                 
+
                  if (tick > INTER_TICK (next))
                    INTER_TICK (next) = tick;
                  else
@@ -3705,7 +3664,7 @@ fix_inter_tick (rtx head, rtx tail)
 }
 
 static int haifa_speculate_insn (rtx, ds_t, rtx *);
-  
+
 /* Check if NEXT is ready to be added to the ready or queue list.
    If "yes", add it to the proper list.
    Returns:
@@ -3714,7 +3673,7 @@ static int haifa_speculate_insn (rtx, ds_t, rtx *);
    0 < N - queued for N cycles.  */
 int
 try_ready (rtx next)
-{  
+{
   ds_t old_ts, *ts;
 
   ts = &TODO_SPEC (next);
@@ -3723,7 +3682,7 @@ try_ready (rtx next)
   gcc_assert (!(old_ts & ~(SPECULATIVE | HARD_DEP))
              && ((old_ts & HARD_DEP)
                  || (old_ts & SPECULATIVE)));
-  
+
   if (sd_lists_empty_p (next, SD_LIST_BACK))
     /* NEXT has all its dependencies resolved.  */
     {
@@ -3754,6 +3713,10 @@ try_ready (rtx next)
            {
              ds_t ds = DEP_STATUS (dep) & SPECULATIVE;
 
+             if (DEBUG_INSN_P (DEP_PRO (dep))
+                 && !DEBUG_INSN_P (next))
+               continue;
+
              if (first_p)
                {
                  first_p = false;
@@ -3795,11 +3758,11 @@ try_ready (rtx next)
     {
       int res;
       rtx new_pat;
-      
+
       gcc_assert ((*ts & SPECULATIVE) && !(*ts & ~SPECULATIVE));
-      
+
       res = haifa_speculate_insn (next, *ts, &new_pat);
-       
+
       switch (res)
        {
        case -1:
@@ -3808,47 +3771,47 @@ try_ready (rtx next)
             so we won't reanalyze anything.  */
          *ts = (*ts & ~SPECULATIVE) | HARD_DEP;
          break;
-         
+
        case 0:
          /* We follow the rule, that every speculative insn
             has non-null ORIG_PAT.  */
          if (!ORIG_PAT (next))
            ORIG_PAT (next) = PATTERN (next);
          break;
-         
-       case 1:                  
+
+       case 1:
          if (!ORIG_PAT (next))
            /* If we gonna to overwrite the original pattern of insn,
               save it.  */
            ORIG_PAT (next) = PATTERN (next);
-         
+
          haifa_change_pattern (next, new_pat);
          break;
-         
+
        default:
          gcc_unreachable ();
        }
     }
-  
+
   /* We need to restore pattern only if (*ts == 0), because otherwise it is
      either correct (*ts & SPECULATIVE),
      or we simply don't care (*ts & HARD_DEP).  */
-  
+
   gcc_assert (!ORIG_PAT (next)
              || !IS_SPECULATION_BRANCHY_CHECK_P (next));
-  
+
   if (*ts & HARD_DEP)
     {
       /* We can't assert (QUEUE_INDEX (next) == QUEUE_NOWHERE) here because
         control-speculative NEXT could have been discarded by sched-rgn.c
         (the same case as when discarded by can_schedule_ready_p ()).  */
       /*gcc_assert (QUEUE_INDEX (next) == QUEUE_NOWHERE);*/
-      
+
       change_queue_index (next, QUEUE_NOWHERE);
       return -1;
     }
   else if (!(*ts & BEGIN_SPEC) && ORIG_PAT (next) && !IS_SPECULATION_CHECK_P (next))
-    /* We should change pattern of every previously speculative 
+    /* We should change pattern of every previously speculative
        instruction - and we determine if NEXT was speculative by using
        ORIG_PAT field.  Except one case - speculation checks have ORIG_PAT
        pat too, so skip them.  */
@@ -3858,12 +3821,12 @@ try_ready (rtx next)
     }
 
   if (sched_verbose >= 2)
-    {        
+    {
       int s = TODO_SPEC (next);
-          
+
       fprintf (sched_dump, ";;\t\tdependencies resolved: insn %s",
                (*current_sched_info->print_insn) (next, 0));
-          
+
       if (spec_info && spec_info->dump)
         {
           if (s & BEGIN_DATA)
@@ -3875,10 +3838,10 @@ try_ready (rtx next)
         }
 
       fprintf (sched_dump, "\n");
-    }          
-  
+    }
+
   adjust_priority (next);
-        
+
   return fix_tick_ready (next);
 }
 
@@ -3901,10 +3864,10 @@ fix_tick_ready (rtx next)
       full_p = (tick == INVALID_TICK);
 
       FOR_EACH_DEP (next, SD_LIST_RES_BACK, sd_it, dep)
-        {       
+        {
           rtx pro = DEP_PRO (dep);
           int tick1;
-              
+
          gcc_assert (INSN_TICK (pro) >= MIN_TICK);
 
           tick1 = INSN_TICK (pro) + dep_cost (dep);
@@ -3937,10 +3900,10 @@ change_queue_index (rtx next, int delay)
 {
   int i = QUEUE_INDEX (next);
 
-  gcc_assert (QUEUE_NOWHERE <= delay && delay <= max_insn_queue_index 
+  gcc_assert (QUEUE_NOWHERE <= delay && delay <= max_insn_queue_index
              && delay != 0);
   gcc_assert (i != QUEUE_SCHEDULED);
-  
+
   if ((delay > 0 && NEXT_Q_AFTER (q_ptr, delay) == i)
       || (delay < 0 && delay == i))
     /* We have nothing to do.  */
@@ -3951,18 +3914,18 @@ change_queue_index (rtx next, int delay)
     ready_remove_insn (next);
   else if (i >= 0)
     queue_remove (next);
-    
+
   /* Add it to the proper place.  */
   if (delay == QUEUE_READY)
     ready_add (readyp, next, false);
   else if (delay >= 1)
     queue_insn (next, delay);
-    
+
   if (sched_verbose >= 2)
-    {        
+    {
       fprintf (sched_dump, ";;\t\ttick updated: insn %s",
               (*current_sched_info->print_insn) (next, 0));
-      
+
       if (delay == QUEUE_READY)
        fprintf (sched_dump, " into ready\n");
       else if (delay >= 1)
@@ -4004,7 +3967,13 @@ sched_extend_ready_list (int new_sched_ready_n_insns)
                             new_sched_ready_n_insns + 1);
 
   for (; i <= new_sched_ready_n_insns; i++)
-    choice_stack[i].state = xmalloc (dfa_state_size);
+    {
+      choice_stack[i].state = xmalloc (dfa_state_size);
+
+      if (targetm.sched.first_cycle_multipass_init)
+       targetm.sched.first_cycle_multipass_init (&(choice_stack[i]
+                                                   .target_data));
+    }
 
   sched_ready_n_insns = new_sched_ready_n_insns;
 }
@@ -4023,7 +3992,13 @@ sched_finish_ready_list (void)
   ready_try = NULL;
 
   for (i = 0; i <= sched_ready_n_insns; i++)
-    free (choice_stack [i].state);
+    {
+      if (targetm.sched.first_cycle_multipass_fini)
+       targetm.sched.first_cycle_multipass_fini (&(choice_stack[i]
+                                                   .target_data));
+
+      free (choice_stack [i].state);
+    }
   free (choice_stack);
   choice_stack = NULL;
 
@@ -4044,10 +4019,10 @@ generate_recovery_code (rtx insn)
 {
   if (TODO_SPEC (insn) & BEGIN_SPEC)
     begin_speculative_block (insn);
-  
+
   /* Here we have insn with no dependencies to
      instructions other then CHECK_SPEC ones.  */
-  
+
   if (TODO_SPEC (insn) & BE_IN_SPEC)
     add_to_speculative_block (insn);
 }
@@ -4091,7 +4066,7 @@ process_insn_forw_deps_be_in_spec (rtx insn, rtx twin, ds_t fs)
                  ds_t new_ds;
 
                  new_ds = (ds & ~BEGIN_SPEC) | fs;
-                 
+
                  if (/* consumer can 'be in speculative'.  */
                      sched_insn_is_legitimate_for_speculation_p (consumer,
                                                                  new_ds))
@@ -4118,7 +4093,7 @@ static void
 begin_speculative_block (rtx insn)
 {
   if (TODO_SPEC (insn) & BEGIN_DATA)
-    nr_begin_data++;      
+    nr_begin_data++;
   if (TODO_SPEC (insn) & BEGIN_CONTROL)
     nr_begin_control++;
 
@@ -4149,7 +4124,7 @@ add_to_speculative_block (rtx insn)
 
   TODO_SPEC (insn) &= ~BE_IN_SPEC;
   gcc_assert (!TODO_SPEC (insn));
-  
+
   DONE_SPEC (insn) |= ts;
 
   /* First we convert all simple checks to branchy.  */
@@ -4260,7 +4235,7 @@ add_to_speculative_block (rtx insn)
 
       twin = XEXP (twins, 1);
       free_INSN_LIST_node (twins);
-      twins = twin;      
+      twins = twin;
     }
 
   calc_priorities (priorities_roots);
@@ -4280,10 +4255,9 @@ xrecalloc (void *p, size_t new_nmemb, size_t old_nmemb, size_t size)
 /* Helper function.
    Find fallthru edge from PRED.  */
 edge
-find_fallthru_edge (basic_block pred)
+find_fallthru_edge_from (basic_block pred)
 {
   edge e;
-  edge_iterator ei;
   basic_block succ;
 
   succ = pred->next_bb;
@@ -4291,21 +4265,23 @@ find_fallthru_edge (basic_block pred)
 
   if (EDGE_COUNT (pred->succs) <= EDGE_COUNT (succ->preds))
     {
-      FOR_EACH_EDGE (e, ei, pred->succs)
-       if (e->flags & EDGE_FALLTHRU)
-         {
-           gcc_assert (e->dest == succ);
-           return e;
-         }
+      e = find_fallthru_edge (pred->succs);
+
+      if (e)
+       {
+         gcc_assert (e->dest == succ);
+         return e;
+       }
     }
   else
     {
-      FOR_EACH_EDGE (e, ei, succ->preds)
-       if (e->flags & EDGE_FALLTHRU)
-         {
-           gcc_assert (e->src == pred);
-           return e;
-         }
+      e = find_fallthru_edge (succ->preds);
+
+      if (e)
+       {
+         gcc_assert (e->src == pred);
+         return e;
+       }
     }
 
   return NULL;
@@ -4347,20 +4323,20 @@ init_before_recovery (basic_block *before_recovery_ptr)
   edge e;
 
   last = EXIT_BLOCK_PTR->prev_bb;
-  e = find_fallthru_edge (last);
+  e = find_fallthru_edge_from (last);
 
   if (e)
     {
-      /* We create two basic blocks: 
+      /* We create two basic blocks:
          1. Single instruction block is inserted right after E->SRC
-         and has jump to 
+         and has jump to
          2. Empty block right before EXIT_BLOCK.
          Between these two blocks recovery blocks will be emitted.  */
 
       basic_block single, empty;
       rtx x, label;
 
-      /* If the fallthrough edge to exit we've found is from the block we've 
+      /* If the fallthrough edge to exit we've found is from the block we've
         created before, don't do anything more.  */
       if (last == after_recovery)
        return;
@@ -4394,7 +4370,7 @@ init_before_recovery (basic_block *before_recovery_ptr)
       JUMP_LABEL (x) = label;
       LABEL_NUSES (label)++;
       haifa_init_insn (x);
-          
+
       emit_barrier_after (x);
 
       sched_init_only_bb (empty, NULL);
@@ -4410,8 +4386,8 @@ init_before_recovery (basic_block *before_recovery_ptr)
 
       if (sched_verbose >= 2 && spec_info->dump)
         fprintf (spec_info->dump,
-                ";;\t\tFixed fallthru to EXIT : %d->>%d->%d->>EXIT\n", 
-                 last->index, single->index, empty->index);      
+                ";;\t\tFixed fallthru to EXIT : %d->>%d->%d->>EXIT\n",
+                 last->index, single->index, empty->index);
     }
   else
     before_recovery = last;
@@ -4424,7 +4400,7 @@ sched_create_recovery_block (basic_block *before_recovery_ptr)
   rtx label;
   rtx barrier;
   basic_block rec;
-  
+
   haifa_recovery_bb_recently_added_p = true;
   haifa_recovery_bb_ever_added_p = true;
 
@@ -4442,8 +4418,8 @@ sched_create_recovery_block (basic_block *before_recovery_ptr)
 
   if (BB_PARTITION (before_recovery) != BB_UNPARTITIONED)
     BB_SET_PARTITION (rec, BB_COLD_PARTITION);
-  
-  if (sched_verbose && spec_info->dump)    
+
+  if (sched_verbose && spec_info->dump)
     fprintf (spec_info->dump, ";;\t\tGenerated recovery block rec%d\n",
              rec->index);
 
@@ -4458,18 +4434,17 @@ sched_create_recovery_edges (basic_block first_bb, basic_block rec,
 {
   rtx label;
   rtx jump;
-  edge e;
   int edge_flags;
 
   /* This is fixing of incoming edge.  */
-  /* ??? Which other flags should be specified?  */      
+  /* ??? Which other flags should be specified?  */
   if (BB_PARTITION (first_bb) != BB_PARTITION (rec))
     /* Partition type is the same, if it is "unpartitioned".  */
     edge_flags = EDGE_CROSSING;
   else
     edge_flags = 0;
-      
-  e = make_edge (first_bb, rec, edge_flags);
+
+  make_edge (first_bb, rec, edge_flags);
   label = block_label (second_bb);
   jump = emit_jump_insn_after (gen_jump (label), BB_END (rec));
   JUMP_LABEL (jump) = label;
@@ -4489,9 +4464,11 @@ sched_create_recovery_edges (basic_block first_bb, basic_block rec,
       edge_flags = EDGE_CROSSING;
     }
   else
-    edge_flags = 0;  
+    edge_flags = 0;
 
-  make_single_succ_edge (rec, second_bb, edge_flags);  
+  make_single_succ_edge (rec, second_bb, edge_flags);
+  if (dom_info_available_p (CDI_DOMINATORS))
+    set_immediate_dominator (CDI_DOMINATORS, rec, first_bb);
 }
 
 /* This function creates recovery code for INSN.  If MUTATE_P is nonzero,
@@ -4539,7 +4516,7 @@ create_check_block_twin (rtx insn, bool mutate_p)
   if (rec != EXIT_BLOCK_PTR)
     {
       /* To have mem_reg alive at the beginning of second_bb,
-        we emit check BEFORE insn, so insn after splitting 
+        we emit check BEFORE insn, so insn after splitting
         insn will be at the beginning of second_bb, which will
         provide us with the correct life information.  */
       check = emit_jump_insn_before (check, insn);
@@ -4617,14 +4594,14 @@ create_check_block_twin (rtx insn, bool mutate_p)
 
       sched_create_recovery_edges (first_bb, rec, second_bb);
 
-      sched_init_only_bb (second_bb, first_bb);      
+      sched_init_only_bb (second_bb, first_bb);
       sched_init_only_bb (rec, EXIT_BLOCK_PTR);
 
       jump = BB_END (rec);
       haifa_init_insn (jump);
     }
 
-  /* Move backward dependences from INSN to CHECK and 
+  /* Move backward dependences from INSN to CHECK and
      move forward dependences from INSN to TWIN.  */
 
   /* First, create dependencies between INSN's producers and CHECK & TWIN.  */
@@ -4637,7 +4614,7 @@ create_check_block_twin (rtx insn, bool mutate_p)
         check --TRUE--> producer  ??? or ANTI ???
         twin  --TRUE--> producer
         twin  --ANTI--> check
-        
+
         If BEGIN_CONTROL: [insn ~~ANTI~~> producer]:
         check --ANTI--> producer
         twin  --ANTI--> producer
@@ -4646,7 +4623,7 @@ create_check_block_twin (rtx insn, bool mutate_p)
         If BE_IN_SPEC: [insn ~~TRUE~~> producer]:
         check ~~TRUE~~> producer
         twin  ~~TRUE~~> producer
-        twin  --ANTI--> check  */                
+        twin  --ANTI--> check  */
 
       ds = DEP_STATUS (dep);
 
@@ -4663,7 +4640,7 @@ create_check_block_twin (rtx insn, bool mutate_p)
        {
          DEP_CON (new_dep) = twin;
          sd_add_dep (new_dep, false);
-       }    
+       }
     }
 
   /* Second, remove backward dependencies of INSN.  */
@@ -4684,11 +4661,11 @@ create_check_block_twin (rtx insn, bool mutate_p)
 
   /* Fields (DONE_SPEC (x) & BEGIN_SPEC) and CHECK_SPEC (x) are set only
      here.  */
-  
+
   gcc_assert (!DONE_SPEC (insn));
-  
+
   if (!mutate_p)
-    { 
+    {
       ds_t ts = TODO_SPEC (insn);
 
       DONE_SPEC (insn) = ts & BEGIN_SPEC;
@@ -4724,7 +4701,7 @@ create_check_block_twin (rtx insn, bool mutate_p)
        }
       else
        {
-         if (spec_info->dump)    
+         if (spec_info->dump)
            fprintf (spec_info->dump, ";;\t\tRemoved simple check : %s\n",
                     (*current_sched_info->print_insn) (insn, 0));
 
@@ -4779,7 +4756,7 @@ fix_recovery_deps (basic_block rec)
   rtx link;
 
   bitmap_initialize (&in_ready, 0);
-  
+
   /* NOTE - a basic block note.  */
   note = NEXT_INSN (BB_HEAD (rec));
   gcc_assert (NOTE_INSN_BASIC_BLOCK_P (note));
@@ -4801,11 +4778,8 @@ fix_recovery_deps (basic_block rec)
            {
              sd_delete_dep (sd_it);
 
-             if (!bitmap_bit_p (&in_ready, INSN_LUID (consumer)))
-               {
-                 ready_list = alloc_INSN_LIST (consumer, ready_list);
-                 bitmap_set_bit (&in_ready, INSN_LUID (consumer));
-               }
+             if (bitmap_set_bit (&in_ready, INSN_LUID (consumer)))
+               ready_list = alloc_INSN_LIST (consumer, ready_list);
            }
          else
            {
@@ -4814,7 +4788,7 @@ fix_recovery_deps (basic_block rec)
              sd_iterator_next (&sd_it);
            }
        }
-      
+
       insn = PREV_INSN (insn);
     }
   while (insn != note);
@@ -4829,10 +4803,10 @@ fix_recovery_deps (basic_block rec)
   /* Fixing jump's dependences.  */
   insn = BB_HEAD (rec);
   jump = BB_END (rec);
-      
+
   gcc_assert (LABEL_P (insn));
   insn = NEXT_INSN (insn);
-  
+
   gcc_assert (NOTE_INSN_BASIC_BLOCK_P (insn));
   add_jump_dependencies (insn, jump);
 }
@@ -4946,7 +4920,7 @@ unlink_bb_notes (basic_block first, basic_block last)
       if (LABEL_P (label))
        note = NEXT_INSN (label);
       else
-       note = label;      
+       note = label;
       gcc_assert (NOTE_INSN_BASIC_BLOCK_P (note));
 
       prev = PREV_INSN (label);
@@ -4960,7 +4934,7 @@ unlink_bb_notes (basic_block first, basic_block last)
 
       if (last == first)
        break;
-      
+
       last = last->prev_bb;
     }
   while (1);
@@ -4975,14 +4949,14 @@ restore_bb_notes (basic_block first)
     return;
 
   /* We DON'T unlink basic block notes of the first block in the ebb.  */
-  first = first->next_bb;  
+  first = first->next_bb;
   /* Remember: FIRST is actually a second basic block in the ebb.  */
 
   while (first != EXIT_BLOCK_PTR
         && bb_header[first->index])
     {
       rtx prev, label, note, next;
-      
+
       label = bb_header[first->index];
       prev = PREV_INSN (label);
       next = NEXT_INSN (prev);
@@ -4990,7 +4964,7 @@ restore_bb_notes (basic_block first)
       if (LABEL_P (label))
        note = NEXT_INSN (label);
       else
-       note = label;      
+       note = label;
       gcc_assert (NOTE_INSN_BASIC_BLOCK_P (note));
 
       bb_header[first->index] = 0;
@@ -4998,7 +4972,7 @@ restore_bb_notes (basic_block first)
       NEXT_INSN (prev) = label;
       NEXT_INSN (note) = next;
       PREV_INSN (next) = note;
-      
+
       first = first->next_bb;
     }
 
@@ -5020,7 +4994,7 @@ fix_jump_move (rtx jump)
 
   gcc_assert (common_sched_info->sched_pass_id == SCHED_EBB_PASS
              || IS_SPECULATION_BRANCHY_CHECK_P (jump));
-  
+
   if (!NOTE_INSN_BASIC_BLOCK_P (BB_END (jump_bb_next)))
     /* if jump_bb_next is not empty.  */
     BB_END (jump_bb) = BB_END (jump_bb_next);
@@ -5049,9 +5023,9 @@ move_block_after_check (rtx jump)
   bb = BLOCK_FOR_INSN (PREV_INSN (jump));
   jump_bb = BLOCK_FOR_INSN (jump);
   jump_bb_next = jump_bb->next_bb;
-  
+
   update_bb_for_insn (jump_bb);
-  
+
   gcc_assert (IS_SPECULATION_CHECK_P (jump)
              || IS_SPECULATION_CHECK_P (BB_END (jump_bb_next)));
 
@@ -5065,7 +5039,7 @@ move_block_after_check (rtx jump)
   move_succs (&t, jump_bb_next);
 
   df_mark_solutions_dirty ();
-  
+
   common_sched_info->fix_recovery_cfg
     (bb->index, jump_bb->index, jump_bb_next->index);
 }
@@ -5143,7 +5117,7 @@ calc_priorities (rtx_vec_t roots)
   int i;
   rtx insn;
 
-  for (i = 0; VEC_iterate (rtx, roots, i, insn); i++)
+  FOR_EACH_VEC_ELT (rtx, roots, i, insn)
     priority (insn);
 }
 
@@ -5158,7 +5132,7 @@ add_jump_dependencies (rtx insn, rtx jump)
       insn = NEXT_INSN (insn);
       if (insn == jump)
        break;
-      
+
       if (dep_list_size (insn) == 0)
        {
          dep_def _new_dep, *new_dep = &_new_dep;
@@ -5232,23 +5206,23 @@ check_cfg (rtx head, rtx tail)
   next_tail = NEXT_INSN (tail);
 
   do
-    {      
-      not_last = head != tail;        
+    {
+      not_last = head != tail;
 
       if (not_first)
        gcc_assert (NEXT_INSN (PREV_INSN (head)) == head);
       if (not_last)
        gcc_assert (PREV_INSN (NEXT_INSN (head)) == head);
 
-      if (LABEL_P (head) 
+      if (LABEL_P (head)
          || (NOTE_INSN_BASIC_BLOCK_P (head)
              && (!not_first
                  || (not_first && !LABEL_P (PREV_INSN (head))))))
        {
-         gcc_assert (bb == 0);   
+         gcc_assert (bb == 0);
          bb = BLOCK_FOR_INSN (head);
          if (bb != 0)
-           gcc_assert (BB_HEAD (bb) == head);      
+           gcc_assert (BB_HEAD (bb) == head);
          else
            /* This is the case of jump table.  See inside_basic_block_p ().  */
            gcc_assert (LABEL_P (head) && !inside_basic_block_p (head));
@@ -5264,7 +5238,7 @@ check_cfg (rtx head, rtx tail)
          gcc_assert (inside_basic_block_p (head)
                      || NOTE_P (head));
          gcc_assert (BLOCK_FOR_INSN (head) == bb);
-       
+
          if (LABEL_P (head))
            {
              head = NEXT_INSN (head);
@@ -5371,7 +5345,7 @@ sched_scan (const struct sched_scan_info_def *ssi,
          unsigned i;
          basic_block x;
 
-         for (i = 0; VEC_iterate (basic_block, bbs, i, x); i++)
+         FOR_EACH_VEC_ELT (basic_block, bbs, i, x)
            init_bb (x);
        }
 
@@ -5382,11 +5356,11 @@ sched_scan (const struct sched_scan_info_def *ssi,
   extend_insn ();
 
   if (bbs != NULL)
-    {      
+    {
       unsigned i;
       basic_block x;
 
-      for (i = 0; VEC_iterate (basic_block, bbs, i, x); i++)
+      FOR_EACH_VEC_ELT (basic_block, bbs, i, x)
        init_insns_in_bb (x);
     }
 
@@ -5398,7 +5372,7 @@ sched_scan (const struct sched_scan_info_def *ssi,
       unsigned i;
       rtx x;
 
-      for (i = 0; VEC_iterate (rtx, insns, i, x); i++)
+      FOR_EACH_VEC_ELT (rtx, insns, i, x)
        init_insn (x);
     }
 
@@ -5479,12 +5453,12 @@ sched_extend_target (void)
 static void
 extend_h_i_d (void)
 {
-  int reserve = (get_max_uid () + 1 
+  int reserve = (get_max_uid () + 1
                  - VEC_length (haifa_insn_data_def, h_i_d));
-  if (reserve > 0 
+  if (reserve > 0
       && ! VEC_space (haifa_insn_data_def, h_i_d, reserve))
     {
-      VEC_safe_grow_cleared (haifa_insn_data_def, heap, h_i_d, 
+      VEC_safe_grow_cleared (haifa_insn_data_def, heap, h_i_d,
                              3 * get_max_uid () / 2);
       sched_extend_target ();
     }
@@ -5528,7 +5502,7 @@ haifa_finish_h_i_d (void)
   haifa_insn_data_t data;
   struct reg_use_data *use, *next;
 
-  for (i = 0; VEC_iterate (haifa_insn_data_def, h_i_d, i, data); i++)
+  FOR_EACH_VEC_ELT (haifa_insn_data_def, h_i_d, i, data)
     {
       if (data->reg_pressure != NULL)
        free (data->reg_pressure);
@@ -5583,7 +5557,7 @@ sched_split_block_1 (basic_block first_bb, rtx after)
   e = split_block (first_bb, after);
   gcc_assert (e->src == first_bb);
 
-  /* sched_split_block emits note if *check == BB_END.  Probably it 
+  /* sched_split_block emits note if *check == BB_END.  Probably it
      is better to rip that note off.  */
 
   return e->dest;
@@ -5607,4 +5581,73 @@ sched_emit_insn (rtx pat)
   return insn;
 }
 
+/* This function returns a candidate satisfying dispatch constraints from
+   the ready list.  */
+
+static rtx
+ready_remove_first_dispatch (struct ready_list *ready)
+{
+  int i;
+  rtx insn = ready_element (ready, 0);
+
+  if (ready->n_ready == 1
+      || INSN_CODE (insn) < 0
+      || !INSN_P (insn)
+      || !active_insn_p (insn)
+      || targetm.sched.dispatch (insn, FITS_DISPATCH_WINDOW))
+    return ready_remove_first (ready);
+
+  for (i = 1; i < ready->n_ready; i++)
+    {
+      insn = ready_element (ready, i);
+
+      if (INSN_CODE (insn) < 0
+         || !INSN_P (insn)
+         || !active_insn_p (insn))
+       continue;
+
+      if (targetm.sched.dispatch (insn, FITS_DISPATCH_WINDOW))
+       {
+         /* Return ith element of ready.  */
+         insn = ready_remove (ready, i);
+         return insn;
+       }
+    }
+
+  if (targetm.sched.dispatch (NULL_RTX, DISPATCH_VIOLATION))
+    return ready_remove_first (ready);
+
+  for (i = 1; i < ready->n_ready; i++)
+    {
+      insn = ready_element (ready, i);
+
+      if (INSN_CODE (insn) < 0
+         || !INSN_P (insn)
+         || !active_insn_p (insn))
+       continue;
+
+      /* Return i-th element of ready.  */
+      if (targetm.sched.dispatch (insn, IS_CMP))
+       return ready_remove (ready, i);
+    }
+
+  return ready_remove_first (ready);
+}
+
+/* Get number of ready insn in the ready list.  */
+
+int
+number_in_ready (void)
+{
+  return ready.n_ready;
+}
+
+/* Get number of ready's in the ready list.  */
+
+rtx
+get_ready_element (int i)
+{
+  return ready_element (&ready, i);
+}
+
 #endif /* INSN_SCHEDULING */