OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / haifa-sched.c
index 3149fb0..0f12cd0 100644 (file)
@@ -1,6 +1,7 @@
 /* Instruction scheduling pass.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
    and currently maintained by, Jim Wilson (wilson@cygnus.com)
 
@@ -8,7 +9,7 @@ This file is part of GCC.
 
 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
+Software Foundation; either version 3, or (at your option) any later
 version.
 
 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
@@ -17,9 +18,8 @@ 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 GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA.  */
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
 
 /* Instruction scheduling pass.  This file, along with sched-deps.c,
    contains the generic parts.  The actual entry point is found for
@@ -144,6 +144,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "target.h"
 #include "output.h"
 #include "params.h"
+#include "dbgcnt.h"
 
 #ifdef INSN_SCHEDULING
 
@@ -206,18 +207,20 @@ static rtx note_list;
 static struct spec_info_def spec_info_var;
 /* Description of the speculative part of the scheduling.
    If NULL - no speculation.  */
-static spec_info_t spec_info;
+spec_info_t spec_info;
 
 /* True, if recovery block was added during scheduling of current block.
    Used to determine, if we need to fix INSN_TICKs.  */
-static bool added_recovery_block_p;
+static bool haifa_recovery_bb_recently_added_p;
+
+/* True, if recovery block was added during this scheduling pass.
+   Used to determine if we should have empty memory pools of dependencies
+   after finishing current region.  */
+bool haifa_recovery_bb_ever_added_p;
 
 /* Counters of different types of speculative instructions.  */
 static int nr_begin_data, nr_be_in_data, nr_begin_control, nr_be_in_control;
 
-/* Pointers to GLAT data.  See init_glat for more information.  */
-regset *glat_start, *glat_end;
-
 /* Array used in {unlink, restore}_bb_notes.  */
 static rtx *bb_header = 0;
 
@@ -326,7 +329,7 @@ static int clock_var;
 /* Number of instructions in current scheduling region.  */
 static int rgn_n_insns;
 
-static int may_trap_exp (rtx, int);
+static int may_trap_exp (const_rtx, int);
 
 /* Nonzero iff the address is comprised from at most 1 register.  */
 #define CONST_BASED_ADDRESS_P(x)                       \
@@ -340,7 +343,7 @@ static int may_trap_exp (rtx, int);
    as found by analyzing insn's expression.  */
 
 static int
-may_trap_exp (rtx x, int is_store)
+may_trap_exp (const_rtx x, int is_store)
 {
   enum rtx_code code;
 
@@ -403,8 +406,9 @@ may_trap_exp (rtx x, int is_store)
     }
 }
 
-/* Classifies insn for the purpose of verifying that it can be
-   moved speculatively, by examining it's patterns, returning:
+/* Classifies rtx X of an insn for the purpose of verifying that X can be
+   executed speculatively (and consequently the insn can be moved
+   speculatively), by examining X, returning:
    TRAP_RISKY: store, or risky non-load insn (e.g. division by variable).
    TRAP_FREE: non-load insn.
    IFREE: load from a globally safe location.
@@ -412,45 +416,20 @@ may_trap_exp (rtx x, int is_store)
    PFREE_CANDIDATE, PRISKY_CANDIDATE: load that need to be checked for
    being either PFREE or PRISKY.  */
 
-int
-haifa_classify_insn (rtx insn)
+static int
+haifa_classify_rtx (const_rtx x)
 {
-  rtx pat = PATTERN (insn);
   int tmp_class = TRAP_FREE;
   int insn_class = TRAP_FREE;
   enum rtx_code code;
 
-  if (GET_CODE (pat) == PARALLEL)
+  if (GET_CODE (x) == PARALLEL)
     {
-      int i, len = XVECLEN (pat, 0);
+      int i, len = XVECLEN (x, 0);
 
       for (i = len - 1; i >= 0; i--)
        {
-         code = GET_CODE (XVECEXP (pat, 0, i));
-         switch (code)
-           {
-           case CLOBBER:
-             /* Test if it is a 'store'.  */
-             tmp_class = may_trap_exp (XEXP (XVECEXP (pat, 0, i), 0), 1);
-             break;
-           case SET:
-             /* Test if it is a store.  */
-             tmp_class = may_trap_exp (SET_DEST (XVECEXP (pat, 0, i)), 1);
-             if (tmp_class == TRAP_RISKY)
-               break;
-             /* Test if it is a load.  */
-             tmp_class
-               = WORST_CLASS (tmp_class,
-                              may_trap_exp (SET_SRC (XVECEXP (pat, 0, i)),
-                                            0));
-             break;
-           case COND_EXEC:
-           case TRAP_IF:
-             tmp_class = TRAP_RISKY;
-             break;
-           default:
-             ;
-           }
+         tmp_class = haifa_classify_rtx (XVECEXP (x, 0, i));
          insn_class = WORST_CLASS (insn_class, tmp_class);
          if (insn_class == TRAP_RISKY || insn_class == IRISKY)
            break;
@@ -458,24 +437,30 @@ haifa_classify_insn (rtx insn)
     }
   else
     {
-      code = GET_CODE (pat);
+      code = GET_CODE (x);
       switch (code)
        {
        case CLOBBER:
          /* Test if it is a 'store'.  */
-         tmp_class = may_trap_exp (XEXP (pat, 0), 1);
+         tmp_class = may_trap_exp (XEXP (x, 0), 1);
          break;
        case SET:
          /* Test if it is a store.  */
-         tmp_class = may_trap_exp (SET_DEST (pat), 1);
+         tmp_class = may_trap_exp (SET_DEST (x), 1);
          if (tmp_class == TRAP_RISKY)
            break;
          /* Test if it is a load.  */
          tmp_class =
            WORST_CLASS (tmp_class,
-                        may_trap_exp (SET_SRC (pat), 0));
+                        may_trap_exp (SET_SRC (x), 0));
          break;
        case COND_EXEC:
+         tmp_class = haifa_classify_rtx (COND_EXEC_CODE (x));
+         if (tmp_class == TRAP_RISKY)
+           break;
+         tmp_class = WORST_CLASS (tmp_class,
+                                  may_trap_exp (COND_EXEC_TEST (x), 0));
+         break;
        case TRAP_IF:
          tmp_class = TRAP_RISKY;
          break;
@@ -487,6 +472,13 @@ haifa_classify_insn (rtx insn)
   return insn_class;
 }
 
+int
+haifa_classify_insn (const_rtx insn)
+{
+  return haifa_classify_rtx (PATTERN (insn));
+}
+
+
 /* A typedef for rtx vector.  */
 typedef VEC(rtx, heap) *rtx_vec_t;
 
@@ -497,7 +489,7 @@ static int rank_for_schedule (const void *, const void *);
 static void swap_sort (rtx *, int);
 static void queue_insn (rtx, int);
 static int schedule_insn (rtx);
-static int find_set_reg_weight (rtx);
+static int find_set_reg_weight (const_rtx);
 static void find_insn_reg_weight (basic_block);
 static void find_insn_reg_weight1 (rtx);
 static void adjust_priority (rtx);
@@ -541,7 +533,7 @@ static rtx ready_remove (struct ready_list *, int);
 static void ready_remove_insn (rtx);
 static int max_issue (struct ready_list *, int *, int);
 
-static rtx choose_ready (struct ready_list *);
+static int choose_ready (struct ready_list *, rtx *);
 
 static void fix_inter_tick (rtx, rtx);
 static int fix_tick_ready (rtx);
@@ -556,7 +548,7 @@ static void extend_global (rtx);
 static void extend_all (rtx);
 static void init_h_i_d (rtx);
 static void generate_recovery_code (rtx);
-static void process_insn_forw_deps_be_in_spec (deps_list_t, rtx, ds_t);
+static void process_insn_forw_deps_be_in_spec (rtx, rtx, ds_t);
 static void begin_speculative_block (rtx);
 static void add_to_speculative_block (rtx);
 static dw_t dep_weak (ds_t);
@@ -573,10 +565,6 @@ static void extend_bb (void);
 static void fix_jump_move (rtx);
 static void move_block_after_check (rtx);
 static void move_succs (VEC(edge,gc) **, basic_block);
-static void init_glat (void);
-static void init_glat1 (basic_block);
-static void attach_life_info1 (basic_block);
-static void free_glat (void);
 static void sched_remove_insn (rtx);
 static void clear_priorities (rtx, rtx_vec_t *);
 static void calc_priorities (rtx_vec_t);
@@ -584,7 +572,6 @@ static void add_jump_dependencies (rtx, rtx);
 #ifdef ENABLE_CHECKING
 static int has_edge_p (VEC(edge,gc) *, int);
 static void check_cfg (rtx, rtx);
-static void check_sched_flags (void);
 #endif
 
 #endif /* INSN_SCHEDULING */
@@ -661,7 +648,7 @@ dep_cost (dep_t link)
   else
     {
       rtx insn = DEP_PRO (link);
-      enum reg_note dep_type = DEP_KIND (link);
+      enum reg_note dep_type = DEP_TYPE (link);
 
       cost = insn_cost (insn);
 
@@ -691,7 +678,7 @@ dep_cost (dep_t link)
          XEXP (dep_cost_rtx_link, 1) = dep_cost_rtx_link;
 
          /* Targets use only REG_NOTE_KIND of the link.  */
-         PUT_REG_NOTE_KIND (dep_cost_rtx_link, DEP_KIND (link));
+         PUT_REG_NOTE_KIND (dep_cost_rtx_link, DEP_TYPE (link));
 
          cost = targetm.sched.adjust_cost (used, dep_cost_rtx_link,
                                            insn, cost);
@@ -733,19 +720,17 @@ contributes_to_priority_p (dep_t dep)
 static int
 priority (rtx insn)
 {
-  dep_link_t link;
-
   if (! INSN_P (insn))
     return 0;
 
-  /* We should not be insterested in priority of an already scheduled insn.  */
+  /* We should not be interested in priority of an already scheduled insn.  */
   gcc_assert (QUEUE_INDEX (insn) != QUEUE_SCHEDULED);
 
   if (!INSN_PRIORITY_KNOWN (insn))
     {
       int this_priority = 0;
 
-      if (deps_list_empty_p (INSN_FORW_DEPS (insn)))
+      if (sd_lists_empty_p (insn, SD_LIST_FORW))
        /* ??? We should set INSN_PRIORITY to insn_cost when and insn has
           some forward deps but all of them are ignored by
           contributes_to_priority hook.  At the moment we set priority of
@@ -776,11 +761,13 @@ priority (rtx insn)
 
          do
            {
-             FOR_EACH_DEP_LINK (link, INSN_FORW_DEPS (twin))
+             sd_iterator_def sd_it;
+             dep_t dep;
+
+             FOR_EACH_DEP (twin, SD_LIST_FORW, sd_it, dep)
                {
                  rtx next;
                  int next_priority;
-                 dep_t dep = DEP_LINK_DEP (link);
 
                  next = DEP_CON (dep);
 
@@ -839,7 +826,6 @@ rank_for_schedule (const void *x, const void *y)
 {
   rtx tmp = *(const rtx *) y;
   rtx tmp2 = *(const rtx *) x;
-  dep_link_t link1, link2;
   int tmp_class, tmp2_class;
   int val, priority_val, weight_val, info_val;
 
@@ -892,31 +878,30 @@ rank_for_schedule (const void *x, const void *y)
   /* Compare insns based on their relation to the last-scheduled-insn.  */
   if (INSN_P (last_scheduled_insn))
     {
+      dep_t dep1;
+      dep_t dep2;
+
       /* Classify the instructions into three classes:
          1) Data dependent on last schedule insn.
          2) Anti/Output dependent on last scheduled insn.
          3) Independent of last scheduled insn, or has latency of one.
          Choose the insn from the highest numbered class if different.  */
-      link1
-       = find_link_by_con_in_deps_list (INSN_FORW_DEPS (last_scheduled_insn),
-                                        tmp);
+      dep1 = sd_find_dep_between (last_scheduled_insn, tmp, true);
 
-      if (link1 == NULL || dep_cost (DEP_LINK_DEP (link1)) == 1)
+      if (dep1 == NULL || dep_cost (dep1) == 1)
        tmp_class = 3;
       else if (/* Data dependence.  */
-              DEP_LINK_KIND (link1) == REG_DEP_TRUE)
+              DEP_TYPE (dep1) == REG_DEP_TRUE)
        tmp_class = 1;
       else
        tmp_class = 2;
 
-      link2
-       = find_link_by_con_in_deps_list (INSN_FORW_DEPS (last_scheduled_insn),
-                                        tmp2);
+      dep2 = sd_find_dep_between (last_scheduled_insn, tmp2, true);
 
-      if (link2 == NULL || dep_cost (DEP_LINK_DEP (link2))  == 1)
+      if (dep2 == NULL || dep_cost (dep2)  == 1)
        tmp2_class = 3;
       else if (/* Data dependence.  */
-              DEP_LINK_KIND (link2) == REG_DEP_TRUE)
+              DEP_TYPE (dep2) == REG_DEP_TRUE)
        tmp2_class = 1;
       else
        tmp2_class = 2;
@@ -929,21 +914,11 @@ rank_for_schedule (const void *x, const void *y)
      This gives the scheduler more freedom when scheduling later
      instructions at the expense of added register pressure.  */
 
-  link1 = DEPS_LIST_FIRST (INSN_FORW_DEPS (tmp));
-  link2 = DEPS_LIST_FIRST (INSN_FORW_DEPS (tmp2));
+  val = (sd_lists_size (tmp2, SD_LIST_FORW)
+        - sd_lists_size (tmp, SD_LIST_FORW));
 
-  while (link1 != NULL && link2 != NULL)
-    {
-      link1 = DEP_LINK_NEXT (link1);
-      link2 = DEP_LINK_NEXT (link2);
-    }
-
-  if (link1 != NULL && link2 == NULL)
-    /* TMP (Y) has more insns that depend on it.  */
-    return -1;
-  if (link1 == NULL && link2 != NULL)
-    /* TMP2 (X) has more insns that depend on it.  */
-    return 1;
+  if (val != 0)
+    return val;
 
   /* If insns are equally good, sort by INSN_LUID (original insn order),
      so that we make the sort stable.  This minimizes instruction movement,
@@ -1156,6 +1131,9 @@ adjust_priority (rtx prev)
 HAIFA_INLINE static void
 advance_one_cycle (void)
 {
+  if (targetm.sched.dfa_pre_advance_cycle)
+    targetm.sched.dfa_pre_advance_cycle ();
+
   if (targetm.sched.dfa_pre_cycle_insn)
     state_transition (curr_state,
                      targetm.sched.dfa_pre_cycle_insn ());
@@ -1165,6 +1143,9 @@ advance_one_cycle (void)
   if (targetm.sched.dfa_post_cycle_insn)
     state_transition (curr_state,
                      targetm.sched.dfa_post_cycle_insn ());
+
+  if (targetm.sched.dfa_post_advance_cycle)
+    targetm.sched.dfa_post_advance_cycle ();
 }
 
 /* Clock at which the previous instruction was issued.  */
@@ -1179,7 +1160,8 @@ static int last_clock_var;
 static int
 schedule_insn (rtx insn)
 {
-  dep_link_t link;
+  sd_iterator_def sd_it;
+  dep_t dep;
   int advance = 0;
 
   if (sched_verbose >= 1)
@@ -1199,12 +1181,7 @@ schedule_insn (rtx insn)
 
   /* Scheduling instruction should have all its dependencies resolved and
      should have been removed from the ready list.  */
-  gcc_assert (INSN_DEP_COUNT (insn) == 0
-             && deps_list_empty_p (INSN_BACK_DEPS (insn)));
-  free_deps_list (INSN_BACK_DEPS (insn));
-
-  /* Now we can free INSN_RESOLVED_BACK_DEPS list.  */
-  delete_deps_list (INSN_RESOLVED_BACK_DEPS (insn));
+  gcc_assert (sd_lists_empty_p (insn, SD_LIST_BACK));
 
   gcc_assert (QUEUE_INDEX (insn) == QUEUE_NOWHERE);
   QUEUE_INDEX (insn) = QUEUE_SCHEDULED;
@@ -1220,19 +1197,15 @@ schedule_insn (rtx insn)
   INSN_TICK (insn) = clock_var;
 
   /* Update dependent instructions.  */
-  FOR_EACH_DEP_LINK (link, INSN_FORW_DEPS (insn))
+  for (sd_it = sd_iterator_start (insn, SD_LIST_FORW);
+       sd_iterator_cond (&sd_it, &dep);)
     {
-      rtx next = DEP_LINK_CON (link);
-
-      /* Resolve the dependence between INSN and NEXT.  */
+      rtx next = DEP_CON (dep);
 
-      INSN_DEP_COUNT (next)--;
-
-      move_dep_link (DEP_NODE_BACK (DEP_LINK_NODE (link)),
-                       INSN_RESOLVED_BACK_DEPS (next));
-
-      gcc_assert ((INSN_DEP_COUNT (next) == 0)
-                 == deps_list_empty_p (INSN_BACK_DEPS (next)));
+      /* Resolve the dependence between INSN and NEXT.
+        sd_resolve_dep () moves current dep to another list thus
+        advancing the iterator.  */
+      sd_resolve_dep (sd_it);
 
       if (!IS_SPECULATION_BRANCHY_CHECK_P (insn))
        {
@@ -1249,11 +1222,23 @@ schedule_insn (rtx insn)
        /* Check always has only one forward dependence (to the first insn in
           the recovery block), therefore, this will be executed only once.  */
        {
-         gcc_assert (DEP_LINK_NEXT (link) == NULL);
+         gcc_assert (sd_lists_empty_p (insn, SD_LIST_FORW));
          fix_recovery_deps (RECOVERY_BLOCK (insn));
        }
     }
 
+  /* This is the place where scheduler doesn't *basically* need backward and
+     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
+     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
+     need memory until beginning of next region.
+     Bottom line: Dependencies are removed for all insns in the end of
+     scheduling the region.  */
+
   /* Annotate the instruction with issue information -- TImode
      indicates that the instruction is expected not to be able
      to issue on the same cycle as the previous insn.  A machine
@@ -1362,7 +1347,7 @@ get_ebb_head_tail (basic_block beg, basic_block end, rtx *headp, rtx *tailp)
 /* Return nonzero if there are no real insns in the range [ HEAD, TAIL ].  */
 
 int
-no_real_insns_p (rtx head, rtx tail)
+no_real_insns_p (const_rtx head, const_rtx tail)
 {
   while (head != NEXT_INSN (tail))
     {
@@ -1412,7 +1397,7 @@ rm_other_notes (rtx head, rtx tail)
    a new register is not needed.  */
 
 static int
-find_set_reg_weight (rtx x)
+find_set_reg_weight (const_rtx x)
 {
   if (GET_CODE (x) == CLOBBER
       && register_operand (SET_DEST (x), VOIDmode))
@@ -1489,9 +1474,17 @@ queue_to_ready (struct ready_list *ready)
 {
   rtx insn;
   rtx link;
+  rtx skip_insn;
 
   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);
+  else
+    skip_insn = NULL_RTX;
+
   /* Add all pending insns that can be scheduled without stalls to the
      ready list.  */
   for (link = insn_queue[q_ptr]; link; link = XEXP (link, 1))
@@ -1507,7 +1500,8 @@ queue_to_ready (struct ready_list *ready)
         See the comment in schedule_block for the rationale.  */
       if (!reload_completed
          && ready->n_ready > MAX_SCHED_READY_INSNS
-         && !SCHED_GROUP_P (insn))
+         && !SCHED_GROUP_P (insn)
+         && insn != skip_insn)
        {
          if (sched_verbose >= 2)
            fprintf (sched_dump, "requeued because ready full\n");
@@ -1585,17 +1579,20 @@ ok_for_early_queue_removal (rtx insn)
            {
              int cost;
 
+             if (prev_insn == current_sched_info->prev_head)
+               {
+                 prev_insn = NULL;
+                 break;
+               }
+
              if (!NOTE_P (prev_insn))
                {
-                 dep_link_t dep_link;
+                 dep_t dep;
 
-                 dep_link = (find_link_by_con_in_deps_list
-                             (INSN_FORW_DEPS (prev_insn), insn));
+                 dep = sd_find_dep_between (prev_insn, insn, true);
 
-                 if (dep_link)
+                 if (dep != NULL)
                    {
-                     dep_t dep = DEP_LINK_DEP (dep_link);
-
                      cost = dep_cost (dep);
 
                      if (targetm.sched.is_costly_dependence (dep, cost,
@@ -1839,7 +1836,7 @@ move_insn (rtx insn)
          gcc_assert (BB_END (bb) == last);
        }
 
-      set_block_for_insn (insn, bb);    
+      df_insn_change_bb (insn, bb);
   
       /* Update BB_END, if needed.  */
       if (BB_END (bb) == last)
@@ -1985,17 +1982,43 @@ max_issue (struct ready_list *ready, int *index, int max_points)
 
 /* The following function chooses insn from READY and modifies
    *N_READY and READY.  The following function is used only for first
-   cycle multipass scheduling.  */
-
-static rtx
-choose_ready (struct ready_list *ready)
+   cycle multipass scheduling.
+   Return:
+   -1 if cycle should be advanced,
+   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)
 {
-  int lookahead = 0;
+  int lookahead;
+
+  if (dbg_cnt (sched_insn) == false)
+    {
+      rtx insn;
+
+      insn = next_nonnote_insn (last_scheduled_insn);
+
+      if (QUEUE_INDEX (insn) == QUEUE_READY)
+       /* INSN is in the ready_list.  */
+       {
+         ready_remove_insn (insn);
+         *insn_ptr = insn;
+         return 0;
+       }
+
+      /* INSN is in the queue.  Advance cycle to move it to the ready list.  */
+      return -1;
+    }
+
+  lookahead = 0;
 
   if (targetm.sched.first_cycle_multipass_dfa_lookahead)
     lookahead = targetm.sched.first_cycle_multipass_dfa_lookahead ();
   if (lookahead <= 0 || SCHED_GROUP_P (ready_element (ready, 0)))
-    return ready_remove_first (ready);
+    {
+      *insn_ptr = ready_remove_first (ready);
+      return 0;
+    }
   else
     {
       /* Try to choose the better insn.  */
@@ -2012,7 +2035,10 @@ choose_ready (struct ready_list *ready)
        }
       insn = ready_element (ready, 0);
       if (INSN_CODE (insn) < 0)
-       return ready_remove_first (ready);
+       {
+         *insn_ptr = ready_remove_first (ready);
+         return 0;
+       }
 
       if (spec_info
          && spec_info->flags & (PREFER_NON_DATA_SPEC
@@ -2054,7 +2080,7 @@ choose_ready (struct ready_list *ready)
           list.  */
        {
          change_queue_index (insn, 1);
-         return 0;
+         return 1;
        }
 
       max_points = ISSUE_POINTS (insn);
@@ -2076,9 +2102,15 @@ choose_ready (struct ready_list *ready)
        }
 
       if (max_issue (ready, &index, max_points) == 0)
-       return ready_remove_first (ready);
+       {
+         *insn_ptr = ready_remove_first (ready);
+         return 0;
+       }
       else
-       return ready_remove (ready, index);
+       {
+         *insn_ptr = ready_remove (ready, index);
+         return 0;
+       }
     }
 }
 
@@ -2110,7 +2142,7 @@ schedule_block (basic_block *target_bb, int rgn_n_insns1)
 
   gcc_assert (head != tail || INSN_P (head));
 
-  added_recovery_block_p = false;
+  haifa_recovery_bb_recently_added_p = false;
 
   /* Debug info.  */
   if (sched_verbose)
@@ -2177,9 +2209,27 @@ schedule_block (basic_block *target_bb, int rgn_n_insns1)
                   ";;\t\t before reload => truncated to %d insns\n", i);
        }
 
-      /* Delay all insns past it for 1 cycle.  */
-      while (i < ready.n_ready)
-       queue_insn (ready_remove (&ready, i), 1);
+      /* Delay all insns past it for 1 cycle.  If debug counter is
+        activated make an exception for the insn right after
+        last_scheduled_insn.  */
+      {
+       rtx skip_insn;
+
+       if (dbg_cnt (sched_insn) == false)
+         skip_insn = next_nonnote_insn (last_scheduled_insn);
+       else
+         skip_insn = NULL_RTX;
+
+       while (i < ready.n_ready)
+         {
+           rtx insn;
+
+           insn = ready_remove (&ready, i);
+
+           if (insn != skip_insn)
+             queue_insn (insn, 1);
+         }
+      }
     }
 
   /* Now we can restore basic block notes and maintain precise cfg.  */
@@ -2279,9 +2329,19 @@ schedule_block (basic_block *target_bb, int rgn_n_insns1)
          /* Select and remove the insn from the ready list.  */
          if (sort_p)
            {
-             insn = choose_ready (&ready);
-             if (!insn)
+             int res;
+
+             insn = NULL_RTX;
+             res = choose_ready (&ready, &insn);
+
+             if (res < 0)
+               /* Finish cycle.  */
+               break;
+             if (res > 0)
+               /* Restart choose_ready ().  */
                continue;
+
+             gcc_assert (insn != NULL_RTX);
            }
          else
            insn = ready_remove_first (&ready);
@@ -2359,7 +2419,7 @@ schedule_block (basic_block *target_bb, int rgn_n_insns1)
             generate_recovery_code (insn);
 
          if (control_flow_insn_p (last_scheduled_insn)      
-             /* This is used to to switch basic blocks by request
+             /* 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
                 edge.  If succeeding block has jump, it [jump] will try
@@ -2473,7 +2533,7 @@ schedule_block (basic_block *target_bb, int rgn_n_insns1)
     }
 
   if (!current_sched_info->queue_must_finish_empty
-      || added_recovery_block_p)
+      || haifa_recovery_bb_recently_added_p)
     {
       /* INSN_TICK (minimum clock tick at which the insn becomes
          ready) may be not correct for the insn in the subsequent
@@ -2485,7 +2545,15 @@ schedule_block (basic_block *target_bb, int rgn_n_insns1)
     }
 
   if (targetm.sched.md_finish)
-    targetm.sched.md_finish (sched_dump, sched_verbose);
+    {
+      targetm.sched.md_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
+        get zero luids.*/
+      extend_h_i_d ();
+    }
 
   /* Update head/tail boundaries.  */
   head = NEXT_INSN (prev_head);
@@ -2612,9 +2680,6 @@ sched_init (void)
       else
        /* So we won't read anything accidentally.  */
        spec_info = 0;
-#ifdef ENABLE_CHECKING
-      check_sched_flags ();
-#endif
     }
   else
     /* So we won't read anything accidentally.  */
@@ -2680,13 +2745,8 @@ sched_init (void)
   init_alias_analysis ();
 
   old_last_basic_block = 0;
-  glat_start = 0;  
-  glat_end = 0;
   extend_bb ();
 
-  if (current_sched_info->flags & USE_GLAT)
-    init_glat ();
-
   /* Compute INSN_REG_WEIGHT for all blocks.  We must do this before
      removing death notes.  */
   FOR_EACH_BB_REVERSE (b)
@@ -2698,6 +2758,8 @@ sched_init (void)
   nr_begin_data = nr_begin_control = nr_be_in_data = nr_be_in_control = 0;
   before_recovery = 0;
 
+  haifa_recovery_bb_ever_added_p = false;
+
 #ifdef ENABLE_CHECKING
   /* This is used preferably for finding bugs in check_cfg () itself.  */
   check_cfg (0, 0);
@@ -2714,7 +2776,6 @@ sched_finish (void)
   dfa_finish ();
   free_dependency_caches ();
   end_alias_analysis ();
-  free_glat ();
 
   if (targetm.sched.md_finish_global)
     targetm.sched.md_finish_global (sched_dump, sched_verbose);
@@ -2757,6 +2818,10 @@ fix_inter_tick (rtx head, rtx tail)
 {
   /* Set of instructions with corrected INSN_TICK.  */
   bitmap_head processed;
+  /* ??? It is doubtful if we should assume that cycle advance happens on
+     basic block boundaries.  Basically insns that are unconditionally ready
+     on the start of the block are more preferable then those which have
+     a one cycle dependency over insn from the previous block.  */
   int next_clock = clock_var + 1;
 
   bitmap_initialize (&processed, 0);
@@ -2769,7 +2834,8 @@ fix_inter_tick (rtx head, rtx tail)
       if (INSN_P (head))
        {
          int tick;
-         dep_link_t link;
+         sd_iterator_def sd_it;
+         dep_t dep;
                   
          tick = INSN_TICK (head);
          gcc_assert (tick >= MIN_TICK);
@@ -2786,11 +2852,11 @@ fix_inter_tick (rtx head, rtx tail)
              INSN_TICK (head) = tick;           
            }
          
-         FOR_EACH_DEP_LINK (link, INSN_FORW_DEPS (head))
+         FOR_EACH_DEP (head, SD_LIST_RES_FORW, sd_it, dep)
            {
              rtx next;
              
-             next = DEP_LINK_CON (link);
+             next = DEP_CON (dep);
              tick = INSN_TICK (next);
 
              if (tick != INVALID_TICK
@@ -2809,7 +2875,7 @@ fix_inter_tick (rtx head, rtx tail)
                    INTER_TICK (next) = tick;
                  else
                    tick = INTER_TICK (next);
-                 
+
                  INSN_TICK (next) = tick;
                }
            }
@@ -2828,7 +2894,6 @@ int
 try_ready (rtx next)
 {  
   ds_t old_ts, *ts;
-  dep_link_t link;
 
   ts = &TODO_SPEC (next);
   old_ts = *ts;
@@ -2837,44 +2902,52 @@ try_ready (rtx next)
              && ((old_ts & HARD_DEP)
                  || (old_ts & SPECULATIVE)));
   
-  if (!(current_sched_info->flags & DO_SPECULATION))
+  if (sd_lists_empty_p (next, SD_LIST_BACK))
+    /* NEXT has all its dependencies resolved.  */
     {
-      if (deps_list_empty_p (INSN_BACK_DEPS (next)))
-        *ts &= ~HARD_DEP;
+      /* Remove HARD_DEP bit from NEXT's status.  */
+      *ts &= ~HARD_DEP;
+
+      if (current_sched_info->flags & DO_SPECULATION)
+       /* Remove all speculative bits from NEXT's status.  */
+       *ts &= ~SPECULATIVE;
     }
   else
     {
+      /* One of the NEXT's dependencies has been resolved.
+        Recalculate NEXT's status.  */
+
       *ts &= ~SPECULATIVE & ~HARD_DEP;
 
-      link = DEPS_LIST_FIRST (INSN_BACK_DEPS (next));
+      if (sd_lists_empty_p (next, SD_LIST_HARD_BACK))
+       /* Now we've got NEXT with speculative deps only.
+          1. Look at the deps to see what we have to do.
+          2. Check if we can do 'todo'.  */
+       {
+         sd_iterator_def sd_it;
+         dep_t dep;
+         bool first_p = true;
 
-      if (link != NULL)
-        {
-         ds_t ds = DEP_LINK_STATUS (link) & SPECULATIVE;
-
-          /* Backward dependencies of the insn are maintained sorted. 
-             So if DEP_STATUS of the first dep is SPECULATIVE,
-             than all other deps are speculative too.  */
-          if (ds != 0)
-            {          
-              /* Now we've got NEXT with speculative deps only.
-                 1. Look at the deps to see what we have to do.
-                 2. Check if we can do 'todo'.  */
-             *ts = ds;
-
-              while ((link = DEP_LINK_NEXT (link)) != NULL)
+         FOR_EACH_DEP (next, SD_LIST_BACK, sd_it, dep)
+           {
+             ds_t ds = DEP_STATUS (dep) & SPECULATIVE;
+
+             if (first_p)
                {
-                 ds = DEP_LINK_STATUS (link) & SPECULATIVE;
-                 *ts = ds_merge (*ts, ds);
-               }
+                 first_p = false;
 
-             if (dep_weak (*ts) < spec_info->weakness_cutoff)
-               /* Too few points.  */
-               *ts = (*ts & ~SPECULATIVE) | HARD_DEP;
+                 *ts = ds;
+               }
+             else
+               *ts = ds_merge (*ts, ds);
            }
-          else
-            *ts |= HARD_DEP;
-        }
+
+         if (dep_weak (*ts) < spec_info->weakness_cutoff)
+           /* Too few points.  */
+           *ts = (*ts & ~SPECULATIVE) | HARD_DEP;
+       }
+      else
+       *ts |= HARD_DEP;
     }
 
   if (*ts & HARD_DEP)
@@ -2993,10 +3066,11 @@ fix_tick_ready (rtx next)
 {
   int tick, delay;
 
-  if (!deps_list_empty_p (INSN_RESOLVED_BACK_DEPS (next)))
+  if (!sd_lists_empty_p (next, SD_LIST_RES_BACK))
     {
       int full_p;
-      dep_link_t link;
+      sd_iterator_def sd_it;
+      dep_t dep;
 
       tick = INSN_TICK (next);
       /* if tick is not equal to INVALID_TICK, then update
@@ -3004,9 +3078,8 @@ fix_tick_ready (rtx next)
         cost.  Otherwise, recalculate from scratch.  */
       full_p = (tick == INVALID_TICK);
 
-      FOR_EACH_DEP_LINK (link, INSN_RESOLVED_BACK_DEPS (next))
+      FOR_EACH_DEP (next, SD_LIST_RES_BACK, sd_it, dep)
         {       
-         dep_t dep = DEP_LINK_DEP (link);
           rtx pro = DEP_PRO (dep);
           int tick1;
               
@@ -3120,11 +3193,18 @@ static void
 extend_global (rtx insn)
 {
   gcc_assert (INSN_P (insn));
+
   /* These structures have scheduler scope.  */
+
+  /* Init h_i_d.  */
   extend_h_i_d ();
   init_h_i_d (insn);
 
-  extend_dependency_caches (1, 0);
+  /* Init data handled in sched-deps.c.  */
+  sd_init_insn (insn);
+
+  /* Extend dependency caches by one element.  */
+  extend_dependency_caches (1, false);
 }
 
 /* Extends global and local scheduler structures to include information
@@ -3152,14 +3232,6 @@ init_h_i_d (rtx insn)
   INSN_TICK (insn) = INVALID_TICK;
   INTER_TICK (insn) = INVALID_TICK;
   find_insn_reg_weight1 (insn);
-
-  /* These two lists will be freed in schedule_insn ().  */
-  INSN_BACK_DEPS (insn) = create_deps_list (false);
-  INSN_RESOLVED_BACK_DEPS (insn) = create_deps_list (false);
-
-  /* This one should be allocated on the obstack because it should live till
-     the scheduling ends.  */
-  INSN_FORW_DEPS (insn) = create_deps_list (true);
 }
 
 /* Generates recovery code for INSN.  */
@@ -3180,18 +3252,19 @@ generate_recovery_code (rtx insn)
    Tries to add speculative dependencies of type FS between instructions
    in deps_list L and TWIN.  */
 static void
-process_insn_forw_deps_be_in_spec (deps_list_t l, rtx twin, ds_t fs)
+process_insn_forw_deps_be_in_spec (rtx insn, rtx twin, ds_t fs)
 {
-  dep_link_t link;
+  sd_iterator_def sd_it;
+  dep_t dep;
 
-  FOR_EACH_DEP_LINK (link, l)
+  FOR_EACH_DEP (insn, SD_LIST_FORW, sd_it, dep)
     {
       ds_t ds;
       rtx consumer;
 
-      consumer = DEP_LINK_CON (link);
+      consumer = DEP_CON (dep);
 
-      ds = DEP_LINK_STATUS (link);
+      ds = DEP_STATUS (dep);
 
       if (/* If we want to create speculative dep.  */
          fs
@@ -3210,15 +3283,29 @@ process_insn_forw_deps_be_in_spec (deps_list_t l, rtx twin, ds_t fs)
                     due to backend decision.  Hence we can't let the
                     probability of the speculative dep to decrease.  */
                  dep_weak (ds) <= dep_weak (fs))
-               /* Transform it to be in speculative.  */
-               ds = (ds & ~BEGIN_SPEC) | 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))
+                   /* Transform it to be in speculative.  */
+                   ds = new_ds;
+               }
            }
          else
            /* Mark the dep as 'be in speculative'.  */
            ds |= fs;
        }
 
-      add_back_forw_dep (consumer, twin, DEP_LINK_KIND (link), ds);
+      {
+       dep_def _new_dep, *new_dep = &_new_dep;
+
+       init_dep_1 (new_dep, twin, consumer, DEP_TYPE (dep), ds);
+       sd_add_dep (new_dep, false);
+      }
     }
 }
 
@@ -3241,7 +3328,8 @@ static void
 add_to_speculative_block (rtx insn)
 {
   ds_t ts;
-  dep_link_t link;
+  sd_iterator_def sd_it;
+  dep_t dep;
   rtx twins = NULL;
   rtx_vec_t priorities_roots;
 
@@ -3259,50 +3347,52 @@ add_to_speculative_block (rtx insn)
   DONE_SPEC (insn) |= ts;
 
   /* First we convert all simple checks to branchy.  */
-  for (link = DEPS_LIST_FIRST (INSN_BACK_DEPS (insn)); link != NULL;)
+  for (sd_it = sd_iterator_start (insn, SD_LIST_SPEC_BACK);
+       sd_iterator_cond (&sd_it, &dep);)
     {
-      rtx check = DEP_LINK_PRO (link);
+      rtx check = DEP_PRO (dep);
 
       if (IS_SPECULATION_SIMPLE_CHECK_P (check))
        {
          create_check_block_twin (check, true);
 
          /* Restart search.  */
-         link = DEPS_LIST_FIRST (INSN_BACK_DEPS (insn));
+         sd_it = sd_iterator_start (insn, SD_LIST_SPEC_BACK);
        }
       else
        /* Continue search.  */
-       link = DEP_LINK_NEXT (link);
+       sd_iterator_next (&sd_it);
     }
 
   priorities_roots = NULL;
   clear_priorities (insn, &priorities_roots);
-  do
+
+  while (1)
     {
-      dep_link_t link;
       rtx check, twin;
       basic_block rec;
 
-      link = DEPS_LIST_FIRST (INSN_BACK_DEPS (insn));
+      /* Get the first backward dependency of INSN.  */
+      sd_it = sd_iterator_start (insn, SD_LIST_SPEC_BACK);
+      if (!sd_iterator_cond (&sd_it, &dep))
+       /* INSN has no backward dependencies left.  */
+       break;
 
-      gcc_assert ((DEP_LINK_STATUS (link) & BEGIN_SPEC) == 0
-                 && (DEP_LINK_STATUS (link) & BE_IN_SPEC) != 0
-                 && (DEP_LINK_STATUS (link) & DEP_TYPES) == DEP_TRUE);
+      gcc_assert ((DEP_STATUS (dep) & BEGIN_SPEC) == 0
+                 && (DEP_STATUS (dep) & BE_IN_SPEC) != 0
+                 && (DEP_STATUS (dep) & DEP_TYPES) == DEP_TRUE);
 
-      check = DEP_LINK_PRO (link);
+      check = DEP_PRO (dep);
 
       gcc_assert (!IS_SPECULATION_CHECK_P (check) && !ORIG_PAT (check)
                  && QUEUE_INDEX (check) == QUEUE_NOWHERE);
-      
+
       rec = BLOCK_FOR_INSN (check);
-      
-      twin = emit_insn_before (copy_rtx (PATTERN (insn)), BB_END (rec));
+
+      twin = emit_insn_before (copy_insn (PATTERN (insn)), BB_END (rec));
       extend_global (twin);
 
-      copy_deps_list_change_con (INSN_RESOLVED_BACK_DEPS (twin),
-                                INSN_RESOLVED_BACK_DEPS (insn),
-                                twin);
+      sd_copy_back_deps (twin, insn, true);
 
       if (sched_verbose && spec_info->dump)
         /* INSN_BB (insn) isn't determined for twin insns yet.
@@ -3314,47 +3404,38 @@ add_to_speculative_block (rtx insn)
 
       /* Add dependences between TWIN and all appropriate
         instructions from REC.  */
-      do
-       {         
-         add_back_forw_dep (twin, check, REG_DEP_TRUE, DEP_TRUE);
-         
-         do              
-           {  
-             link = DEP_LINK_NEXT (link);
+      FOR_EACH_DEP (insn, SD_LIST_SPEC_BACK, sd_it, dep)
+       {
+         rtx pro = DEP_PRO (dep);
 
-             if (link != NULL)
-               {
-                 check = DEP_LINK_PRO (link);
-                 if (BLOCK_FOR_INSN (check) == rec)
-                   break;
-               }
-             else
-               break;
+         gcc_assert (DEP_TYPE (dep) == REG_DEP_TRUE);
+
+         /* INSN might have dependencies from the instructions from
+            several recovery blocks.  At this iteration we process those
+            producers that reside in REC.  */
+         if (BLOCK_FOR_INSN (pro) == rec)
+           {
+             dep_def _new_dep, *new_dep = &_new_dep;
+
+             init_dep (new_dep, pro, twin, REG_DEP_TRUE);
+             sd_add_dep (new_dep, false);
            }
-         while (1);
        }
-      while (link != NULL);
 
-      process_insn_forw_deps_be_in_spec (INSN_FORW_DEPS (insn), twin, ts);
+      process_insn_forw_deps_be_in_spec (insn, twin, ts);
 
       /* Remove all dependencies between INSN and insns in REC.  */
-      for (link = DEPS_LIST_FIRST (INSN_BACK_DEPS (insn)); link != NULL;)
+      for (sd_it = sd_iterator_start (insn, SD_LIST_SPEC_BACK);
+          sd_iterator_cond (&sd_it, &dep);)
        {
-         check = DEP_LINK_PRO (link);
+         rtx pro = DEP_PRO (dep);
 
-         if (BLOCK_FOR_INSN (check) == rec)
-           {
-             delete_back_forw_dep (link);
-
-             /* Restart search.  */
-             link = DEPS_LIST_FIRST (INSN_BACK_DEPS (insn));
-           }
+         if (BLOCK_FOR_INSN (pro) == rec)
+           sd_delete_dep (sd_it);
          else
-           /* Continue search.  */
-           link = DEP_LINK_NEXT (link);
+           sd_iterator_next (&sd_it);
        }
     }
-  while (!deps_list_empty_p (INSN_BACK_DEPS (insn)));
 
   /* We couldn't have added the dependencies between INSN and TWINS earlier
      because that would make TWINS appear in the INSN_BACK_DEPS (INSN).  */
@@ -3363,7 +3444,13 @@ add_to_speculative_block (rtx insn)
       rtx twin;
 
       twin = XEXP (twins, 0);
-      add_back_forw_dep (twin, insn, REG_DEP_OUTPUT, DEP_OUTPUT);
+
+      {
+       dep_def _new_dep, *new_dep = &_new_dep;
+
+       init_dep (new_dep, insn, twin, REG_DEP_OUTPUT);
+       sd_add_dep (new_dep, false);
+      }
 
       twin = XEXP (twins, 1);
       free_INSN_LIST_node (twins);
@@ -3519,7 +3606,8 @@ create_recovery_block (void)
   rtx barrier;
   basic_block rec;
   
-  added_recovery_block_p = true;
+  haifa_recovery_bb_recently_added_p = true;
+  haifa_recovery_bb_ever_added_p = true;
 
   if (!before_recovery)
     init_before_recovery ();
@@ -3553,8 +3641,10 @@ create_check_block_twin (rtx insn, bool mutate_p)
 {
   basic_block rec;
   rtx label, check, twin;
-  dep_link_t link;
   ds_t fs;
+  sd_iterator_def sd_it;
+  dep_t dep;
+  dep_def _new_dep, *new_dep = &_new_dep;
 
   gcc_assert (ORIG_PAT (insn)
              && (!mutate_p 
@@ -3603,14 +3693,17 @@ create_check_block_twin (rtx insn, bool mutate_p)
      in the recovery block).  */
   if (rec != EXIT_BLOCK_PTR)
     {
-      FOR_EACH_DEP_LINK (link, INSN_RESOLVED_BACK_DEPS (insn))
-       if ((DEP_LINK_STATUS (link) & DEP_OUTPUT) != 0)
+      sd_iterator_def sd_it;
+      dep_t dep;
+
+      FOR_EACH_DEP (insn, SD_LIST_RES_BACK, sd_it, dep)
+       if ((DEP_STATUS (dep) & DEP_OUTPUT) != 0)
          {
-           struct _dep _dep, *dep = &_dep;
+           struct _dep _dep2, *dep2 = &_dep2;
 
-           init_dep (dep, DEP_LINK_PRO (link), check, REG_DEP_TRUE);
+           init_dep (dep2, DEP_PRO (dep), check, REG_DEP_TRUE);
 
-           add_back_dep_to_deps_list (INSN_RESOLVED_BACK_DEPS (check), dep);
+           sd_add_dep (dep2, true);
          }
 
       twin = emit_insn_after (ORIG_PAT (insn), BB_END (rec));
@@ -3631,9 +3724,9 @@ create_check_block_twin (rtx insn, bool mutate_p)
         (TRUE | OUTPUT).  */
     }
 
-  copy_deps_list_change_con (INSN_RESOLVED_BACK_DEPS (twin),
-                            INSN_RESOLVED_BACK_DEPS (insn),
-                            twin);
+  /* Copy all resolved back dependencies of INSN to TWIN.  This will
+     provide correct value for INSN_TICK (TWIN).  */
+  sd_copy_back_deps (twin, insn, true);
 
   if (rec != EXIT_BLOCK_PTR)
     /* In case of branchy check, fix CFG.  */
@@ -3696,10 +3789,11 @@ create_check_block_twin (rtx insn, bool mutate_p)
 
   /* Move backward dependences from INSN to CHECK and 
      move forward dependences from INSN to TWIN.  */
-  FOR_EACH_DEP_LINK (link, INSN_BACK_DEPS (insn))
+
+  /* First, create dependencies between INSN's producers and CHECK & TWIN.  */
+  FOR_EACH_DEP (insn, SD_LIST_BACK, sd_it, dep)
     {
-      rtx pro = DEP_LINK_PRO (link);
-      enum reg_note dk = DEP_LINK_KIND (link);
+      rtx pro = DEP_PRO (dep);
       ds_t ds;
 
       /* If BEGIN_DATA: [insn ~~TRUE~~> producer]:
@@ -3717,7 +3811,7 @@ create_check_block_twin (rtx insn, bool mutate_p)
         twin  ~~TRUE~~> producer
         twin  --ANTI--> check  */                
 
-      ds = DEP_LINK_STATUS (link);
+      ds = DEP_STATUS (dep);
 
       if (ds & BEGIN_SPEC)
        {
@@ -3725,30 +3819,30 @@ create_check_block_twin (rtx insn, bool mutate_p)
          ds &= ~BEGIN_SPEC;
        }
 
+      init_dep_1 (new_dep, pro, check, DEP_TYPE (dep), ds);
+      sd_add_dep (new_dep, false);
+
       if (rec != EXIT_BLOCK_PTR)
        {
-         add_back_forw_dep (check, pro, dk, ds);
-         add_back_forw_dep (twin, pro, dk, ds);
+         DEP_CON (new_dep) = twin;
+         sd_add_dep (new_dep, false);
        }    
-      else
-       add_back_forw_dep (check, pro, dk, ds);
     }
 
-  for (link = DEPS_LIST_FIRST (INSN_BACK_DEPS (insn)); link != NULL;)
-    if ((DEP_LINK_STATUS (link) & BEGIN_SPEC)
-       || mutate_p)
-      /* We can delete this dep only if we totally overcome it with
-        BEGIN_SPECULATION.  */
-      {
-        delete_back_forw_dep (link);
-
-       /* Restart search.  */
-        link = DEPS_LIST_FIRST (INSN_BACK_DEPS (insn));
-      }
-    else
-      /* Continue search.  */
-      link = DEP_LINK_NEXT (link);    
+  /* Second, remove backward dependencies of INSN.  */
+  for (sd_it = sd_iterator_start (insn, SD_LIST_SPEC_BACK);
+       sd_iterator_cond (&sd_it, &dep);)
+    {
+      if ((DEP_STATUS (dep) & BEGIN_SPEC)
+         || mutate_p)
+       /* We can delete this dep because we overcome it with
+          BEGIN_SPECULATION.  */
+       sd_delete_dep (sd_it);
+      else
+       sd_iterator_next (&sd_it);
+    }
 
+  /* Future Speculations.  Determine what BE_IN speculations will be like.  */
   fs = 0;
 
   /* Fields (DONE_SPEC (x) & BEGIN_SPEC) and CHECK_SPEC (x) are set only
@@ -3763,16 +3857,19 @@ create_check_block_twin (rtx insn, bool mutate_p)
       DONE_SPEC (insn) = ts & BEGIN_SPEC;
       CHECK_SPEC (check) = ts & BEGIN_SPEC;
 
+      /* Luckiness of future speculations solely depends upon initial
+        BEGIN speculation.  */
       if (ts & BEGIN_DATA)
        fs = set_dep_weak (fs, BE_IN_DATA, get_dep_weak (ts, BEGIN_DATA));
       if (ts & BEGIN_CONTROL)
-       fs = set_dep_weak (fs, BE_IN_CONTROL, get_dep_weak (ts, BEGIN_CONTROL));
+       fs = set_dep_weak (fs, BE_IN_CONTROL,
+                          get_dep_weak (ts, BEGIN_CONTROL));
     }
   else
     CHECK_SPEC (check) = CHECK_SPEC (insn);
 
   /* Future speculations: call the helper.  */
-  process_insn_forw_deps_be_in_spec (INSN_FORW_DEPS (insn), twin, fs);
+  process_insn_forw_deps_be_in_spec (insn, twin, fs);
 
   if (rec != EXIT_BLOCK_PTR)
     {
@@ -3782,35 +3879,45 @@ create_check_block_twin (rtx insn, bool mutate_p)
 
       if (!mutate_p)
        {
-         add_back_forw_dep (check, insn, REG_DEP_TRUE, DEP_TRUE);
-         add_back_forw_dep (twin, insn, REG_DEP_OUTPUT, DEP_OUTPUT);
+         init_dep (new_dep, insn, check, REG_DEP_TRUE);
+         sd_add_dep (new_dep, false);
+
+         init_dep (new_dep, insn, twin, REG_DEP_OUTPUT);
+         sd_add_dep (new_dep, false);
        }
       else
        {
-         dep_link_t link;
-
          if (spec_info->dump)    
            fprintf (spec_info->dump, ";;\t\tRemoved simple check : %s\n",
                     (*current_sched_info->print_insn) (insn, 0));
 
-         /* Remove all forward dependencies of the INSN.  */
-         link = DEPS_LIST_FIRST (INSN_FORW_DEPS (insn));
-         while (link != NULL)
-           {
-             delete_back_forw_dep (link);
-             link = DEPS_LIST_FIRST (INSN_FORW_DEPS (insn));
-           }
+         /* Remove all dependencies of the INSN.  */
+         {
+           sd_it = sd_iterator_start (insn, (SD_LIST_FORW
+                                             | SD_LIST_BACK
+                                             | SD_LIST_RES_BACK));
+           while (sd_iterator_cond (&sd_it, &dep))
+             sd_delete_dep (sd_it);
+         }
 
+         /* If former check (INSN) already was moved to the ready (or queue)
+            list, add new check (CHECK) there too.  */
          if (QUEUE_INDEX (insn) != QUEUE_NOWHERE)
            try_ready (check);
 
+         /* Remove old check from instruction stream and free its
+            data.  */
          sched_remove_insn (insn);
        }
 
-      add_back_forw_dep (twin, check, REG_DEP_ANTI, DEP_ANTI);
+      init_dep (new_dep, check, twin, REG_DEP_ANTI);
+      sd_add_dep (new_dep, false);
     }
   else
-    add_back_forw_dep (check, insn, REG_DEP_TRUE, DEP_TRUE | DEP_OUTPUT);
+    {
+      init_dep_1 (new_dep, insn, check, REG_DEP_TRUE, DEP_TRUE | DEP_OUTPUT);
+      sd_add_dep (new_dep, false);
+    }
 
   if (!mutate_p)
     /* Fix priorities.  If MUTATE_P is nonzero, this is not necessary,
@@ -3830,10 +3937,9 @@ create_check_block_twin (rtx insn, bool mutate_p)
 static void
 fix_recovery_deps (basic_block rec)
 {
-  dep_link_t link;
   rtx note, insn, jump, ready_list = 0;
   bitmap_head in_ready;
-  rtx link1;
+  rtx link;
 
   bitmap_initialize (&in_ready, 0);
   
@@ -3845,32 +3951,30 @@ fix_recovery_deps (basic_block rec)
   insn = PREV_INSN (insn);
 
   do
-    {    
-      for (link = DEPS_LIST_FIRST (INSN_FORW_DEPS (insn)); link != NULL;)
-       {
-         rtx consumer;
+    {
+      sd_iterator_def sd_it;
+      dep_t dep;
 
-         consumer = DEP_LINK_CON (link);
+      for (sd_it = sd_iterator_start (insn, SD_LIST_FORW);
+          sd_iterator_cond (&sd_it, &dep);)
+       {
+         rtx consumer = DEP_CON (dep);
 
          if (BLOCK_FOR_INSN (consumer) != rec)
            {
-             delete_back_forw_dep (link);
+             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));
                }
-
-             /* Restart search.  */
-             link = DEPS_LIST_FIRST (INSN_FORW_DEPS (insn));
            }
          else
            {
-             gcc_assert ((DEP_LINK_STATUS (link) & DEP_TYPES) == DEP_TRUE);
+             gcc_assert ((DEP_STATUS (dep) & DEP_TYPES) == DEP_TRUE);
 
-             /* Continue search.  */
-             link = DEP_LINK_NEXT (link);
+             sd_iterator_next (&sd_it);
            }
        }
       
@@ -3881,8 +3985,8 @@ fix_recovery_deps (basic_block rec)
   bitmap_clear (&in_ready);
 
   /* Try to add instructions to the ready or queue list.  */
-  for (link1 = ready_list; link1; link1 = XEXP (link1, 1))
-    try_ready (XEXP (link1, 0));
+  for (link = ready_list; link; link = XEXP (link, 1))
+    try_ready (XEXP (link, 0));
   free_INSN_LIST_list (&ready_list);
 
   /* Fixing jump's dependences.  */
@@ -3911,6 +4015,31 @@ change_pattern (rtx insn, rtx new_pat)
   dfa_clear_single_insn_cache (insn);
 }
 
+/* Return true if INSN can potentially be speculated with type DS.  */
+bool
+sched_insn_is_legitimate_for_speculation_p (const_rtx insn, ds_t ds)
+{
+  if (HAS_INTERNAL_DEP (insn))
+    return false;
+
+  if (!NONJUMP_INSN_P (insn))
+    return false;
+
+  if (SCHED_GROUP_P (insn))
+    return false;
+
+  if (IS_SPECULATION_CHECK_P (insn))
+    return false;
+
+  if (side_effects_p (PATTERN (insn)))
+    return false;
+
+  if ((ds & BE_IN_SPEC)
+      && may_trap_p (PATTERN (insn)))
+    return false;
+
+  return true;
+}
 
 /* -1 - can't speculate,
    0 - for speculation with REQUEST mode it is OK to use
@@ -3920,25 +4049,15 @@ static int
 speculate_insn (rtx insn, ds_t request, rtx *new_pat)
 {
   gcc_assert (current_sched_info->flags & DO_SPECULATION
-              && (request & SPECULATIVE));
+              && (request & SPECULATIVE)
+             && sched_insn_is_legitimate_for_speculation_p (insn, request));
 
-  if (!NONJUMP_INSN_P (insn)
-      || HAS_INTERNAL_DEP (insn)
-      || SCHED_GROUP_P (insn)
-      || side_effects_p (PATTERN (insn))
-      || (request & spec_info->mask) != request)    
+  if ((request & spec_info->mask) != request)
     return -1;
-  
-  gcc_assert (!IS_SPECULATION_CHECK_P (insn));
 
-  if (request & BE_IN_SPEC)
-    {            
-      if (may_trap_p (PATTERN (insn)))
-        return -1;
-      
-      if (!(request & BEGIN_SPEC))
-        return 0;
-    }
+  if (request & BE_IN_SPEC
+      && !(request & BEGIN_SPEC))
+    return 0;
 
   return targetm.sched.speculate_insn (insn, request & BEGIN_SPEC, new_pat);
 }
@@ -4064,13 +4183,6 @@ extend_bb (void)
 
   old_last_basic_block = last_basic_block;
 
-  if (current_sched_info->flags & USE_GLAT)
-    {
-      glat_start = xrealloc (glat_start,
-                             last_basic_block * sizeof (*glat_start));
-      glat_end = xrealloc (glat_end, last_basic_block * sizeof (*glat_end));
-    }
-
   /* The following is done to keep current_sched_info->next_tail non null.  */
 
   insn = BB_END (EXIT_BLOCK_PTR->prev_bb);
@@ -4080,8 +4192,9 @@ extend_bb (void)
          /* Don't emit a NOTE if it would end up before a BARRIER.  */
          && !BARRIER_P (NEXT_INSN (insn))))
     {
-      emit_note_after (NOTE_INSN_DELETED, insn);
-      /* Make insn to appear outside BB.  */
+      rtx note = emit_note_after (NOTE_INSN_DELETED, insn);
+      /* Make insn appear outside BB.  */
+      set_block_for_insn (note, NULL);
       BB_END (EXIT_BLOCK_PTR->prev_bb) = insn;
     }
 }
@@ -4092,15 +4205,10 @@ extend_bb (void)
 void
 add_block (basic_block bb, basic_block ebb)
 {
-  gcc_assert (current_sched_info->flags & DETACH_LIFE_INFO
-             && bb->il.rtl->global_live_at_start == 0
-             && bb->il.rtl->global_live_at_end == 0);
+  gcc_assert (current_sched_info->flags & NEW_BBS);
 
   extend_bb ();
 
-  glat_start[bb->index] = 0;
-  glat_end[bb->index] = 0;
-
   if (current_sched_info->add_block)
     /* This changes only data structures of the front-end.  */
     current_sched_info->add_block (bb, ebb);
@@ -4163,6 +4271,8 @@ move_block_after_check (rtx jump)
   move_succs (&(jump_bb->succs), bb);
   move_succs (&(jump_bb_next->succs), jump_bb);
   move_succs (&t, jump_bb_next);
+
+  df_mark_solutions_dirty ();
   
   if (current_sched_info->fix_recovery_cfg)
     current_sched_info->fix_recovery_cfg 
@@ -4188,120 +4298,13 @@ move_succs (VEC(edge,gc) **succsp, basic_block to)
   *succsp = 0;
 }
 
-/* Initialize GLAT (global_live_at_{start, end}) structures.
-   GLAT structures are used to substitute global_live_{start, end}
-   regsets during scheduling.  This is necessary to use such functions as
-   split_block (), as they assume consistency of register live information.  */
-static void
-init_glat (void)
-{
-  basic_block bb;
-
-  FOR_ALL_BB (bb)
-    init_glat1 (bb);
-}
-
-/* Helper function for init_glat.  */
-static void
-init_glat1 (basic_block bb)
-{
-  gcc_assert (bb->il.rtl->global_live_at_start != 0
-             && bb->il.rtl->global_live_at_end != 0);
-
-  glat_start[bb->index] = bb->il.rtl->global_live_at_start;
-  glat_end[bb->index] = bb->il.rtl->global_live_at_end;
-  
-  if (current_sched_info->flags & DETACH_LIFE_INFO)
-    {
-      bb->il.rtl->global_live_at_start = 0;
-      bb->il.rtl->global_live_at_end = 0;
-    }
-}
-
-/* Attach reg_live_info back to basic blocks.
-   Also save regsets, that should not have been changed during scheduling,
-   for checking purposes (see check_reg_live).  */
-void
-attach_life_info (void)
-{
-  basic_block bb;
-
-  FOR_ALL_BB (bb)
-    attach_life_info1 (bb);
-}
-
-/* Helper function for attach_life_info.  */
-static void
-attach_life_info1 (basic_block bb)
-{
-  gcc_assert (bb->il.rtl->global_live_at_start == 0
-             && bb->il.rtl->global_live_at_end == 0);
-
-  if (glat_start[bb->index])
-    {
-      gcc_assert (glat_end[bb->index]);    
-
-      bb->il.rtl->global_live_at_start = glat_start[bb->index];
-      bb->il.rtl->global_live_at_end = glat_end[bb->index];
-
-      /* Make them NULL, so they won't be freed in free_glat.  */
-      glat_start[bb->index] = 0;
-      glat_end[bb->index] = 0;
-
-#ifdef ENABLE_CHECKING
-      if (bb->index < NUM_FIXED_BLOCKS
-         || current_sched_info->region_head_or_leaf_p (bb, 0))
-       {
-         glat_start[bb->index] = ALLOC_REG_SET (&reg_obstack);
-         COPY_REG_SET (glat_start[bb->index],
-                       bb->il.rtl->global_live_at_start);
-       }
-
-      if (bb->index < NUM_FIXED_BLOCKS
-         || current_sched_info->region_head_or_leaf_p (bb, 1))
-       {       
-         glat_end[bb->index] = ALLOC_REG_SET (&reg_obstack);
-         COPY_REG_SET (glat_end[bb->index], bb->il.rtl->global_live_at_end);
-       }
-#endif
-    }
-  else
-    {
-      gcc_assert (!glat_end[bb->index]);
-
-      bb->il.rtl->global_live_at_start = ALLOC_REG_SET (&reg_obstack);
-      bb->il.rtl->global_live_at_end = ALLOC_REG_SET (&reg_obstack);
-    }
-}
-
-/* Free GLAT information.  */
-static void
-free_glat (void)
-{
-#ifdef ENABLE_CHECKING
-  if (current_sched_info->flags & DETACH_LIFE_INFO)
-    {
-      basic_block bb;
-
-      FOR_ALL_BB (bb)
-       {
-         if (glat_start[bb->index])
-           FREE_REG_SET (glat_start[bb->index]);
-         if (glat_end[bb->index])
-           FREE_REG_SET (glat_end[bb->index]);
-       }
-    }
-#endif
-
-  free (glat_start);
-  free (glat_end);
-}
-
 /* Remove INSN from the instruction stream.
    INSN should have any dependencies.  */
 static void
 sched_remove_insn (rtx insn)
 {
+  sd_finish_insn (insn);
+
   change_queue_index (insn, QUEUE_NOWHERE);
   current_sched_info->add_remove_insn (insn, 1);
   remove_insn (insn);
@@ -4313,14 +4316,14 @@ sched_remove_insn (rtx insn)
 static void
 clear_priorities (rtx insn, rtx_vec_t *roots_ptr)
 {
-  dep_link_t link;
+  sd_iterator_def sd_it;
+  dep_t dep;
   bool insn_is_root_p = true;
 
   gcc_assert (QUEUE_INDEX (insn) != QUEUE_SCHEDULED);
 
-  FOR_EACH_DEP_LINK (link, INSN_BACK_DEPS (insn))
+  FOR_EACH_DEP (insn, SD_LIST_BACK, sd_it, dep)
     {
-      dep_t dep = DEP_LINK_DEP (link);
       rtx pro = DEP_PRO (dep);
 
       if (INSN_PRIORITY_STATUS (pro) >= 0
@@ -4365,12 +4368,17 @@ add_jump_dependencies (rtx insn, rtx jump)
       if (insn == jump)
        break;
       
-      if (deps_list_empty_p (INSN_FORW_DEPS (insn)))
-       add_back_forw_dep (jump, insn, REG_DEP_ANTI, DEP_ANTI);
+      if (sd_lists_empty_p (insn, SD_LIST_FORW))
+       {
+         dep_def _new_dep, *new_dep = &_new_dep;
+
+         init_dep (new_dep, insn, jump, REG_DEP_ANTI);
+         sd_add_dep (new_dep, false);
+       }
     }
   while (1);
 
-  gcc_assert (!deps_list_empty_p (INSN_BACK_DEPS (jump)));
+  gcc_assert (!sd_lists_empty_p (jump, SD_LIST_BACK));
 }
 
 /* Return the NOTE_INSN_BASIC_BLOCK of BB.  */
@@ -4388,36 +4396,6 @@ bb_note (basic_block bb)
 }
 
 #ifdef ENABLE_CHECKING
-extern void debug_spec_status (ds_t);
-
-/* Dump information about the dependence status S.  */
-void
-debug_spec_status (ds_t s)
-{
-  FILE *f = stderr;
-
-  if (s & BEGIN_DATA)
-    fprintf (f, "BEGIN_DATA: %d; ", get_dep_weak (s, BEGIN_DATA));
-  if (s & BE_IN_DATA)
-    fprintf (f, "BE_IN_DATA: %d; ", get_dep_weak (s, BE_IN_DATA));
-  if (s & BEGIN_CONTROL)
-    fprintf (f, "BEGIN_CONTROL: %d; ", get_dep_weak (s, BEGIN_CONTROL));
-  if (s & BE_IN_CONTROL)
-    fprintf (f, "BE_IN_CONTROL: %d; ", get_dep_weak (s, BE_IN_CONTROL));
-
-  if (s & HARD_DEP)
-    fprintf (f, "HARD_DEP; ");
-
-  if (s & DEP_TRUE)
-    fprintf (f, "DEP_TRUE; ");
-  if (s & DEP_ANTI)
-    fprintf (f, "DEP_ANTI; ");
-  if (s & DEP_OUTPUT)
-    fprintf (f, "DEP_OUTPUT; ");
-
-  fprintf (f, "\n");
-}
-
 /* Helper function for check_cfg.
    Return nonzero, if edge vector pointed to by EL has edge with TYPE in
    its flags.  */
@@ -4524,66 +4502,6 @@ check_cfg (rtx head, rtx tail)
 
   gcc_assert (bb == 0);
 }
-
-/* Perform a few consistency checks of flags in different data structures.  */
-static void
-check_sched_flags (void)
-{
-  unsigned int f = current_sched_info->flags;
-
-  if (flag_sched_stalled_insns)
-    gcc_assert (!(f & DO_SPECULATION));
-  if (f & DO_SPECULATION)
-    gcc_assert (!flag_sched_stalled_insns
-               && (f & DETACH_LIFE_INFO)
-               && spec_info
-               && spec_info->mask);
-  if (f & DETACH_LIFE_INFO)
-    gcc_assert (f & USE_GLAT);
-}
-
-/* Check global_live_at_{start, end} regsets.
-   If FATAL_P is TRUE, then abort execution at the first failure.
-   Otherwise, print diagnostics to STDERR (this mode is for calling
-   from debugger).  */
-void
-check_reg_live (bool fatal_p)
-{
-  basic_block bb;
-
-  FOR_ALL_BB (bb)
-    {
-      int i;
-
-      i = bb->index;
-
-      if (glat_start[i])
-       {
-         bool b = bitmap_equal_p (bb->il.rtl->global_live_at_start,
-                                  glat_start[i]);
-
-         if (!b)
-           {
-             gcc_assert (!fatal_p);
-
-             fprintf (stderr, ";; check_reg_live_at_start (%d) failed.\n", i);
-           }
-       }
-
-      if (glat_end[i])
-       {
-         bool b = bitmap_equal_p (bb->il.rtl->global_live_at_end,
-                                  glat_end[i]);
-
-         if (!b)
-           {
-             gcc_assert (!fatal_p);
-
-             fprintf (stderr, ";; check_reg_live_at_end (%d) failed.\n", i);
-           }
-       }
-    }
-}
 #endif /* ENABLE_CHECKING */
 
 #endif /* INSN_SCHEDULING */