IA MCU psABI support: changes to libraries
[gcc.git] / gcc / sched-deps.c
index 09523e78749e9aa31d104b6ac9a685a7fe8485b0..b62dc00a583a5fe83708d28f0ee00337f7643e9f 100644 (file)
@@ -1,9 +1,6 @@
 /* Instruction scheduling pass.  This file computes dependencies between
    instructions.
-   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-   2011
-   Free Software Foundation, Inc.
+   Copyright (C) 1992-2015 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
    and currently maintained by, Jim Wilson (wilson@cygnus.com)
 
@@ -29,6 +26,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "tm.h"
 #include "diagnostic-core.h"
 #include "rtl.h"
+#include "alias.h"
+#include "symtab.h"
+#include "tree.h"              /* FIXME: Used by call_may_noreturn_p.  */
 #include "tm_p.h"
 #include "hard-reg-set.h"
 #include "regs.h"
@@ -38,8 +38,15 @@ along with GCC; see the file COPYING3.  If not see
 #include "insn-attr.h"
 #include "except.h"
 #include "recog.h"
+#include "emit-rtl.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfgbuild.h"
+#include "predict.h"
+#include "basic-block.h"
 #include "sched-int.h"
 #include "params.h"
+#include "alloc-pool.h"
 #include "cselib.h"
 #include "ira.h"
 #include "target.h"
@@ -52,17 +59,12 @@ along with GCC; see the file COPYING3.  If not see
 #define CHECK (false)
 #endif
 
-/* In deps->last_pending_memory_flush marks JUMP_INSNs that weren't
-   added to the list because of flush_pending_lists, stands just
-   for itself and not for any other pending memory reads/writes.  */
-#define NON_FLUSH_JUMP_KIND REG_DEP_ANTI
-#define NON_FLUSH_JUMP_P(x) (REG_NOTE_KIND (x) == NON_FLUSH_JUMP_KIND)
-
 /* Holds current parameters for the dependency analyzer.  */
 struct sched_deps_info_def *sched_deps_info;
 
 /* The data is specific to the Haifa scheduler.  */
-VEC(haifa_deps_insn_data_def, heap) *h_d_i_d = NULL;
+vec<haifa_deps_insn_data_def>
+    h_d_i_d = vNULL;
 
 /* Return the major type present in the DS.  */
 enum reg_note
@@ -74,6 +76,9 @@ ds_to_dk (ds_t ds)
   if (ds & DEP_OUTPUT)
     return REG_DEP_OUTPUT;
 
+  if (ds & DEP_CONTROL)
+    return REG_DEP_CONTROL;
+
   gcc_assert (ds & DEP_ANTI);
 
   return REG_DEP_ANTI;
@@ -91,6 +96,9 @@ dk_to_ds (enum reg_note dk)
     case REG_DEP_OUTPUT:
       return DEP_OUTPUT;
 
+    case REG_DEP_CONTROL:
+      return DEP_CONTROL;
+
     default:
       gcc_assert (dk == REG_DEP_ANTI);
       return DEP_ANTI;
@@ -101,20 +109,23 @@ dk_to_ds (enum reg_note dk)
 
 /* Init DEP with the arguments.  */
 void
-init_dep_1 (dep_t dep, rtx pro, rtx con, enum reg_note type, ds_t ds)
+init_dep_1 (dep_t dep, rtx_insn *pro, rtx_insn *con, enum reg_note type, ds_t ds)
 {
   DEP_PRO (dep) = pro;
   DEP_CON (dep) = con;
   DEP_TYPE (dep) = type;
   DEP_STATUS (dep) = ds;
   DEP_COST (dep) = UNKNOWN_DEP_COST;
+  DEP_NONREG (dep) = 0;
+  DEP_MULTIPLE (dep) = 0;
+  DEP_REPLACE (dep) = NULL;
 }
 
 /* Init DEP with the arguments.
    While most of the scheduler (including targets) only need the major type
    of the dependency, it is convenient to hide full dep_status from them.  */
 void
-init_dep (dep_t dep, rtx pro, rtx con, enum reg_note kind)
+init_dep (dep_t dep, rtx_insn *pro, rtx_insn *con, enum reg_note kind)
 {
   ds_t ds;
 
@@ -187,6 +198,10 @@ dump_dep (FILE *dump, dep_t dep, int flags)
          t = 'o';
          break;
 
+       case REG_DEP_CONTROL:
+         t = 'c';
+         break;
+
        case REG_DEP_ANTI:
          t = 'a';
          break;
@@ -312,7 +327,7 @@ dep_link_is_detached_p (dep_link_t link)
 }
 
 /* Pool to hold all dependency nodes (dep_node_t).  */
-static alloc_pool dn_pool;
+static pool_allocator<_dep_node> *dn_pool;
 
 /* Number of dep_nodes out there.  */
 static int dn_pool_diff = 0;
@@ -321,7 +336,7 @@ static int dn_pool_diff = 0;
 static dep_node_t
 create_dep_node (void)
 {
-  dep_node_t n = (dep_node_t) pool_alloc (dn_pool);
+  dep_node_t n = dn_pool->allocate ();
   dep_link_t back = DEP_NODE_BACK (n);
   dep_link_t forw = DEP_NODE_FORW (n);
 
@@ -345,13 +360,15 @@ delete_dep_node (dep_node_t n)
   gcc_assert (dep_link_is_detached_p (DEP_NODE_BACK (n))
              && dep_link_is_detached_p (DEP_NODE_FORW (n)));
 
+  XDELETE (DEP_REPLACE (DEP_NODE_DEP (n)));
+
   --dn_pool_diff;
 
-  pool_free (dn_pool, n);
+  dn_pool->remove (n);
 }
 
 /* Pool to hold dependencies lists (deps_list_t).  */
-static alloc_pool dl_pool;
+static pool_allocator<_deps_list> *dl_pool;
 
 /* Number of deps_lists out there.  */
 static int dl_pool_diff = 0;
@@ -369,7 +386,7 @@ deps_list_empty_p (deps_list_t l)
 static deps_list_t
 create_deps_list (void)
 {
-  deps_list_t l = (deps_list_t) pool_alloc (dl_pool);
+  deps_list_t l = dl_pool->allocate ();
 
   DEPS_LIST_FIRST (l) = NULL;
   DEPS_LIST_N_LINKS (l) = 0;
@@ -386,7 +403,7 @@ free_deps_list (deps_list_t l)
 
   --dl_pool_diff;
 
-  pool_free (dl_pool, l);
+  dl_pool->remove (l);
 }
 
 /* Return true if there is no dep_nodes and deps_lists out there.
@@ -420,13 +437,24 @@ static bool
 dep_spec_p (dep_t dep)
 {
   if (current_sched_info->flags & DO_SPECULATION)
-    return (DEP_STATUS (dep) & SPECULATIVE) != 0;
+    {
+      if (DEP_STATUS (dep) & SPECULATIVE)
+       return true;
+    }
+  if (current_sched_info->flags & DO_PREDICATION)
+    {
+      if (DEP_TYPE (dep) == REG_DEP_CONTROL)
+       return true;
+    }
+  if (DEP_REPLACE (dep) != NULL)
+    return true;
   return false;
 }
 
 static regset reg_pending_sets;
 static regset reg_pending_clobbers;
 static regset reg_pending_uses;
+static regset reg_pending_control_uses;
 static enum reg_pending_barrier_mode reg_pending_barrier;
 
 /* Hard registers implicitly clobbered or used (or may be implicitly
@@ -454,22 +482,29 @@ static HARD_REG_SET implicit_reg_pending_uses;
 static bitmap_head *true_dependency_cache = NULL;
 static bitmap_head *output_dependency_cache = NULL;
 static bitmap_head *anti_dependency_cache = NULL;
+static bitmap_head *control_dependency_cache = NULL;
 static bitmap_head *spec_dependency_cache = NULL;
 static int cache_size;
 
+/* True if we should mark added dependencies as a non-register deps.  */
+static bool mark_as_hard;
+
 static int deps_may_trap_p (const_rtx);
-static void add_dependence_list (rtx, rtx, int, enum reg_note);
-static void add_dependence_list_and_free (struct deps_desc *, rtx,
-                                         rtx *, int, enum reg_note);
-static void delete_all_dependences (rtx);
-static void fixup_sched_groups (rtx);
-
-static void flush_pending_lists (struct deps_desc *, rtx, int, int);
-static void sched_analyze_1 (struct deps_desc *, rtx, rtx);
-static void sched_analyze_2 (struct deps_desc *, rtx, rtx);
-static void sched_analyze_insn (struct deps_desc *, rtx, rtx);
-
-static bool sched_has_condition_p (const_rtx);
+static void add_dependence_1 (rtx_insn *, rtx_insn *, enum reg_note);
+static void add_dependence_list (rtx_insn *, rtx_insn_list *, int,
+                                enum reg_note, bool);
+static void add_dependence_list_and_free (struct deps_desc *, rtx_insn *,
+                                         rtx_insn_list **, int, enum reg_note,
+                                         bool);
+static void delete_all_dependences (rtx_insn *);
+static void chain_to_prev_insn (rtx_insn *);
+
+static void flush_pending_lists (struct deps_desc *, rtx_insn *, int, int);
+static void sched_analyze_1 (struct deps_desc *, rtx, rtx_insn *);
+static void sched_analyze_2 (struct deps_desc *, rtx, rtx_insn *);
+static void sched_analyze_insn (struct deps_desc *, rtx, rtx_insn *);
+
+static bool sched_has_condition_p (const rtx_insn *);
 static int conditions_mutex_p (const_rtx, const_rtx, bool, bool);
 
 static enum DEPS_ADJUST_RESULT maybe_add_or_update_dep_1 (dep_t, bool,
@@ -499,38 +534,18 @@ deps_may_trap_p (const_rtx mem)
 
 /* Find the condition under which INSN is executed.  If REV is not NULL,
    it is set to TRUE when the returned comparison should be reversed
-   to get the actual condition.
-   We only do actual work the first time we come here for an insn; the
-   results are cached in INSN_COND and INSN_REVERSE_COND.  */
+   to get the actual condition.  */
 static rtx
-sched_get_condition_with_rev (const_rtx insn, bool *rev)
+sched_get_condition_with_rev_uncached (const rtx_insn *insn, bool *rev)
 {
   rtx pat = PATTERN (insn);
   rtx src;
 
-  if (INSN_COND (insn) == const_true_rtx)
-    return NULL_RTX;
-
-  if (INSN_COND (insn) != NULL_RTX)
-    {
-      if (rev)
-       *rev = INSN_REVERSE_COND (insn);
-      return INSN_COND (insn);
-    }
-
-  INSN_COND (insn) = const_true_rtx;
-  INSN_REVERSE_COND (insn) = false;
-  if (pat == 0)
-    return 0;
-
   if (rev)
     *rev = false;
 
   if (GET_CODE (pat) == COND_EXEC)
-    {
-      INSN_COND (insn) = COND_EXEC_TEST (pat);
-      return COND_EXEC_TEST (pat);
-    }
+    return COND_EXEC_TEST (pat);
 
   if (!any_condjump_p (insn) || !onlyjump_p (insn))
     return 0;
@@ -538,10 +553,7 @@ sched_get_condition_with_rev (const_rtx insn, bool *rev)
   src = SET_SRC (pc_set (insn));
 
   if (XEXP (src, 2) == pc_rtx)
-    {
-      INSN_COND (insn) = XEXP (src, 0);
-      return XEXP (src, 0);
-    }
+    return XEXP (src, 0);
   else if (XEXP (src, 1) == pc_rtx)
     {
       rtx cond = XEXP (src, 0);
@@ -552,17 +564,71 @@ sched_get_condition_with_rev (const_rtx insn, bool *rev)
 
       if (rev)
        *rev = true;
-      INSN_COND (insn) = cond;
-      INSN_REVERSE_COND (insn) = true;
       return cond;
     }
 
   return 0;
 }
 
+/* Return the condition under which INSN does not execute (i.e.  the
+   not-taken condition for a conditional branch), or NULL if we cannot
+   find such a condition.  The caller should make a copy of the condition
+   before using it.  */
+rtx
+sched_get_reverse_condition_uncached (const rtx_insn *insn)
+{
+  bool rev;
+  rtx cond = sched_get_condition_with_rev_uncached (insn, &rev);
+  if (cond == NULL_RTX)
+    return cond;
+  if (!rev)
+    {
+      enum rtx_code revcode = reversed_comparison_code (cond, insn);
+      cond = gen_rtx_fmt_ee (revcode, GET_MODE (cond),
+                            XEXP (cond, 0),
+                            XEXP (cond, 1));
+    }
+  return cond;
+}
+
+/* Caching variant of sched_get_condition_with_rev_uncached.
+   We only do actual work the first time we come here for an insn; the
+   results are cached in INSN_CACHED_COND and INSN_REVERSE_COND.  */
+static rtx
+sched_get_condition_with_rev (const rtx_insn *insn, bool *rev)
+{
+  bool tmp;
+
+  if (INSN_LUID (insn) == 0)
+    return sched_get_condition_with_rev_uncached (insn, rev);
+
+  if (INSN_CACHED_COND (insn) == const_true_rtx)
+    return NULL_RTX;
+
+  if (INSN_CACHED_COND (insn) != NULL_RTX)
+    {
+      if (rev)
+       *rev = INSN_REVERSE_COND (insn);
+      return INSN_CACHED_COND (insn);
+    }
+
+  INSN_CACHED_COND (insn) = sched_get_condition_with_rev_uncached (insn, &tmp);
+  INSN_REVERSE_COND (insn) = tmp;
+
+  if (INSN_CACHED_COND (insn) == NULL_RTX)
+    {
+      INSN_CACHED_COND (insn) = const_true_rtx;
+      return NULL_RTX;
+    }
+
+  if (rev)
+    *rev = INSN_REVERSE_COND (insn);
+  return INSN_CACHED_COND (insn);
+}
+
 /* True when we can find a condition under which INSN is executed.  */
 static bool
-sched_has_condition_p (const_rtx insn)
+sched_has_condition_p (const rtx_insn *insn)
 {
   return !! sched_get_condition_with_rev (insn, NULL);
 }
@@ -579,7 +645,7 @@ conditions_mutex_p (const_rtx cond1, const_rtx cond2, bool rev1, bool rev2)
          (rev1==rev2
          ? reversed_comparison_code (cond2, NULL)
          : GET_CODE (cond2))
-      && XEXP (cond1, 0) == XEXP (cond2, 0)
+      && rtx_equal_p (XEXP (cond1, 0), XEXP (cond2, 0))
       && XEXP (cond1, 1) == XEXP (cond2, 1))
     return 1;
   return 0;
@@ -588,7 +654,7 @@ conditions_mutex_p (const_rtx cond1, const_rtx cond2, bool rev1, bool rev2)
 /* Return true if insn1 and insn2 can never depend on one another because
    the conditions under which they are executed are mutually exclusive.  */
 bool
-sched_insns_conditions_mutex_p (const_rtx insn1, const_rtx insn2)
+sched_insns_conditions_mutex_p (const rtx_insn *insn1, const rtx_insn *insn2)
 {
   rtx cond1, cond2;
   bool rev1 = false, rev2 = false;
@@ -615,7 +681,7 @@ sched_insns_conditions_mutex_p (const_rtx insn1, const_rtx insn2)
 
 /* 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)
+sched_insn_is_legitimate_for_speculation_p (const rtx_insn *insn, ds_t ds)
 {
   if (HAS_INTERNAL_DEP (insn))
     return false;
@@ -626,7 +692,7 @@ sched_insn_is_legitimate_for_speculation_p (const_rtx insn, ds_t ds)
   if (SCHED_GROUP_P (insn))
     return false;
 
-  if (IS_SPECULATION_CHECK_P (CONST_CAST_RTX (insn)))
+  if (IS_SPECULATION_CHECK_P (CONST_CAST_RTX_INSN (insn)))
     return false;
 
   if (side_effects_p (PATTERN (insn)))
@@ -741,7 +807,7 @@ sd_lists_empty_p (const_rtx insn, sd_list_types_def list_types)
 
 /* Initialize data for INSN.  */
 void
-sd_init_insn (rtx insn)
+sd_init_insn (rtx_insn *insn)
 {
   INSN_HARD_BACK_DEPS (insn) = create_deps_list ();
   INSN_SPEC_BACK_DEPS (insn) = create_deps_list ();
@@ -754,7 +820,7 @@ sd_init_insn (rtx insn)
 
 /* Free data for INSN.  */
 void
-sd_finish_insn (rtx insn)
+sd_finish_insn (rtx_insn *insn)
 {
   /* ??? It would be nice to deallocate dependency caches here.  */
 
@@ -848,12 +914,10 @@ sd_find_dep_between (rtx pro, rtx con, bool resolved_p)
       int elem_luid = INSN_LUID (pro);
       int insn_luid = INSN_LUID (con);
 
-      gcc_assert (output_dependency_cache != NULL
-                 && anti_dependency_cache != NULL);
-
       if (!bitmap_bit_p (&true_dependency_cache[insn_luid], elem_luid)
          && !bitmap_bit_p (&output_dependency_cache[insn_luid], elem_luid)
-         && !bitmap_bit_p (&anti_dependency_cache[insn_luid], elem_luid))
+         && !bitmap_bit_p (&anti_dependency_cache[insn_luid], elem_luid)
+         && !bitmap_bit_p (&control_dependency_cache[insn_luid], elem_luid))
        return NULL;
     }
 
@@ -873,8 +937,8 @@ sd_find_dep_between (rtx pro, rtx con, bool resolved_p)
 static enum DEPS_ADJUST_RESULT
 maybe_add_or_update_dep_1 (dep_t dep, bool resolved_p, rtx mem1, rtx mem2)
 {
-  rtx elem = DEP_PRO (dep);
-  rtx insn = DEP_CON (dep);
+  rtx_insn *elem = DEP_PRO (dep);
+  rtx_insn *insn = DEP_CON (dep);
 
   gcc_assert (INSN_P (insn) && INSN_P (elem));
 
@@ -906,7 +970,8 @@ ask_dependency_caches (dep_t dep)
 
   gcc_assert (true_dependency_cache != NULL
              && output_dependency_cache != NULL
-             && anti_dependency_cache != NULL);
+             && anti_dependency_cache != NULL
+             && control_dependency_cache != NULL);
 
   if (!(current_sched_info->flags & USE_DEPS_LIST))
     {
@@ -918,6 +983,8 @@ ask_dependency_caches (dep_t dep)
        present_dep_type = REG_DEP_OUTPUT;
       else if (bitmap_bit_p (&anti_dependency_cache[insn_luid], elem_luid))
        present_dep_type = REG_DEP_ANTI;
+      else if (bitmap_bit_p (&control_dependency_cache[insn_luid], elem_luid))
+       present_dep_type = REG_DEP_CONTROL;
       else
        /* There is no existing dep so it should be created.  */
        return DEP_CREATED;
@@ -936,6 +1003,8 @@ ask_dependency_caches (dep_t dep)
        present_dep_types |= DEP_OUTPUT;
       if (bitmap_bit_p (&anti_dependency_cache[insn_luid], elem_luid))
        present_dep_types |= DEP_ANTI;
+      if (bitmap_bit_p (&control_dependency_cache[insn_luid], elem_luid))
+       present_dep_types |= DEP_CONTROL;
 
       if (present_dep_types == 0)
        /* There is no existing dep so it should be created.  */
@@ -989,6 +1058,10 @@ set_dependency_caches (dep_t dep)
          bitmap_set_bit (&anti_dependency_cache[insn_luid], elem_luid);
          break;
 
+       case REG_DEP_CONTROL:
+         bitmap_set_bit (&control_dependency_cache[insn_luid], elem_luid);
+         break;
+
        default:
          gcc_unreachable ();
        }
@@ -1003,6 +1076,8 @@ set_dependency_caches (dep_t dep)
        bitmap_set_bit (&output_dependency_cache[insn_luid], elem_luid);
       if (ds & DEP_ANTI)
        bitmap_set_bit (&anti_dependency_cache[insn_luid], elem_luid);
+      if (ds & DEP_CONTROL)
+       bitmap_set_bit (&control_dependency_cache[insn_luid], elem_luid);
 
       if (ds & SPECULATIVE)
        {
@@ -1034,6 +1109,10 @@ update_dependency_caches (dep_t dep, enum reg_note old_type)
          bitmap_clear_bit (&anti_dependency_cache[insn_luid], elem_luid);
          break;
 
+       case REG_DEP_CONTROL:
+         bitmap_clear_bit (&control_dependency_cache[insn_luid], elem_luid);
+         break;
+
        default:
          gcc_unreachable ();
        }
@@ -1049,8 +1128,8 @@ change_spec_dep_to_hard (sd_iterator_def sd_it)
   dep_node_t node = DEP_LINK_NODE (*sd_it.linkp);
   dep_link_t link = DEP_NODE_BACK (node);
   dep_t dep = DEP_NODE_DEP (node);
-  rtx elem = DEP_PRO (dep);
-  rtx insn = DEP_CON (dep);
+  rtx_insn *elem = DEP_PRO (dep);
+  rtx_insn *insn = DEP_CON (dep);
 
   move_dep_link (link, INSN_SPEC_BACK_DEPS (insn), INSN_HARD_BACK_DEPS (insn));
 
@@ -1076,6 +1155,9 @@ update_dep (dep_t dep, dep_t new_dep,
   enum reg_note old_type = DEP_TYPE (dep);
   bool was_spec = dep_spec_p (dep);
 
+  DEP_NONREG (dep) |= DEP_NONREG (new_dep);
+  DEP_MULTIPLE (dep) = 1;
+
   /* If this is a more restrictive type of dependence than the
      existing one, then change the existing dependence to this
      type.  */
@@ -1161,6 +1243,13 @@ add_or_update_dep_1 (dep_t new_dep, bool resolved_p,
       switch (ask_dependency_caches (new_dep))
        {
        case DEP_PRESENT:
+         dep_t present_dep;
+         sd_iterator_def sd_it;
+      
+         present_dep = sd_find_dep_between_no_cache (DEP_PRO (new_dep),
+                                                     DEP_CON (new_dep),
+                                                     resolved_p, &sd_it);
+         DEP_MULTIPLE (present_dep) = 1;
          return DEP_PRESENT;
 
        case DEP_CHANGED:
@@ -1224,7 +1313,7 @@ get_back_and_forw_lists (dep_t dep, bool resolved_p,
                         deps_list_t *back_list_ptr,
                         deps_list_t *forw_list_ptr)
 {
-  rtx con = DEP_CON (dep);
+  rtx_insn *con = DEP_CON (dep);
 
   if (!resolved_p)
     {
@@ -1250,8 +1339,8 @@ sd_add_dep (dep_t dep, bool resolved_p)
   dep_node_t n = create_dep_node ();
   deps_list_t con_back_deps;
   deps_list_t pro_forw_deps;
-  rtx elem = DEP_PRO (dep);
-  rtx insn = DEP_CON (dep);
+  rtx_insn *elem = DEP_PRO (dep);
+  rtx_insn *insn = DEP_CON (dep);
 
   gcc_assert (INSN_P (insn) && INSN_P (elem) && insn != elem);
 
@@ -1293,8 +1382,8 @@ sd_resolve_dep (sd_iterator_def sd_it)
 {
   dep_node_t node = DEP_LINK_NODE (*sd_it.linkp);
   dep_t dep = DEP_NODE_DEP (node);
-  rtx pro = DEP_PRO (dep);
-  rtx con = DEP_CON (dep);
+  rtx_insn *pro = DEP_PRO (dep);
+  rtx_insn *con = DEP_CON (dep);
 
   if (dep_spec_p (dep))
     move_dep_link (DEP_NODE_BACK (node), INSN_SPEC_BACK_DEPS (con),
@@ -1314,11 +1403,10 @@ sd_unresolve_dep (sd_iterator_def sd_it)
 {
   dep_node_t node = DEP_LINK_NODE (*sd_it.linkp);
   dep_t dep = DEP_NODE_DEP (node);
-  rtx pro = DEP_PRO (dep);
-  rtx con = DEP_CON (dep);
+  rtx_insn *pro = DEP_PRO (dep);
+  rtx_insn *con = DEP_CON (dep);
 
-  if ((current_sched_info->flags & DO_SPECULATION)
-      && (DEP_STATUS (dep) & SPECULATIVE))
+  if (dep_spec_p (dep))
     move_dep_link (DEP_NODE_BACK (node), INSN_RESOLVED_BACK_DEPS (con),
                   INSN_SPEC_BACK_DEPS (con));
   else
@@ -1332,7 +1420,7 @@ sd_unresolve_dep (sd_iterator_def sd_it)
 /* Make TO depend on all the FROM's producers.
    If RESOLVED_P is true add dependencies to the resolved lists.  */
 void
-sd_copy_back_deps (rtx to, rtx from, bool resolved_p)
+sd_copy_back_deps (rtx_insn *to, rtx_insn *from, bool resolved_p)
 {
   sd_list_types_def list_type;
   sd_iterator_def sd_it;
@@ -1357,8 +1445,8 @@ sd_delete_dep (sd_iterator_def sd_it)
 {
   dep_node_t n = DEP_LINK_NODE (*sd_it.linkp);
   dep_t dep = DEP_NODE_DEP (n);
-  rtx pro = DEP_PRO (dep);
-  rtx con = DEP_CON (dep);
+  rtx_insn *pro = DEP_PRO (dep);
+  rtx_insn *con = DEP_CON (dep);
   deps_list_t con_back_deps;
   deps_list_t pro_forw_deps;
 
@@ -1369,6 +1457,7 @@ sd_delete_dep (sd_iterator_def sd_it)
 
       bitmap_clear_bit (&true_dependency_cache[insn_luid], elem_luid);
       bitmap_clear_bit (&anti_dependency_cache[insn_luid], elem_luid);
+      bitmap_clear_bit (&control_dependency_cache[insn_luid], elem_luid);
       bitmap_clear_bit (&output_dependency_cache[insn_luid], elem_luid);
 
       if (current_sched_info->flags & DO_SPECULATION)
@@ -1434,63 +1523,111 @@ sd_debug_lists (rtx insn, sd_list_types_def types)
   fprintf (stderr, "\n");
 }
 
-/* A convenience wrapper to operate on an entire list.  */
+/* A wrapper around add_dependence_1, to add a dependence of CON on
+   PRO, with type DEP_TYPE.  This function implements special handling
+   for REG_DEP_CONTROL dependencies.  For these, we optionally promote
+   the type to REG_DEP_ANTI if we can determine that predication is
+   impossible; otherwise we add additional true dependencies on the
+   INSN_COND_DEPS list of the jump (which PRO must be).  */
+void
+add_dependence (rtx_insn *con, rtx_insn *pro, enum reg_note dep_type)
+{
+  if (dep_type == REG_DEP_CONTROL
+      && !(current_sched_info->flags & DO_PREDICATION))
+    dep_type = REG_DEP_ANTI;
+
+  /* A REG_DEP_CONTROL dependence may be eliminated through predication,
+     so we must also make the insn dependent on the setter of the
+     condition.  */
+  if (dep_type == REG_DEP_CONTROL)
+    {
+      rtx_insn *real_pro = pro;
+      rtx_insn *other = real_insn_for_shadow (real_pro);
+      rtx cond;
+
+      if (other != NULL_RTX)
+       real_pro = other;
+      cond = sched_get_reverse_condition_uncached (real_pro);
+      /* Verify that the insn does not use a different value in
+        the condition register than the one that was present at
+        the jump.  */
+      if (cond == NULL_RTX)
+       dep_type = REG_DEP_ANTI;
+      else if (INSN_CACHED_COND (real_pro) == const_true_rtx)
+       {
+         HARD_REG_SET uses;
+         CLEAR_HARD_REG_SET (uses);
+         note_uses (&PATTERN (con), record_hard_reg_uses, &uses);
+         if (TEST_HARD_REG_BIT (uses, REGNO (XEXP (cond, 0))))
+           dep_type = REG_DEP_ANTI;
+       }
+      if (dep_type == REG_DEP_CONTROL)
+       {
+         if (sched_verbose >= 5)
+           fprintf (sched_dump, "making DEP_CONTROL for %d\n",
+                    INSN_UID (real_pro));
+         add_dependence_list (con, INSN_COND_DEPS (real_pro), 0,
+                              REG_DEP_TRUE, false);
+       }
+    }
+         
+  add_dependence_1 (con, pro, dep_type);
+}
+
+/* A convenience wrapper to operate on an entire list.  HARD should be
+   true if DEP_NONREG should be set on newly created dependencies.  */
 
 static void
-add_dependence_list (rtx insn, rtx list, int uncond, enum reg_note dep_type)
+add_dependence_list (rtx_insn *insn, rtx_insn_list *list, int uncond,
+                    enum reg_note dep_type, bool hard)
 {
-  for (; list; list = XEXP (list, 1))
+  mark_as_hard = hard;
+  for (; list; list = list->next ())
     {
-      if (uncond || ! sched_insns_conditions_mutex_p (insn, XEXP (list, 0)))
-       add_dependence (insn, XEXP (list, 0), dep_type);
+      if (uncond || ! sched_insns_conditions_mutex_p (insn, list->insn ()))
+       add_dependence (insn, list->insn (), dep_type);
     }
+  mark_as_hard = false;
 }
 
 /* Similar, but free *LISTP at the same time, when the context
-   is not readonly.  */
+   is not readonly.  HARD should be true if DEP_NONREG should be set on
+   newly created dependencies.  */
 
 static void
-add_dependence_list_and_free (struct deps_desc *deps, rtx insn, rtx *listp,
-                              int uncond, enum reg_note dep_type)
+add_dependence_list_and_free (struct deps_desc *deps, rtx_insn *insn,
+                             rtx_insn_list **listp,
+                              int uncond, enum reg_note dep_type, bool hard)
 {
-  rtx list, next;
+  add_dependence_list (insn, *listp, uncond, dep_type, hard);
 
   /* We don't want to short-circuit dependencies involving debug
      insns, because they may cause actual dependencies to be
      disregarded.  */
   if (deps->readonly || DEBUG_INSN_P (insn))
-    {
-      add_dependence_list (insn, *listp, uncond, dep_type);
-      return;
-    }
+    return;
 
-  for (list = *listp, *listp = NULL; list ; list = next)
-    {
-      next = XEXP (list, 1);
-      if (uncond || ! sched_insns_conditions_mutex_p (insn, XEXP (list, 0)))
-       add_dependence (insn, XEXP (list, 0), dep_type);
-      free_INSN_LIST_node (list);
-    }
+  free_INSN_LIST_list (listp);
 }
 
-/* Remove all occurences of INSN from LIST.  Return the number of
-   occurences removed.  */
+/* Remove all occurrences of INSN from LIST.  Return the number of
+   occurrences removed.  */
 
 static int
-remove_from_dependence_list (rtx insn, rtx* listp)
+remove_from_dependence_list (rtx_insn *insn, rtx_insn_list **listp)
 {
   int removed = 0;
 
   while (*listp)
     {
-      if (XEXP (*listp, 0) == insn)
+      if ((*listp)->insn () == insn)
         {
           remove_free_INSN_LIST_node (listp);
           removed++;
           continue;
         }
 
-      listp = &XEXP (*listp, 1);
+      listp = (rtx_insn_list **)&XEXP (*listp, 1);
     }
 
   return removed;
@@ -1498,7 +1635,9 @@ remove_from_dependence_list (rtx insn, rtx* listp)
 
 /* Same as above, but process two lists at once.  */
 static int
-remove_from_both_dependence_lists (rtx insn, rtx *listp, rtx *exprp)
+remove_from_both_dependence_lists (rtx_insn *insn,
+                                  rtx_insn_list **listp,
+                                  rtx_expr_list **exprp)
 {
   int removed = 0;
 
@@ -1512,8 +1651,8 @@ remove_from_both_dependence_lists (rtx insn, rtx *listp, rtx *exprp)
           continue;
         }
 
-      listp = &XEXP (*listp, 1);
-      exprp = &XEXP (*exprp, 1);
+      listp = (rtx_insn_list **)&XEXP (*listp, 1);
+      exprp = (rtx_expr_list **)&XEXP (*exprp, 1);
     }
 
   return removed;
@@ -1521,7 +1660,7 @@ remove_from_both_dependence_lists (rtx insn, rtx *listp, rtx *exprp)
 
 /* Clear all dependencies for an insn.  */
 static void
-delete_all_dependences (rtx insn)
+delete_all_dependences (rtx_insn *insn)
 {
   sd_iterator_def sd_it;
   dep_t dep;
@@ -1542,16 +1681,16 @@ delete_all_dependences (rtx insn)
    the previous nonnote insn.  */
 
 static void
-fixup_sched_groups (rtx insn)
+chain_to_prev_insn (rtx_insn *insn)
 {
   sd_iterator_def sd_it;
   dep_t dep;
-  rtx prev_nonnote;
+  rtx_insn *prev_nonnote;
 
   FOR_EACH_DEP (insn, SD_LIST_BACK, sd_it, dep)
     {
-      rtx i = insn;
-      rtx pro = DEP_PRO (dep);
+      rtx_insn *i = insn;
+      rtx_insn *pro = DEP_PRO (dep);
 
       do
        {
@@ -1591,11 +1730,12 @@ fixup_sched_groups (rtx insn)
 
 static void
 add_insn_mem_dependence (struct deps_desc *deps, bool read_p,
-                        rtx insn, rtx mem)
+                        rtx_insn *insn, rtx mem)
 {
-  rtx *insn_list;
-  rtx *mem_list;
-  rtx link;
+  rtx_insn_list **insn_list;
+  rtx_insn_list *insn_node;
+  rtx_expr_list **mem_list;
+  rtx_expr_list *mem_node;
 
   gcc_assert (!deps->readonly);
   if (read_p)
@@ -1612,16 +1752,17 @@ add_insn_mem_dependence (struct deps_desc *deps, bool read_p,
       deps->pending_write_list_length++;
     }
 
-  link = alloc_INSN_LIST (insn, *insn_list);
-  *insn_list = link;
+  insn_node = alloc_INSN_LIST (insn, *insn_list);
+  *insn_list = insn_node;
 
   if (sched_deps_info->use_cselib)
     {
       mem = shallow_copy_rtx (mem);
-      XEXP (mem, 0) = cselib_subst_to_values (XEXP (mem, 0), GET_MODE (mem));
+      XEXP (mem, 0) = cselib_subst_to_values_from_insn (XEXP (mem, 0),
+                                                       GET_MODE (mem), insn);
     }
-  link = alloc_EXPR_LIST (VOIDmode, canon_rtx (mem), *mem_list);
-  *mem_list = link;
+  mem_node = alloc_EXPR_LIST (VOIDmode, canon_rtx (mem), *mem_list);
+  *mem_list = mem_node;
 }
 
 /* Make a dependency between every memory reference on the pending lists
@@ -1629,13 +1770,13 @@ add_insn_mem_dependence (struct deps_desc *deps, bool read_p,
    dependencies for a read operation, similarly with FOR_WRITE.  */
 
 static void
-flush_pending_lists (struct deps_desc *deps, rtx insn, int for_read,
+flush_pending_lists (struct deps_desc *deps, rtx_insn *insn, int for_read,
                     int for_write)
 {
   if (for_write)
     {
       add_dependence_list_and_free (deps, insn, &deps->pending_read_insns,
-                                    1, REG_DEP_ANTI);
+                                    1, REG_DEP_ANTI, true);
       if (!deps->readonly)
         {
           free_EXPR_LIST_list (&deps->pending_read_mems);
@@ -1644,11 +1785,26 @@ flush_pending_lists (struct deps_desc *deps, rtx insn, int for_read,
     }
 
   add_dependence_list_and_free (deps, insn, &deps->pending_write_insns, 1,
-                               for_read ? REG_DEP_ANTI : REG_DEP_OUTPUT);
+                               for_read ? REG_DEP_ANTI : REG_DEP_OUTPUT,
+                               true);
 
   add_dependence_list_and_free (deps, insn,
                                 &deps->last_pending_memory_flush, 1,
-                                for_read ? REG_DEP_ANTI : REG_DEP_OUTPUT);
+                                for_read ? REG_DEP_ANTI : REG_DEP_OUTPUT,
+                               true);
+
+  add_dependence_list_and_free (deps, insn, &deps->pending_jump_insns, 1,
+                               REG_DEP_ANTI, true);
+
+  if (DEBUG_INSN_P (insn))
+    {
+      if (for_write)
+       free_INSN_LIST_list (&deps->pending_read_insns);
+      free_INSN_LIST_list (&deps->pending_write_insns);
+      free_INSN_LIST_list (&deps->last_pending_memory_flush);
+      free_INSN_LIST_list (&deps->pending_jump_insns);
+    }
+
   if (!deps->readonly)
     {
       free_EXPR_LIST_list (&deps->pending_write_mems);
@@ -1657,15 +1813,16 @@ flush_pending_lists (struct deps_desc *deps, rtx insn, int for_read,
       deps->last_pending_memory_flush = alloc_INSN_LIST (insn, NULL_RTX);
       deps->pending_flush_length = 1;
     }
+  mark_as_hard = false;
 }
 \f
 /* Instruction which dependencies we are analyzing.  */
-static rtx cur_insn = NULL_RTX;
+static rtx_insn *cur_insn = NULL;
 
 /* Implement hooks for haifa scheduler.  */
 
 static void
-haifa_start_insn (rtx insn)
+haifa_start_insn (rtx_insn *insn)
 {
   gcc_assert (insn && !cur_insn);
 
@@ -1697,7 +1854,7 @@ haifa_note_reg_use (int regno)
 }
 
 static void
-haifa_note_mem_dep (rtx mem, rtx pending_mem, rtx pending_insn, ds_t ds)
+haifa_note_mem_dep (rtx mem, rtx pending_mem, rtx_insn *pending_insn, ds_t ds)
 {
   if (!(ds & SPECULATIVE))
     {
@@ -1712,18 +1869,21 @@ haifa_note_mem_dep (rtx mem, rtx pending_mem, rtx pending_insn, ds_t ds)
 
     init_dep_1 (dep, pending_insn, cur_insn, ds_to_dt (ds),
                 current_sched_info->flags & USE_DEPS_LIST ? ds : 0);
+    DEP_NONREG (dep) = 1;
     maybe_add_or_update_dep_1 (dep, false, pending_mem, mem);
   }
 
 }
 
 static void
-haifa_note_dep (rtx elem, ds_t ds)
+haifa_note_dep (rtx_insn *elem, ds_t ds)
 {
   dep_def _dep;
   dep_t dep = &_dep;
 
   init_dep (dep, elem, cur_insn, ds_to_dt (ds));
+  if (mark_as_hard)
+    DEP_NONREG (dep) = 1;
   maybe_add_or_update_dep_1 (dep, false, NULL_RTX, NULL_RTX);
 }
 
@@ -1749,14 +1909,14 @@ note_reg_clobber (int r)
 }
 
 static void
-note_mem_dep (rtx m1, rtx m2, rtx e, ds_t ds)
+note_mem_dep (rtx m1, rtx m2, rtx_insn *e, ds_t ds)
 {
   if (sched_deps_info->note_mem_dep)
     sched_deps_info->note_mem_dep (m1, m2, e, ds);
 }
 
 static void
-note_dep (rtx e, ds_t ds)
+note_dep (rtx_insn *e, ds_t ds)
 {
   if (sched_deps_info->note_dep)
     sched_deps_info->note_dep (e, ds);
@@ -1770,10 +1930,12 @@ ds_to_dt (ds_t ds)
     return REG_DEP_TRUE;
   else if (ds & DEP_OUTPUT)
     return REG_DEP_OUTPUT;
+  else if (ds & DEP_ANTI)
+    return REG_DEP_ANTI;
   else
     {
-      gcc_assert (ds & DEP_ANTI);
-      return REG_DEP_ANTI;
+      gcc_assert (ds & DEP_CONTROL);
+      return REG_DEP_CONTROL;
     }
 }
 
@@ -1785,7 +1947,7 @@ ds_to_dt (ds_t ds)
 
 /* Allocate and return reg_use_data structure for REGNO and INSN.  */
 static struct reg_use_data *
-create_insn_reg_use (int regno, rtx insn)
+create_insn_reg_use (int regno, rtx_insn *insn)
 {
   struct reg_use_data *use;
 
@@ -1797,8 +1959,8 @@ create_insn_reg_use (int regno, rtx insn)
   return use;
 }
 
-/* Allocate and return reg_set_data structure for REGNO and INSN.  */
-static struct reg_set_data *
+/* Allocate reg_set_data structure for REGNO and INSN.  */
+static void
 create_insn_reg_set (int regno, rtx insn)
 {
   struct reg_set_data *set;
@@ -1808,16 +1970,14 @@ create_insn_reg_set (int regno, rtx insn)
   set->insn = insn;
   set->next_insn_set = INSN_REG_SET_LIST (insn);
   INSN_REG_SET_LIST (insn) = set;
-  return set;
 }
 
 /* Set up insn register uses for INSN and dependency context DEPS.  */
 static void
-setup_insn_reg_uses (struct deps_desc *deps, rtx insn)
+setup_insn_reg_uses (struct deps_desc *deps, rtx_insn *insn)
 {
   unsigned i;
   reg_set_iterator rsi;
-  rtx list;
   struct reg_use_data *use, *use2, *next;
   struct deps_reg *reg_last;
 
@@ -1838,9 +1998,9 @@ setup_insn_reg_uses (struct deps_desc *deps, rtx insn)
       reg_last = &deps->reg_last[i];
 
       /* Create the cycle list of uses.  */
-      for (list = reg_last->uses; list; list = XEXP (list, 1))
+      for (rtx_insn_list *list = reg_last->uses; list; list = list->next ())
        {
-         use2 = create_insn_reg_use (i, XEXP (list, 0));
+         use2 = create_insn_reg_use (i, list->insn ());
          next = use->next_regno_use;
          use->next_regno_use = use2;
          use2->next_regno_use = next;
@@ -1958,8 +2118,7 @@ mark_insn_reg_birth (rtx insn, rtx reg, bool clobber_p, bool unused_p)
 
   regno = REGNO (reg);
   if (regno < FIRST_PSEUDO_REGISTER)
-    mark_insn_hard_regno_birth (insn, regno,
-                               hard_regno_nregs[regno][GET_MODE (reg)],
+    mark_insn_hard_regno_birth (insn, regno, REG_NREGS (reg),
                                clobber_p, unused_p);
   else
     mark_insn_pseudo_birth (insn, regno, clobber_p, unused_p);
@@ -2018,7 +2177,7 @@ mark_reg_death (rtx reg)
 
   regno = REGNO (reg);
   if (regno < FIRST_PSEUDO_REGISTER)
-    mark_hard_regno_death (regno, hard_regno_nregs[regno][GET_MODE (reg)]);
+    mark_hard_regno_death (regno, REG_NREGS (reg));
   else
     mark_pseudo_death (regno);
 }
@@ -2044,14 +2203,14 @@ mark_insn_reg_clobber (rtx reg, const_rtx setter, void *data)
 
 /* Set up reg pressure info related to INSN.  */
 void
-init_insn_reg_pressure_info (rtx insn)
+init_insn_reg_pressure_info (rtx_insn *insn)
 {
   int i, len;
   enum reg_class cl;
   static struct reg_pressure_data *pressure_info;
   rtx link;
 
-  gcc_assert (sched_pressure_p);
+  gcc_assert (sched_pressure != SCHED_PRESSURE_NONE);
 
   if (! INSN_P (insn))
     return;
@@ -2082,8 +2241,9 @@ init_insn_reg_pressure_info (rtx insn)
   len = sizeof (struct reg_pressure_data) * ira_pressure_classes_num;
   pressure_info
     = INSN_REG_PRESSURE (insn) = (struct reg_pressure_data *) xmalloc (len);
-  INSN_MAX_REG_PRESSURE (insn) = (int *) xcalloc (ira_pressure_classes_num
-                                                 * sizeof (int), 1);
+  if (sched_pressure == SCHED_PRESSURE_WEIGHTED)
+    INSN_MAX_REG_PRESSURE (insn) = (int *) xcalloc (ira_pressure_classes_num
+                                                   * sizeof (int), 1);
   for (i = 0; i < ira_pressure_classes_num; i++)
     {
       cl = ira_pressure_classes[i];
@@ -2156,8 +2316,8 @@ maybe_extend_reg_info_p (void)
    CLOBBER, PRE_DEC, POST_DEC, PRE_INC, POST_INC or USE.  */
 
 static void
-sched_analyze_reg (struct deps_desc *deps, int regno, enum machine_mode mode,
-                  enum rtx_code ref, rtx insn)
+sched_analyze_reg (struct deps_desc *deps, int regno, machine_mode mode,
+                  enum rtx_code ref, rtx_insn *insn)
 {
   /* We could emit new pseudos in renaming.  Extend the reg structures.  */
   if (!reload_completed && sel_sched_p ()
@@ -2225,7 +2385,7 @@ sched_analyze_reg (struct deps_desc *deps, int regno, enum machine_mode mode,
              = alloc_INSN_LIST (insn, deps->sched_before_next_call);
          else
            add_dependence_list (insn, deps->last_function_call, 1,
-                                REG_DEP_ANTI);
+                                REG_DEP_ANTI, false);
        }
     }
 }
@@ -2235,7 +2395,7 @@ sched_analyze_reg (struct deps_desc *deps, int regno, enum machine_mode mode,
    destination of X, and reads of everything mentioned.  */
 
 static void
-sched_analyze_1 (struct deps_desc *deps, rtx x, rtx insn)
+sched_analyze_1 (struct deps_desc *deps, rtx x, rtx_insn *insn)
 {
   rtx dest = XEXP (x, 0);
   enum rtx_code code = GET_CODE (x);
@@ -2303,7 +2463,7 @@ sched_analyze_1 (struct deps_desc *deps, rtx x, rtx insn)
   if (REG_P (dest))
     {
       int regno = REGNO (dest);
-      enum machine_mode mode = GET_MODE (dest);
+      machine_mode mode = GET_MODE (dest);
 
       sched_analyze_reg (deps, regno, mode, code, insn);
 
@@ -2327,20 +2487,21 @@ sched_analyze_1 (struct deps_desc *deps, rtx x, rtx insn)
 
       if (sched_deps_info->use_cselib)
        {
-         enum machine_mode address_mode
-           = targetm.addr_space.address_mode (MEM_ADDR_SPACE (dest));
+         machine_mode address_mode = get_address_mode (dest);
 
          t = shallow_copy_rtx (dest);
          cselib_lookup_from_insn (XEXP (t, 0), address_mode, 1,
                                   GET_MODE (t), insn);
-         XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0), GET_MODE (t));
+         XEXP (t, 0)
+           = cselib_subst_to_values_from_insn (XEXP (t, 0), GET_MODE (t),
+                                               insn);
        }
       t = canon_rtx (t);
 
       /* Pending lists can't get larger with a readonly context.  */
       if (!deps->readonly
           && ((deps->pending_read_list_length + deps->pending_write_list_length)
-              > MAX_PENDING_LIST_LENGTH))
+              >= MAX_PENDING_LIST_LENGTH))
        {
          /* Flush all pending reads and writes to prevent the pending lists
             from getting any larger.  Insn scheduling runs too slowly when
@@ -2351,36 +2512,40 @@ sched_analyze_1 (struct deps_desc *deps, rtx x, rtx insn)
        }
       else
        {
-         rtx pending, pending_mem;
+         rtx_insn_list *pending;
+         rtx_expr_list *pending_mem;
 
          pending = deps->pending_read_insns;
          pending_mem = deps->pending_read_mems;
          while (pending)
            {
-             if (anti_dependence (XEXP (pending_mem, 0), t)
-                 && ! sched_insns_conditions_mutex_p (insn, XEXP (pending, 0)))
-               note_mem_dep (t, XEXP (pending_mem, 0), XEXP (pending, 0),
+             if (anti_dependence (pending_mem->element (), t)
+                 && ! sched_insns_conditions_mutex_p (insn, pending->insn ()))
+               note_mem_dep (t, pending_mem->element (), pending->insn (),
                              DEP_ANTI);
 
-             pending = XEXP (pending, 1);
-             pending_mem = XEXP (pending_mem, 1);
+             pending = pending->next ();
+             pending_mem = pending_mem->next ();
            }
 
          pending = deps->pending_write_insns;
          pending_mem = deps->pending_write_mems;
          while (pending)
            {
-             if (output_dependence (XEXP (pending_mem, 0), t)
-                 && ! sched_insns_conditions_mutex_p (insn, XEXP (pending, 0)))
-               note_mem_dep (t, XEXP (pending_mem, 0), XEXP (pending, 0),
+             if (output_dependence (pending_mem->element (), t)
+                 && ! sched_insns_conditions_mutex_p (insn, pending->insn ()))
+               note_mem_dep (t, pending_mem->element (),
+                             pending->insn (),
                              DEP_OUTPUT);
 
-             pending = XEXP (pending, 1);
-             pending_mem = XEXP (pending_mem, 1);
+             pending = pending->next ();
+             pending_mem = pending_mem-> next ();
            }
 
          add_dependence_list (insn, deps->last_pending_memory_flush, 1,
-                              REG_DEP_ANTI);
+                              REG_DEP_ANTI, true);
+         add_dependence_list (insn, deps->pending_jump_insns, 1,
+                              REG_DEP_CONTROL, true);
 
           if (!deps->readonly)
             add_insn_mem_dependence (deps, false, insn, dest);
@@ -2404,7 +2569,7 @@ sched_analyze_1 (struct deps_desc *deps, rtx x, rtx insn)
 
 /* Analyze the uses of memory and registers in rtx X in INSN.  */
 static void
-sched_analyze_2 (struct deps_desc *deps, rtx x, rtx insn)
+sched_analyze_2 (struct deps_desc *deps, rtx x, rtx_insn *insn)
 {
   int i;
   int j;
@@ -2425,10 +2590,7 @@ sched_analyze_2 (struct deps_desc *deps, rtx x, rtx insn)
 
   switch (code)
     {
-    case CONST_INT:
-    case CONST_DOUBLE:
-    case CONST_FIXED:
-    case CONST_VECTOR:
+    CASE_CONST_ANY:
     case SYMBOL_REF:
     case CONST:
     case LABEL_REF:
@@ -2438,8 +2600,10 @@ sched_analyze_2 (struct deps_desc *deps, rtx x, rtx insn)
 
       return;
 
-#ifdef HAVE_cc0
     case CC0:
+      if (!HAVE_cc0)
+       gcc_unreachable ();
+
       /* User of CC0 depends on immediately preceding insn.  */
       SCHED_GROUP_P (insn) = 1;
        /* Don't move CC0 setter to another block (it can set up the
@@ -2450,12 +2614,11 @@ sched_analyze_2 (struct deps_desc *deps, rtx x, rtx insn)
        sched_deps_info->finish_rhs ();
 
       return;
-#endif
 
     case REG:
       {
        int regno = REGNO (x);
-       enum machine_mode mode = GET_MODE (x);
+       machine_mode mode = GET_MODE (x);
 
        sched_analyze_reg (deps, regno, mode, USE, insn);
 
@@ -2479,19 +2642,21 @@ sched_analyze_2 (struct deps_desc *deps, rtx x, rtx insn)
     case MEM:
       {
        /* Reading memory.  */
-       rtx u;
-       rtx pending, pending_mem;
+       rtx_insn_list *u;
+       rtx_insn_list *pending;
+       rtx_expr_list *pending_mem;
        rtx t = x;
 
        if (sched_deps_info->use_cselib)
          {
-           enum machine_mode address_mode
-             = targetm.addr_space.address_mode (MEM_ADDR_SPACE (t));
+           machine_mode address_mode = get_address_mode (t);
 
            t = shallow_copy_rtx (t);
            cselib_lookup_from_insn (XEXP (t, 0), address_mode, 1,
                                     GET_MODE (t), insn);
-           XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0), GET_MODE (t));
+           XEXP (t, 0)
+             = cselib_subst_to_values_from_insn (XEXP (t, 0), GET_MODE (t),
+                                                 insn);
          }
 
        if (!DEBUG_INSN_P (insn))
@@ -2501,56 +2666,63 @@ sched_analyze_2 (struct deps_desc *deps, rtx x, rtx insn)
            pending_mem = deps->pending_read_mems;
            while (pending)
              {
-               if (read_dependence (XEXP (pending_mem, 0), t)
+               if (read_dependence (pending_mem->element (), t)
                    && ! sched_insns_conditions_mutex_p (insn,
-                                                        XEXP (pending, 0)))
-                 note_mem_dep (t, XEXP (pending_mem, 0), XEXP (pending, 0),
+                                                        pending->insn ()))
+                 note_mem_dep (t, pending_mem->element (),
+                               pending->insn (),
                                DEP_ANTI);
 
-               pending = XEXP (pending, 1);
-               pending_mem = XEXP (pending_mem, 1);
+               pending = pending->next ();
+               pending_mem = pending_mem->next ();
              }
 
            pending = deps->pending_write_insns;
            pending_mem = deps->pending_write_mems;
            while (pending)
              {
-               if (true_dependence (XEXP (pending_mem, 0), VOIDmode,
-                                    t, rtx_varies_p)
+               if (true_dependence (pending_mem->element (), VOIDmode, t)
                    && ! sched_insns_conditions_mutex_p (insn,
-                                                        XEXP (pending, 0)))
-                 note_mem_dep (t, XEXP (pending_mem, 0), XEXP (pending, 0),
+                                                        pending->insn ()))
+                 note_mem_dep (t, pending_mem->element (),
+                               pending->insn (),
                                sched_deps_info->generate_spec_deps
                                ? BEGIN_DATA | DEP_TRUE : DEP_TRUE);
 
-               pending = XEXP (pending, 1);
-               pending_mem = XEXP (pending_mem, 1);
+               pending = pending->next ();
+               pending_mem = pending_mem->next ();
              }
 
-           for (u = deps->last_pending_memory_flush; u; u = XEXP (u, 1))
-             {
-               if (! NON_FLUSH_JUMP_P (u))
-                 add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
-               else if (deps_may_trap_p (x))
-                 {
-                   if ((sched_deps_info->generate_spec_deps)
-                       && sel_sched_p () && (spec_info->mask & BEGIN_CONTROL))
-                     {
-                       ds_t ds = set_dep_weak (DEP_ANTI, BEGIN_CONTROL,
-                                               MAX_DEP_WEAK);
-
-                       note_dep (XEXP (u, 0), ds);
-                     }
-                   else
-                     add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
-                 }
-             }
+           for (u = deps->last_pending_memory_flush; u; u = u->next ())
+             add_dependence (insn, u->insn (), REG_DEP_ANTI);
+
+           for (u = deps->pending_jump_insns; u; u = u->next ())
+             if (deps_may_trap_p (x))
+               {
+                 if ((sched_deps_info->generate_spec_deps)
+                     && sel_sched_p () && (spec_info->mask & BEGIN_CONTROL))
+                   {
+                     ds_t ds = set_dep_weak (DEP_ANTI, BEGIN_CONTROL,
+                                             MAX_DEP_WEAK);
+                     
+                     note_dep (u->insn (), ds);
+                   }
+                 else
+                   add_dependence (insn, u->insn (), REG_DEP_CONTROL);
+               }
          }
 
        /* Always add these dependencies to pending_reads, since
           this insn may be followed by a write.  */
-        if (!deps->readonly)
-          add_insn_mem_dependence (deps, true, insn, x);
+       if (!deps->readonly)
+         {
+           if ((deps->pending_read_list_length
+                + deps->pending_write_list_length)
+               >= MAX_PENDING_LIST_LENGTH
+               && !DEBUG_INSN_P (insn))
+             flush_pending_lists (deps, insn, true, true);
+           add_insn_mem_dependence (deps, true, insn, x);
+         }
 
        sched_analyze_2 (deps, XEXP (x, 0), insn);
 
@@ -2568,6 +2740,25 @@ sched_analyze_2 (struct deps_desc *deps, rtx x, rtx insn)
     case PREFETCH:
       if (PREFETCH_SCHEDULE_BARRIER_P (x))
        reg_pending_barrier = TRUE_BARRIER;
+      /* Prefetch insn contains addresses only.  So if the prefetch
+        address has no registers, there will be no dependencies on
+        the prefetch insn.  This is wrong with result code
+        correctness point of view as such prefetch can be moved below
+        a jump insn which usually generates MOVE_BARRIER preventing
+        to move insns containing registers or memories through the
+        barrier.  It is also wrong with generated code performance
+        point of view as prefetch withouth dependecies will have a
+        tendency to be issued later instead of earlier.  It is hard
+        to generate accurate dependencies for prefetch insns as
+        prefetch has only the start address but it is better to have
+        something than nothing.  */
+      if (!deps->readonly)
+       {
+         rtx x = gen_rtx_MEM (Pmode, XEXP (PATTERN (insn), 0));
+         if (sched_deps_info->use_cselib)
+           cselib_lookup_from_insn (x, Pmode, true, VOIDmode, insn);
+         add_insn_mem_dependence (deps, true, insn, x);
+       }
       break;
 
     case UNSPEC_VOLATILE:
@@ -2584,7 +2775,8 @@ sched_analyze_2 (struct deps_desc *deps, rtx x, rtx insn)
           Consider for instance a volatile asm that changes the fpu rounding
           mode.  An insn should not be moved across this even if it only uses
           pseudo-regs because it might give an incorrectly rounded result.  */
-       if (code != ASM_OPERANDS || MEM_VOLATILE_P (x))
+       if ((code != ASM_OPERANDS || MEM_VOLATILE_P (x))
+           && !DEBUG_INSN_P (insn))
          reg_pending_barrier = TRUE_BARRIER;
 
        /* For all ASM_OPERANDS, we must traverse the vector of input operands.
@@ -2654,9 +2846,46 @@ sched_analyze_2 (struct deps_desc *deps, rtx x, rtx insn)
     sched_deps_info->finish_rhs ();
 }
 
+/* Try to group two fusible insns together to prevent scheduler
+   from scheduling them apart.  */
+
+static void
+sched_macro_fuse_insns (rtx_insn *insn)
+{
+  rtx_insn *prev;
+
+  if (any_condjump_p (insn))
+    {
+      unsigned int condreg1, condreg2;
+      rtx cc_reg_1;
+      targetm.fixed_condition_code_regs (&condreg1, &condreg2);
+      cc_reg_1 = gen_rtx_REG (CCmode, condreg1);
+      prev = prev_nonnote_nondebug_insn (insn);
+      if (!reg_referenced_p (cc_reg_1, PATTERN (insn))
+          || !prev
+          || !modified_in_p (cc_reg_1, prev))
+        return;
+    }
+  else
+    {
+      rtx insn_set = single_set (insn);
+
+      prev = prev_nonnote_nondebug_insn (insn);
+      if (!prev
+          || !insn_set
+          || !single_set (prev))
+        return;
+
+    }
+
+  if (targetm.sched.macro_fusion_pair_p (prev, insn))
+    SCHED_GROUP_P (insn) = 1;
+
+}
+
 /* Analyze an INSN with pattern X to find all dependencies.  */
 static void
-sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
+sched_analyze_insn (struct deps_desc *deps, rtx x, rtx_insn *insn)
 {
   RTX_CODE code = GET_CODE (x);
   rtx link;
@@ -2668,7 +2897,7 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
       HARD_REG_SET temp;
 
       extract_insn (insn);
-      preprocess_constraints ();
+      preprocess_constraints (insn);
       ira_implicitly_set_insn_hard_regs (&temp);
       AND_COMPL_HARD_REG_SET (temp, ira_no_alloc_regs);
       IOR_HARD_REG_SET (implicit_reg_pending_clobbers, temp);
@@ -2677,11 +2906,35 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
   can_start_lhs_rhs_p = (NONJUMP_INSN_P (insn)
                         && code == SET);
 
+  /* Group compare and branch insns for macro-fusion.  */
+  if (targetm.sched.macro_fusion_p
+      && targetm.sched.macro_fusion_p ())
+    sched_macro_fuse_insns (insn);
+
   if (may_trap_p (x))
-    /* Avoid moving trapping instructions accross function calls that might
+    /* Avoid moving trapping instructions across function calls that might
        not always return.  */
     add_dependence_list (insn, deps->last_function_call_may_noreturn,
-                        1, REG_DEP_ANTI);
+                        1, REG_DEP_ANTI, true);
+
+  /* We must avoid creating a situation in which two successors of the
+     current block have different unwind info after scheduling.  If at any
+     point the two paths re-join this leads to incorrect unwind info.  */
+  /* ??? There are certain situations involving a forced frame pointer in
+     which, with extra effort, we could fix up the unwind info at a later
+     CFG join.  However, it seems better to notice these cases earlier
+     during prologue generation and avoid marking the frame pointer setup
+     as frame-related at all.  */
+  if (RTX_FRAME_RELATED_P (insn))
+    {
+      /* Make sure prologue insn is scheduled before next jump.  */
+      deps->sched_before_next_jump
+       = alloc_INSN_LIST (insn, deps->sched_before_next_jump);
+
+      /* Make sure epilogue insn is scheduled after preceding jumps.  */
+      add_dependence_list (insn, deps->pending_jump_insns, 1, REG_DEP_ANTI,
+                          true);
+    }
 
   if (code == COND_EXEC)
     {
@@ -2701,7 +2954,7 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
         instruction so that reg-stack won't get confused.  */
       if (code == CLOBBER)
        add_dependence_list (insn, deps->last_function_call, 1,
-                            REG_DEP_OUTPUT);
+                            REG_DEP_OUTPUT, true);
     }
   else if (code == PARALLEL)
     {
@@ -2732,51 +2985,43 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
        {
          if (GET_CODE (XEXP (link, 0)) == CLOBBER)
            sched_analyze_1 (deps, XEXP (link, 0), insn);
-         else
+         else if (GET_CODE (XEXP (link, 0)) != SET)
            sched_analyze_2 (deps, XEXP (link, 0), insn);
        }
-      if (find_reg_note (insn, REG_SETJMP, NULL))
+      /* Don't schedule anything after a tail call, tail call needs
+        to use at least all call-saved registers.  */
+      if (SIBLING_CALL_P (insn))
+       reg_pending_barrier = TRUE_BARRIER;
+      else if (find_reg_note (insn, REG_SETJMP, NULL))
        reg_pending_barrier = MOVE_BARRIER;
     }
 
   if (JUMP_P (insn))
     {
-      rtx next;
-      next = next_nonnote_nondebug_insn (insn);
+      rtx_insn *next = next_nonnote_nondebug_insn (insn);
       if (next && BARRIER_P (next))
        reg_pending_barrier = MOVE_BARRIER;
       else
        {
-         rtx pending, pending_mem;
+         rtx_insn_list *pending;
+         rtx_expr_list *pending_mem;
 
           if (sched_deps_info->compute_jump_reg_dependencies)
             {
-              regset_head tmp_uses, tmp_sets;
-              INIT_REG_SET (&tmp_uses);
-              INIT_REG_SET (&tmp_sets);
-
               (*sched_deps_info->compute_jump_reg_dependencies)
-                (insn, &deps->reg_conditional_sets, &tmp_uses, &tmp_sets);
+               (insn, reg_pending_control_uses);
+
               /* Make latency of jump equal to 0 by using anti-dependence.  */
-              EXECUTE_IF_SET_IN_REG_SET (&tmp_uses, 0, i, rsi)
+              EXECUTE_IF_SET_IN_REG_SET (reg_pending_control_uses, 0, i, rsi)
                 {
                   struct deps_reg *reg_last = &deps->reg_last[i];
-                  add_dependence_list (insn, reg_last->sets, 0, REG_DEP_ANTI);
+                  add_dependence_list (insn, reg_last->sets, 0, REG_DEP_ANTI,
+                                      false);
                   add_dependence_list (insn, reg_last->implicit_sets,
-                                      0, REG_DEP_ANTI);
+                                      0, REG_DEP_ANTI, false);
                   add_dependence_list (insn, reg_last->clobbers, 0,
-                                      REG_DEP_ANTI);
-
-                  if (!deps->readonly)
-                    {
-                      reg_last->uses_length++;
-                      reg_last->uses = alloc_INSN_LIST (insn, reg_last->uses);
-                    }
+                                      REG_DEP_ANTI, false);
                 }
-              IOR_REG_SET (reg_pending_sets, &tmp_sets);
-
-              CLEAR_REG_SET (&tmp_uses);
-              CLEAR_REG_SET (&tmp_sets);
             }
 
          /* All memory writes and volatile reads must happen before the
@@ -2787,25 +3032,29 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
          pending_mem = deps->pending_write_mems;
          while (pending)
            {
-             if (! sched_insns_conditions_mutex_p (insn, XEXP (pending, 0)))
-               add_dependence (insn, XEXP (pending, 0), REG_DEP_OUTPUT);
-             pending = XEXP (pending, 1);
-             pending_mem = XEXP (pending_mem, 1);
+             if (! sched_insns_conditions_mutex_p (insn, pending->insn ()))
+               add_dependence (insn, pending->insn (),
+                               REG_DEP_OUTPUT);
+             pending = pending->next ();
+             pending_mem = pending_mem->next ();
            }
 
          pending = deps->pending_read_insns;
          pending_mem = deps->pending_read_mems;
          while (pending)
            {
-             if (MEM_VOLATILE_P (XEXP (pending_mem, 0))
-                 && ! sched_insns_conditions_mutex_p (insn, XEXP (pending, 0)))
-               add_dependence (insn, XEXP (pending, 0), REG_DEP_OUTPUT);
-             pending = XEXP (pending, 1);
-             pending_mem = XEXP (pending_mem, 1);
+             if (MEM_VOLATILE_P (pending_mem->element ())
+                 && ! sched_insns_conditions_mutex_p (insn, pending->insn ()))
+               add_dependence (insn, pending->insn (),
+                               REG_DEP_OUTPUT);
+             pending = pending->next ();
+             pending_mem = pending_mem->next ();
            }
 
          add_dependence_list (insn, deps->last_pending_memory_flush, 1,
-                              REG_DEP_ANTI);
+                              REG_DEP_ANTI, true);
+         add_dependence_list (insn, deps->pending_jump_insns, 1,
+                              REG_DEP_ANTI, true);
        }
     }
 
@@ -2819,7 +3068,7 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
       || (NONJUMP_INSN_P (insn) && control_flow_insn_p (insn)))
     reg_pending_barrier = MOVE_BARRIER;
 
-  if (sched_pressure_p)
+  if (sched_pressure != SCHED_PRESSURE_NONE)
     {
       setup_insn_reg_uses (deps, insn);
       init_insn_reg_pressure_info (insn);
@@ -2828,8 +3077,8 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
   /* Add register dependencies for insn.  */
   if (DEBUG_INSN_P (insn))
     {
-      rtx prev = deps->last_debug_insn;
-      rtx u;
+      rtx_insn *prev = deps->last_debug_insn;
+      rtx_insn_list *u;
 
       if (!deps->readonly)
        deps->last_debug_insn = insn;
@@ -2838,17 +3087,20 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
        add_dependence (insn, prev, REG_DEP_ANTI);
 
       add_dependence_list (insn, deps->last_function_call, 1,
-                          REG_DEP_ANTI);
+                          REG_DEP_ANTI, false);
 
-      for (u = deps->last_pending_memory_flush; u; u = XEXP (u, 1))
-       if (! NON_FLUSH_JUMP_P (u) || !sel_sched_p ())
-         add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
+      if (!sel_sched_p ())
+       for (u = deps->last_pending_memory_flush; u; u = u->next ())
+         add_dependence (insn, u->insn (), REG_DEP_ANTI);
 
       EXECUTE_IF_SET_IN_REG_SET (reg_pending_uses, 0, i, rsi)
        {
          struct deps_reg *reg_last = &deps->reg_last[i];
-         add_dependence_list (insn, reg_last->sets, 1, REG_DEP_ANTI);
-         add_dependence_list (insn, reg_last->clobbers, 1, REG_DEP_ANTI);
+         add_dependence_list (insn, reg_last->sets, 1, REG_DEP_ANTI, false);
+         /* There's no point in making REG_DEP_CONTROL dependencies for
+            debug insns.  */
+         add_dependence_list (insn, reg_last->clobbers, 1, REG_DEP_ANTI,
+                              false);
 
          if (!deps->readonly)
            reg_last->uses = alloc_INSN_LIST (insn, reg_last->uses);
@@ -2874,9 +3126,11 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
       EXECUTE_IF_SET_IN_REG_SET (reg_pending_uses, 0, i, rsi)
        {
          struct deps_reg *reg_last = &deps->reg_last[i];
-         add_dependence_list (insn, reg_last->sets, 0, REG_DEP_TRUE);
-         add_dependence_list (insn, reg_last->implicit_sets, 0, REG_DEP_ANTI);
-         add_dependence_list (insn, reg_last->clobbers, 0, REG_DEP_TRUE);
+         add_dependence_list (insn, reg_last->sets, 0, REG_DEP_TRUE, false);
+         add_dependence_list (insn, reg_last->implicit_sets, 0, REG_DEP_ANTI,
+                              false);
+         add_dependence_list (insn, reg_last->clobbers, 0, REG_DEP_TRUE,
+                              false);
 
          if (!deps->readonly)
            {
@@ -2889,10 +3143,11 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
        if (TEST_HARD_REG_BIT (implicit_reg_pending_uses, i))
          {
            struct deps_reg *reg_last = &deps->reg_last[i];
-           add_dependence_list (insn, reg_last->sets, 0, REG_DEP_TRUE);
+           add_dependence_list (insn, reg_last->sets, 0, REG_DEP_TRUE, false);
            add_dependence_list (insn, reg_last->implicit_sets, 0,
-                                REG_DEP_ANTI);
-           add_dependence_list (insn, reg_last->clobbers, 0, REG_DEP_TRUE);
+                                REG_DEP_ANTI, false);
+           add_dependence_list (insn, reg_last->clobbers, 0, REG_DEP_TRUE,
+                                false);
 
            if (!deps->readonly)
              {
@@ -2913,9 +3168,9 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
              for (list = reg_last->uses; list; list = XEXP (list, 1))
                {
                  rtx other = XEXP (list, 0);
-                 if (INSN_COND (other) != const_true_rtx
-                     && refers_to_regno_p (i, i + 1, INSN_COND (other), NULL))
-                   INSN_COND (other) = const_true_rtx;
+                 if (INSN_CACHED_COND (other) != const_true_rtx
+                     && refers_to_regno_p (i, INSN_CACHED_COND (other)))
+                   INSN_CACHED_COND (other) = const_true_rtx;
                }
            }
        }
@@ -2927,10 +3182,14 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
          EXECUTE_IF_SET_IN_REG_SET (reg_pending_clobbers, 0, i, rsi)
            {
              struct deps_reg *reg_last = &deps->reg_last[i];
-             add_dependence_list (insn, reg_last->sets, 0, REG_DEP_OUTPUT);
+             add_dependence_list (insn, reg_last->sets, 0, REG_DEP_OUTPUT,
+                                  false);
              add_dependence_list (insn, reg_last->implicit_sets, 0,
-                                  REG_DEP_ANTI);
-             add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI);
+                                  REG_DEP_ANTI, false);
+             add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI,
+                                  false);
+             add_dependence_list (insn, reg_last->control_uses, 0,
+                                  REG_DEP_CONTROL, false);
 
              if (!deps->readonly)
                {
@@ -2942,17 +3201,19 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
          EXECUTE_IF_SET_IN_REG_SET (reg_pending_sets, 0, i, rsi)
            {
              struct deps_reg *reg_last = &deps->reg_last[i];
-             add_dependence_list (insn, reg_last->sets, 0, REG_DEP_OUTPUT);
+             add_dependence_list (insn, reg_last->sets, 0, REG_DEP_OUTPUT,
+                                  false);
              add_dependence_list (insn, reg_last->implicit_sets, 0,
-                                  REG_DEP_ANTI);
-             add_dependence_list (insn, reg_last->clobbers, 0, REG_DEP_OUTPUT);
-             add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI);
+                                  REG_DEP_ANTI, false);
+             add_dependence_list (insn, reg_last->clobbers, 0, REG_DEP_OUTPUT,
+                                  false);
+             add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI,
+                                  false);
+             add_dependence_list (insn, reg_last->control_uses, 0,
+                                  REG_DEP_CONTROL, false);
 
              if (!deps->readonly)
-               {
-                 reg_last->sets = alloc_INSN_LIST (insn, reg_last->sets);
-                 SET_REGNO_REG_SET (&deps->reg_conditional_sets, i);
-               }
+               reg_last->sets = alloc_INSN_LIST (insn, reg_last->sets);
            }
        }
       else
@@ -2960,18 +3221,22 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
          EXECUTE_IF_SET_IN_REG_SET (reg_pending_clobbers, 0, i, rsi)
            {
              struct deps_reg *reg_last = &deps->reg_last[i];
-             if (reg_last->uses_length > MAX_PENDING_LIST_LENGTH
-                 || reg_last->clobbers_length > MAX_PENDING_LIST_LENGTH)
+             if (reg_last->uses_length >= MAX_PENDING_LIST_LENGTH
+                 || reg_last->clobbers_length >= MAX_PENDING_LIST_LENGTH)
                {
                  add_dependence_list_and_free (deps, insn, &reg_last->sets, 0,
-                                               REG_DEP_OUTPUT);
+                                               REG_DEP_OUTPUT, false);
                  add_dependence_list_and_free (deps, insn,
                                                &reg_last->implicit_sets, 0,
-                                               REG_DEP_ANTI);
+                                               REG_DEP_ANTI, false);
                  add_dependence_list_and_free (deps, insn, &reg_last->uses, 0,
-                                               REG_DEP_ANTI);
-                 add_dependence_list_and_free
-                   (deps, insn, &reg_last->clobbers, 0, REG_DEP_OUTPUT);
+                                               REG_DEP_ANTI, false);
+                 add_dependence_list_and_free (deps, insn,
+                                               &reg_last->control_uses, 0,
+                                               REG_DEP_ANTI, false);
+                 add_dependence_list_and_free (deps, insn,
+                                               &reg_last->clobbers, 0,
+                                               REG_DEP_OUTPUT, false);
 
                  if (!deps->readonly)
                    {
@@ -2982,10 +3247,14 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
                }
              else
                {
-                 add_dependence_list (insn, reg_last->sets, 0, REG_DEP_OUTPUT);
+                 add_dependence_list (insn, reg_last->sets, 0, REG_DEP_OUTPUT,
+                                      false);
                  add_dependence_list (insn, reg_last->implicit_sets, 0,
-                                      REG_DEP_ANTI);
-                 add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI);
+                                      REG_DEP_ANTI, false);
+                 add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI,
+                                      false);
+                 add_dependence_list (insn, reg_last->control_uses, 0,
+                                      REG_DEP_CONTROL, false);
                }
 
              if (!deps->readonly)
@@ -3000,33 +3269,45 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
              struct deps_reg *reg_last = &deps->reg_last[i];
 
              add_dependence_list_and_free (deps, insn, &reg_last->sets, 0,
-                                           REG_DEP_OUTPUT);
+                                           REG_DEP_OUTPUT, false);
              add_dependence_list_and_free (deps, insn,
                                            &reg_last->implicit_sets,
-                                           0, REG_DEP_ANTI);
+                                           0, REG_DEP_ANTI, false);
              add_dependence_list_and_free (deps, insn, &reg_last->clobbers, 0,
-                                           REG_DEP_OUTPUT);
+                                           REG_DEP_OUTPUT, false);
              add_dependence_list_and_free (deps, insn, &reg_last->uses, 0,
-                                           REG_DEP_ANTI);
+                                           REG_DEP_ANTI, false);
+             add_dependence_list (insn, reg_last->control_uses, 0,
+                                  REG_DEP_CONTROL, false);
 
              if (!deps->readonly)
                {
                  reg_last->sets = alloc_INSN_LIST (insn, reg_last->sets);
                  reg_last->uses_length = 0;
                  reg_last->clobbers_length = 0;
-                 CLEAR_REGNO_REG_SET (&deps->reg_conditional_sets, i);
                }
            }
        }
+      if (!deps->readonly)
+       {
+         EXECUTE_IF_SET_IN_REG_SET (reg_pending_control_uses, 0, i, rsi)
+           {
+             struct deps_reg *reg_last = &deps->reg_last[i];
+             reg_last->control_uses
+               = alloc_INSN_LIST (insn, reg_last->control_uses);
+           }
+       }
     }
 
   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     if (TEST_HARD_REG_BIT (implicit_reg_pending_clobbers, i))
       {
        struct deps_reg *reg_last = &deps->reg_last[i];
-       add_dependence_list (insn, reg_last->sets, 0, REG_DEP_ANTI);
-       add_dependence_list (insn, reg_last->clobbers, 0, REG_DEP_ANTI);
-       add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI);
+       add_dependence_list (insn, reg_last->sets, 0, REG_DEP_ANTI, false);
+       add_dependence_list (insn, reg_last->clobbers, 0, REG_DEP_ANTI, false);
+       add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI, false);
+       add_dependence_list (insn, reg_last->control_uses, 0, REG_DEP_ANTI,
+                            false);
 
        if (!deps->readonly)
          reg_last->implicit_sets
@@ -3050,6 +3331,7 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
   CLEAR_REG_SET (reg_pending_uses);
   CLEAR_REG_SET (reg_pending_clobbers);
   CLEAR_REG_SET (reg_pending_sets);
+  CLEAR_REG_SET (reg_pending_control_uses);
   CLEAR_HARD_REG_SET (implicit_reg_pending_clobbers);
   CLEAR_HARD_REG_SET (implicit_reg_pending_uses);
 
@@ -3063,15 +3345,16 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
          EXECUTE_IF_SET_IN_REG_SET (&deps->reg_last_in_use, 0, i, rsi)
            {
              struct deps_reg *reg_last = &deps->reg_last[i];
-             add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI);
+             add_dependence_list (insn, reg_last->uses, 0, REG_DEP_ANTI,
+                                  true);
              add_dependence_list (insn, reg_last->sets, 0,
                                   reg_pending_barrier == TRUE_BARRIER
-                                  ? REG_DEP_TRUE : REG_DEP_ANTI);
+                                  ? REG_DEP_TRUE : REG_DEP_ANTI, true);
              add_dependence_list (insn, reg_last->implicit_sets, 0,
-                                  REG_DEP_ANTI);
+                                  REG_DEP_ANTI, true);
              add_dependence_list (insn, reg_last->clobbers, 0,
                                   reg_pending_barrier == TRUE_BARRIER
-                                  ? REG_DEP_TRUE : REG_DEP_ANTI);
+                                  ? REG_DEP_TRUE : REG_DEP_ANTI, true);
            }
        }
       else
@@ -3080,16 +3363,21 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
            {
              struct deps_reg *reg_last = &deps->reg_last[i];
              add_dependence_list_and_free (deps, insn, &reg_last->uses, 0,
-                                           REG_DEP_ANTI);
+                                           REG_DEP_ANTI, true);
+             add_dependence_list_and_free (deps, insn,
+                                           &reg_last->control_uses, 0,
+                                           REG_DEP_CONTROL, true);
              add_dependence_list_and_free (deps, insn, &reg_last->sets, 0,
                                            reg_pending_barrier == TRUE_BARRIER
-                                           ? REG_DEP_TRUE : REG_DEP_ANTI);
+                                           ? REG_DEP_TRUE : REG_DEP_ANTI,
+                                           true);
              add_dependence_list_and_free (deps, insn,
                                            &reg_last->implicit_sets, 0,
-                                           REG_DEP_ANTI);
+                                           REG_DEP_ANTI, true);
              add_dependence_list_and_free (deps, insn, &reg_last->clobbers, 0,
                                            reg_pending_barrier == TRUE_BARRIER
-                                           ? REG_DEP_TRUE : REG_DEP_ANTI);
+                                           ? REG_DEP_TRUE : REG_DEP_ANTI,
+                                           true);
 
               if (!deps->readonly)
                 {
@@ -3107,13 +3395,11 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
             SET_REGNO_REG_SET (&deps->reg_last_in_use, i);
           }
 
-      /* Flush pending lists on jumps, but not on speculative checks.  */
-      if (JUMP_P (insn) && !(sel_sched_p ()
-                             && sel_insn_is_speculation_check (insn)))
+      /* Don't flush pending lists on speculative checks for
+        selective scheduling.  */
+      if (!sel_sched_p () || !sel_insn_is_speculation_check (insn))
        flush_pending_lists (deps, insn, true, true);
 
-      if (!deps->readonly)
-        CLEAR_REG_SET (&deps->reg_conditional_sets);
       reg_pending_barrier = NOT_A_BARRIER;
     }
 
@@ -3141,7 +3427,7 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
               instructions that follow seem like they should be part
               of the call group.
 
-              Also, if we did, fixup_sched_groups() would move the
+              Also, if we did, chain_to_prev_insn would move the
               deps of the debug insn to the call insn, modifying
               non-debug post-dependency counts of the debug insn
               dependencies and otherwise messing with the scheduling
@@ -3218,12 +3504,23 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
             change_spec_dep_to_hard (sd_it);
         }
     }
+
+  /* We do not yet have code to adjust REG_ARGS_SIZE, therefore we must
+     honor their original ordering.  */
+  if (find_reg_note (insn, REG_ARGS_SIZE, NULL))
+    {
+      if (deps->last_args_size)
+       add_dependence (insn, deps->last_args_size, REG_DEP_OUTPUT);
+      deps->last_args_size = insn;
+    }
 }
 
 /* Return TRUE if INSN might not always return normally (e.g. call exit,
    longjmp, loop forever, ...).  */
+/* FIXME: Why can't this function just use flags_from_decl_or_type and
+   test for ECF_NORETURN?  */
 static bool
-call_may_noreturn_p (rtx insn)
+call_may_noreturn_p (rtx_insn *insn)
 {
   rtx call;
 
@@ -3232,14 +3529,8 @@ call_may_noreturn_p (rtx insn)
       && !RTL_LOOPING_CONST_OR_PURE_CALL_P (insn))
     return false;
 
-  call = PATTERN (insn);
-  if (GET_CODE (call) == PARALLEL)
-    call = XVECEXP (call, 0, 0);
-  if (GET_CODE (call) == SET)
-    call = SET_SRC (call);
-  if (GET_CODE (call) == CALL
-      && MEM_P (XEXP (call, 0))
-      && GET_CODE (XEXP (XEXP (call, 0), 0)) == SYMBOL_REF)
+  call = get_call_rtx_from (insn);
+  if (call && GET_CODE (XEXP (XEXP (call, 0), 0)) == SYMBOL_REF)
     {
       rtx symbol = XEXP (XEXP (call, 0), 0);
       if (SYMBOL_REF_DECL (symbol)
@@ -3287,41 +3578,97 @@ call_may_noreturn_p (rtx insn)
   return true;
 }
 
+/* Return true if INSN should be made dependent on the previous instruction
+   group, and if all INSN's dependencies should be moved to the first
+   instruction of that group.  */
+
+static bool
+chain_to_prev_insn_p (rtx_insn *insn)
+{
+  /* INSN forms a group with the previous instruction.  */
+  if (SCHED_GROUP_P (insn))
+    return true;
+
+  /* If the previous instruction clobbers a register R and this one sets
+     part of R, the clobber was added specifically to help us track the
+     liveness of R.  There's no point scheduling the clobber and leaving
+     INSN behind, especially if we move the clobber to another block.  */
+  rtx_insn *prev = prev_nonnote_nondebug_insn (insn);
+  if (prev
+      && INSN_P (prev)
+      && BLOCK_FOR_INSN (prev) == BLOCK_FOR_INSN (insn)
+      && GET_CODE (PATTERN (prev)) == CLOBBER)
+    {
+      rtx x = XEXP (PATTERN (prev), 0);
+      if (set_of (x, insn))
+       return true;
+    }
+
+  return false;
+}
+
 /* Analyze INSN with DEPS as a context.  */
 void
-deps_analyze_insn (struct deps_desc *deps, rtx insn)
+deps_analyze_insn (struct deps_desc *deps, rtx_insn *insn)
 {
   if (sched_deps_info->start_insn)
     sched_deps_info->start_insn (insn);
 
   /* Record the condition for this insn.  */
   if (NONDEBUG_INSN_P (insn))
-    sched_get_condition_with_rev (insn, NULL);
+    {
+      rtx t;
+      sched_get_condition_with_rev (insn, NULL);
+      t = INSN_CACHED_COND (insn);
+      INSN_COND_DEPS (insn) = NULL;
+      if (reload_completed
+         && (current_sched_info->flags & DO_PREDICATION)
+         && COMPARISON_P (t)
+         && REG_P (XEXP (t, 0))
+         && CONSTANT_P (XEXP (t, 1)))
+       {
+         unsigned int regno;
+         int nregs;
+         rtx_insn_list *cond_deps = NULL;
+         t = XEXP (t, 0);
+         regno = REGNO (t);
+         nregs = REG_NREGS (t);
+         while (nregs-- > 0)
+           {
+             struct deps_reg *reg_last = &deps->reg_last[regno + nregs];
+             cond_deps = concat_INSN_LIST (reg_last->sets, cond_deps);
+             cond_deps = concat_INSN_LIST (reg_last->clobbers, cond_deps);
+             cond_deps = concat_INSN_LIST (reg_last->implicit_sets, cond_deps);
+           }
+         INSN_COND_DEPS (insn) = cond_deps;
+       }
+    }
 
-  if (NONJUMP_INSN_P (insn) || DEBUG_INSN_P (insn) || JUMP_P (insn))
+  if (JUMP_P (insn))
     {
       /* Make each JUMP_INSN (but not a speculative check)
          a scheduling barrier for memory references.  */
       if (!deps->readonly
-          && JUMP_P (insn)
           && !(sel_sched_p ()
                && sel_insn_is_speculation_check (insn)))
         {
           /* Keep the list a reasonable size.  */
-          if (deps->pending_flush_length++ > MAX_PENDING_LIST_LENGTH)
+          if (deps->pending_flush_length++ >= MAX_PENDING_LIST_LENGTH)
             flush_pending_lists (deps, insn, true, true);
           else
-           {
-             deps->last_pending_memory_flush
-               = alloc_INSN_LIST (insn, deps->last_pending_memory_flush);
-             /* Signal to sched_analyze_insn that this jump stands
-                just for its own, not any other pending memory
-                reads/writes flush_pending_lists had to flush.  */
-             PUT_REG_NOTE_KIND (deps->last_pending_memory_flush,
-                                NON_FLUSH_JUMP_KIND);
-           }
+           deps->pending_jump_insns
+              = alloc_INSN_LIST (insn, deps->pending_jump_insns);
         }
 
+      /* For each insn which shouldn't cross a jump, add a dependence.  */
+      add_dependence_list_and_free (deps, insn,
+                                   &deps->sched_before_next_jump, 1,
+                                   REG_DEP_ANTI, true);
+
+      sched_analyze_insn (deps, PATTERN (insn), insn);
+    }
+  else if (NONJUMP_INSN_P (insn) || DEBUG_INSN_P (insn))
+    {
       sched_analyze_insn (deps, PATTERN (insn), insn);
     }
   else if (CALL_P (insn))
@@ -3372,7 +3719,7 @@ deps_analyze_insn (struct deps_desc *deps, rtx insn)
          between that insn and this call insn.  */
       add_dependence_list_and_free (deps, insn,
                                     &deps->sched_before_next_call, 1,
-                                    REG_DEP_ANTI);
+                                    REG_DEP_ANTI, true);
 
       sched_analyze_insn (deps, PATTERN (insn), insn);
 
@@ -3416,24 +3763,19 @@ deps_analyze_insn (struct deps_desc *deps, rtx insn)
   if (sched_deps_info->use_cselib)
     cselib_process_insn (insn);
 
-  /* EH_REGION insn notes can not appear until well after we complete
-     scheduling.  */
-  if (NOTE_P (insn))
-    gcc_assert (NOTE_KIND (insn) != NOTE_INSN_EH_REGION_BEG
-               && NOTE_KIND (insn) != NOTE_INSN_EH_REGION_END);
-
   if (sched_deps_info->finish_insn)
     sched_deps_info->finish_insn ();
 
   /* Fixup the dependencies in the sched group.  */
   if ((NONJUMP_INSN_P (insn) || JUMP_P (insn))
-      && SCHED_GROUP_P (insn) && !sel_sched_p ())
-    fixup_sched_groups (insn);
+      && chain_to_prev_insn_p (insn)
+      && !sel_sched_p ())
+    chain_to_prev_insn (insn);
 }
 
 /* Initialize DEPS for the new block beginning with HEAD.  */
 void
-deps_start_bb (struct deps_desc *deps, rtx head)
+deps_start_bb (struct deps_desc *deps, rtx_insn *head)
 {
   gcc_assert (!deps->readonly);
 
@@ -3442,7 +3784,7 @@ deps_start_bb (struct deps_desc *deps, rtx head)
      hard registers correct.  */
   if (! reload_completed && !LABEL_P (head))
     {
-      rtx insn = prev_nonnote_nondebug_insn (head);
+      rtx_insn *insn = prev_nonnote_nondebug_insn (head);
 
       if (insn && CALL_P (insn))
        deps->in_post_call_group_p = post_call_initial;
@@ -3452,9 +3794,9 @@ deps_start_bb (struct deps_desc *deps, rtx head)
 /* Analyze every insn between HEAD and TAIL inclusive, creating backward
    dependencies for each insn.  */
 void
-sched_analyze (struct deps_desc *deps, rtx head, rtx tail)
+sched_analyze (struct deps_desc *deps, rtx_insn *head, rtx_insn *tail)
 {
-  rtx insn;
+  rtx_insn *insn;
 
   if (sched_deps_info->use_cselib)
     cselib_init (CSELIB_RECORD_MEMORY);
@@ -3468,6 +3810,10 @@ sched_analyze (struct deps_desc *deps, rtx head, rtx tail)
        {
          /* And initialize deps_lists.  */
          sd_init_insn (insn);
+         /* Clean up SCHED_GROUP_P which may be set by last
+            scheduler pass.  */
+         if (SCHED_GROUP_P (insn))
+           SCHED_GROUP_P (insn) = 0;
        }
 
       deps_analyze_insn (deps, insn);
@@ -3485,7 +3831,7 @@ sched_analyze (struct deps_desc *deps, rtx head, rtx tail)
 /* Helper for sched_free_deps ().
    Delete INSN's (RESOLVED_P) backward dependencies.  */
 static void
-delete_dep_nodes_in_back_deps (rtx insn, bool resolved_p)
+delete_dep_nodes_in_back_deps (rtx_insn *insn, bool resolved_p)
 {
   sd_iterator_def sd_it;
   dep_t dep;
@@ -3513,10 +3859,10 @@ delete_dep_nodes_in_back_deps (rtx insn, bool resolved_p)
 /* Delete (RESOLVED_P) dependencies between HEAD and TAIL together with
    deps_lists.  */
 void
-sched_free_deps (rtx head, rtx tail, bool resolved_p)
+sched_free_deps (rtx_insn *head, rtx_insn *tail, bool resolved_p)
 {
-  rtx insn;
-  rtx next_tail = NEXT_INSN (tail);
+  rtx_insn *insn;
+  rtx_insn *next_tail = NEXT_INSN (tail);
 
   /* We make two passes since some insns may be scheduled before their
      dependencies are resolved.  */
@@ -3555,12 +3901,12 @@ init_deps (struct deps_desc *deps, bool lazy_reg_last)
   else
     deps->reg_last = XCNEWVEC (struct deps_reg, max_reg);
   INIT_REG_SET (&deps->reg_last_in_use);
-  INIT_REG_SET (&deps->reg_conditional_sets);
 
   deps->pending_read_insns = 0;
   deps->pending_read_mems = 0;
   deps->pending_write_insns = 0;
   deps->pending_write_mems = 0;
+  deps->pending_jump_insns = 0;
   deps->pending_read_list_length = 0;
   deps->pending_write_list_length = 0;
   deps->pending_flush_length = 0;
@@ -3568,8 +3914,10 @@ init_deps (struct deps_desc *deps, bool lazy_reg_last)
   deps->last_function_call = 0;
   deps->last_function_call_may_noreturn = 0;
   deps->sched_before_next_call = 0;
+  deps->sched_before_next_jump = 0;
   deps->in_post_call_group_p = not_post_call;
   deps->last_debug_insn = 0;
+  deps->last_args_size = 0;
   deps->last_reg_pending_barrier = NOT_A_BARRIER;
   deps->readonly = 0;
 }
@@ -3620,11 +3968,12 @@ free_deps (struct deps_desc *deps)
        free_INSN_LIST_list (&reg_last->sets);
       if (reg_last->implicit_sets)
        free_INSN_LIST_list (&reg_last->implicit_sets);
+      if (reg_last->control_uses)
+       free_INSN_LIST_list (&reg_last->control_uses);
       if (reg_last->clobbers)
        free_INSN_LIST_list (&reg_last->clobbers);
     }
   CLEAR_REG_SET (&deps->reg_last_in_use);
-  CLEAR_REG_SET (&deps->reg_conditional_sets);
 
   /* As we initialize reg_last lazily, it is possible that we didn't allocate
      it at all.  */
@@ -3634,10 +3983,9 @@ free_deps (struct deps_desc *deps)
   deps = NULL;
 }
 
-/* Remove INSN from dependence contexts DEPS.  Caution: reg_conditional_sets
-   is not handled.  */
+/* Remove INSN from dependence contexts DEPS.  */
 void
-remove_from_deps (struct deps_desc *deps, rtx insn)
+remove_from_deps (struct deps_desc *deps, rtx_insn *insn)
 {
   int removed;
   unsigned i;
@@ -3650,6 +3998,9 @@ remove_from_deps (struct deps_desc *deps, rtx insn)
   removed = remove_from_both_dependence_lists (insn, &deps->pending_write_insns,
                                                &deps->pending_write_mems);
   deps->pending_write_list_length -= removed;
+
+  removed = remove_from_dependence_list (insn, &deps->pending_jump_insns);
+  deps->pending_flush_length -= removed;
   removed = remove_from_dependence_list (insn, &deps->last_pending_memory_flush);
   deps->pending_flush_length -= removed;
 
@@ -3682,12 +4033,9 @@ remove_from_deps (struct deps_desc *deps, rtx insn)
 static void
 init_deps_data_vector (void)
 {
-  int reserve = (sched_max_luid + 1
-                 - VEC_length (haifa_deps_insn_data_def, h_d_i_d));
-  if (reserve > 0
-      && ! VEC_space (haifa_deps_insn_data_def, h_d_i_d, reserve))
-    VEC_safe_grow_cleared (haifa_deps_insn_data_def, heap, h_d_i_d,
-                           3 * sched_max_luid / 2);
+  int reserve = (sched_max_luid + 1 - h_d_i_d.length ());
+  if (reserve > 0 && ! h_d_i_d.space (reserve))
+    h_d_i_d.safe_grow_cleared (3 * sched_max_luid / 2);
 }
 
 /* If it is profitable to use them, initialize or extend (depending on
@@ -3697,7 +4045,7 @@ sched_deps_init (bool global_p)
 {
   /* Average number of insns in the basic block.
      '+ 1' is used to make it nonzero.  */
-  int insns_in_block = sched_max_luid / n_basic_blocks + 1;
+  int insns_in_block = sched_max_luid / n_basic_blocks_for_fn (cfun) + 1;
 
   init_deps_data_vector ();
 
@@ -3717,10 +4065,10 @@ sched_deps_init (bool global_p)
 
   if (global_p)
     {
-      dl_pool = create_alloc_pool ("deps_list", sizeof (struct _deps_list),
+      dl_pool = new pool_allocator<_deps_list> ("deps_list",
                                    /* Allocate lists for one block at a time.  */
                                    insns_in_block);
-      dn_pool = create_alloc_pool ("dep_node", sizeof (struct _dep_node),
+      dn_pool = new pool_allocator<_dep_node> ("dep_node",
                                    /* Allocate nodes for one block at a time.
                                       We assume that average insn has
                                       5 producers.  */
@@ -3744,6 +4092,8 @@ extend_dependency_caches (int n, bool create_p)
                                            output_dependency_cache, luid);
       anti_dependency_cache = XRESIZEVEC (bitmap_head, anti_dependency_cache,
                                          luid);
+      control_dependency_cache = XRESIZEVEC (bitmap_head, control_dependency_cache,
+                                         luid);
 
       if (current_sched_info->flags & DO_SPECULATION)
         spec_dependency_cache = XRESIZEVEC (bitmap_head, spec_dependency_cache,
@@ -3754,6 +4104,7 @@ extend_dependency_caches (int n, bool create_p)
          bitmap_initialize (&true_dependency_cache[i], 0);
          bitmap_initialize (&output_dependency_cache[i], 0);
          bitmap_initialize (&anti_dependency_cache[i], 0);
+         bitmap_initialize (&control_dependency_cache[i], 0);
 
           if (current_sched_info->flags & DO_SPECULATION)
             bitmap_initialize (&spec_dependency_cache[i], 0);
@@ -3767,11 +4118,12 @@ void
 sched_deps_finish (void)
 {
   gcc_assert (deps_pools_are_empty_p ());
-  free_alloc_pool_if_empty (&dn_pool);
-  free_alloc_pool_if_empty (&dl_pool);
-  gcc_assert (dn_pool == NULL && dl_pool == NULL);
+  dn_pool->release_if_empty ();
+  dn_pool = NULL;
+  dl_pool->release_if_empty ();
+  dl_pool = NULL;
 
-  VEC_free (haifa_deps_insn_data_def, heap, h_d_i_d);
+  h_d_i_d.release ();
   cache_size = 0;
 
   if (true_dependency_cache)
@@ -3783,6 +4135,7 @@ sched_deps_finish (void)
          bitmap_clear (&true_dependency_cache[i]);
          bitmap_clear (&output_dependency_cache[i]);
          bitmap_clear (&anti_dependency_cache[i]);
+         bitmap_clear (&control_dependency_cache[i]);
 
           if (sched_deps_info->generate_spec_deps)
             bitmap_clear (&spec_dependency_cache[i]);
@@ -3793,6 +4146,8 @@ sched_deps_finish (void)
       output_dependency_cache = NULL;
       free (anti_dependency_cache);
       anti_dependency_cache = NULL;
+      free (control_dependency_cache);
+      control_dependency_cache = NULL;
 
       if (sched_deps_info->generate_spec_deps)
         {
@@ -3814,6 +4169,7 @@ init_deps_global (void)
   reg_pending_sets = ALLOC_REG_SET (&reg_obstack);
   reg_pending_clobbers = ALLOC_REG_SET (&reg_obstack);
   reg_pending_uses = ALLOC_REG_SET (&reg_obstack);
+  reg_pending_control_uses = ALLOC_REG_SET (&reg_obstack);
   reg_pending_barrier = NOT_A_BARRIER;
 
   if (!sel_sched_p () || sched_emulate_haifa_p)
@@ -3838,6 +4194,7 @@ finish_deps_global (void)
   FREE_REG_SET (reg_pending_sets);
   FREE_REG_SET (reg_pending_clobbers);
   FREE_REG_SET (reg_pending_uses);
+  FREE_REG_SET (reg_pending_control_uses);
 }
 
 /* Estimate the weakness of dependence between MEM1 and MEM2.  */
@@ -3871,8 +4228,8 @@ estimate_dep_weak (rtx mem1, rtx mem2)
 /* Add or update backward dependence between INSN and ELEM with type DEP_TYPE.
    This function can handle same INSN and ELEM (INSN == ELEM).
    It is a convenience wrapper.  */
-void
-add_dependence (rtx insn, rtx elem, enum reg_note dep_type)
+static void
+add_dependence_1 (rtx_insn *insn, rtx_insn *elem, enum reg_note dep_type)
 {
   ds_t ds;
   bool internal;
@@ -3881,6 +4238,8 @@ add_dependence (rtx insn, rtx elem, enum reg_note dep_type)
     ds = DEP_TRUE;
   else if (dep_type == REG_DEP_OUTPUT)
     ds = DEP_OUTPUT;
+  else if (dep_type == REG_DEP_CONTROL)
+    ds = DEP_CONTROL;
   else
     {
       gcc_assert (dep_type == REG_DEP_ANTI);
@@ -3900,8 +4259,9 @@ add_dependence (rtx insn, rtx elem, enum reg_note dep_type)
     cur_insn = NULL;
 }
 
-/* Return weakness of speculative type TYPE in the dep_status DS.  */
-dw_t
+/* Return weakness of speculative type TYPE in the dep_status DS,
+   without checking to prevent ICEs on malformed input.  */
+static dw_t
 get_dep_weak_1 (ds_t ds, ds_t type)
 {
   ds = ds & type;
@@ -3918,6 +4278,7 @@ get_dep_weak_1 (ds_t ds, ds_t type)
   return (dw_t) ds;
 }
 
+/* Return weakness of speculative type TYPE in the dep_status DS.  */
 dw_t
 get_dep_weak (ds_t ds, ds_t type)
 {
@@ -4147,10 +4508,12 @@ dump_ds (FILE *f, ds_t s)
 
   if (s & DEP_TRUE)
     fprintf (f, "DEP_TRUE; ");
-  if (s & DEP_ANTI)
-    fprintf (f, "DEP_ANTI; ");
   if (s & DEP_OUTPUT)
     fprintf (f, "DEP_OUTPUT; ");
+  if (s & DEP_ANTI)
+    fprintf (f, "DEP_ANTI; ");
+  if (s & DEP_CONTROL)
+    fprintf (f, "DEP_CONTROL; ");
 
   fprintf (f, "}");
 }
@@ -4185,10 +4548,13 @@ check_dep (dep_t dep, bool relaxed_p)
   else if (dt == REG_DEP_OUTPUT)
     gcc_assert ((ds & DEP_OUTPUT)
                && !(ds & DEP_TRUE));
-  else
-    gcc_assert ((dt == REG_DEP_ANTI)
-               && (ds & DEP_ANTI)
+  else if (dt == REG_DEP_ANTI)
+    gcc_assert ((ds & DEP_ANTI)
                && !(ds & (DEP_OUTPUT | DEP_TRUE)));
+  else
+    gcc_assert (dt == REG_DEP_CONTROL
+               && (ds & DEP_CONTROL)
+               && !(ds & (DEP_OUTPUT | DEP_ANTI | DEP_TRUE)));
 
   /* HARD_DEP can not appear in dep_status of a link.  */
   gcc_assert (!(ds & HARD_DEP));
@@ -4246,4 +4612,314 @@ check_dep (dep_t dep, bool relaxed_p)
 }
 #endif /* ENABLE_CHECKING */
 
+/* The following code discovers opportunities to switch a memory reference
+   and an increment by modifying the address.  We ensure that this is done
+   only for dependencies that are only used to show a single register
+   dependence (using DEP_NONREG and DEP_MULTIPLE), and so that every memory
+   instruction involved is subject to only one dep that can cause a pattern
+   change.
+
+   When we discover a suitable dependency, we fill in the dep_replacement
+   structure to show how to modify the memory reference.  */
+
+/* Holds information about a pair of memory reference and register increment
+   insns which depend on each other, but could possibly be interchanged.  */
+struct mem_inc_info
+{
+  rtx_insn *inc_insn;
+  rtx_insn *mem_insn;
+
+  rtx *mem_loc;
+  /* A register occurring in the memory address for which we wish to break
+     the dependence.  This must be identical to the destination register of
+     the increment.  */
+  rtx mem_reg0;
+  /* Any kind of index that is added to that register.  */
+  rtx mem_index;
+  /* The constant offset used in the memory address.  */
+  HOST_WIDE_INT mem_constant;
+  /* The constant added in the increment insn.  Negated if the increment is
+     after the memory address.  */
+  HOST_WIDE_INT inc_constant;
+  /* The source register used in the increment.  May be different from mem_reg0
+     if the increment occurs before the memory address.  */
+  rtx inc_input;
+};
+
+/* Verify that the memory location described in MII can be replaced with
+   one using NEW_ADDR.  Return the new memory reference or NULL_RTX.  The
+   insn remains unchanged by this function.  */
+
+static rtx
+attempt_change (struct mem_inc_info *mii, rtx new_addr)
+{
+  rtx mem = *mii->mem_loc;
+  rtx new_mem;
+
+  /* Jump through a lot of hoops to keep the attributes up to date.  We
+     do not want to call one of the change address variants that take
+     an offset even though we know the offset in many cases.  These
+     assume you are changing where the address is pointing by the
+     offset.  */
+  new_mem = replace_equiv_address_nv (mem, new_addr);
+  if (! validate_change (mii->mem_insn, mii->mem_loc, new_mem, 0))
+    {
+      if (sched_verbose >= 5)
+       fprintf (sched_dump, "validation failure\n");
+      return NULL_RTX;
+    }
+
+  /* Put back the old one.  */
+  validate_change (mii->mem_insn, mii->mem_loc, mem, 0);
+
+  return new_mem;
+}
+
+/* Return true if INSN is of a form "a = b op c" where a and b are
+   regs.  op is + if c is a reg and +|- if c is a const.  Fill in
+   informantion in MII about what is found.
+   BEFORE_MEM indicates whether the increment is found before or after
+   a corresponding memory reference.  */
+
+static bool
+parse_add_or_inc (struct mem_inc_info *mii, rtx_insn *insn, bool before_mem)
+{
+  rtx pat = single_set (insn);
+  rtx src, cst;
+  bool regs_equal;
+
+  if (RTX_FRAME_RELATED_P (insn) || !pat)
+    return false;
+
+  /* Result must be single reg.  */
+  if (!REG_P (SET_DEST (pat)))
+    return false;
+
+  if (GET_CODE (SET_SRC (pat)) != PLUS)
+    return false;
+
+  mii->inc_insn = insn;
+  src = SET_SRC (pat);
+  mii->inc_input = XEXP (src, 0);
+
+  if (!REG_P (XEXP (src, 0)))
+    return false;
+
+  if (!rtx_equal_p (SET_DEST (pat), mii->mem_reg0))
+    return false;
+
+  cst = XEXP (src, 1);
+  if (!CONST_INT_P (cst))
+    return false;
+  mii->inc_constant = INTVAL (cst);
+
+  regs_equal = rtx_equal_p (mii->inc_input, mii->mem_reg0);
+
+  if (!before_mem)
+    {
+      mii->inc_constant = -mii->inc_constant;
+      if (!regs_equal)
+       return false;
+    }
+
+  if (regs_equal && REGNO (SET_DEST (pat)) == STACK_POINTER_REGNUM)
+    {
+      /* Note that the sign has already been reversed for !before_mem.  */
+      if (STACK_GROWS_DOWNWARD)
+       return mii->inc_constant > 0;
+      else
+       return mii->inc_constant < 0;
+    }
+  return true;
+}
+
+/* Once a suitable mem reference has been found and the corresponding data
+   in MII has been filled in, this function is called to find a suitable
+   add or inc insn involving the register we found in the memory
+   reference.  */
+
+static bool
+find_inc (struct mem_inc_info *mii, bool backwards)
+{
+  sd_iterator_def sd_it;
+  dep_t dep;
+
+  sd_it = sd_iterator_start (mii->mem_insn,
+                            backwards ? SD_LIST_HARD_BACK : SD_LIST_FORW);
+  while (sd_iterator_cond (&sd_it, &dep))
+    {
+      dep_node_t node = DEP_LINK_NODE (*sd_it.linkp);
+      rtx_insn *pro = DEP_PRO (dep);
+      rtx_insn *con = DEP_CON (dep);
+      rtx_insn *inc_cand = backwards ? pro : con;
+      if (DEP_NONREG (dep) || DEP_MULTIPLE (dep))
+       goto next;
+      if (parse_add_or_inc (mii, inc_cand, backwards))
+       {
+         struct dep_replacement *desc;
+         df_ref def;
+         rtx newaddr, newmem;
+
+         if (sched_verbose >= 5)
+           fprintf (sched_dump, "candidate mem/inc pair: %d %d\n",
+                    INSN_UID (mii->mem_insn), INSN_UID (inc_cand));
+
+         /* Need to assure that none of the operands of the inc
+            instruction are assigned to by the mem insn.  */
+         FOR_EACH_INSN_DEF (def, mii->mem_insn)
+           if (reg_overlap_mentioned_p (DF_REF_REG (def), mii->inc_input)
+               || reg_overlap_mentioned_p (DF_REF_REG (def), mii->mem_reg0))
+             {
+               if (sched_verbose >= 5)
+                 fprintf (sched_dump,
+                          "inc conflicts with store failure.\n");
+               goto next;
+             }
+
+         newaddr = mii->inc_input;
+         if (mii->mem_index != NULL_RTX)
+           newaddr = gen_rtx_PLUS (GET_MODE (newaddr), newaddr,
+                                   mii->mem_index);
+         newaddr = plus_constant (GET_MODE (newaddr), newaddr,
+                                  mii->mem_constant + mii->inc_constant);
+         newmem = attempt_change (mii, newaddr);
+         if (newmem == NULL_RTX)
+           goto next;
+         if (sched_verbose >= 5)
+           fprintf (sched_dump, "successful address replacement\n");
+         desc = XCNEW (struct dep_replacement);
+         DEP_REPLACE (dep) = desc;
+         desc->loc = mii->mem_loc;
+         desc->newval = newmem;
+         desc->orig = *desc->loc;
+         desc->insn = mii->mem_insn;
+         move_dep_link (DEP_NODE_BACK (node), INSN_HARD_BACK_DEPS (con),
+                        INSN_SPEC_BACK_DEPS (con));
+         if (backwards)
+           {
+             FOR_EACH_DEP (mii->inc_insn, SD_LIST_BACK, sd_it, dep)
+               add_dependence_1 (mii->mem_insn, DEP_PRO (dep),
+                                 REG_DEP_TRUE);
+           }
+         else
+           {
+             FOR_EACH_DEP (mii->inc_insn, SD_LIST_FORW, sd_it, dep)
+               add_dependence_1 (DEP_CON (dep), mii->mem_insn,
+                                 REG_DEP_ANTI);
+           }
+         return true;
+       }
+    next:
+      sd_iterator_next (&sd_it);
+    }
+  return false;
+}
+
+/* A recursive function that walks ADDRESS_OF_X to find memory references
+   which could be modified during scheduling.  We call find_inc for each
+   one we find that has a recognizable form.  MII holds information about
+   the pair of memory/increment instructions.
+   We ensure that every instruction with a memory reference (which will be
+   the location of the replacement) is assigned at most one breakable
+   dependency.  */
+
+static bool
+find_mem (struct mem_inc_info *mii, rtx *address_of_x)
+{
+  rtx x = *address_of_x;
+  enum rtx_code code = GET_CODE (x);
+  const char *const fmt = GET_RTX_FORMAT (code);
+  int i;
+
+  if (code == MEM)
+    {
+      rtx reg0 = XEXP (x, 0);
+
+      mii->mem_loc = address_of_x;
+      mii->mem_index = NULL_RTX;
+      mii->mem_constant = 0;
+      if (GET_CODE (reg0) == PLUS && CONST_INT_P (XEXP (reg0, 1)))
+       {
+         mii->mem_constant = INTVAL (XEXP (reg0, 1));
+         reg0 = XEXP (reg0, 0);
+       }
+      if (GET_CODE (reg0) == PLUS)
+       {
+         mii->mem_index = XEXP (reg0, 1);
+         reg0 = XEXP (reg0, 0);
+       }
+      if (REG_P (reg0))
+       {
+         df_ref use;
+         int occurrences = 0;
+
+         /* Make sure this reg appears only once in this insn.  Can't use
+            count_occurrences since that only works for pseudos.  */
+         FOR_EACH_INSN_USE (use, mii->mem_insn)
+           if (reg_overlap_mentioned_p (reg0, DF_REF_REG (use)))
+             if (++occurrences > 1)
+               {
+                 if (sched_verbose >= 5)
+                   fprintf (sched_dump, "mem count failure\n");
+                 return false;
+               }
+
+         mii->mem_reg0 = reg0;
+         return find_inc (mii, true) || find_inc (mii, false);
+       }
+      return false;
+    }
+
+  if (code == SIGN_EXTRACT || code == ZERO_EXTRACT)
+    {
+      /* If REG occurs inside a MEM used in a bit-field reference,
+        that is unacceptable.  */
+      return false;
+    }
+
+  /* Time for some deep diving.  */
+  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+    {
+      if (fmt[i] == 'e')
+       {
+         if (find_mem (mii, &XEXP (x, i)))
+           return true;
+       }
+      else if (fmt[i] == 'E')
+       {
+         int j;
+         for (j = XVECLEN (x, i) - 1; j >= 0; j--)
+           if (find_mem (mii, &XVECEXP (x, i, j)))
+             return true;
+       }
+    }
+  return false;
+}
+
+
+/* Examine the instructions between HEAD and TAIL and try to find
+   dependencies that can be broken by modifying one of the patterns.  */
+
+void
+find_modifiable_mems (rtx_insn *head, rtx_insn *tail)
+{
+  rtx_insn *insn, *next_tail = NEXT_INSN (tail);
+  int success_in_block = 0;
+
+  for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
+    {
+      struct mem_inc_info mii;
+
+      if (!NONDEBUG_INSN_P (insn) || RTX_FRAME_RELATED_P (insn))
+       continue;
+
+      mii.mem_insn = insn;
+      if (find_mem (&mii, &PATTERN (insn)))
+       success_in_block++;
+    }
+  if (success_in_block && sched_verbose >= 5)
+    fprintf (sched_dump, "%d candidates for address modification found.\n",
+            success_in_block);
+}
+
 #endif /* INSN_SCHEDULING */