IA MCU psABI support: changes to libraries
[gcc.git] / gcc / sched-deps.c
index a8b0d521912a49f83fb51ad57867221224052692..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, 2012
-   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,8 @@ 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"
@@ -39,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"
@@ -57,7 +63,8 @@ along with GCC; see the file COPYING3.  If not see
 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
@@ -102,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;
 
@@ -317,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;
@@ -326,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);
 
@@ -350,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;
@@ -374,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;
@@ -391,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.
@@ -434,6 +446,8 @@ dep_spec_p (dep_t dep)
       if (DEP_TYPE (dep) == REG_DEP_CONTROL)
        return true;
     }
+  if (DEP_REPLACE (dep) != NULL)
+    return true;
   return false;
 }
 
@@ -472,20 +486,25 @@ 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_1 (rtx, rtx, enum reg_note);
-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 chain_to_prev_insn (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,
@@ -517,7 +536,7 @@ deps_may_trap_p (const_rtx mem)
    it is set to TRUE when the returned comparison should be reversed
    to get the actual condition.  */
 static rtx
-sched_get_condition_with_rev_uncached (const_rtx insn, bool *rev)
+sched_get_condition_with_rev_uncached (const rtx_insn *insn, bool *rev)
 {
   rtx pat = PATTERN (insn);
   rtx src;
@@ -556,7 +575,7 @@ sched_get_condition_with_rev_uncached (const_rtx insn, bool *rev)
    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)
+sched_get_reverse_condition_uncached (const rtx_insn *insn)
 {
   bool rev;
   rtx cond = sched_get_condition_with_rev_uncached (insn, &rev);
@@ -576,7 +595,7 @@ sched_get_reverse_condition_uncached (const_rtx insn)
    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, bool *rev)
+sched_get_condition_with_rev (const rtx_insn *insn, bool *rev)
 {
   bool tmp;
 
@@ -609,7 +628,7 @@ sched_get_condition_with_rev (const_rtx insn, bool *rev)
 
 /* 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);
 }
@@ -635,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;
@@ -662,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;
@@ -673,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)))
@@ -788,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 ();
@@ -801,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.  */
 
@@ -918,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));
 
@@ -1109,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));
 
@@ -1136,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.  */
@@ -1221,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:
@@ -1284,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)
     {
@@ -1310,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);
 
@@ -1353,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),
@@ -1374,8 +1403,8 @@ 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 (dep_spec_p (dep))
     move_dep_link (DEP_NODE_BACK (node), INSN_RESOLVED_BACK_DEPS (con),
@@ -1391,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;
@@ -1416,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;
 
@@ -1501,7 +1530,7 @@ sd_debug_lists (rtx insn, sd_list_types_def types)
    impossible; otherwise we add additional true dependencies on the
    INSN_COND_DEPS list of the jump (which PRO must be).  */
 void
-add_dependence (rtx con, rtx pro, enum reg_note dep_type)
+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))
@@ -1512,8 +1541,8 @@ add_dependence (rtx con, rtx pro, enum reg_note dep_type)
      condition.  */
   if (dep_type == REG_DEP_CONTROL)
     {
-      rtx real_pro = pro;
-      rtx other = real_insn_for_shadow (real_pro);
+      rtx_insn *real_pro = pro;
+      rtx_insn *other = real_insn_for_shadow (real_pro);
       rtx cond;
 
       if (other != NULL_RTX)
@@ -1538,70 +1567,67 @@ add_dependence (rtx con, rtx pro, enum reg_note dep_type)
            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);
+                              REG_DEP_TRUE, false);
        }
     }
          
   add_dependence_1 (con, pro, dep_type);
 }
 
-/* A convenience wrapper to operate on an entire list.  */
+/* 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 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;
@@ -1609,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;
 
@@ -1623,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;
@@ -1632,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;
@@ -1653,16 +1681,16 @@ delete_all_dependences (rtx insn)
    the previous nonnote insn.  */
 
 static void
-chain_to_prev_insn (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
        {
@@ -1702,11 +1730,12 @@ chain_to_prev_insn (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)
@@ -1723,8 +1752,8 @@ 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)
     {
@@ -1732,8 +1761,8 @@ add_insn_mem_dependence (struct deps_desc *deps, bool read_p,
       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
@@ -1741,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);
@@ -1756,14 +1785,25 @@ 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);
+                               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)
     {
@@ -1773,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);
 
@@ -1813,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))
     {
@@ -1828,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);
 }
 
@@ -1865,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);
@@ -1903,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;
 
@@ -1915,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;
@@ -1926,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;
 
@@ -1956,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;
@@ -2076,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);
@@ -2136,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);
 }
@@ -2162,7 +2203,7 @@ 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;
@@ -2275,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 ()
@@ -2344,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);
        }
     }
 }
@@ -2354,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);
@@ -2422,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);
 
@@ -2446,7 +2487,7 @@ sched_analyze_1 (struct deps_desc *deps, rtx x, rtx insn)
 
       if (sched_deps_info->use_cselib)
        {
-         enum machine_mode address_mode = get_address_mode (dest);
+         machine_mode address_mode = get_address_mode (dest);
 
          t = shallow_copy_rtx (dest);
          cselib_lookup_from_insn (XEXP (t, 0), address_mode, 1,
@@ -2460,7 +2501,7 @@ sched_analyze_1 (struct deps_desc *deps, rtx x, rtx insn)
       /* 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
@@ -2471,38 +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);
+                              REG_DEP_CONTROL, true);
 
           if (!deps->readonly)
             add_insn_mem_dependence (deps, false, insn, dest);
@@ -2526,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;
@@ -2557,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
@@ -2569,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);
 
@@ -2598,13 +2642,14 @@ 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 = get_address_mode (t);
+           machine_mode address_mode = get_address_mode (t);
 
            t = shallow_copy_rtx (t);
            cselib_lookup_from_insn (XEXP (t, 0), address_mode, 1,
@@ -2621,35 +2666,37 @@ 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)
+               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))
-             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 = XEXP (u, 1))
+           for (u = deps->pending_jump_insns; u; u = u->next ())
              if (deps_may_trap_p (x))
                {
                  if ((sched_deps_info->generate_spec_deps)
@@ -2658,17 +2705,24 @@ sched_analyze_2 (struct deps_desc *deps, rtx x, rtx insn)
                      ds_t ds = set_dep_weak (DEP_ANTI, BEGIN_CONTROL,
                                              MAX_DEP_WEAK);
                      
-                     note_dep (XEXP (u, 0), ds);
+                     note_dep (u->insn (), ds);
                    }
                  else
-                   add_dependence (insn, XEXP (u, 0), REG_DEP_CONTROL);
+                   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);
 
@@ -2686,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:
@@ -2702,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.
@@ -2772,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;
@@ -2786,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);
@@ -2795,11 +2906,16 @@ 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 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
@@ -2816,7 +2932,8 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
        = 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);
+      add_dependence_list (insn, deps->pending_jump_insns, 1, REG_DEP_ANTI,
+                          true);
     }
 
   if (code == COND_EXEC)
@@ -2837,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)
     {
@@ -2881,13 +2998,13 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
 
   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)
             {
@@ -2898,11 +3015,12 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
               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);
+                                      REG_DEP_ANTI, false);
                 }
             }
 
@@ -2914,27 +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);
+                              REG_DEP_ANTI, true);
        }
     }
 
@@ -2957,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;
@@ -2967,19 +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 (!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->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);
+         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);
@@ -3005,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)
            {
@@ -3020,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)
              {
@@ -3045,7 +3169,7 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
                {
                  rtx other = XEXP (list, 0);
                  if (INSN_CACHED_COND (other) != const_true_rtx
-                     && refers_to_regno_p (i, i + 1, INSN_CACHED_COND (other), NULL))
+                     && refers_to_regno_p (i, INSN_CACHED_COND (other)))
                    INSN_CACHED_COND (other) = const_true_rtx;
                }
            }
@@ -3058,12 +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);
+                                  REG_DEP_CONTROL, false);
 
              if (!deps->readonly)
                {
@@ -3075,13 +3201,16 @@ 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);
+                                  REG_DEP_CONTROL, false);
 
              if (!deps->readonly)
                reg_last->sets = alloc_INSN_LIST (insn, reg_last->sets);
@@ -3092,21 +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);
+                                               REG_DEP_ANTI, false);
                  add_dependence_list_and_free (deps, insn,
                                                &reg_last->control_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->clobbers, 0,
+                                               REG_DEP_OUTPUT, false);
 
                  if (!deps->readonly)
                    {
@@ -3117,12 +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);
+                                      REG_DEP_CONTROL, false);
                }
 
              if (!deps->readonly)
@@ -3137,16 +3269,16 @@ 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);
+                                  REG_DEP_CONTROL, false);
 
              if (!deps->readonly)
                {
@@ -3171,10 +3303,11 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
     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->control_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
@@ -3212,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
@@ -3229,19 +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);
+                                           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)
                 {
@@ -3259,9 +3395,9 @@ 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);
 
       reg_pending_barrier = NOT_A_BARRIER;
@@ -3368,6 +3504,15 @@ 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,
@@ -3375,7 +3520,7 @@ sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
 /* 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;
 
@@ -3384,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)
@@ -3444,10 +3583,8 @@ call_may_noreturn_p (rtx insn)
    instruction of that group.  */
 
 static bool
-chain_to_prev_insn_p (rtx insn)
+chain_to_prev_insn_p (rtx_insn *insn)
 {
-  rtx prev, x;
-
   /* INSN forms a group with the previous instruction.  */
   if (SCHED_GROUP_P (insn))
     return true;
@@ -3456,13 +3593,13 @@ chain_to_prev_insn_p (rtx insn)
      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.  */
-  prev = prev_nonnote_nondebug_insn (insn);
+  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)
     {
-      x = XEXP (PATTERN (prev), 0);
+      rtx x = XEXP (PATTERN (prev), 0);
       if (set_of (x, insn))
        return true;
     }
@@ -3472,7 +3609,7 @@ chain_to_prev_insn_p (rtx insn)
 
 /* 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);
@@ -3483,7 +3620,7 @@ deps_analyze_insn (struct deps_desc *deps, rtx insn)
       rtx t;
       sched_get_condition_with_rev (insn, NULL);
       t = INSN_CACHED_COND (insn);
-      INSN_COND_DEPS (insn) = NULL_RTX;
+      INSN_COND_DEPS (insn) = NULL;
       if (reload_completed
          && (current_sched_info->flags & DO_PREDICATION)
          && COMPARISON_P (t)
@@ -3492,18 +3629,18 @@ deps_analyze_insn (struct deps_desc *deps, rtx insn)
        {
          unsigned int regno;
          int nregs;
+         rtx_insn_list *cond_deps = NULL;
          t = XEXP (t, 0);
          regno = REGNO (t);
-         nregs = hard_regno_nregs[regno][GET_MODE (t)];
-         t = NULL_RTX;
+         nregs = REG_NREGS (t);
          while (nregs-- > 0)
            {
              struct deps_reg *reg_last = &deps->reg_last[regno + nregs];
-             t = concat_INSN_LIST (reg_last->sets, t);
-             t = concat_INSN_LIST (reg_last->clobbers, t);
-             t = concat_INSN_LIST (reg_last->implicit_sets, t);
+             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) = t;
+         INSN_COND_DEPS (insn) = cond_deps;
        }
     }
 
@@ -3516,7 +3653,7 @@ deps_analyze_insn (struct deps_desc *deps, rtx insn)
                && 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->pending_jump_insns
@@ -3526,7 +3663,7 @@ deps_analyze_insn (struct deps_desc *deps, rtx insn)
       /* 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);
+                                   REG_DEP_ANTI, true);
 
       sched_analyze_insn (deps, PATTERN (insn), insn);
     }
@@ -3582,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);
 
@@ -3626,12 +3763,6 @@ 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 ();
 
@@ -3644,7 +3775,7 @@ deps_analyze_insn (struct deps_desc *deps, rtx 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);
 
@@ -3653,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;
@@ -3663,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);
@@ -3679,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);
@@ -3696,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;
@@ -3724,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.  */
@@ -3782,6 +3917,7 @@ init_deps (struct deps_desc *deps, bool lazy_reg_last)
   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;
 }
@@ -3849,7 +3985,7 @@ free_deps (struct deps_desc *deps)
 
 /* 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;
@@ -3897,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
@@ -3912,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 ();
 
@@ -3932,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.  */
@@ -3985,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)
@@ -4095,7 +4229,7 @@ estimate_dep_weak (rtx mem1, rtx mem2)
    This function can handle same INSN and ELEM (INSN == ELEM).
    It is a convenience wrapper.  */
 static void
-add_dependence_1 (rtx insn, rtx elem, enum reg_note dep_type)
+add_dependence_1 (rtx_insn *insn, rtx_insn *elem, enum reg_note dep_type)
 {
   ds_t ds;
   bool internal;
@@ -4125,8 +4259,9 @@ add_dependence_1 (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;
@@ -4143,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)
 {
@@ -4476,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 */