]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/haifa-sched.c
Correct a function pre/postcondition [PR102403].
[thirdparty/gcc.git] / gcc / haifa-sched.c
index 4ff2b78ee28a0acd7c75c8a41903f7331176dda8..e14051f4c0744c0ecb541cb7f97fdd40604fb7c4 100644 (file)
@@ -1,5 +1,5 @@
 /* Instruction scheduling pass.
-   Copyright (C) 1992-2014 Free Software Foundation, Inc.
+   Copyright (C) 1992-2021 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
    and currently maintained by, Jim Wilson (wilson@cygnus.com)
 
@@ -125,28 +125,27 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
-#include "diagnostic-core.h"
-#include "hard-reg-set.h"
+#include "backend.h"
+#include "target.h"
 #include "rtl.h"
+#include "cfghooks.h"
+#include "df.h"
+#include "memmodel.h"
 #include "tm_p.h"
-#include "regs.h"
-#include "function.h"
-#include "flags.h"
 #include "insn-config.h"
-#include "insn-attr.h"
-#include "except.h"
+#include "regs.h"
+#include "ira.h"
 #include "recog.h"
+#include "insn-attr.h"
+#include "cfgrtl.h"
+#include "cfgbuild.h"
 #include "sched-int.h"
-#include "target.h"
 #include "common/common-target.h"
-#include "params.h"
 #include "dbgcnt.h"
 #include "cfgloop.h"
-#include "ira.h"
-#include "emit-rtl.h"  /* FIXME: Can go away once crtl is moved to rtl.h.  */
-#include "hash-table.h"
 #include "dumpfile.h"
+#include "print-rtl.h"
+#include "function-abi.h"
 
 #ifdef INSN_SCHEDULING
 
@@ -205,17 +204,14 @@ static int modulo_last_stage;
 
 /* sched-verbose controls the amount of debugging output the
    scheduler prints.  It is controlled by -fsched-verbose=N:
-   N>0 and no -DSR : the output is directed to stderr.
-   N>=10 will direct the printouts to stderr (regardless of -dSR).
-   N=1: same as -dSR.
+   N=0: no debugging output.
+   N=1: default value.
    N=2: bb's probabilities, detailed ready list info, unit/insn info.
    N=3: rtl at abort point, control-flow, regions info.
    N=5: dependences info.  */
-
 int sched_verbose = 0;
 
-/* Debugging file.  All printouts are sent to dump, which is always set,
-   either to stderr, or to the dump listing file (-dRS).  */
+/* Debugging file.  All printouts are sent to dump. */
 FILE *sched_dump = 0;
 
 /* This is a placeholder for the scheduler parameters common
@@ -229,7 +225,7 @@ struct common_sched_info_def *common_sched_info;
 #define FEEDS_BACKTRACK_INSN(INSN) (HID (INSN)->feeds_backtrack_insn)
 #define SHADOW_P(INSN) (HID (INSN)->shadow_p)
 #define MUST_RECOMPUTE_SPEC_P(INSN) (HID (INSN)->must_recompute_spec)
-/* Cached cost of the instruction.  Use insn_cost to get cost of the
+/* Cached cost of the instruction.  Use insn_sched_cost to get cost of the
    insn.  -1 here means that the field is not initialized.  */
 #define INSN_COST(INSN)        (HID (INSN)->cost)
 
@@ -239,6 +235,13 @@ struct common_sched_info_def *common_sched_info;
 /* The minimal value of the INSN_TICK of an instruction.  */
 #define MIN_TICK (-max_insn_queue_index)
 
+/* Original order of insns in the ready list.
+   Used to keep order of normal insns while separating DEBUG_INSNs.  */
+#define INSN_RFS_DEBUG_ORIG_ORDER(INSN) (HID (INSN)->rfs_debug_orig_order)
+
+/* The deciding reason for INSN's place in the ready list.  */
+#define INSN_LAST_RFS_WIN(INSN) (HID (INSN)->last_rfs_win)
+
 /* List of important notes we must keep around.  This is a pointer to the
    last element in the list.  */
 rtx_insn *note_list;
@@ -318,7 +321,7 @@ bool adding_bb_to_current_region_p = true;
    the base maximal time of functional unit reservations and getting a
    result.  This is the longest time an insn may be queued.  */
 
-static rtx *insn_queue;
+static rtx_insn_list **insn_queue;
 static int q_ptr = 0;
 static int q_size = 0;
 #define NEXT_Q(X) (((X)+1) & max_insn_queue_index)
@@ -399,13 +402,13 @@ const struct common_sched_info_def haifa_common_sched_info =
   };
 
 /* Mapping from instruction UID to its Logical UID.  */
-vec<int> sched_luids = vNULL;
+vec<int> sched_luids;
 
 /* Next LUID to assign to an instruction.  */
 int sched_max_luid = 1;
 
 /* Haifa Instruction Data.  */
-vec<haifa_insn_data_def> h_i_d = vNULL;
+vec<haifa_insn_data_def> h_i_d;
 
 void (* sched_init_only_bb) (basic_block, basic_block);
 
@@ -419,7 +422,7 @@ basic_block (* sched_create_empty_bb) (basic_block);
 /* Return the number of cycles until INSN is expected to be ready.
    Return zero if it already is.  */
 static int
-insn_delay (rtx insn)
+insn_delay (rtx_insn *insn)
 {
   return MAX (INSN_TICK (insn) - clock_var, 0);
 }
@@ -580,7 +583,7 @@ set_modulo_params (int ii, int max_stages, int insns, int max_uid)
   modulo_max_stages = max_stages;
   modulo_n_insns = insns;
   modulo_iter0_max_uid = max_uid;
-  modulo_backtracks_left = PARAM_VALUE (PARAM_MAX_MODULO_BACKTRACK_ATTEMPTS);
+  modulo_backtracks_left = param_max_modulo_backtrack_attempts;
 }
 
 /* A structure to record a pair of insns where the first one is a real
@@ -601,18 +604,17 @@ struct delay_pair
 
 /* Helpers for delay hashing.  */
 
-struct delay_i1_hasher : typed_noop_remove <delay_pair>
+struct delay_i1_hasher : nofree_ptr_hash <delay_pair>
 {
-  typedef delay_pair value_type;
-  typedef void compare_type;
-  static inline hashval_t hash (const value_type *);
-  static inline bool equal (const value_type *, const compare_type *);
+  typedef void *compare_type;
+  static inline hashval_t hash (const delay_pair *);
+  static inline bool equal (const delay_pair *, const void *);
 };
 
 /* Returns a hash value for X, based on hashing just I1.  */
 
 inline hashval_t
-delay_i1_hasher::hash (const value_type *x)
+delay_i1_hasher::hash (const delay_pair *x)
 {
   return htab_hash_pointer (x->i1);
 }
@@ -620,23 +622,22 @@ delay_i1_hasher::hash (const value_type *x)
 /* Return true if I1 of pair X is the same as that of pair Y.  */
 
 inline bool
-delay_i1_hasher::equal (const value_type *x, const compare_type *y)
+delay_i1_hasher::equal (const delay_pair *x, const void *y)
 {
   return x->i1 == y;
 }
 
-struct delay_i2_hasher : typed_free_remove <delay_pair>
+struct delay_i2_hasher : free_ptr_hash <delay_pair>
 {
-  typedef delay_pair value_type;
-  typedef void compare_type;
-  static inline hashval_t hash (const value_type *);
-  static inline bool equal (const value_type *, const compare_type *);
+  typedef void *compare_type;
+  static inline hashval_t hash (const delay_pair *);
+  static inline bool equal (const delay_pair *, const void *);
 };
 
 /* Returns a hash value for X, based on hashing just I2.  */
 
 inline hashval_t
-delay_i2_hasher::hash (const value_type *x)
+delay_i2_hasher::hash (const delay_pair *x)
 {
   return htab_hash_pointer (x->i2);
 }
@@ -644,7 +645,7 @@ delay_i2_hasher::hash (const value_type *x)
 /* Return true if I2 of pair X is the same as that of pair Y.  */
 
 inline bool
-delay_i2_hasher::equal (const value_type *x, const compare_type *y)
+delay_i2_hasher::equal (const delay_pair *x, const void *y)
 {
   return x->i2 == y;
 }
@@ -750,17 +751,17 @@ record_delay_slot_pair (rtx_insn *i1, rtx_insn *i2, int cycles, int stages)
 
 /* Examine the delay pair hashtable to see if INSN is a shadow for another,
    and return the other insn if so.  Return NULL otherwise.  */
-rtx
-real_insn_for_shadow (rtx insn)
+rtx_insn *
+real_insn_for_shadow (rtx_insn *insn)
 {
   struct delay_pair *pair;
 
   if (!delay_htab)
-    return NULL_RTX;
+    return NULL;
 
   pair = delay_htab_i2->find_with_hash (insn, htab_hash_pointer (insn));
   if (!pair || pair->stages > 0)
-    return NULL_RTX;
+    return NULL;
   return pair->i1;
 }
 
@@ -826,12 +827,13 @@ add_delay_dependencies (rtx_insn *insn)
 \f
 /* Forward declarations.  */
 
-static int priority (rtx);
+static int priority (rtx_insn *, bool force_recompute = false);
+static int autopref_rank_for_schedule (const rtx_insn *, const rtx_insn *);
 static int rank_for_schedule (const void *, const void *);
 static void swap_sort (rtx_insn **, int);
 static void queue_insn (rtx_insn *, int, const char *);
 static int schedule_insn (rtx_insn *);
-static void adjust_priority (rtx);
+static void adjust_priority (rtx_insn *);
 static void advance_one_cycle (void);
 static void extend_h_i_d (void);
 
@@ -862,9 +864,9 @@ static int early_queue_to_ready (state_t, struct ready_list *);
 /* The following functions are used to implement multi-pass scheduling
    on the first cycle.  */
 static rtx_insn *ready_remove (struct ready_list *, int);
-static void ready_remove_insn (rtx);
+static void ready_remove_insn (rtx_insn *);
 
-static void fix_inter_tick (rtx, rtx);
+static void fix_inter_tick (rtx_insn *, rtx_insn *);
 static int fix_tick_ready (rtx_insn *);
 static void change_queue_index (rtx_insn *, int);
 
@@ -872,25 +874,25 @@ static void change_queue_index (rtx_insn *, int);
    speculative instructions.  */
 
 static void extend_h_i_d (void);
-static void init_h_i_d (rtx);
-static int haifa_speculate_insn (rtx, ds_t, rtx *);
+static void init_h_i_d (rtx_insn *);
+static int haifa_speculate_insn (rtx_insn *, ds_t, rtx *);
 static void generate_recovery_code (rtx_insn *);
-static void process_insn_forw_deps_be_in_spec (rtx, rtx, ds_t);
+static void process_insn_forw_deps_be_in_spec (rtx_insn *, rtx_insn *, ds_t);
 static void begin_speculative_block (rtx_insn *);
 static void add_to_speculative_block (rtx_insn *);
 static void init_before_recovery (basic_block *);
 static void create_check_block_twin (rtx_insn *, bool);
 static void fix_recovery_deps (basic_block);
-static bool haifa_change_pattern (rtx, rtx);
-static void dump_new_block_header (int, basic_block, rtx, rtx);
+static bool haifa_change_pattern (rtx_insn *, rtx);
+static void dump_new_block_header (int, basic_block, rtx_insn *, rtx_insn *);
 static void restore_bb_notes (basic_block);
-static void fix_jump_move (rtx);
-static void move_block_after_check (rtx);
+static void fix_jump_move (rtx_insn *);
+static void move_block_after_check (rtx_insn *);
 static void move_succs (vec<edge, va_gc> **, basic_block);
 static void sched_remove_insn (rtx_insn *);
 static void clear_priorities (rtx_insn *, rtx_vec_t *);
-static void calc_priorities (rtx_vec_t);
-static void add_jump_dependencies (rtx, rtx);
+static void calc_priorities (const rtx_vec_t &);
+static void add_jump_dependencies (rtx_insn *, rtx_insn *);
 
 #endif /* INSN_SCHEDULING */
 \f
@@ -928,6 +930,18 @@ static bitmap saved_reg_live;
 /* Registers mentioned in the current region.  */
 static bitmap region_ref_regs;
 
+/* Temporary bitmap used for SCHED_PRESSURE_MODEL.  */
+static bitmap tmp_bitmap;
+
+/* Effective number of available registers of a given class (see comment
+   in sched_pressure_start_bb).  */
+static int sched_class_regs_num[N_REG_CLASSES];
+/* The number of registers that the function would need to save before it
+   uses them, and the number of fixed_regs.  Helpers for calculating of
+   sched_class_regs_num.  */
+static int call_saved_regs_num[N_REG_CLASSES];
+static int fixed_regs_num[N_REG_CLASSES];
+
 /* Initiate register pressure relative info for scheduling the current
    region.  Currently it is only clearing register mentioned in the
    current region.  */
@@ -1006,18 +1020,13 @@ initiate_reg_pressure_info (bitmap live)
 static void
 setup_ref_regs (rtx x)
 {
-  int i, j, regno;
+  int i, j;
   const RTX_CODE code = GET_CODE (x);
   const char *fmt;
 
   if (REG_P (x))
     {
-      regno = REGNO (x);
-      if (HARD_REGISTER_NUM_P (regno))
-       bitmap_set_range (region_ref_regs, regno,
-                         hard_regno_nregs[regno][GET_MODE (x)]);
-      else
-       bitmap_set_bit (region_ref_regs, REGNO (x));
+      bitmap_set_range (region_ref_regs, REGNO (x), REG_NREGS (x));
       return;
     }
   fmt = GET_RTX_FORMAT (code);
@@ -1037,14 +1046,13 @@ static void
 initiate_bb_reg_pressure_info (basic_block bb)
 {
   unsigned int i ATTRIBUTE_UNUSED;
-  rtx insn;
+  rtx_insn *insn;
 
   if (current_nr_blocks > 1)
     FOR_BB_INSNS (bb, insn)
       if (NONDEBUG_INSN_P (insn))
        setup_ref_regs (PATTERN (insn));
   initiate_reg_pressure_info (df_get_live_in (bb));
-#ifdef EH_RETURN_DATA_REGNO
   if (bb_has_eh_pred (bb))
     for (i = 0; ; ++i)
       {
@@ -1056,7 +1064,6 @@ initiate_bb_reg_pressure_info (basic_block bb)
          mark_regno_birth_or_death (curr_reg_live, curr_reg_pressure,
                                     regno, true);
       }
-#endif
 }
 
 /* Save current register pressure related info.  */
@@ -1111,7 +1118,7 @@ print_curr_reg_pressure (void)
       gcc_assert (curr_reg_pressure[cl] >= 0);
       fprintf (sched_dump, "  %s:%d(%d)", reg_class_names[cl],
               curr_reg_pressure[cl],
-              curr_reg_pressure[cl] - ira_class_hard_regs_num[cl]);
+              curr_reg_pressure[cl] - sched_class_regs_num[cl]);
     }
   fprintf (sched_dump, "\n");
 }
@@ -1144,7 +1151,7 @@ cond_clobbered_p (rtx_insn *insn, HARD_REG_SET set_regs)
 /* This function should be called after modifying the pattern of INSN,
    to update scheduler data structures as needed.  */
 static void
-update_insn_after_change (rtx insn)
+update_insn_after_change (rtx_insn *insn)
 {
   sd_iterator_def sd_it;
   dep_t dep;
@@ -1163,6 +1170,12 @@ update_insn_after_change (rtx insn)
   INSN_COST (insn) = -1;
   /* Invalidate INSN_TICK, so it'll be recalculated.  */
   INSN_TICK (insn) = INVALID_TICK;
+
+  /* Invalidate autoprefetch data entry.  */
+  INSN_AUTOPREF_MULTIPASS_DATA (insn)[0].status
+    = AUTOPREF_MULTIPASS_DATA_UNINITIALIZED;
+  INSN_AUTOPREF_MULTIPASS_DATA (insn)[1].status
+    = AUTOPREF_MULTIPASS_DATA_UNINITIALIZED;
 }
 
 
@@ -1184,7 +1197,7 @@ static void restore_pattern (dep_t, bool);
    false.  */
 
 static ds_t
-recompute_todo_spec (rtx next, bool for_backtrack)
+recompute_todo_spec (rtx_insn *next, bool for_backtrack)
 {
   ds_t new_ds;
   sd_iterator_def sd_it;
@@ -1201,6 +1214,11 @@ recompute_todo_spec (rtx next, bool for_backtrack)
   if (!sd_lists_empty_p (next, SD_LIST_HARD_BACK))
     return HARD_DEP;
 
+  /* If NEXT is intended to sit adjacent to this instruction, we don't
+     want to try to break any dependencies.  Treat it as a HARD_DEP.  */
+  if (SCHED_GROUP_P (next))
+    return HARD_DEP;
+
   /* Now we've got NEXT with speculative deps only.
      1. Look at the deps to see what we have to do.
      2. Check if we can do 'todo'.  */
@@ -1268,7 +1286,8 @@ recompute_todo_spec (rtx next, bool for_backtrack)
   
   else if (n_control == 1 && n_replace == 0 && n_spec == 0)
     {
-      rtx pro, other, new_pat;
+      rtx_insn *pro, *other;
+      rtx new_pat;
       rtx cond = NULL_RTX;
       bool success;
       rtx_insn *prev = NULL;
@@ -1354,7 +1373,7 @@ static rtx_insn *last_scheduled_insn;
    block, or the prev_head of the scheduling block.  Used by
    rank_for_schedule, so that insns independent of the last scheduled
    insn will be preferred over dependent instructions.  */
-static rtx last_nondebug_scheduled_insn;
+static rtx_insn *last_nondebug_scheduled_insn;
 
 /* Pointer that iterates through the list of unscheduled insns if we
    have a dbg_cnt enabled.  It always points at an insn prior to the
@@ -1365,10 +1384,13 @@ static rtx_insn *nonscheduled_insns_begin;
    This is the number of cycles between instruction issue and
    instruction results.  */
 int
-insn_cost (rtx insn)
+insn_sched_cost (rtx_insn *insn)
 {
   int cost;
 
+  if (sched_fusion)
+    return 0;
+
   if (sel_sched_p ())
     {
       if (recog_memoized (insn) < 0)
@@ -1449,7 +1471,7 @@ dep_cost_1 (dep_t link, dw_t dw)
     {
       enum reg_note dep_type = DEP_TYPE (link);
 
-      cost = insn_cost (insn);
+      cost = insn_sched_cost (insn);
 
       if (INSN_CODE (insn) >= 0)
        {
@@ -1467,27 +1489,9 @@ dep_cost_1 (dep_t link, dw_t dw)
        }
 
 
-      if (targetm.sched.adjust_cost_2)
-       cost = targetm.sched.adjust_cost_2 (used, (int) dep_type, insn, cost,
-                                           dw);
-      else if (targetm.sched.adjust_cost != NULL)
-       {
-         /* This variable is used for backward compatibility with the
-            targets.  */
-         rtx dep_cost_rtx_link = alloc_INSN_LIST (NULL_RTX, NULL_RTX);
-
-         /* Make it self-cycled, so that if some tries to walk over this
-            incomplete list he/she will be caught in an endless loop.  */
-         XEXP (dep_cost_rtx_link, 1) = dep_cost_rtx_link;
-
-         /* Targets use only REG_NOTE_KIND of the link.  */
-         PUT_REG_NOTE_KIND (dep_cost_rtx_link, DEP_TYPE (link));
-
-         cost = targetm.sched.adjust_cost (used, dep_cost_rtx_link,
-                                           insn, cost);
-
-         free_INSN_LIST_node (dep_cost_rtx_link);
-       }
+      if (targetm.sched.adjust_cost)
+       cost = targetm.sched.adjust_cost (used, (int) dep_type, insn, cost,
+                                         dw);
 
       if (cost < 0)
        cost = 0;
@@ -1509,7 +1513,7 @@ dep_cost (dep_t link)
 /* Use this sel-sched.c friendly function in reorder2 instead of increasing
    INSN_PRIORITY explicitly.  */
 void
-increase_insn_priority (rtx insn, int amount)
+increase_insn_priority (rtx_insn *insn, int amount)
 {
   if (!sel_sched_p ())
     {
@@ -1558,7 +1562,7 @@ contributes_to_priority_p (dep_t dep)
 /* Compute the number of nondebug deps in list LIST for INSN.  */
 
 static int
-dep_list_size (rtx insn, sd_list_types_def list)
+dep_list_size (rtx_insn *insn, sd_list_types_def list)
 {
   sd_iterator_def sd_it;
   dep_t dep;
@@ -1580,9 +1584,11 @@ dep_list_size (rtx insn, sd_list_types_def list)
   return nodbgcount;
 }
 
+bool sched_fusion;
+
 /* Compute the priority number for INSN.  */
 static int
-priority (rtx insn)
+priority (rtx_insn *insn, bool force_recompute)
 {
   if (! INSN_P (insn))
     return 0;
@@ -1590,19 +1596,27 @@ priority (rtx insn)
   /* We should not be interested in priority of an already scheduled insn.  */
   gcc_assert (QUEUE_INDEX (insn) != QUEUE_SCHEDULED);
 
-  if (!INSN_PRIORITY_KNOWN (insn))
+  if (force_recompute || !INSN_PRIORITY_KNOWN (insn))
     {
       int this_priority = -1;
 
-      if (dep_list_size (insn, SD_LIST_FORW) == 0)
-       /* ??? We should set INSN_PRIORITY to insn_cost when and insn has
-          some forward deps but all of them are ignored by
+      if (sched_fusion)
+       {
+         int this_fusion_priority;
+
+         targetm.sched.fusion_priority (insn, FUSION_MAX_PRIORITY,
+                                        &this_fusion_priority, &this_priority);
+         INSN_FUSION_PRIORITY (insn) = this_fusion_priority;
+       }
+      else if (dep_list_size (insn, SD_LIST_FORW) == 0)
+       /* ??? We should set INSN_PRIORITY to insn_sched_cost when and insn
+          has some forward deps but all of them are ignored by
           contributes_to_priority hook.  At the moment we set priority of
           such insn to 0.  */
-       this_priority = insn_cost (insn);
+       this_priority = insn_sched_cost (insn);
       else
        {
-         rtx prev_first, twin;
+         rtx_insn *prev_first, *twin;
          basic_block rec;
 
          /* For recovery check instructions we calculate priority slightly
@@ -1631,7 +1645,7 @@ priority (rtx insn)
 
              FOR_EACH_DEP (twin, SD_LIST_FORW, sd_it, dep)
                {
-                 rtx next;
+                 rtx_insn *next;
                  int next_priority;
 
                  next = DEP_CON (dep);
@@ -1670,7 +1684,7 @@ priority (rtx insn)
        {
          gcc_assert (this_priority == -1);
 
-         this_priority = insn_cost (insn);
+         this_priority = insn_sched_cost (insn);
        }
 
       INSN_PRIORITY (insn) = this_priority;
@@ -1687,7 +1701,7 @@ priority (rtx insn)
    in that class that die in INSN.  */
 
 static void
-calculate_reg_deaths (rtx insn, int *death)
+calculate_reg_deaths (rtx_insn *insn, int *death)
 {
   int i;
   struct reg_use_data *use;
@@ -1702,11 +1716,11 @@ calculate_reg_deaths (rtx insn, int *death)
 /* Setup info about the current register pressure impact of scheduling
    INSN at the current scheduling point.  */
 static void
-setup_insn_reg_pressure_info (rtx insn)
+setup_insn_reg_pressure_info (rtx_insn *insn)
 {
   int i, change, before, after, hard_regno;
   int excess_cost_change;
-  enum machine_mode mode;
+  machine_mode mode;
   enum reg_class cl;
   struct reg_pressure_data *pressure_info;
   int *max_reg_pressure;
@@ -1724,9 +1738,9 @@ setup_insn_reg_pressure_info (rtx insn)
       cl = ira_pressure_classes[i];
       gcc_assert (curr_reg_pressure[cl] >= 0);
       change = (int) pressure_info[i].set_increase - death[cl];
-      before = MAX (0, max_reg_pressure[i] - ira_class_hard_regs_num[cl]);
+      before = MAX (0, max_reg_pressure[i] - sched_class_regs_num[cl]);
       after = MAX (0, max_reg_pressure[i] + change
-                  - ira_class_hard_regs_num[cl]);
+                  - sched_class_regs_num[cl]);
       hard_regno = ira_class_hard_regs[cl][0];
       gcc_assert (hard_regno >= 0);
       mode = reg_raw_mode[hard_regno];
@@ -1815,7 +1829,7 @@ struct model_pressure_data {
    than the main schedule.  */
 struct model_insn_info {
   /* The instruction itself.  */
-  rtx insn;
+  rtx_insn *insn;
 
   /* If this instruction is in model_worklist, these fields link to the
      previous (higher-priority) and next (lower-priority) instructions
@@ -1876,7 +1890,7 @@ struct model_pressure_group {
 
 /* Index POINT gives the instruction at point POINT of the model schedule.
    This array doesn't change during main scheduling.  */
-static vec<rtx> model_schedule;
+static vec<rtx_insn *> model_schedule;
 
 /* The list of instructions in the model worklist, sorted in order of
    decreasing priority.  */
@@ -1927,7 +1941,7 @@ static unsigned int model_next_priority;
    doesn't belong to that schedule.  */
 
 static int
-model_index (rtx insn)
+model_index (rtx_insn *insn)
 {
   if (INSN_MODEL_INDEX (insn) == 0)
     return model_num_insns;
@@ -2063,7 +2077,7 @@ model_update_pressure (struct model_pressure_group *group,
 
       /* Check whether the maximum pressure in the overall schedule
         has increased.  (This means that the MODEL_MAX_PRESSURE of
-        every point <= POINT will need to increae too; see below.)  */
+        every point <= POINT will need to increase too; see below.)  */
       if (group->limits[pci].pressure < ref_pressure)
        group->limits[pci].pressure = ref_pressure;
 
@@ -2096,7 +2110,7 @@ model_update_pressure (struct model_pressure_group *group,
 /* INSN has just been scheduled.  Update the model schedule accordingly.  */
 
 static void
-model_recompute (rtx insn)
+model_recompute (rtx_insn *insn)
 {
   struct {
     int last_use;
@@ -2125,10 +2139,11 @@ model_recompute (rtx insn)
      registers that will be born in the range [model_curr_point, POINT).  */
   num_uses = 0;
   num_pending_births = 0;
+  bitmap_clear (tmp_bitmap);
   for (use = INSN_REG_USE_LIST (insn); use != NULL; use = use->next_insn_use)
     {
       new_last = model_last_use_except (use);
-      if (new_last < point)
+      if (new_last < point && bitmap_set_bit (tmp_bitmap, use->regno))
        {
          gcc_assert (num_uses < ARRAY_SIZE (uses));
          uses[num_uses].last_use = new_last;
@@ -2229,7 +2244,7 @@ model_recompute (rtx insn)
 /* After DEP, which was cancelled, has been resolved for insn NEXT,
    check whether the insn's pattern needs restoring.  */
 static bool
-must_restore_pattern_p (rtx next, dep_t dep)
+must_restore_pattern_p (rtx_insn *next, dep_t dep)
 {
   if (QUEUE_INDEX (next) == QUEUE_SCHEDULED)
     return false;
@@ -2340,7 +2355,7 @@ must_restore_pattern_p (rtx next, dep_t dep)
 /* Return the cost of increasing the pressure in class CL from FROM to TO.
 
    Here we use the very simplistic cost model that every register above
-   ira_class_hard_regs_num[CL] has a spill cost of 1.  We could use other
+   sched_class_regs_num[CL] has a spill cost of 1.  We could use other
    measures instead, such as one based on MEMORY_MOVE_COST.  However:
 
       (1) In order for an instruction to be scheduled, the higher cost
@@ -2364,7 +2379,7 @@ must_restore_pattern_p (rtx next, dep_t dep)
 static int
 model_spill_cost (int cl, int from, int to)
 {
-  from = MAX (from, ira_class_hard_regs_num[cl]);
+  from = MAX (from, sched_class_regs_num[cl]);
   return MAX (to, from) - from;
 }
 
@@ -2405,7 +2420,7 @@ model_excess_group_cost (struct model_pressure_group *group,
    if PRINT_P.  */
 
 static int
-model_excess_cost (rtx insn, bool print_p)
+model_excess_cost (rtx_insn *insn, bool print_p)
 {
   int point, pci, cl, cost, this_cost, delta;
   struct reg_pressure_data *insn_reg_pressure;
@@ -2470,7 +2485,7 @@ model_set_excess_costs (rtx_insn **insns, int count)
   bool print_p;
 
   /* Record the baseECC value for each instruction in the model schedule,
-     except that negative costs are converted to zero ones now rather thatn
+     except that negative costs are converted to zero ones now rather than
      later.  Do not assign a cost to debug instructions, since they must
      not change code-generation decisions.  Experiments suggest we also
      get better results by not assigning a cost to instructions from
@@ -2521,31 +2536,59 @@ model_set_excess_costs (rtx_insn **insns, int count)
 
 /* Enum of rank_for_schedule heuristic decisions.  */
 enum rfs_decision {
-  RFS_DEBUG, RFS_LIVE_RANGE_SHRINK1, RFS_LIVE_RANGE_SHRINK2,
+  RFS_LIVE_RANGE_SHRINK1, RFS_LIVE_RANGE_SHRINK2,
   RFS_SCHED_GROUP, RFS_PRESSURE_DELAY, RFS_PRESSURE_TICK,
-  RFS_FEEDS_BACKTRACK_INSN, RFS_PRIORITY, RFS_SPECULATION,
+  RFS_FEEDS_BACKTRACK_INSN, RFS_PRIORITY, RFS_AUTOPREF, RFS_SPECULATION,
   RFS_SCHED_RANK, RFS_LAST_INSN, RFS_PRESSURE_INDEX,
-  RFS_DEP_COUNT, RFS_TIE, RFS_N };
+  RFS_DEP_COUNT, RFS_TIE, RFS_FUSION, RFS_COST, RFS_N };
 
 /* Corresponding strings for print outs.  */
 static const char *rfs_str[RFS_N] = {
-  "RFS_DEBUG", "RFS_LIVE_RANGE_SHRINK1", "RFS_LIVE_RANGE_SHRINK2",
+  "RFS_LIVE_RANGE_SHRINK1", "RFS_LIVE_RANGE_SHRINK2",
   "RFS_SCHED_GROUP", "RFS_PRESSURE_DELAY", "RFS_PRESSURE_TICK",
-  "RFS_FEEDS_BACKTRACK_INSN", "RFS_PRIORITY", "RFS_SPECULATION",
+  "RFS_FEEDS_BACKTRACK_INSN", "RFS_PRIORITY", "RFS_AUTOPREF", "RFS_SPECULATION",
   "RFS_SCHED_RANK", "RFS_LAST_INSN", "RFS_PRESSURE_INDEX",
-  "RFS_DEP_COUNT", "RFS_TIE" };
+  "RFS_DEP_COUNT", "RFS_TIE", "RFS_FUSION", "RFS_COST" };
 
 /* Statistical breakdown of rank_for_schedule decisions.  */
-typedef struct { unsigned stats[RFS_N]; } rank_for_schedule_stats_t;
+struct rank_for_schedule_stats_t { unsigned stats[RFS_N]; };
 static rank_for_schedule_stats_t rank_for_schedule_stats;
 
+/* Return the result of comparing insns TMP and TMP2 and update
+   Rank_For_Schedule statistics.  */
 static int
-rfs_result (enum rfs_decision decision, int result)
+rfs_result (enum rfs_decision decision, int result, rtx tmp, rtx tmp2)
 {
   ++rank_for_schedule_stats.stats[decision];
+  if (result < 0)
+    INSN_LAST_RFS_WIN (tmp) = decision;
+  else if (result > 0)
+    INSN_LAST_RFS_WIN (tmp2) = decision;
+  else
+    gcc_unreachable ();
   return result;
 }
 
+/* Sorting predicate to move DEBUG_INSNs to the top of ready list, while
+   keeping normal insns in original order.  */
+
+static int
+rank_for_schedule_debug (const void *x, const void *y)
+{
+  rtx_insn *tmp = *(rtx_insn * const *) y;
+  rtx_insn *tmp2 = *(rtx_insn * const *) x;
+
+  /* Schedule debug insns as early as possible.  */
+  if (DEBUG_INSN_P (tmp) && !DEBUG_INSN_P (tmp2))
+    return -1;
+  else if (!DEBUG_INSN_P (tmp) && DEBUG_INSN_P (tmp2))
+    return 1;
+  else if (DEBUG_INSN_P (tmp) && DEBUG_INSN_P (tmp2))
+    return INSN_LUID (tmp) - INSN_LUID (tmp2);
+  else
+    return INSN_RFS_DEBUG_ORIG_ORDER (tmp2) - INSN_RFS_DEBUG_ORIG_ORDER (tmp);
+}
+
 /* Returns a positive value if x is preferred; returns a negative value if
    y is preferred.  Should never return 0, since that will make the sort
    unstable.  */
@@ -2558,17 +2601,6 @@ rank_for_schedule (const void *x, const void *y)
   int tmp_class, tmp2_class;
   int val, priority_val, info_val, diff;
 
-  if (MAY_HAVE_DEBUG_INSNS)
-    {
-      /* Schedule debug insns as early as possible.  */
-      if (DEBUG_INSN_P (tmp) && !DEBUG_INSN_P (tmp2))
-       return rfs_result (RFS_DEBUG, -1);
-      else if (!DEBUG_INSN_P (tmp) && DEBUG_INSN_P (tmp2))
-       return rfs_result (RFS_DEBUG, 1);
-      else if (DEBUG_INSN_P (tmp) && DEBUG_INSN_P (tmp2))
-       return rfs_result (RFS_DEBUG, INSN_LUID (tmp) - INSN_LUID (tmp2));
-    }
-
   if (live_range_shrinkage_p)
     {
       /* Don't use SCHED_PRESSURE_MODEL -- it results in much worse
@@ -2578,22 +2610,72 @@ rank_for_schedule (const void *x, const void *y)
           || INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp2) < 0)
          && (diff = (INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp)
                      - INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp2))) != 0)
-       return rfs_result (RFS_LIVE_RANGE_SHRINK1, diff);
+       return rfs_result (RFS_LIVE_RANGE_SHRINK1, diff, tmp, tmp2);
       /* Sort by INSN_LUID (original insn order), so that we make the
         sort stable.  This minimizes instruction movement, thus
         minimizing sched's effect on debugging and cross-jumping.  */
       return rfs_result (RFS_LIVE_RANGE_SHRINK2,
-                        INSN_LUID (tmp) - INSN_LUID (tmp2));
+                        INSN_LUID (tmp) - INSN_LUID (tmp2), tmp, tmp2);
     }
 
   /* The insn in a schedule group should be issued the first.  */
   if (flag_sched_group_heuristic &&
       SCHED_GROUP_P (tmp) != SCHED_GROUP_P (tmp2))
-    return rfs_result (RFS_SCHED_GROUP, SCHED_GROUP_P (tmp2) ? 1 : -1);
+    return rfs_result (RFS_SCHED_GROUP, SCHED_GROUP_P (tmp2) ? 1 : -1,
+                      tmp, tmp2);
 
   /* Make sure that priority of TMP and TMP2 are initialized.  */
   gcc_assert (INSN_PRIORITY_KNOWN (tmp) && INSN_PRIORITY_KNOWN (tmp2));
 
+  if (sched_fusion)
+    {
+      /* The instruction that has the same fusion priority as the last
+        instruction is the instruction we picked next.  If that is not
+        the case, we sort ready list firstly by fusion priority, then
+        by priority, and at last by INSN_LUID.  */
+      int a = INSN_FUSION_PRIORITY (tmp);
+      int b = INSN_FUSION_PRIORITY (tmp2);
+      int last = -1;
+
+      if (last_nondebug_scheduled_insn
+         && !NOTE_P (last_nondebug_scheduled_insn)
+         && BLOCK_FOR_INSN (tmp)
+              == BLOCK_FOR_INSN (last_nondebug_scheduled_insn))
+       last = INSN_FUSION_PRIORITY (last_nondebug_scheduled_insn);
+
+      if (a != last && b != last)
+       {
+         if (a == b)
+           {
+             a = INSN_PRIORITY (tmp);
+             b = INSN_PRIORITY (tmp2);
+           }
+         if (a != b)
+           return rfs_result (RFS_FUSION, b - a, tmp, tmp2);
+         else
+           return rfs_result (RFS_FUSION,
+                              INSN_LUID (tmp) - INSN_LUID (tmp2), tmp, tmp2);
+       }
+      else if (a == b)
+       {
+         gcc_assert (last_nondebug_scheduled_insn
+                     && !NOTE_P (last_nondebug_scheduled_insn));
+         last = INSN_PRIORITY (last_nondebug_scheduled_insn);
+
+         a = abs (INSN_PRIORITY (tmp) - last);
+         b = abs (INSN_PRIORITY (tmp2) - last);
+         if (a != b)
+           return rfs_result (RFS_FUSION, a - b, tmp, tmp2);
+         else
+           return rfs_result (RFS_FUSION,
+                              INSN_LUID (tmp) - INSN_LUID (tmp2), tmp, tmp2);
+       }
+      else if (a == last)
+       return rfs_result (RFS_FUSION, -1, tmp, tmp2);
+      else
+       return rfs_result (RFS_FUSION, 1, tmp, tmp2);
+    }
+
   if (sched_pressure != SCHED_PRESSURE_NONE)
     {
       /* Prefer insn whose scheduling results in the smallest register
@@ -2602,7 +2684,7 @@ rank_for_schedule (const void *x, const void *y)
                   + insn_delay (tmp)
                   - INSN_REG_PRESSURE_EXCESS_COST_CHANGE (tmp2)
                   - insn_delay (tmp2))))
-       return rfs_result (RFS_PRESSURE_DELAY, diff);
+       return rfs_result (RFS_PRESSURE_DELAY, diff, tmp, tmp2);
     }
 
   if (sched_pressure != SCHED_PRESSURE_NONE
@@ -2610,7 +2692,7 @@ rank_for_schedule (const void *x, const void *y)
       && INSN_TICK (tmp2) != INSN_TICK (tmp))
     {
       diff = INSN_TICK (tmp) - INSN_TICK (tmp2);
-      return rfs_result (RFS_PRESSURE_TICK, diff);
+      return rfs_result (RFS_PRESSURE_TICK, diff, tmp, tmp2);
     }
 
   /* If we are doing backtracking in this schedule, prefer insns that
@@ -2620,14 +2702,21 @@ rank_for_schedule (const void *x, const void *y)
     {
       priority_val = FEEDS_BACKTRACK_INSN (tmp2) - FEEDS_BACKTRACK_INSN (tmp);
       if (priority_val)
-       return rfs_result (RFS_FEEDS_BACKTRACK_INSN, priority_val);
+       return rfs_result (RFS_FEEDS_BACKTRACK_INSN, priority_val, tmp, tmp2);
     }
 
   /* Prefer insn with higher priority.  */
   priority_val = INSN_PRIORITY (tmp2) - INSN_PRIORITY (tmp);
 
   if (flag_sched_critical_path_heuristic && priority_val)
-    return rfs_result (RFS_PRIORITY, priority_val);
+    return rfs_result (RFS_PRIORITY, priority_val, tmp, tmp2);
+
+  if (param_sched_autopref_queue_depth >= 0)
+    {
+      int autopref = autopref_rank_for_schedule (tmp, tmp2);
+      if (autopref != 0)
+       return rfs_result (RFS_AUTOPREF, autopref, tmp, tmp2);
+    }
 
   /* Prefer speculative insn with greater dependencies weakness.  */
   if (flag_sched_spec_insn_heuristic && spec_info)
@@ -2650,12 +2739,12 @@ rank_for_schedule (const void *x, const void *y)
 
       dw = dw2 - dw1;
       if (dw > (NO_DEP_WEAK / 8) || dw < -(NO_DEP_WEAK / 8))
-       return rfs_result (RFS_SPECULATION, dw);
+       return rfs_result (RFS_SPECULATION, dw, tmp, tmp2);
     }
 
   info_val = (*current_sched_info->rank) (tmp, tmp2);
   if (flag_sched_rank_heuristic && info_val)
-    return rfs_result (RFS_SCHED_RANK, info_val);
+    return rfs_result (RFS_SCHED_RANK, info_val, tmp, tmp2);
 
   /* Compare insns based on their relation to the last scheduled
      non-debug insn.  */
@@ -2663,7 +2752,7 @@ rank_for_schedule (const void *x, const void *y)
     {
       dep_t dep1;
       dep_t dep2;
-      rtx last = last_nondebug_scheduled_insn;
+      rtx_insn *last = last_nondebug_scheduled_insn;
 
       /* Classify the instructions into three classes:
          1) Data dependent on last schedule insn.
@@ -2691,16 +2780,15 @@ rank_for_schedule (const void *x, const void *y)
        tmp2_class = 2;
 
       if ((val = tmp2_class - tmp_class))
-       return rfs_result (RFS_LAST_INSN, val);
+       return rfs_result (RFS_LAST_INSN, val, tmp, tmp2);
     }
 
   /* Prefer instructions that occur earlier in the model schedule.  */
-  if (sched_pressure == SCHED_PRESSURE_MODEL
-      && INSN_BB (tmp) == target_bb && INSN_BB (tmp2) == target_bb)
+  if (sched_pressure == SCHED_PRESSURE_MODEL)
     {
       diff = model_index (tmp) - model_index (tmp2);
-      gcc_assert (diff != 0);
-      return rfs_result (RFS_PRESSURE_INDEX, diff);
+      if (diff != 0)
+       return rfs_result (RFS_PRESSURE_INDEX, diff, tmp, tmp2);
     }
 
   /* Prefer the insn which has more later insns that depend on it.
@@ -2711,12 +2799,20 @@ rank_for_schedule (const void *x, const void *y)
         - dep_list_size (tmp, SD_LIST_FORW));
 
   if (flag_sched_dep_count_heuristic && val != 0)
-    return rfs_result (RFS_DEP_COUNT, val);
+    return rfs_result (RFS_DEP_COUNT, val, tmp, tmp2);
+
+  /* Sort by INSN_COST rather than INSN_LUID.  This means that instructions
+     which take longer to execute are prioritised and it leads to more
+     dual-issue opportunities on in-order cores which have this feature.  */
+
+  if (INSN_COST (tmp) != INSN_COST (tmp2))
+    return rfs_result (RFS_COST, INSN_COST (tmp2) - INSN_COST (tmp),
+                      tmp, tmp2);
 
   /* If insns are equally good, sort by INSN_LUID (original insn order),
      so that we make the sort stable.  This minimizes instruction movement,
      thus minimizing sched's effect on debugging and cross-jumping.  */
-  return rfs_result (RFS_TIE, INSN_LUID (tmp) - INSN_LUID (tmp2));
+  return rfs_result (RFS_TIE, INSN_LUID (tmp) - INSN_LUID (tmp2), tmp, tmp2);
 }
 
 /* Resort the array A in which only element at index N may be out of order.  */
@@ -2744,7 +2840,7 @@ HAIFA_INLINE static void
 queue_insn (rtx_insn *insn, int n_cycles, const char *reason)
 {
   int next_q = NEXT_Q_AFTER (q_ptr, n_cycles);
-  rtx link = alloc_INSN_LIST (insn, insn_queue[next_q]);
+  rtx_insn_list *link = alloc_INSN_LIST (insn, insn_queue[next_q]);
   int new_tick;
 
   gcc_assert (n_cycles <= max_insn_queue_index);
@@ -2781,7 +2877,7 @@ queue_insn (rtx_insn *insn, int n_cycles, const char *reason)
 
 /* Remove INSN from queue.  */
 static void
-queue_remove (rtx insn)
+queue_remove (rtx_insn *insn)
 {
   gcc_assert (QUEUE_INDEX (insn) >= 0);
   remove_free_INSN_LIST_elem (insn, &insn_queue[QUEUE_INDEX (insn)]);
@@ -2908,7 +3004,7 @@ ready_remove (struct ready_list *ready, int index)
 
 /* Remove INSN from the ready list.  */
 static void
-ready_remove_insn (rtx insn)
+ready_remove_insn (rtx_insn *insn)
 {
   int i;
 
@@ -2934,54 +3030,93 @@ rank_for_schedule_stats_diff (rank_for_schedule_stats_t *was,
 /* Print rank_for_schedule statistics.  */
 static void
 print_rank_for_schedule_stats (const char *prefix,
-                              const rank_for_schedule_stats_t *stats)
+                              const rank_for_schedule_stats_t *stats,
+                              struct ready_list *ready)
 {
   for (int i = 0; i < RFS_N; ++i)
     if (stats->stats[i])
-      fprintf (sched_dump, "%s%20s: %u\n", prefix, rfs_str[i], stats->stats[i]);
+      {
+       fprintf (sched_dump, "%s%20s: %u", prefix, rfs_str[i], stats->stats[i]);
+
+       if (ready != NULL)
+         /* Print out insns that won due to RFS_<I>.  */
+         {
+           rtx_insn **p = ready_lastpos (ready);
+
+           fprintf (sched_dump, ":");
+           /* Start with 1 since least-priority insn didn't have any wins.  */
+           for (int j = 1; j < ready->n_ready; ++j)
+             if (INSN_LAST_RFS_WIN (p[j]) == i)
+               fprintf (sched_dump, " %s",
+                        (*current_sched_info->print_insn) (p[j], 0));
+         }
+       fprintf (sched_dump, "\n");
+      }
 }
 
-/* Sort the ready list READY by ascending priority, using the SCHED_SORT
-   macro.  */
+/* Separate DEBUG_INSNS from normal insns.  DEBUG_INSNs go to the end
+   of array.  */
+static void
+ready_sort_debug (struct ready_list *ready)
+{
+  int i;
+  rtx_insn **first = ready_lastpos (ready);
 
-void
-ready_sort (struct ready_list *ready)
+  for (i = 0; i < ready->n_ready; ++i)
+    if (!DEBUG_INSN_P (first[i]))
+      INSN_RFS_DEBUG_ORIG_ORDER (first[i]) = i;
+
+  qsort (first, ready->n_ready, sizeof (rtx), rank_for_schedule_debug);
+}
+
+/* Sort non-debug insns in the ready list READY by ascending priority.
+   Assumes that all debug insns are separated from the real insns.  */
+static void
+ready_sort_real (struct ready_list *ready)
 {
   int i;
   rtx_insn **first = ready_lastpos (ready);
+  int n_ready_real = ready->n_ready - ready->n_debug;
 
   if (sched_pressure == SCHED_PRESSURE_WEIGHTED)
-    {
-      for (i = 0; i < ready->n_ready; i++)
-       if (!DEBUG_INSN_P (first[i]))
-         setup_insn_reg_pressure_info (first[i]);
-    }
-  if (sched_pressure == SCHED_PRESSURE_MODEL
-      && model_curr_point < model_num_insns)
-    model_set_excess_costs (first, ready->n_ready);
+    for (i = 0; i < n_ready_real; ++i)
+      setup_insn_reg_pressure_info (first[i]);
+  else if (sched_pressure == SCHED_PRESSURE_MODEL
+          && model_curr_point < model_num_insns)
+    model_set_excess_costs (first, n_ready_real);
 
   rank_for_schedule_stats_t stats1;
   if (sched_verbose >= 4)
     stats1 = rank_for_schedule_stats;
 
-  if (ready->n_ready == 2)
-    swap_sort (first, ready->n_ready);
-  else if (ready->n_ready > 2)
-    qsort (first, ready->n_ready, sizeof (rtx), rank_for_schedule);
+  if (n_ready_real == 2)
+    swap_sort (first, n_ready_real);
+  else if (n_ready_real > 2)
+    qsort (first, n_ready_real, sizeof (rtx), rank_for_schedule);
 
   if (sched_verbose >= 4)
     {
       rank_for_schedule_stats_diff (&stats1, &rank_for_schedule_stats);
-      print_rank_for_schedule_stats (";;\t\t", &stats1);
+      print_rank_for_schedule_stats (";;\t\t", &stats1, ready);
     }
 }
 
+/* Sort the ready list READY by ascending priority.  */
+static void
+ready_sort (struct ready_list *ready)
+{
+  if (ready->n_debug > 0)
+    ready_sort_debug (ready);
+  else
+    ready_sort_real (ready);
+}
+
 /* PREV is an insn that is ready to execute.  Adjust its priority if that
    will help shorten or lengthen register lifetimes as appropriate.  Also
    provide a hook for the target to tweak itself.  */
 
 HAIFA_INLINE static void
-adjust_priority (rtx prev)
+adjust_priority (rtx_insn *prev)
 {
   /* ??? There used to be code here to try and estimate how an insn
      affected register lifetimes, but it did it by looking at REG_DEAD
@@ -3020,14 +3155,16 @@ advance_state (state_t state)
 HAIFA_INLINE static void
 advance_one_cycle (void)
 {
+  int i;
+
   advance_state (curr_state);
-  if (sched_verbose >= 4)
-    fprintf (sched_dump, ";;\tAdvance the current state.\n");
+  for (i = 4; i <= sched_verbose; ++i)
+    fprintf (sched_dump, ";;\tAdvance the current state: %d.\n", clock_var);
 }
 
 /* Update register pressure after scheduling INSN.  */
 static void
-update_register_pressure (rtx insn)
+update_register_pressure (rtx_insn *insn)
 {
   struct reg_use_data *use;
   struct reg_set_data *set;
@@ -3047,11 +3184,11 @@ update_register_pressure (rtx insn)
    meaning in sched-int.h::_haifa_insn_data) for all current BB insns
    after insn AFTER.  */
 static void
-setup_insn_max_reg_pressure (rtx after, bool update_p)
+setup_insn_max_reg_pressure (rtx_insn *after, bool update_p)
 {
   int i, p;
   bool eq_p;
-  rtx insn;
+  rtx_insn *insn;
   static int max_reg_pressure[N_REG_CLASSES];
 
   save_reg_pressure ();
@@ -3091,7 +3228,7 @@ setup_insn_max_reg_pressure (rtx after, bool update_p)
    also max register pressure for unscheduled insns of the current
    BB.  */
 static void
-update_reg_and_insn_max_reg_pressure (rtx insn)
+update_reg_and_insn_max_reg_pressure (rtx_insn *insn)
 {
   int i;
   int before[N_REG_CLASSES];
@@ -3110,7 +3247,7 @@ update_reg_and_insn_max_reg_pressure (rtx insn)
    insns starting after insn AFTER.  Set up also max register pressure
    for all insns of the basic block.  */
 void
-sched_setup_bb_reg_pressure_info (basic_block bb, rtx after)
+sched_setup_bb_reg_pressure_info (basic_block bb, rtx_insn *after)
 {
   gcc_assert (sched_pressure == SCHED_PRESSURE_WEIGHTED);
   initiate_bb_reg_pressure_info (bb);
@@ -3124,7 +3261,7 @@ sched_setup_bb_reg_pressure_info (basic_block bb, rtx after)
    only be scheduled once their control dependency is resolved.  */
 
 static void
-check_clobbered_conditions (rtx insn)
+check_clobbered_conditions (rtx_insn *insn)
 {
   HARD_REG_SET t;
   int i;
@@ -3146,13 +3283,13 @@ check_clobbered_conditions (rtx insn)
     }
   for (i = 0; i <= max_insn_queue_index; i++)
     {
-      rtx link;
+      rtx_insn_list *link;
       int q = NEXT_Q_AFTER (q_ptr, i);
 
     restart_queue:
-      for (link = insn_queue[q]; link; link = XEXP (link, 1))
+      for (link = insn_queue[q]; link; link = link->next ())
        {
-         rtx_insn *x = as_a <rtx_insn *> (XEXP (link, 0));
+         rtx_insn *x = link->insn ();
          if (TODO_SPEC (x) == DEP_CONTROL && cond_clobbered_p (x, t))
            {
              queue_remove (x);
@@ -3277,7 +3414,7 @@ model_remove_from_worklist (struct model_insn_info *insn)
 }
 
 /* Add INSN to the model worklist.  Start looking for a suitable position
-   between neighbors PREV and NEXT, testing at most MAX_SCHED_READY_INSNS
+   between neighbors PREV and NEXT, testing at most param_max_sched_ready_insns
    insns either side.  A null PREV indicates the beginning of the list and
    a null NEXT indicates the end.  */
 
@@ -3288,7 +3425,7 @@ model_add_to_worklist (struct model_insn_info *insn,
 {
   int count;
 
-  count = MAX_SCHED_READY_INSNS;
+  count = param_max_sched_ready_insns;
   if (count > 0 && prev && model_order_p (insn, prev))
     do
       {
@@ -3316,7 +3453,7 @@ model_promote_insn (struct model_insn_info *insn)
   int count;
 
   prev = insn->prev;
-  count = MAX_SCHED_READY_INSNS;
+  count = param_max_sched_ready_insns;
   while (count > 0 && prev && model_order_p (insn, prev))
     {
       count--;
@@ -3332,7 +3469,7 @@ model_promote_insn (struct model_insn_info *insn)
 /* Add INSN to the end of the model schedule.  */
 
 static void
-model_add_to_schedule (rtx insn)
+model_add_to_schedule (rtx_insn *insn)
 {
   unsigned int point;
 
@@ -3351,7 +3488,7 @@ model_add_to_schedule (rtx insn)
 static void
 model_analyze_insns (void)
 {
-  rtx start, end, iter;
+  rtx_insn *start, *end, *iter;
   sd_iterator_def sd_it;
   dep_t dep;
   struct model_insn_info *insn, *con;
@@ -3602,7 +3739,7 @@ model_choose_insn (void)
     {
       fprintf (sched_dump, ";;\t+--- worklist:\n");
       insn = model_worklist;
-      count = MAX_SCHED_READY_INSNS;
+      count = param_max_sched_ready_insns;
       while (count > 0 && insn)
        {
          fprintf (sched_dump, ";;\t+---   %d [%d, %d, %d, %d]\n",
@@ -3634,7 +3771,7 @@ model_choose_insn (void)
 
      Failing that, just pick the highest-priority instruction in the
      worklist.  */
-  count = MAX_SCHED_READY_INSNS;
+  count = param_max_sched_ready_insns;
   insn = model_worklist;
   fallback = 0;
   for (;;)
@@ -3692,7 +3829,7 @@ static void
 model_reset_queue_indices (void)
 {
   unsigned int i;
-  rtx insn;
+  rtx_insn *insn;
 
   FOR_EACH_VEC_ELT (model_schedule, i, insn)
     QUEUE_INDEX (insn) = MODEL_INSN_INFO (insn)->old_queue;
@@ -3720,15 +3857,13 @@ model_dump_pressure_summary (void)
    scheduling region.  */
 
 static void
-model_start_schedule (void)
+model_start_schedule (basic_block bb)
 {
-  basic_block bb;
-
   model_next_priority = 1;
   model_schedule.create (sched_max_luid);
   model_insns = XCNEWVEC (struct model_insn_info, sched_max_luid);
 
-  bb = BLOCK_FOR_INSN (NEXT_INSN (current_sched_info->prev_head));
+  gcc_assert (bb == BLOCK_FOR_INSN (NEXT_INSN (current_sched_info->prev_head)));
   initiate_reg_pressure_info (df_get_live_in (bb));
 
   model_analyze_insns ();
@@ -3766,6 +3901,56 @@ model_end_schedule (void)
   model_finalize_pressure_group (&model_before_pressure);
   model_schedule.release ();
 }
+
+/* Prepare reg pressure scheduling for basic block BB.  */
+static void
+sched_pressure_start_bb (basic_block bb)
+{
+  /* Set the number of available registers for each class taking into account
+     relative probability of current basic block versus function prologue and
+     epilogue.
+     * If the basic block executes much more often than the prologue/epilogue
+     (e.g., inside a hot loop), then cost of spill in the prologue is close to
+     nil, so the effective number of available registers is
+     (ira_class_hard_regs_num[cl] - fixed_regs_num[cl] - 0).
+     * If the basic block executes as often as the prologue/epilogue,
+     then spill in the block is as costly as in the prologue, so the effective
+     number of available registers is
+     (ira_class_hard_regs_num[cl] - fixed_regs_num[cl]
+      - call_saved_regs_num[cl]).
+     Note that all-else-equal, we prefer to spill in the prologue, since that
+     allows "extra" registers for other basic blocks of the function.
+     * If the basic block is on the cold path of the function and executes
+     rarely, then we should always prefer to spill in the block, rather than
+     in the prologue/epilogue.  The effective number of available register is
+     (ira_class_hard_regs_num[cl] - fixed_regs_num[cl]
+      - call_saved_regs_num[cl]).  */
+  {
+    int i;
+    int entry_freq = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count.to_frequency (cfun);
+    int bb_freq = bb->count.to_frequency (cfun);
+
+    if (bb_freq == 0)
+      {
+       if (entry_freq == 0)
+         entry_freq = bb_freq = 1;
+      }
+    if (bb_freq < entry_freq)
+      bb_freq = entry_freq;
+
+    for (i = 0; i < ira_pressure_classes_num; ++i)
+      {
+       enum reg_class cl = ira_pressure_classes[i];
+       sched_class_regs_num[cl] = ira_class_hard_regs_num[cl]
+                                  - fixed_regs_num[cl];
+       sched_class_regs_num[cl]
+         -= (call_saved_regs_num[cl] * entry_freq) / bb_freq;
+      }
+  }
+
+  if (sched_pressure == SCHED_PRESSURE_MODEL)
+    model_start_schedule (bb);
+}
 \f
 /* A structure that holds local state for the loop in schedule_block.  */
 struct sched_block_state
@@ -3835,7 +4020,7 @@ schedule_insn (rtx_insn *insn)
   gcc_assert (sd_lists_empty_p (insn, SD_LIST_HARD_BACK));
 
   /* Reset debug insns invalidated by moving this insn.  */
-  if (MAY_HAVE_DEBUG_INSNS && !DEBUG_INSN_P (insn))
+  if (MAY_HAVE_DEBUG_BIND_INSNS && !DEBUG_INSN_P (insn))
     for (sd_it = sd_iterator_start (insn, SD_LIST_BACK);
         sd_iterator_cond (&sd_it, &dep);)
       {
@@ -3848,7 +4033,7 @@ schedule_insn (rtx_insn *insn)
            continue;
          }
 
-       gcc_assert (DEBUG_INSN_P (dbg));
+       gcc_assert (DEBUG_BIND_INSN_P (dbg));
 
        if (sched_verbose >= 6)
          fprintf (sched_dump, ";;\t\tresetting: debug insn %d\n",
@@ -3912,8 +4097,8 @@ schedule_insn (rtx_insn *insn)
   gcc_assert (INSN_TICK (insn) >= MIN_TICK);
   if (INSN_TICK (insn) > clock_var)
     /* INSN has been prematurely moved from the queue to the ready list.
-       This is possible only if following flag is set.  */
-    gcc_assert (flag_sched_stalled_insns);
+       This is possible only if following flags are set.  */
+    gcc_assert (flag_sched_stalled_insns || sched_fusion);
 
   /* ??? Probably, if INSN is scheduled prematurely, we should leave
      INSN_TICK untouched.  This is a machine-dependent issue, actually.  */
@@ -4056,6 +4241,15 @@ remove_notes (rtx_insn *head, rtx_insn *tail)
          if (insn != tail)
            {
              remove_insn (insn);
+             /* If an insn was split just before the EPILOGUE_BEG note and
+                that split created new basic blocks, we could have a
+                BASIC_BLOCK note here.  Safely advance over it in that case
+                and assert that we land on a real insn.  */
+             if (NOTE_P (next)
+                 && NOTE_KIND (next) == NOTE_INSN_BASIC_BLOCK
+                 && next != next_tail)
+               next = NEXT_INSN (next);
+             gcc_assert (INSN_P (next));
              add_reg_note (next, REG_SAVE_NOTE,
                            GEN_INT (NOTE_INSN_EPILOGUE_BEG));
              break;
@@ -4101,7 +4295,7 @@ struct haifa_saved_data
   state_t curr_state;
 
   rtx_insn *last_scheduled_insn;
-  rtx last_nondebug_scheduled_insn;
+  rtx_insn *last_nondebug_scheduled_insn;
   rtx_insn *nonscheduled_insns_begin;
   int cycle_issued_insns;
 
@@ -4111,7 +4305,7 @@ struct haifa_saved_data
   /* We don't need to save q_ptr, as its value is arbitrary and we can set it
      to 0 when restoring.  */
   int q_size;
-  rtx *insn_queue;
+  rtx_insn_list **insn_queue;
 
   /* Describe pattern replacements that occurred since this backtrack point
      was queued.  */
@@ -4131,7 +4325,7 @@ static struct haifa_saved_data *backtrack_queue;
 /* For every dependency of INSN, set the FEEDS_BACKTRACK_INSN bit according
    to SET_P.  */
 static void
-mark_backtrack_feeds (rtx insn, int set_p)
+mark_backtrack_feeds (rtx_insn *insn, int set_p)
 {
   sd_iterator_def sd_it;
   dep_t dep;
@@ -4162,7 +4356,7 @@ save_backtrack_point (struct delay_pair *pair,
   save->ready.vec = XNEWVEC (rtx_insn *, ready.veclen);
   memcpy (save->ready.vec, ready.vec, ready.veclen * sizeof (rtx));
 
-  save->insn_queue = XNEWVEC (rtx, max_insn_queue_index + 1);
+  save->insn_queue = XNEWVEC (rtx_insn_list *, max_insn_queue_index + 1);
   save->q_size = q_size;
   for (i = 0; i <= max_insn_queue_index; i++)
     {
@@ -4237,10 +4431,10 @@ toggle_cancelled_flags (bool set)
   for (i = 0; i <= max_insn_queue_index; i++)
     {
       int q = NEXT_Q_AFTER (q_ptr, i);
-      rtx link;
-      for (link = insn_queue[q]; link; link = XEXP (link, 1))
+      rtx_insn_list *link;
+      for (link = insn_queue[q]; link; link = link->next ())
        {
-         rtx insn = XEXP (link, 0);
+         rtx_insn *insn = link->insn ();
          FOR_EACH_DEP (insn, SD_LIST_BACK, sd_it, dep)
            if (!DEBUG_INSN_P (DEP_PRO (dep)))
              {
@@ -4277,15 +4471,15 @@ undo_replacements_for_backtrack (struct haifa_saved_data *save)
    queued nowhere.  */
 
 static void
-unschedule_insns_until (rtx insn)
+unschedule_insns_until (rtx_insn *insn)
 {
-  auto_vec<rtx> recompute_vec;
+  auto_vec<rtx_insn *> recompute_vec;
 
   /* Make two passes over the insns to be unscheduled.  First, we clear out
      dependencies and other trivial bookkeeping.  */
   for (;;)
     {
-      rtx last;
+      rtx_insn *last;
       sd_iterator_def sd_it;
       dep_t dep;
 
@@ -4323,7 +4517,7 @@ unschedule_insns_until (rtx insn)
      up-to-date.  */
   while (!recompute_vec.is_empty ())
     {
-      rtx con;
+      rtx_insn *con;
 
       con = recompute_vec.pop ();
       MUST_RECOMPUTE_SPEC_P (con) = 0;
@@ -4347,7 +4541,6 @@ unschedule_insns_until (rtx insn)
 static void
 restore_last_backtrack_point (struct sched_block_state *psched_block)
 {
-  rtx link;
   int i;
   struct haifa_saved_data *save = backtrack_queue;
 
@@ -4382,9 +4575,9 @@ restore_last_backtrack_point (struct sched_block_state *psched_block)
     {
       int q = NEXT_Q_AFTER (q_ptr, i);
 
-      for (link = insn_queue[q]; link; link = XEXP (link, 1))
+      for (rtx_insn_list *link = insn_queue[q]; link; link = link->next ())
        {
-         rtx x = XEXP (link, 0);
+         rtx_insn *x = link->insn ();
          QUEUE_INDEX (x) = QUEUE_NOWHERE;
          INSN_TICK (x) = INVALID_TICK;
        }
@@ -4414,9 +4607,9 @@ restore_last_backtrack_point (struct sched_block_state *psched_block)
 
       insn_queue[q] = save->insn_queue[q];
 
-      for (link = insn_queue[q]; link; link = XEXP (link, 1))
+      for (rtx_insn_list *link = insn_queue[q]; link; link = link->next ())
        {
-         rtx x = XEXP (link, 0);
+         rtx_insn *x = link->insn ();
          QUEUE_INDEX (x) = i;
          TODO_SPEC (x) = recompute_todo_spec (x, true);
          INSN_TICK (x) = save->clock_var + i;
@@ -4529,7 +4722,12 @@ apply_replacement (dep_t dep, bool immediately)
       success = validate_change (desc->insn, desc->loc, desc->newval, 0);
       gcc_assert (success);
 
+      rtx_insn *insn = DEP_PRO (dep);
+
+      /* Recompute priority since dependent priorities may have changed.  */
+      priority (insn, true);
       update_insn_after_change (desc->insn);
+
       if ((TODO_SPEC (desc->insn) & (HARD_DEP | DEP_POSTPONED)) == 0)
        fix_tick_ready (desc->insn);
 
@@ -4583,7 +4781,17 @@ restore_pattern (dep_t dep, bool immediately)
 
       success = validate_change (desc->insn, desc->loc, desc->orig, 0);
       gcc_assert (success);
+
+      rtx_insn *insn = DEP_PRO (dep);
+
+      if (QUEUE_INDEX (insn) != QUEUE_SCHEDULED)
+       {
+         /* Recompute priority since dependent priorities may have changed.  */
+         priority (insn, true);
+       }
+
       update_insn_after_change (desc->insn);
+
       if (backtrack_queue != NULL)
        {
          backtrack_queue->replacement_deps.safe_push (dep);
@@ -4625,7 +4833,7 @@ perform_replacements_new_cycle (void)
    reduced on recursive calls.  Return true if we produced a good
    estimate, or false if we exceeded the budget.  */
 static bool
-estimate_insn_tick (bitmap processed, rtx insn, int budget)
+estimate_insn_tick (bitmap processed, rtx_insn *insn, int budget)
 {
   sd_iterator_def sd_it;
   dep_t dep;
@@ -4669,14 +4877,12 @@ estimate_insn_tick (bitmap processed, rtx insn, int budget)
 static int
 estimate_shadow_tick (struct delay_pair *p)
 {
-  bitmap_head processed;
+  auto_bitmap processed;
   int t;
   bool cutoff;
-  bitmap_initialize (&processed, 0);
 
-  cutoff = !estimate_insn_tick (&processed, p->i2,
+  cutoff = !estimate_insn_tick (processed, p->i2,
                                max_insn_queue_index + pair_delay (p));
-  bitmap_clear (&processed);
   if (cutoff)
     return max_insn_queue_index;
   t = INSN_TICK_ESTIMATE (p->i2) - (clock_var + pair_delay (p) + 1);
@@ -4810,7 +5016,7 @@ get_ebb_head_tail (basic_block beg, basic_block end,
                reorder_insns_nobb (note, note, end_tail);
 
                if (end_tail == BB_END (end))
-                 SET_BB_END (end) = note;
+                 BB_END (end) = note;
 
                if (BLOCK_FOR_INSN (note) != end)
                  df_insn_change_bb (note, end);
@@ -4830,7 +5036,7 @@ get_ebb_head_tail (basic_block beg, basic_block end,
 /* Return nonzero if there are no real insns in the range [ HEAD, TAIL ].  */
 
 int
-no_real_insns_p (const_rtx head, const_rtx tail)
+no_real_insns_p (const rtx_insn *head, const rtx_insn *tail)
 {
   while (head != NEXT_INSN (tail))
     {
@@ -4869,7 +5075,7 @@ restore_other_notes (rtx_insn *head, basic_block head_bb)
       SET_NEXT_INSN (note_list) = head;
 
       if (BLOCK_FOR_INSN (head) != head_bb)
-       SET_BB_END (head_bb) = note_list;
+       BB_END (head_bb) = note_list;
 
       head = note_head;
     }
@@ -4925,8 +5131,8 @@ static void
 queue_to_ready (struct ready_list *ready)
 {
   rtx_insn *insn;
-  rtx link;
-  rtx skip_insn;
+  rtx_insn_list *link;
+  rtx_insn *skip_insn;
 
   q_ptr = NEXT_Q (q_ptr);
 
@@ -4935,13 +5141,13 @@ queue_to_ready (struct ready_list *ready)
        nonscheduled insn.  */
     skip_insn = first_nonscheduled_insn ();
   else
-    skip_insn = NULL_RTX;
+    skip_insn = NULL;
 
   /* Add all pending insns that can be scheduled without stalls to the
      ready list.  */
-  for (link = insn_queue[q_ptr]; link; link = XEXP (link, 1))
+  for (link = insn_queue[q_ptr]; link; link = link->next ())
     {
-      insn = as_a <rtx_insn *> (XEXP (link, 0));
+      insn = link->insn ();
       q_size -= 1;
 
       if (sched_verbose >= 2)
@@ -4951,12 +5157,12 @@ queue_to_ready (struct ready_list *ready)
       /* If the ready list is full, delay the insn for 1 cycle.
         See the comment in schedule_block for the rationale.  */
       if (!reload_completed
-         && (ready->n_ready - ready->n_debug > MAX_SCHED_READY_INSNS
+         && (ready->n_ready - ready->n_debug > param_max_sched_ready_insns
              || (sched_pressure == SCHED_PRESSURE_MODEL
-                 /* Limit pressure recalculations to MAX_SCHED_READY_INSNS
-                    instructions too.  */
+                 /* Limit pressure recalculations to
+                    param_max_sched_ready_insns instructions too.  */
                  && model_index (insn) > (model_curr_point
-                                          + MAX_SCHED_READY_INSNS)))
+                                          + param_max_sched_ready_insns)))
          && !(sched_pressure == SCHED_PRESSURE_MODEL
               && model_curr_point < model_num_insns
               /* Always allow the next model instruction to issue.  */
@@ -4987,9 +5193,9 @@ queue_to_ready (struct ready_list *ready)
        {
          if ((link = insn_queue[NEXT_Q_AFTER (q_ptr, stalls)]))
            {
-             for (; link; link = XEXP (link, 1))
+             for (; link; link = link->next ())
                {
-                 insn = as_a <rtx_insn *> (XEXP (link, 0));
+                 insn = link->insn ();
                  q_size -= 1;
 
                  if (sched_verbose >= 2)
@@ -5030,11 +5236,10 @@ queue_to_ready (struct ready_list *ready)
    addition) depending on user flags and target hooks.  */
 
 static bool
-ok_for_early_queue_removal (rtx insn)
+ok_for_early_queue_removal (rtx_insn *insn)
 {
   if (targetm.sched.is_costly_dependence)
     {
-      rtx prev_insn;
       int n_cycles;
       int i = scheduled_insns.length ();
       for (n_cycles = flag_sched_stalled_insns_dep; n_cycles; n_cycles--)
@@ -5043,7 +5248,7 @@ ok_for_early_queue_removal (rtx insn)
            {
              int cost;
 
-             prev_insn = scheduled_insns[i];
+             rtx_insn *prev_insn = scheduled_insns[i];
 
              if (!NOTE_P (prev_insn))
                {
@@ -5081,9 +5286,9 @@ static int
 early_queue_to_ready (state_t state, struct ready_list *ready)
 {
   rtx_insn *insn;
-  rtx link;
-  rtx next_link;
-  rtx prev_link;
+  rtx_insn_list *link;
+  rtx_insn_list *next_link;
+  rtx_insn_list *prev_link;
   bool move_to_ready;
   int cost;
   state_t temp_state = alloca (dfa_state_size);
@@ -5117,8 +5322,8 @@ early_queue_to_ready (state_t state, struct ready_list *ready)
          prev_link = 0;
          while (link)
            {
-             next_link = XEXP (link, 1);
-             insn = as_a <rtx_insn *> (XEXP (link, 0));
+             next_link = link->next ();
+             insn = link->insn ();
              if (insn && sched_verbose > 6)
                print_rtl_single (sched_dump, insn);
 
@@ -5205,6 +5410,9 @@ debug_ready_list_1 (struct ready_list *ready, signed char *ready_try)
       fprintf (sched_dump, ":prio=%d", INSN_PRIORITY (p[i]));
       if (INSN_TICK (p[i]) > clock_var)
        fprintf (sched_dump, ":delay=%d", INSN_TICK (p[i]) - clock_var);
+      if (sched_pressure == SCHED_PRESSURE_MODEL)
+       fprintf (sched_dump, ":idx=%d",
+                model_index (p[i]));
       if (sched_pressure != SCHED_PRESSURE_NONE)
        fprintf (sched_dump, ")");
     }
@@ -5222,9 +5430,10 @@ debug_ready_list (struct ready_list *ready)
    NOTEs.  This is used for NOTE_INSN_EPILOGUE_BEG, so that sched-ebb
    replaces the epilogue note in the correct basic block.  */
 void
-reemit_notes (rtx insn)
+reemit_notes (rtx_insn *insn)
 {
-  rtx note, last = insn;
+  rtx note;
+  rtx_insn *last = insn;
 
   for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
     {
@@ -5234,13 +5443,14 @@ reemit_notes (rtx insn)
 
          last = emit_note_before (note_type, last);
          remove_note (insn, note);
+         df_insn_create_insn_record (last);
        }
     }
 }
 
 /* Move INSN.  Reemit notes if needed.  Update CFG, if needed.  */
 static void
-move_insn (rtx_insn *insn, rtx last, rtx nt)
+move_insn (rtx_insn *insn, rtx_insn *last, rtx nt)
 {
   if (PREV_INSN (insn) != last)
     {
@@ -5268,7 +5478,7 @@ move_insn (rtx_insn *insn, rtx last, rtx nt)
 
          gcc_assert (BLOCK_FOR_INSN (PREV_INSN (insn)) == bb);
 
-         SET_BB_END (bb) = PREV_INSN (insn);
+         BB_END (bb) = PREV_INSN (insn);
        }
 
       gcc_assert (BB_END (bb) != last);
@@ -5317,7 +5527,7 @@ move_insn (rtx_insn *insn, rtx last, rtx nt)
 
       /* Update BB_END, if needed.  */
       if (BB_END (bb) == last)
-       SET_BB_END (bb) = insn;
+       BB_END (bb) = insn;
     }
 
   SCHED_GROUP_P (insn) = 0;
@@ -5340,6 +5550,314 @@ insn_finishes_cycle_p (rtx_insn *insn)
   return false;
 }
 
+/* Helper for autopref_multipass_init.  Given a SET in PAT and whether
+   we're expecting a memory WRITE or not, check that the insn is relevant to
+   the autoprefetcher modelling code.  Return true iff that is the case.
+   If it is relevant, record the base register of the memory op in BASE and
+   the offset in OFFSET.  */
+
+static bool
+analyze_set_insn_for_autopref (rtx pat, bool write, rtx *base, int *offset)
+{
+  if (GET_CODE (pat) != SET)
+    return false;
+
+  rtx mem = write ? SET_DEST (pat) : SET_SRC (pat);
+  if (!MEM_P (mem))
+    return false;
+
+  struct address_info info;
+  decompose_mem_address (&info, mem);
+
+  /* TODO: Currently only (base+const) addressing is supported.  */
+  if (info.base == NULL || !REG_P (*info.base)
+      || (info.disp != NULL && !CONST_INT_P (*info.disp)))
+    return false;
+
+  *base = *info.base;
+  *offset = info.disp ? INTVAL (*info.disp) : 0;
+  return true;
+}
+
+/* Functions to model cache auto-prefetcher.
+
+   Some of the CPUs have cache auto-prefetcher, which /seems/ to initiate
+   memory prefetches if it sees instructions with consequitive memory accesses
+   in the instruction stream.  Details of such hardware units are not published,
+   so we can only guess what exactly is going on there.
+   In the scheduler, we model abstract auto-prefetcher.  If there are memory
+   insns in the ready list (or the queue) that have same memory base, but
+   different offsets, then we delay the insns with larger offsets until insns
+   with smaller offsets get scheduled.  If PARAM_SCHED_AUTOPREF_QUEUE_DEPTH
+   is "1", then we look at the ready list; if it is N>1, then we also look
+   through N-1 queue entries.
+   If the param is N>=0, then rank_for_schedule will consider auto-prefetching
+   among its heuristics.
+   Param value of "-1" disables modelling of the auto-prefetcher.  */
+
+/* Initialize autoprefetcher model data for INSN.  */
+static void
+autopref_multipass_init (const rtx_insn *insn, int write)
+{
+  autopref_multipass_data_t data = &INSN_AUTOPREF_MULTIPASS_DATA (insn)[write];
+
+  gcc_assert (data->status == AUTOPREF_MULTIPASS_DATA_UNINITIALIZED);
+  data->base = NULL_RTX;
+  data->offset = 0;
+  /* Set insn entry initialized, but not relevant for auto-prefetcher.  */
+  data->status = AUTOPREF_MULTIPASS_DATA_IRRELEVANT;
+
+  rtx pat = PATTERN (insn);
+
+  /* We have a multi-set insn like a load-multiple or store-multiple.
+     We care about these as long as all the memory ops inside the PARALLEL
+     have the same base register.  We care about the minimum and maximum
+     offsets from that base but don't check for the order of those offsets
+     within the PARALLEL insn itself.  */
+  if (GET_CODE (pat) == PARALLEL)
+    {
+      int n_elems = XVECLEN (pat, 0);
+
+      int i, offset;
+      rtx base, prev_base = NULL_RTX;
+      int min_offset = INT_MAX;
+
+      for (i = 0; i < n_elems; i++)
+       {
+         rtx set = XVECEXP (pat, 0, i);
+         if (GET_CODE (set) != SET)
+           return;
+
+         if (!analyze_set_insn_for_autopref (set, write, &base, &offset))
+           return;
+
+         /* Ensure that all memory operations in the PARALLEL use the same
+            base register.  */
+         if (i > 0 && REGNO (base) != REGNO (prev_base))
+           return;
+         prev_base = base;
+         min_offset = MIN (min_offset, offset);
+       }
+
+      /* If we reached here then we have a valid PARALLEL of multiple memory ops
+        with prev_base as the base and min_offset containing the offset.  */
+      gcc_assert (prev_base);
+      data->base = prev_base;
+      data->offset = min_offset;
+      data->status = AUTOPREF_MULTIPASS_DATA_NORMAL;
+      return;
+    }
+
+  /* Otherwise this is a single set memory operation.  */
+  rtx set = single_set (insn);
+  if (set == NULL_RTX)
+    return;
+
+  if (!analyze_set_insn_for_autopref (set, write, &data->base,
+                                      &data->offset))
+    return;
+
+  /* This insn is relevant for the auto-prefetcher.
+     The base and offset fields will have been filled in the
+     analyze_set_insn_for_autopref call above.  */
+  data->status = AUTOPREF_MULTIPASS_DATA_NORMAL;
+}
+
+/* Helper function for rank_for_schedule sorting.  */
+static int
+autopref_rank_for_schedule (const rtx_insn *insn1, const rtx_insn *insn2)
+{
+  int r = 0;
+  for (int write = 0; write < 2 && !r; ++write)
+    {
+      autopref_multipass_data_t data1
+       = &INSN_AUTOPREF_MULTIPASS_DATA (insn1)[write];
+      autopref_multipass_data_t data2
+       = &INSN_AUTOPREF_MULTIPASS_DATA (insn2)[write];
+
+      if (data1->status == AUTOPREF_MULTIPASS_DATA_UNINITIALIZED)
+       autopref_multipass_init (insn1, write);
+
+      if (data2->status == AUTOPREF_MULTIPASS_DATA_UNINITIALIZED)
+       autopref_multipass_init (insn2, write);
+
+      int irrel1 = data1->status == AUTOPREF_MULTIPASS_DATA_IRRELEVANT;
+      int irrel2 = data2->status == AUTOPREF_MULTIPASS_DATA_IRRELEVANT;
+
+      if (!irrel1 && !irrel2)
+       /* Sort memory references from lowest offset to the largest.  */
+       r = data1->offset - data2->offset;
+      else if (write)
+       /* Schedule "irrelevant" insns before memory stores to resolve
+          as many producer dependencies of stores as possible.  */
+       r = irrel2 - irrel1;
+      else
+       /* Schedule "irrelevant" insns after memory reads to avoid breaking
+          memory read sequences.  */
+       r = irrel1 - irrel2;
+    }
+
+  return r;
+}
+
+/* True if header of debug dump was printed.  */
+static bool autopref_multipass_dfa_lookahead_guard_started_dump_p;
+
+/* Helper for autopref_multipass_dfa_lookahead_guard.
+   Return "1" if INSN1 should be delayed in favor of INSN2.  */
+static int
+autopref_multipass_dfa_lookahead_guard_1 (const rtx_insn *insn1,
+                                         const rtx_insn *insn2, int write)
+{
+  autopref_multipass_data_t data1
+    = &INSN_AUTOPREF_MULTIPASS_DATA (insn1)[write];
+  autopref_multipass_data_t data2
+    = &INSN_AUTOPREF_MULTIPASS_DATA (insn2)[write];
+
+  if (data2->status == AUTOPREF_MULTIPASS_DATA_UNINITIALIZED)
+    autopref_multipass_init (insn2, write);
+  if (data2->status == AUTOPREF_MULTIPASS_DATA_IRRELEVANT)
+    return 0;
+
+  if (rtx_equal_p (data1->base, data2->base)
+      && data1->offset > data2->offset)
+    {
+      if (sched_verbose >= 2)
+       {
+          if (!autopref_multipass_dfa_lookahead_guard_started_dump_p)
+           {
+             fprintf (sched_dump,
+                      ";;\t\tnot trying in max_issue due to autoprefetch "
+                      "model: ");
+             autopref_multipass_dfa_lookahead_guard_started_dump_p = true;
+           }
+
+         fprintf (sched_dump, " %d(%d)", INSN_UID (insn1), INSN_UID (insn2));
+       }
+
+      return 1;
+    }
+
+  return 0;
+}
+
+/* General note:
+
+   We could have also hooked autoprefetcher model into
+   first_cycle_multipass_backtrack / first_cycle_multipass_issue hooks
+   to enable intelligent selection of "[r1+0]=r2; [r1+4]=r3" on the same cycle
+   (e.g., once "[r1+0]=r2" is issued in max_issue(), "[r1+4]=r3" gets
+   unblocked).  We don't bother about this yet because target of interest
+   (ARM Cortex-A15) can issue only 1 memory operation per cycle.  */
+
+/* Implementation of first_cycle_multipass_dfa_lookahead_guard hook.
+   Return "1" if INSN1 should not be considered in max_issue due to
+   auto-prefetcher considerations.  */
+int
+autopref_multipass_dfa_lookahead_guard (rtx_insn *insn1, int ready_index)
+{
+  int r = 0;
+
+  /* Exit early if the param forbids this or if we're not entering here through
+     normal haifa scheduling.  This can happen if selective scheduling is
+     explicitly enabled.  */
+  if (!insn_queue || param_sched_autopref_queue_depth <= 0)
+    return 0;
+
+  if (sched_verbose >= 2 && ready_index == 0)
+    autopref_multipass_dfa_lookahead_guard_started_dump_p = false;
+
+  for (int write = 0; write < 2; ++write)
+    {
+      autopref_multipass_data_t data1
+       = &INSN_AUTOPREF_MULTIPASS_DATA (insn1)[write];
+
+      if (data1->status == AUTOPREF_MULTIPASS_DATA_UNINITIALIZED)
+       autopref_multipass_init (insn1, write);
+      if (data1->status == AUTOPREF_MULTIPASS_DATA_IRRELEVANT)
+       continue;
+
+      if (ready_index == 0
+         && data1->status == AUTOPREF_MULTIPASS_DATA_DONT_DELAY)
+       /* We allow only a single delay on priviledged instructions.
+          Doing otherwise would cause infinite loop.  */
+       {
+         if (sched_verbose >= 2)
+           {
+             if (!autopref_multipass_dfa_lookahead_guard_started_dump_p)
+               {
+                 fprintf (sched_dump,
+                          ";;\t\tnot trying in max_issue due to autoprefetch "
+                          "model: ");
+                 autopref_multipass_dfa_lookahead_guard_started_dump_p = true;
+               }
+
+             fprintf (sched_dump, " *%d*", INSN_UID (insn1));
+           }
+         continue;
+       }
+
+      for (int i2 = 0; i2 < ready.n_ready; ++i2)
+       {
+         rtx_insn *insn2 = get_ready_element (i2);
+         if (insn1 == insn2)
+           continue;
+         r = autopref_multipass_dfa_lookahead_guard_1 (insn1, insn2, write);
+         if (r)
+           {
+             if (ready_index == 0)
+               {
+                 r = -1;
+                 data1->status = AUTOPREF_MULTIPASS_DATA_DONT_DELAY;
+               }
+             goto finish;
+           }
+       }
+
+      if (param_sched_autopref_queue_depth == 1)
+       continue;
+
+      /* Everything from the current queue slot should have been moved to
+        the ready list.  */
+      gcc_assert (insn_queue[NEXT_Q_AFTER (q_ptr, 0)] == NULL_RTX);
+
+      int n_stalls = param_sched_autopref_queue_depth - 1;
+      if (n_stalls > max_insn_queue_index)
+       n_stalls = max_insn_queue_index;
+
+      for (int stalls = 1; stalls <= n_stalls; ++stalls)
+       {
+         for (rtx_insn_list *link = insn_queue[NEXT_Q_AFTER (q_ptr, stalls)];
+              link != NULL_RTX;
+              link = link->next ())
+           {
+             rtx_insn *insn2 = link->insn ();
+             r = autopref_multipass_dfa_lookahead_guard_1 (insn1, insn2,
+                                                           write);
+             if (r)
+               {
+                 /* Queue INSN1 until INSN2 can issue.  */
+                 r = -stalls;
+                 if (ready_index == 0)
+                   data1->status = AUTOPREF_MULTIPASS_DATA_DONT_DELAY;
+                 goto finish;
+               }
+           }
+       }
+    }
+
+    finish:
+  if (sched_verbose >= 2
+      && autopref_multipass_dfa_lookahead_guard_started_dump_p
+      && (ready_index == ready.n_ready - 1 || r < 0))
+    /* This does not /always/ trigger.  We don't output EOL if the last
+       insn is not recognized (INSN_CODE < 0) and lookahead_guard is not
+       called.  We can live with this.  */
+    fprintf (sched_dump, "\n");
+
+  return r;
+}
+
 /* Define type for target data used in multipass scheduling.  */
 #ifndef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T
 # define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DATA_T int
@@ -5379,15 +5897,6 @@ int dfa_lookahead;
    could achieve DFA_LOOKAHEAD ** N , where N is the queue length.  */
 static int max_lookahead_tries;
 
-/* The following value is value of hook
-   `first_cycle_multipass_dfa_lookahead' at the last call of
-   `max_issue'.  */
-static int cached_first_cycle_multipass_dfa_lookahead = 0;
-
-/* The following value is value of `issue_rate' at the last call of
-   `sched_init'.  */
-static int cached_issue_rate = 0;
-
 /* The following function returns maximal (or close to maximal) number
    of insns which can be issued on the same cycle and one of which
    insns is insns with the best rank (the first insn in READY).  To
@@ -5411,14 +5920,16 @@ max_issue (struct ready_list *ready, int privileged_n, state_t state,
   struct choice_entry *top;
   rtx_insn *insn;
 
+  if (sched_fusion)
+    return 0;
+
   n_ready = ready->n_ready;
   gcc_assert (dfa_lookahead >= 1 && privileged_n >= 0
              && privileged_n <= n_ready);
 
   /* Init MAX_LOOKAHEAD_TRIES.  */
-  if (cached_first_cycle_multipass_dfa_lookahead != dfa_lookahead)
+  if (max_lookahead_tries == 0)
     {
-      cached_first_cycle_multipass_dfa_lookahead = dfa_lookahead;
       max_lookahead_tries = 100;
       for (i = 0; i < issue_rate; i++)
        max_lookahead_tries *= dfa_lookahead;
@@ -5581,8 +6092,6 @@ static int
 choose_ready (struct ready_list *ready, bool first_cycle_insn_p,
              rtx_insn **insn_ptr)
 {
-  int lookahead;
-
   if (dbg_cnt (sched_insn) == false)
     {
       if (nonscheduled_insns_begin == NULL_RTX)
@@ -5603,14 +6112,10 @@ choose_ready (struct ready_list *ready, bool first_cycle_insn_p,
       return -1;
     }
 
-  lookahead = 0;
-
-  if (targetm.sched.first_cycle_multipass_dfa_lookahead)
-    lookahead = targetm.sched.first_cycle_multipass_dfa_lookahead ();
-  if (lookahead <= 0 || SCHED_GROUP_P (ready_element (ready, 0))
+  if (dfa_lookahead <= 0 || SCHED_GROUP_P (ready_element (ready, 0))
       || DEBUG_INSN_P (ready_element (ready, 0)))
     {
-      if (targetm.sched.dispatch (NULL_RTX, IS_DISPATCH_ON))
+      if (targetm.sched.dispatch (NULL, IS_DISPATCH_ON))
        *insn_ptr = ready_remove_first_dispatch (ready);
       else
        *insn_ptr = ready_remove_first (ready);
@@ -5709,7 +6214,7 @@ choose_ready (struct ready_list *ready, bool first_cycle_insn_p,
    block.  TARGET_BB is the argument passed to schedule_block.  */
 
 static void
-commit_schedule (rtx_insn *prev_head, rtx tail, basic_block *target_bb)
+commit_schedule (rtx_insn *prev_head, rtx_insn *tail, basic_block *target_bb)
 {
   unsigned int i;
   rtx_insn *insn;
@@ -5726,7 +6231,7 @@ commit_schedule (rtx_insn *prev_head, rtx tail, basic_block *target_bb)
 
          if (sched_verbose)
            {
-             rtx x;
+             rtx_insn *x;
 
              x = next_real_insn (last_scheduled_insn);
              gcc_assert (x);
@@ -5764,7 +6269,10 @@ prune_ready_list (state_t temp_state, bool first_cycle_insn_p,
 {
   int i, pass;
   bool sched_group_found = false;
-  int min_cost_group = 1;
+  int min_cost_group = 0;
+
+  if (sched_fusion)
+    return;
 
   for (i = 0; i < ready.n_ready; i++)
     {
@@ -5777,8 +6285,8 @@ prune_ready_list (state_t temp_state, bool first_cycle_insn_p,
     }
 
   /* Make two passes if there's a SCHED_GROUP_P insn; make sure to handle
-     such an insn first and note its cost, then schedule all other insns
-     for one cycle later.  */
+     such an insn first and note its cost.  If at least one SCHED_GROUP_P insn
+     gets queued, then all other insns get queued for one cycle later.  */
   for (pass = sched_group_found ? 0 : 1; pass < 2; )
     {
       int n = ready.n_ready;
@@ -5791,7 +6299,8 @@ prune_ready_list (state_t temp_state, bool first_cycle_insn_p,
          if (DEBUG_INSN_P (insn))
            continue;
 
-         if (sched_group_found && !SCHED_GROUP_P (insn))
+         if (sched_group_found && !SCHED_GROUP_P (insn)
+             && ((pass == 0) || (min_cost_group >= 1)))
            {
              if (pass == 0)
                continue;
@@ -5864,7 +6373,15 @@ prune_ready_list (state_t temp_state, bool first_cycle_insn_p,
              if (SCHED_GROUP_P (insn) && cost > min_cost_group)
                min_cost_group = cost;
              ready_remove (&ready, i);
-             queue_insn (insn, cost, reason);
+             /* Normally we'd want to queue INSN for COST cycles.  However,
+                if SCHED_GROUP_P is set, then we must ensure that nothing
+                else comes between INSN and its predecessor.  If there is
+                some other insn ready to fire on the next cycle, then that
+                invariant would be broken.
+
+                So when SCHED_GROUP_P is set, just queue this insn for a
+                single cycle.  */
+             queue_insn (insn, SCHED_GROUP_P (insn) ? 1 : cost, reason);
              if (i + 1 < n)
                break;
            }
@@ -5885,11 +6402,11 @@ verify_shadows (void)
     {
       int t;
       struct delay_pair *pair = save->delay_pair;
-      rtx i1 = pair->i1;
+      rtx_insn *i1 = pair->i1;
 
       for (; pair; pair = pair->next_same_i1)
        {
-         rtx i2 = pair->i2;
+         rtx_insn *i2 = pair->i2;
 
          if (QUEUE_INDEX (i2) == QUEUE_SCHEDULED)
            continue;
@@ -5931,12 +6448,12 @@ verify_shadows (void)
 /* Print instructions together with useful scheduling information between
    HEAD and TAIL (inclusive).  */
 static void
-dump_insn_stream (rtx head, rtx tail)
+dump_insn_stream (rtx_insn *head, rtx_insn *tail)
 {
   fprintf (sched_dump, ";;\t| insn | prio |\n");
 
-  rtx next_tail = NEXT_INSN (tail);
-  for (rtx insn = head; insn != next_tail; insn = NEXT_INSN (insn))
+  rtx_insn *next_tail = NEXT_INSN (tail);
+  for (rtx_insn *insn = head; insn != next_tail; insn = NEXT_INSN (insn))
     {
       int priority = NOTE_P (insn) ? 0 : INSN_PRIORITY (insn);
       const char *pattern = (NOTE_P (insn)
@@ -5948,7 +6465,7 @@ dump_insn_stream (rtx head, rtx tail)
 
       if (sched_verbose >= 4)
        {
-         if (NOTE_P (insn) || recog_memoized (insn) < 0)
+         if (NOTE_P (insn) || LABEL_P (insn) || recog_memoized (insn) < 0)
            fprintf (sched_dump, "nothing");
          else
            print_reservation (sched_dump, insn);
@@ -5972,12 +6489,12 @@ schedule_block (basic_block *target_bb, state_t init_state)
 
   /* Head/tail info for this block.  */
   rtx_insn *prev_head = current_sched_info->prev_head;
-  rtx next_tail = current_sched_info->next_tail;
+  rtx_insn *next_tail = current_sched_info->next_tail;
   rtx_insn *head = NEXT_INSN (prev_head);
   rtx_insn *tail = PREV_INSN (next_tail);
 
   if ((current_sched_info->flags & DONT_BREAK_DEPENDENCIES) == 0
-      && sched_pressure != SCHED_PRESSURE_MODEL)
+      && sched_pressure != SCHED_PRESSURE_MODEL && !sched_fusion)
     find_modifiable_mems (head, tail);
 
   /* We used to have code to avoid getting parameters moved from hard
@@ -6024,7 +6541,7 @@ schedule_block (basic_block *target_bb, state_t init_state)
 
   /* We start inserting insns after PREV_HEAD.  */
   last_scheduled_insn = prev_head;
-  last_nondebug_scheduled_insn = NULL_RTX;
+  last_nondebug_scheduled_insn = NULL;
   nonscheduled_insns_begin = NULL;
 
   gcc_assert ((NOTE_P (last_scheduled_insn)
@@ -6036,7 +6553,7 @@ schedule_block (basic_block *target_bb, state_t init_state)
   q_ptr = 0;
   q_size = 0;
 
-  insn_queue = XALLOCAVEC (rtx, max_insn_queue_index + 1);
+  insn_queue = XALLOCAVEC (rtx_insn_list *, max_insn_queue_index + 1);
   memset (insn_queue, 0, (max_insn_queue_index + 1) * sizeof (rtx));
 
   /* Start just before the beginning of time.  */
@@ -6046,27 +6563,30 @@ schedule_block (basic_block *target_bb, state_t init_state)
      in try_ready () (which is called through init_ready_list ()).  */
   (*current_sched_info->init_ready_list) ();
 
-  if (sched_pressure == SCHED_PRESSURE_MODEL)
-    model_start_schedule ();
+  if (sched_pressure)
+    sched_pressure_start_bb (*target_bb);
 
   /* The algorithm is O(n^2) in the number of ready insns at any given
      time in the worst case.  Before reload we are more likely to have
      big lists so truncate them to a reasonable size.  */
   if (!reload_completed
-      && ready.n_ready - ready.n_debug > MAX_SCHED_READY_INSNS)
+      && ready.n_ready - ready.n_debug > param_max_sched_ready_insns)
     {
-      ready_sort (&ready);
+      ready_sort_debug (&ready);
+      ready_sort_real (&ready);
 
-      /* Find first free-standing insn past MAX_SCHED_READY_INSNS.
+      /* Find first free-standing insn past param_max_sched_ready_insns.
          If there are debug insns, we know they're first.  */
-      for (i = MAX_SCHED_READY_INSNS + ready.n_debug; i < ready.n_ready; i++)
+      for (i = param_max_sched_ready_insns + ready.n_debug; i < ready.n_ready;
+          i++)
        if (!SCHED_GROUP_P (ready_element (&ready, i)))
          break;
 
       if (sched_verbose >= 2)
        {
          fprintf (sched_dump,
-                  ";;\t\tReady list on entry: %d insns\n", ready.n_ready);
+                  ";;\t\tReady list on entry: %d insns:  ", ready.n_ready);
+         debug_ready_list (&ready);
          fprintf (sched_dump,
                   ";;\t\t before reload => truncated to %d insns\n", i);
        }
@@ -6360,7 +6880,7 @@ schedule_block (basic_block *target_bb, state_t init_state)
           if (TODO_SPEC (insn) & SPECULATIVE)
             generate_recovery_code (insn);
 
-         if (targetm.sched.dispatch (NULL_RTX, IS_DISPATCH_ON))
+         if (targetm.sched.dispatch (NULL, IS_DISPATCH_ON))
            targetm.sched.dispatch_do (insn, ADD_TO_DISPATCH_WINDOW);
 
          /* Update counters, etc in the scheduler's front end.  */
@@ -6373,7 +6893,7 @@ schedule_block (basic_block *target_bb, state_t init_state)
            {
              memcpy (temp_state, curr_state, dfa_state_size);
              cost = state_transition (curr_state, insn);
-             if (sched_pressure != SCHED_PRESSURE_WEIGHTED)
+             if (sched_pressure != SCHED_PRESSURE_WEIGHTED && !sched_fusion)
                gcc_assert (cost < 0);
              if (memcmp (temp_state, curr_state, dfa_state_size) != 0)
                cycle_issued_insns++;
@@ -6417,7 +6937,7 @@ schedule_block (basic_block *target_bb, state_t init_state)
       if (!must_backtrack)
        for (i = 0; i < ready.n_ready; i++)
          {
-           rtx insn = ready_element (&ready, i);
+           rtx_insn *insn = ready_element (&ready, i);
            if (INSN_EXACT_TICK (insn) == clock_var)
              {
                must_backtrack = true;
@@ -6471,7 +6991,7 @@ schedule_block (basic_block *target_bb, state_t init_state)
   if (ls.modulo_epilogue)
     success = true;
  end_schedule:
-  if (!ls.first_cycle_insn_p)
+  if (!ls.first_cycle_insn_p || advance)
     advance_one_cycle ();
   perform_replacements_new_cycle ();
   if (modulo_ii > 0)
@@ -6482,7 +7002,7 @@ schedule_block (basic_block *target_bb, state_t init_state)
     restart_debug_insn_loop:
       for (i = ready.n_ready - 1; i >= 0; i--)
        {
-         rtx x;
+         rtx_insn *x;
 
          x = ready_element (&ready, i);
          if (DEPS_LIST_FIRST (INSN_HARD_BACK_DEPS (x)) != NULL
@@ -6501,11 +7021,11 @@ schedule_block (basic_block *target_bb, state_t init_state)
        }
       for (i = 0; i <= max_insn_queue_index; i++)
        {
-         rtx link;
+         rtx_insn_list *link;
          while ((link = insn_queue[i]) != NULL)
            {
-             rtx_insn *x = as_a <rtx_insn *> (XEXP (link, 0));
-             insn_queue[i] = XEXP (link, 1);
+             rtx_insn *x = link->insn ();
+             insn_queue[i] = link->next ();
              QUEUE_INDEX (x) = QUEUE_NOWHERE;
              free_INSN_LIST_node (link);
              resolve_dependencies (x);
@@ -6532,7 +7052,7 @@ schedule_block (basic_block *target_bb, state_t init_state)
       /* We must maintain QUEUE_INDEX between blocks in region.  */
       for (i = ready.n_ready - 1; i >= 0; i--)
        {
-         rtx x;
+         rtx_insn *x;
 
          x = ready_element (&ready, i);
          QUEUE_INDEX (x) = QUEUE_NOWHERE;
@@ -6542,12 +7062,12 @@ schedule_block (basic_block *target_bb, state_t init_state)
       if (q_size)
        for (i = 0; i <= max_insn_queue_index; i++)
          {
-           rtx link;
-           for (link = insn_queue[i]; link; link = XEXP (link, 1))
+           rtx_insn_list *link;
+           for (link = insn_queue[i]; link; link = link->next ())
              {
-               rtx x;
+               rtx_insn *x;
 
-               x = XEXP (link, 0);
+               x = link->insn ();
                QUEUE_INDEX (x) = QUEUE_NOWHERE;
                TODO_SPEC (x) = HARD_DEP;
              }
@@ -6603,7 +7123,8 @@ schedule_block (basic_block *target_bb, state_t init_state)
       if (sched_verbose >= 2)
        {
          dump_insn_stream (head, tail);
-         print_rank_for_schedule_stats (";; TOTAL ", &rank_for_schedule_stats);
+         print_rank_for_schedule_stats (";; TOTAL ", &rank_for_schedule_stats,
+                                        NULL);
        }
 
       fprintf (sched_dump, "\n");
@@ -6622,9 +7143,9 @@ schedule_block (basic_block *target_bb, state_t init_state)
 /* Set_priorities: compute priority of each insn in the block.  */
 
 int
-set_priorities (rtx head, rtx tail)
+set_priorities (rtx_insn *head, rtx_insn *tail)
 {
-  rtx insn;
+  rtx_insn *insn;
   int n_insn;
   int sched_max_insns_priority =
        current_sched_info->sched_max_insns_priority;
@@ -6655,17 +7176,14 @@ set_priorities (rtx head, rtx tail)
   return n_insn;
 }
 
-/* Set dump and sched_verbose for the desired debugging output.  If no
-   dump-file was specified, but -fsched-verbose=N (any N), print to stderr.
-   For -fsched-verbose=N, N>=10, print everything to stderr.  */
+/* Set sched_dump and sched_verbose for the desired debugging output. */
 void
 setup_sched_dump (void)
 {
   sched_verbose = sched_verbose_param;
-  if (sched_verbose_param == 0 && dump_file)
-    sched_verbose = 1;
-  sched_dump = ((sched_verbose_param >= 10 || !dump_file)
-               ? stderr : dump_file);
+  sched_dump = dump_file;
+  if (!dump_file)
+    sched_verbose = 0;
 }
 
 /* Allocate data for register pressure sensitive scheduling.  */
@@ -6694,6 +7212,27 @@ alloc_global_sched_pressure_data (void)
          saved_reg_live = BITMAP_ALLOC (NULL);
          region_ref_regs = BITMAP_ALLOC (NULL);
        }
+      if (sched_pressure == SCHED_PRESSURE_MODEL)
+       tmp_bitmap = BITMAP_ALLOC (NULL);
+
+      /* Calculate number of CALL_SAVED_REGS and FIXED_REGS in register classes
+        that we calculate register pressure for.  */
+      for (int c = 0; c < ira_pressure_classes_num; ++c)
+       {
+         enum reg_class cl = ira_pressure_classes[c];
+
+         call_saved_regs_num[cl] = 0;
+         fixed_regs_num[cl] = 0;
+
+         for (int i = 0; i < ira_class_hard_regs_num[cl]; ++i)
+           {
+             unsigned int regno = ira_class_hard_regs[cl][i];
+             if (fixed_regs[regno])
+               ++fixed_regs_num[cl];
+             else if (!crtl->abi->clobbers_full_reg_p (regno))
+               ++call_saved_regs_num[cl];
+           }
+       }
     }
 }
 
@@ -6711,6 +7250,8 @@ free_global_sched_pressure_data (void)
          BITMAP_FREE (region_ref_regs);
          BITMAP_FREE (saved_reg_live);
        }
+      if (sched_pressure == SCHED_PRESSURE_MODEL)
+       BITMAP_FREE (tmp_bitmap);
       BITMAP_FREE (curr_reg_live);
       free (sched_regno_pressure_class);
     }
@@ -6723,13 +7264,8 @@ free_global_sched_pressure_data (void)
 void
 sched_init (void)
 {
-  /* Disable speculative loads in their presence if cc0 defined.  */
-#ifdef HAVE_cc0
-  flag_schedule_speculative_load = 0;
-#endif
-
-  if (targetm.sched.dispatch (NULL_RTX, IS_DISPATCH_ON))
-    targetm.sched.dispatch_do (NULL_RTX, DISPATCH_INIT);
+  if (targetm.sched.dispatch (NULL, IS_DISPATCH_ON))
+    targetm.sched.dispatch_do (NULL, DISPATCH_INIT);
 
   if (live_range_shrinkage_p)
     sched_pressure = SCHED_PRESSURE_WEIGHTED;
@@ -6737,7 +7273,7 @@ sched_init (void)
           && !reload_completed
           && common_sched_info->sched_pass_id == SCHED_RGN_PASS)
     sched_pressure = ((enum sched_pressure_algorithm)
-                     PARAM_VALUE (PARAM_SCHED_PRESSURE_ALGORITHM));
+                     param_sched_pressure_algorithm);
   else
     sched_pressure = SCHED_PRESSURE_NONE;
 
@@ -6752,11 +7288,10 @@ sched_init (void)
 
       if (spec_info->mask != 0)
         {
-          spec_info->data_weakness_cutoff =
-            (PARAM_VALUE (PARAM_SCHED_SPEC_PROB_CUTOFF) * MAX_DEP_WEAK) / 100;
-          spec_info->control_weakness_cutoff =
-            (PARAM_VALUE (PARAM_SCHED_SPEC_PROB_CUTOFF)
-             * REG_BR_PROB_BASE) / 100;
+         spec_info->data_weakness_cutoff
+           = (param_sched_spec_prob_cutoff * MAX_DEP_WEAK) / 100;
+         spec_info->control_weakness_cutoff
+           = (param_sched_spec_prob_cutoff * REG_BR_PROB_BASE) / 100;
         }
       else
        /* So we won't read anything accidentally.  */
@@ -6773,18 +7308,17 @@ sched_init (void)
   else
     issue_rate = 1;
 
-  if (cached_issue_rate != issue_rate)
-    {
-      cached_issue_rate = issue_rate;
-      /* To invalidate max_lookahead_tries:  */
-      cached_first_cycle_multipass_dfa_lookahead = 0;
-    }
-
-  if (targetm.sched.first_cycle_multipass_dfa_lookahead)
+  if (targetm.sched.first_cycle_multipass_dfa_lookahead
+      /* Don't use max_issue with reg_pressure scheduling.  Multipass
+        scheduling and reg_pressure scheduling undo each other's decisions.  */
+      && sched_pressure == SCHED_PRESSURE_NONE)
     dfa_lookahead = targetm.sched.first_cycle_multipass_dfa_lookahead ();
   else
     dfa_lookahead = 0;
 
+  /* Set to "0" so that we recalculate.  */
+  max_lookahead_tries = 0;
+
   if (targetm.sched.init_dfa_pre_cycle_insn)
     targetm.sched.init_dfa_pre_cycle_insn ();
 
@@ -6844,20 +7378,16 @@ haifa_sched_init (void)
   /* Initialize luids, dependency caches, target and h_i_d for the
      whole function.  */
   {
-    bb_vec_t bbs;
-    bbs.create (n_basic_blocks_for_fn (cfun));
-    basic_block bb;
-
     sched_init_bbs ();
 
+    auto_vec<basic_block> bbs (n_basic_blocks_for_fn (cfun));
+    basic_block bb;
     FOR_EACH_BB_FN (bb, cfun)
       bbs.quick_push (bb);
     sched_init_luids (bbs);
     sched_deps_init (true);
     sched_extend_target ();
     haifa_init_h_i_d (bbs);
-
-    bbs.release ();
   }
 
   sched_init_only_bb = haifa_init_only_bb;
@@ -6908,6 +7438,7 @@ haifa_sched_finish (void)
   sched_deps_finish ();
   sched_finish_luids ();
   current_sched_info = NULL;
+  insn_queue = NULL;
   sched_finish ();
 }
 
@@ -6946,18 +7477,16 @@ free_delay_pairs (void)
    INSN_TICKs of their dependents.
    HEAD and TAIL are the begin and the end of the current scheduled block.  */
 static void
-fix_inter_tick (rtx head, rtx tail)
+fix_inter_tick (rtx_insn *head, rtx_insn *tail)
 {
   /* Set of instructions with corrected INSN_TICK.  */
-  bitmap_head processed;
+  auto_bitmap processed;
   /* ??? It is doubtful if we should assume that cycle advance happens on
      basic block boundaries.  Basically insns that are unconditionally ready
      on the start of the block are more preferable then those which have
      a one cycle dependency over insn from the previous block.  */
   int next_clock = clock_var + 1;
 
-  bitmap_initialize (&processed, 0);
-
   /* Iterates over scheduled instructions and fix their INSN_TICKs and
      INSN_TICKs of dependent instructions, so that INSN_TICKs are consistent
      across different blocks.  */
@@ -6973,7 +7502,7 @@ fix_inter_tick (rtx head, rtx tail)
          gcc_assert (tick >= MIN_TICK);
 
          /* Fix INSN_TICK of instruction from just scheduled block.  */
-         if (bitmap_set_bit (&processed, INSN_LUID (head)))
+         if (bitmap_set_bit (processed, INSN_LUID (head)))
            {
              tick -= next_clock;
 
@@ -6997,7 +7526,7 @@ fix_inter_tick (rtx head, rtx tail)
                  /* If NEXT has its INSN_TICK calculated, fix it.
                     If not - it will be properly calculated from
                     scratch later in fix_tick_ready.  */
-                 && bitmap_set_bit (&processed, INSN_LUID (next)))
+                 && bitmap_set_bit (processed, INSN_LUID (next)))
                {
                  tick -= next_clock;
 
@@ -7014,7 +7543,6 @@ fix_inter_tick (rtx head, rtx tail)
            }
        }
     }
-  bitmap_clear (&processed);
 }
 
 /* Check if NEXT is ready to be added to the ready or queue list.
@@ -7193,7 +7721,7 @@ fix_tick_ready (rtx_insn *next)
   INSN_TICK (next) = tick;
 
   delay = tick - clock_var;
-  if (delay <= 0 || sched_pressure != SCHED_PRESSURE_NONE)
+  if (delay <= 0 || sched_pressure != SCHED_PRESSURE_NONE || sched_fusion)
     delay = QUEUE_READY;
 
   change_queue_index (next, delay);
@@ -7342,7 +7870,7 @@ generate_recovery_code (rtx_insn *insn)
    Tries to add speculative dependencies of type FS between instructions
    in deps_list L and TWIN.  */
 static void
-process_insn_forw_deps_be_in_spec (rtx insn, rtx twin, ds_t fs)
+process_insn_forw_deps_be_in_spec (rtx_insn *insn, rtx_insn *twin, ds_t fs)
 {
   sd_iterator_def sd_it;
   dep_t dep;
@@ -7350,7 +7878,7 @@ process_insn_forw_deps_be_in_spec (rtx insn, rtx twin, ds_t fs)
   FOR_EACH_DEP (insn, SD_LIST_FORW, sd_it, dep)
     {
       ds_t ds;
-      rtx consumer;
+      rtx_insn *consumer;
 
       consumer = DEP_CON (dep);
 
@@ -7413,7 +7941,7 @@ begin_speculative_block (rtx_insn *insn)
   TODO_SPEC (insn) &= ~BEGIN_SPEC;
 }
 
-static void haifa_init_insn (rtx);
+static void haifa_init_insn (rtx_insn *);
 
 /* Generates recovery code for BE_IN speculative INSN.  */
 static void
@@ -7422,8 +7950,7 @@ add_to_speculative_block (rtx_insn *insn)
   ds_t ts;
   sd_iterator_def sd_it;
   dep_t dep;
-  rtx twins = NULL;
-  rtx_vec_t priorities_roots;
+  auto_vec<rtx_insn *, 10> twins;
 
   ts = TODO_SPEC (insn);
   gcc_assert (!(ts & ~BE_IN_SPEC));
@@ -7456,7 +7983,7 @@ add_to_speculative_block (rtx_insn *insn)
        sd_iterator_next (&sd_it);
     }
 
-  priorities_roots.create (0);
+  auto_vec<rtx_insn *> priorities_roots;
   clear_priorities (insn, &priorities_roots);
 
   while (1)
@@ -7492,7 +8019,7 @@ add_to_speculative_block (rtx_insn *insn)
         fprintf (spec_info->dump, ";;\t\tGenerated twin insn : %d/rec%d\n",
                  INSN_UID (twin), rec->index);
 
-      twins = alloc_INSN_LIST (twin, twins);
+      twins.safe_push (twin);
 
       /* Add dependences between TWIN and all appropriate
         instructions from REC.  */
@@ -7531,26 +8058,17 @@ add_to_speculative_block (rtx_insn *insn)
 
   /* We couldn't have added the dependencies between INSN and TWINS earlier
      because that would make TWINS appear in the INSN_BACK_DEPS (INSN).  */
-  while (twins)
+  unsigned int i;
+  rtx_insn *twin;
+  FOR_EACH_VEC_ELT_REVERSE (twins, i, twin)
     {
-      rtx twin;
-
-      twin = XEXP (twins, 0);
+      dep_def _new_dep, *new_dep = &_new_dep;
 
-      {
-       dep_def _new_dep, *new_dep = &_new_dep;
-
-       init_dep (new_dep, insn, twin, REG_DEP_OUTPUT);
-       sd_add_dep (new_dep, false);
-      }
-
-      twin = XEXP (twins, 1);
-      free_INSN_LIST_node (twins);
-      twins = twin;
+      init_dep (new_dep, insn, twin, REG_DEP_OUTPUT);
+      sd_add_dep (new_dep, false);
     }
 
   calc_priorities (priorities_roots);
-  priorities_roots.release ();
 }
 
 /* Extends and fills with zeros (only the new part) array pointed to by P.  */
@@ -7580,7 +8098,7 @@ find_fallthru_edge_from (basic_block pred)
 
       if (e)
        {
-         gcc_assert (e->dest == succ);
+         gcc_assert (e->dest == succ || e->dest->index == EXIT_BLOCK);
          return e;
        }
     }
@@ -7609,12 +8127,12 @@ sched_extend_bb (void)
       || (!NOTE_P (insn)
          && !LABEL_P (insn)
          /* Don't emit a NOTE if it would end up before a BARRIER.  */
-         && !BARRIER_P (NEXT_INSN (end))))
+         && !BARRIER_P (next_nondebug_insn (end))))
     {
       rtx_note *note = emit_note_after (NOTE_INSN_DELETED, end);
       /* Make note appear outside BB.  */
       set_block_for_insn (note, NULL);
-      SET_BB_END (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb) = end;
+      BB_END (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb) = end;
     }
 }
 
@@ -7644,8 +8162,6 @@ init_before_recovery (basic_block *before_recovery_ptr)
          Between these two blocks recovery blocks will be emitted.  */
 
       basic_block single, empty;
-      rtx_insn *x;
-      rtx label;
 
       /* If the fallthrough edge to exit we've found is from the block we've
         created before, don't do anything more.  */
@@ -7666,8 +8182,6 @@ init_before_recovery (basic_block *before_recovery_ptr)
 
       single->count = last->count;
       empty->count = last->count;
-      single->frequency = last->frequency;
-      empty->frequency = last->frequency;
       BB_COPY_PARTITION (single, last);
       BB_COPY_PARTITION (empty, last);
 
@@ -7676,8 +8190,9 @@ init_before_recovery (basic_block *before_recovery_ptr)
       make_single_succ_edge (empty, EXIT_BLOCK_PTR_FOR_FN (cfun),
                             EDGE_FALLTHRU);
 
-      label = block_label (empty);
-      x = emit_jump_insn_after (gen_jump (label), BB_END (single));
+      rtx_code_label *label = block_label (empty);
+      rtx_jump_insn *x = emit_jump_insn_after (targetm.gen_jump (label),
+                                              BB_END (single));
       JUMP_LABEL (x) = label;
       LABEL_NUSES (label)++;
       haifa_init_insn (x);
@@ -7708,7 +8223,6 @@ init_before_recovery (basic_block *before_recovery_ptr)
 basic_block
 sched_create_recovery_block (basic_block *before_recovery_ptr)
 {
-  rtx label;
   rtx_insn *barrier;
   basic_block rec;
 
@@ -7720,7 +8234,7 @@ sched_create_recovery_block (basic_block *before_recovery_ptr)
   barrier = get_last_bb_insn (before_recovery);
   gcc_assert (BARRIER_P (barrier));
 
-  label = emit_label_after (gen_label_rtx (), barrier);
+  rtx_insn *label = emit_label_after (gen_label_rtx (), barrier);
 
   rec = create_basic_block (label, label, before_recovery);
 
@@ -7743,8 +8257,6 @@ void
 sched_create_recovery_edges (basic_block first_bb, basic_block rec,
                             basic_block second_bb)
 {
-  rtx label;
-  rtx jump;
   int edge_flags;
 
   /* This is fixing of incoming edge.  */
@@ -7755,9 +8267,19 @@ sched_create_recovery_edges (basic_block first_bb, basic_block rec,
   else
     edge_flags = 0;
 
-  make_edge (first_bb, rec, edge_flags);
-  label = block_label (second_bb);
-  jump = emit_jump_insn_after (gen_jump (label), BB_END (rec));
+  edge e2 = single_succ_edge (first_bb);
+  edge e = make_edge (first_bb, rec, edge_flags);
+
+  /* TODO: The actual probability can be determined and is computed as
+     'todo_spec' variable in create_check_block_twin and
+     in sel-sched.c `check_ds' in create_speculation_check.  */
+  e->probability = profile_probability::very_unlikely ();
+  rec->count = e->count ();
+  e2->probability = e->probability.invert ();
+
+  rtx_code_label *label = block_label (second_bb);
+  rtx_jump_insn *jump = emit_jump_insn_after (targetm.gen_jump (label),
+                                             BB_END (rec));
   JUMP_LABEL (jump) = label;
   LABEL_NUSES (label)++;
 
@@ -7765,8 +8287,7 @@ sched_create_recovery_edges (basic_block first_bb, basic_block rec,
     /* Partition type is the same, if it is "unpartitioned".  */
     {
       /* Rewritten from cfgrtl.c.  */
-      if (flag_reorder_blocks_and_partition
-         && targetm_common.have_named_sections)
+      if (crtl->has_bb_partition && targetm_common.have_named_sections)
        {
          /* We don't need the same note for the check because
             any_condjump_p (check) == true.  */
@@ -7899,7 +8420,7 @@ create_check_block_twin (rtx_insn *insn, bool mutate_p)
     /* In case of branchy check, fix CFG.  */
     {
       basic_block first_bb, second_bb;
-      rtx jump;
+      rtx_insn *jump;
 
       first_bb = BLOCK_FOR_INSN (check);
       second_bb = sched_split_block (first_bb, check);
@@ -7950,7 +8471,7 @@ create_check_block_twin (rtx_insn *insn, bool mutate_p)
 
       if (rec != EXIT_BLOCK_PTR_FOR_FN (cfun))
        {
-         SET_DEP_CON (new_dep) = twin;
+         DEP_CON (new_dep) = twin;
          sd_add_dep (new_dep, false);
        }
     }
@@ -8049,11 +8570,10 @@ create_check_block_twin (rtx_insn *insn, bool mutate_p)
     /* Fix priorities.  If MUTATE_P is nonzero, this is not necessary,
        because it'll be done later in add_to_speculative_block.  */
     {
-      rtx_vec_t priorities_roots = rtx_vec_t ();
+      auto_vec<rtx_insn *> priorities_roots;
 
       clear_priorities (twin, &priorities_roots);
       calc_priorities (priorities_roots);
-      priorities_roots.release ();
     }
 }
 
@@ -8064,11 +8584,8 @@ static void
 fix_recovery_deps (basic_block rec)
 {
   rtx_insn *note, *insn, *jump;
-  rtx ready_list = 0;
-  bitmap_head in_ready;
-  rtx link;
-
-  bitmap_initialize (&in_ready, 0);
+  auto_vec<rtx_insn *, 10> ready_list;
+  auto_bitmap in_ready;
 
   /* NOTE - a basic block note.  */
   note = NEXT_INSN (BB_HEAD (rec));
@@ -8091,8 +8608,8 @@ fix_recovery_deps (basic_block rec)
            {
              sd_delete_dep (sd_it);
 
-             if (bitmap_set_bit (&in_ready, INSN_LUID (consumer)))
-               ready_list = alloc_INSN_LIST (consumer, ready_list);
+             if (bitmap_set_bit (in_ready, INSN_LUID (consumer)))
+               ready_list.safe_push (consumer);
            }
          else
            {
@@ -8106,12 +8623,11 @@ fix_recovery_deps (basic_block rec)
     }
   while (insn != note);
 
-  bitmap_clear (&in_ready);
-
   /* Try to add instructions to the ready or queue list.  */
-  for (link = ready_list; link; link = XEXP (link, 1))
-    try_ready (as_a <rtx_insn *> (XEXP (link, 0)));
-  free_INSN_LIST_list (&ready_list);
+  unsigned int i;
+  rtx_insn *temp;
+  FOR_EACH_VEC_ELT_REVERSE (ready_list, i, temp)
+    try_ready (temp);
 
   /* Fixing jump's dependences.  */
   insn = BB_HEAD (rec);
@@ -8127,7 +8643,7 @@ fix_recovery_deps (basic_block rec)
 /* Change pattern of INSN to NEW_PAT.  Invalidate cached haifa
    instruction data.  */
 static bool
-haifa_change_pattern (rtx insn, rtx new_pat)
+haifa_change_pattern (rtx_insn *insn, rtx new_pat)
 {
   int t;
 
@@ -8144,7 +8660,7 @@ haifa_change_pattern (rtx insn, rtx new_pat)
    current instruction pattern,
    1 - need to change pattern for *NEW_PAT to be speculative.  */
 int
-sched_speculate_insn (rtx insn, ds_t request, rtx *new_pat)
+sched_speculate_insn (rtx_insn *insn, ds_t request, rtx *new_pat)
 {
   gcc_assert (current_sched_info->flags & DO_SPECULATION
               && (request & SPECULATIVE)
@@ -8161,7 +8677,7 @@ sched_speculate_insn (rtx insn, ds_t request, rtx *new_pat)
 }
 
 static int
-haifa_speculate_insn (rtx insn, ds_t request, rtx *new_pat)
+haifa_speculate_insn (rtx_insn *insn, ds_t request, rtx *new_pat)
 {
   gcc_assert (sched_deps_info->generate_spec_deps
              && !IS_SPECULATION_CHECK_P (insn));
@@ -8177,7 +8693,7 @@ haifa_speculate_insn (rtx insn, ds_t request, rtx *new_pat)
    ends with TAIL, before scheduling it.
    I is zero, if scheduler is about to start with the fresh ebb.  */
 static void
-dump_new_block_header (int i, basic_block bb, rtx head, rtx tail)
+dump_new_block_header (int i, basic_block bb, rtx_insn *head, rtx_insn *tail)
 {
   if (!i)
     fprintf (sched_dump,
@@ -8288,7 +8804,7 @@ restore_bb_notes (basic_block first)
    Fix CFG after both in- and inter-block movement of
    control_flow_insn_p JUMP.  */
 static void
-fix_jump_move (rtx jump)
+fix_jump_move (rtx_insn *jump)
 {
   basic_block bb, jump_bb, jump_bb_next;
 
@@ -8301,25 +8817,25 @@ fix_jump_move (rtx jump)
 
   if (!NOTE_INSN_BASIC_BLOCK_P (BB_END (jump_bb_next)))
     /* if jump_bb_next is not empty.  */
-    SET_BB_END (jump_bb) = BB_END (jump_bb_next);
+    BB_END (jump_bb) = BB_END (jump_bb_next);
 
   if (BB_END (bb) != PREV_INSN (jump))
     /* Then there are instruction after jump that should be placed
        to jump_bb_next.  */
-    SET_BB_END (jump_bb_next) = BB_END (bb);
+    BB_END (jump_bb_next) = BB_END (bb);
   else
     /* Otherwise jump_bb_next is empty.  */
-    SET_BB_END (jump_bb_next) = NEXT_INSN (BB_HEAD (jump_bb_next));
+    BB_END (jump_bb_next) = NEXT_INSN (BB_HEAD (jump_bb_next));
 
   /* To make assertion in move_insn happy.  */
-  SET_BB_END (bb) = PREV_INSN (jump);
+  BB_END (bb) = PREV_INSN (jump);
 
   update_bb_for_insn (jump_bb_next);
 }
 
 /* Fix CFG after interblock movement of control_flow_insn_p JUMP.  */
 static void
-move_block_after_check (rtx jump)
+move_block_after_check (rtx_insn *jump)
 {
   basic_block bb, jump_bb, jump_bb_next;
   vec<edge, va_gc> *t;
@@ -8416,7 +8932,7 @@ clear_priorities (rtx_insn *insn, rtx_vec_t *roots_ptr)
    changed.  ROOTS is a vector of instructions whose priority computation will
    trigger initialization of all cleared priorities.  */
 static void
-calc_priorities (rtx_vec_t roots)
+calc_priorities (const rtx_vec_t &roots)
 {
   int i;
   rtx_insn *insn;
@@ -8429,7 +8945,7 @@ calc_priorities (rtx_vec_t roots)
 /* Add dependences between JUMP and other instructions in the recovery
    block.  INSN is the first insn the recovery block.  */
 static void
-add_jump_dependencies (rtx insn, rtx jump)
+add_jump_dependencies (rtx_insn *insn, rtx_insn *jump)
 {
   do
     {
@@ -8456,12 +8972,12 @@ sched_extend_luids (void)
 {
   int new_luids_max_uid = get_max_uid () + 1;
 
-  sched_luids.safe_grow_cleared (new_luids_max_uid);
+  sched_luids.safe_grow_cleared (new_luids_max_uid, true);
 }
 
 /* Initialize LUID for INSN.  */
 void
-sched_init_insn_luid (rtx insn)
+sched_init_insn_luid (rtx_insn *insn)
 {
   int i = INSN_P (insn) ? 1 : common_sched_info->luid_for_non_insn (insn);
   int luid;
@@ -8481,7 +8997,7 @@ sched_init_insn_luid (rtx insn)
    The hook common_sched_info->luid_for_non_insn () is used to determine
    if notes, labels, etc. need luids.  */
 void
-sched_init_luids (bb_vec_t bbs)
+sched_init_luids (const bb_vec_t &bbs)
 {
   int i;
   basic_block bb;
@@ -8489,7 +9005,7 @@ sched_init_luids (bb_vec_t bbs)
   sched_extend_luids ();
   FOR_EACH_VEC_ELT (bbs, i, bb)
     {
-      rtx insn;
+      rtx_insn *insn;
 
       FOR_BB_INSNS (bb, insn)
        sched_init_insn_luid (insn);
@@ -8506,7 +9022,7 @@ sched_finish_luids (void)
 
 /* Return logical uid of INSN.  Helpful while debugging.  */
 int
-insn_luid (rtx insn)
+insn_luid (rtx_insn *insn)
 {
   return INSN_LUID (insn);
 }
@@ -8528,7 +9044,7 @@ extend_h_i_d (void)
   if (reserve > 0
       && ! h_i_d.space (reserve))
     {
-      h_i_d.safe_grow_cleared (3 * get_max_uid () / 2);
+      h_i_d.safe_grow_cleared (3 * get_max_uid () / 2, true);
       sched_extend_target ();
     }
 }
@@ -8536,7 +9052,7 @@ extend_h_i_d (void)
 /* Initialize h_i_d entry of the INSN with default values.
    Values, that are not explicitly initialized here, hold zero.  */
 static void
-init_h_i_d (rtx insn)
+init_h_i_d (rtx_insn *insn)
 {
   if (INSN_LUID (insn) > 0)
     {
@@ -8546,12 +9062,16 @@ init_h_i_d (rtx insn)
       INSN_EXACT_TICK (insn) = INVALID_TICK;
       INTER_TICK (insn) = INVALID_TICK;
       TODO_SPEC (insn) = HARD_DEP;
+      INSN_AUTOPREF_MULTIPASS_DATA (insn)[0].status
+       = AUTOPREF_MULTIPASS_DATA_UNINITIALIZED;
+      INSN_AUTOPREF_MULTIPASS_DATA (insn)[1].status
+       = AUTOPREF_MULTIPASS_DATA_UNINITIALIZED;
     }
 }
 
 /* Initialize haifa_insn_data for BBS.  */
 void
-haifa_init_h_i_d (bb_vec_t bbs)
+haifa_init_h_i_d (const bb_vec_t &bbs)
 {
   int i;
   basic_block bb;
@@ -8559,7 +9079,7 @@ haifa_init_h_i_d (bb_vec_t bbs)
   extend_h_i_d ();
   FOR_EACH_VEC_ELT (bbs, i, bb)
     {
-      rtx insn;
+      rtx_insn *insn;
 
       FOR_BB_INSNS (bb, insn)
        init_h_i_d (insn);
@@ -8572,24 +9092,31 @@ haifa_finish_h_i_d (void)
 {
   int i;
   haifa_insn_data_t data;
-  struct reg_use_data *use, *next;
+  reg_use_data *use, *next_use;
+  reg_set_data *set, *next_set;
 
   FOR_EACH_VEC_ELT (h_i_d, i, data)
     {
       free (data->max_reg_pressure);
       free (data->reg_pressure);
-      for (use = data->reg_use_list; use != NULL; use = next)
+      for (use = data->reg_use_list; use != NULL; use = next_use)
        {
-         next = use->next_insn_use;
+         next_use = use->next_insn_use;
          free (use);
        }
+      for (set = data->reg_set_list; set != NULL; set = next_set)
+       {
+         next_set = set->next_insn_set;
+         free (set);
+       }
+
     }
   h_i_d.release ();
 }
 
 /* Init data for the new insn INSN.  */
 static void
-haifa_init_insn (rtx insn)
+haifa_init_insn (rtx_insn *insn)
 {
   gcc_assert (insn != NULL);
 
@@ -8697,7 +9224,7 @@ ready_remove_first_dispatch (struct ready_list *ready)
        }
     }
 
-  if (targetm.sched.dispatch (NULL_RTX, DISPATCH_VIOLATION))
+  if (targetm.sched.dispatch (NULL, DISPATCH_VIOLATION))
     return ready_remove_first (ready);
 
   for (i = 1; i < ready->n_ready; i++)
@@ -8727,7 +9254,7 @@ number_in_ready (void)
 
 /* Get number of ready's in the ready list.  */
 
-rtx
+rtx_insn *
 get_ready_element (int i)
 {
   return ready_element (&ready, i);