re PR debug/66691 (ICE on valid code at -O3 with -g enabled in simplify_subreg, at...
[gcc.git] / gcc / sched-rgn.c
index 1663e2fd95dae337d6861e2e13562a39760cd022..ccdde706ea7866434c35d36deb0f4915e358d28f 100644 (file)
@@ -1,5 +1,5 @@
 /* Instruction scheduling pass.
-   Copyright (C) 1992-2013 Free Software Foundation, Inc.
+   Copyright (C) 1992-2015 Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
    and currently maintained by, Jim Wilson (wilson@cygnus.com)
 
@@ -53,17 +53,24 @@ along with GCC; see the file COPYING3.  If not see
 #include "hard-reg-set.h"
 #include "regs.h"
 #include "function.h"
+#include "profile.h"
 #include "flags.h"
 #include "insn-config.h"
 #include "insn-attr.h"
 #include "except.h"
 #include "recog.h"
 #include "params.h"
+#include "dominance.h"
+#include "cfg.h"
+#include "cfganal.h"
+#include "predict.h"
+#include "basic-block.h"
 #include "sched-int.h"
 #include "sel-sched.h"
 #include "target.h"
 #include "tree-pass.h"
 #include "dbgcnt.h"
+#include "emit-rtl.h"
 
 #ifdef INSN_SCHEDULING
 
@@ -79,6 +86,9 @@ static int is_cfg_nonregular (void);
 /* Number of regions in the procedure.  */
 int nr_regions = 0;
 
+/* Same as above before adding any new regions.  */
+static int nr_regions_initial = 0;
+
 /* Table of region descriptions.  */
 region *rgn_table = NULL;
 
@@ -226,18 +236,19 @@ static edgeset *ancestor_edges;
 static int check_live_1 (int, rtx);
 static void update_live_1 (int, rtx);
 static int is_pfree (rtx, int, int);
-static int find_conditional_protection (rtx, int);
+static int find_conditional_protection (rtx_insn *, int);
 static int is_conditionally_protected (rtx, int, int);
 static int is_prisky (rtx, int, int);
-static int is_exception_free (rtx, int, int);
+static int is_exception_free (rtx_insn *, int, int);
 
 static bool sets_likely_spilled (rtx);
 static void sets_likely_spilled_1 (rtx, const_rtx, void *);
-static void add_branch_dependences (rtx, rtx);
+static void add_branch_dependences (rtx_insn *, rtx_insn *);
 static void compute_block_dependences (int);
 
 static void schedule_region (int);
-static void concat_insn_mem_list (rtx, rtx, rtx *, rtx *);
+static void concat_insn_mem_list (rtx_insn_list *, rtx_expr_list *,
+                                 rtx_insn_list **, rtx_expr_list **);
 static void propagate_deps (int, struct deps_desc *);
 static void free_pending_lists (void);
 
@@ -253,7 +264,7 @@ static int
 is_cfg_nonregular (void)
 {
   basic_block b;
-  rtx insn;
+  rtx_insn *insn;
 
   /* If we have a label that could be the target of a nonlocal goto, then
      the cfg is not well structured.  */
@@ -272,10 +283,11 @@ is_cfg_nonregular (void)
 
   /* If we have insns which refer to labels as non-jumped-to operands,
      then we consider the cfg not well structured.  */
-  FOR_EACH_BB (b)
+  FOR_EACH_BB_FN (b, cfun)
     FOR_BB_INSNS (b, insn)
       {
-       rtx note, next, set, dest;
+       rtx note, set, dest;
+       rtx_insn *next;
 
        /* If this function has a computed jump, then we consider the cfg
           not well structured.  */
@@ -317,7 +329,7 @@ is_cfg_nonregular (void)
      Unreachable loops with a single block are detected here.  This
      test is redundant with the one in find_rgns, but it's much
      cheaper to go ahead and catch the trivial case here.  */
-  FOR_EACH_BB (b)
+  FOR_EACH_BB_FN (b, cfun)
     {
       if (EDGE_COUNT (b->preds) == 0
          || (single_pred_p (b)
@@ -401,7 +413,8 @@ debug_region (int rgn)
 
   for (bb = 0; bb < rgn_table[rgn].rgn_nr_blocks; bb++)
     {
-      dump_bb (stderr, BASIC_BLOCK (rgn_bb_table[current_blocks + bb]),
+      dump_bb (stderr,
+              BASIC_BLOCK_FOR_FN (cfun, rgn_bb_table[current_blocks + bb]),
               0, TDF_SLIM | TDF_BLOCKS);
       fprintf (stderr, "\n");
     }
@@ -440,7 +453,7 @@ dump_region_dot (FILE *f, int rgn)
       edge e;
       edge_iterator ei;
       int src_bb_num = rgn_bb_table[current_blocks + i];
-      basic_block bb = BASIC_BLOCK (src_bb_num);
+      basic_block bb = BASIC_BLOCK_FOR_FN (cfun, src_bb_num);
 
       FOR_EACH_EDGE (e, ei, bb->succs)
         if (bb_in_region_p (e->dest->index, rgn))
@@ -478,7 +491,7 @@ find_single_block_region (bool ebbs_p)
       probability_cutoff = PARAM_VALUE (TRACER_MIN_BRANCH_PROBABILITY);
     probability_cutoff = REG_BR_PROB_BASE / 100 * probability_cutoff;
 
-    FOR_EACH_BB (ebb_start)
+    FOR_EACH_BB_FN (ebb_start, cfun)
       {
         RGN_NR_BLOCKS (nr_regions) = 0;
         RGN_BLOCKS (nr_regions) = i;
@@ -511,7 +524,7 @@ find_single_block_region (bool ebbs_p)
       }
   }
   else
-    FOR_EACH_BB (bb)
+    FOR_EACH_BB_FN (bb, cfun)
       {
         rgn_bb_table[nr_regions] = bb->index;
         RGN_NR_BLOCKS (nr_regions) = 1;
@@ -535,7 +548,7 @@ rgn_estimate_number_of_insns (basic_block bb)
 
   if (MAY_HAVE_DEBUG_INSNS)
     {
-      rtx insn;
+      rtx_insn *insn;
 
       FOR_BB_INSNS (bb, insn)
        if (DEBUG_INSN_P (insn))
@@ -554,7 +567,7 @@ too_large (int block, int *num_bbs, int *num_insns)
 {
   (*num_bbs)++;
   (*num_insns) += (common_sched_info->estimate_number_of_insns
-                   (BASIC_BLOCK (block)));
+                   (BASIC_BLOCK_FOR_FN (cfun, block)));
 
   return ((*num_bbs > PARAM_VALUE (PARAM_MAX_SCHED_REGION_BLOCKS))
          || (*num_insns > PARAM_VALUE (PARAM_MAX_SCHED_REGION_INSNS)));
@@ -641,23 +654,23 @@ haifa_find_rgns (void)
      STACK, SP and DFS_NR are only used during the first traversal.  */
 
   /* Allocate and initialize variables for the first traversal.  */
-  max_hdr = XNEWVEC (int, last_basic_block);
-  dfs_nr = XCNEWVEC (int, last_basic_block);
+  max_hdr = XNEWVEC (int, last_basic_block_for_fn (cfun));
+  dfs_nr = XCNEWVEC (int, last_basic_block_for_fn (cfun));
   stack = XNEWVEC (edge_iterator, n_edges_for_fn (cfun));
 
-  inner = sbitmap_alloc (last_basic_block);
+  inner = sbitmap_alloc (last_basic_block_for_fn (cfun));
   bitmap_ones (inner);
 
-  header = sbitmap_alloc (last_basic_block);
+  header = sbitmap_alloc (last_basic_block_for_fn (cfun));
   bitmap_clear (header);
 
-  in_queue = sbitmap_alloc (last_basic_block);
+  in_queue = sbitmap_alloc (last_basic_block_for_fn (cfun));
   bitmap_clear (in_queue);
 
-  in_stack = sbitmap_alloc (last_basic_block);
+  in_stack = sbitmap_alloc (last_basic_block_for_fn (cfun));
   bitmap_clear (in_stack);
 
-  for (i = 0; i < last_basic_block; i++)
+  for (i = 0; i < last_basic_block_for_fn (cfun); i++)
     max_hdr[i] = -1;
 
   #define EDGE_PASSED(E) (ei_end_p ((E)) || ei_edge ((E))->aux)
@@ -744,7 +757,7 @@ haifa_find_rgns (void)
     }
 
   /* Reset ->aux field used by EDGE_PASSED.  */
-  FOR_ALL_BB (bb)
+  FOR_ALL_BB_FN (bb, cfun)
     {
       edge_iterator ei;
       edge e;
@@ -761,7 +774,7 @@ haifa_find_rgns (void)
      the entry node by placing a nonzero value in dfs_nr.  Thus if
      dfs_nr is zero for any block, then it must be unreachable.  */
   unreachable = 0;
-  FOR_EACH_BB (bb)
+  FOR_EACH_BB_FN (bb, cfun)
     if (dfs_nr[bb->index] == 0)
       {
        unreachable = 1;
@@ -772,7 +785,7 @@ haifa_find_rgns (void)
      to hold degree counts.  */
   degree = dfs_nr;
 
-  FOR_EACH_BB (bb)
+  FOR_EACH_BB_FN (bb, cfun)
     degree[bb->index] = EDGE_COUNT (bb->preds);
 
   /* Do not perform region scheduling if there are any unreachable
@@ -798,14 +811,15 @@ haifa_find_rgns (void)
       extend_regions_p = PARAM_VALUE (PARAM_MAX_SCHED_EXTEND_REGIONS_ITERS) > 0;
       if (extend_regions_p)
         {
-          degree1 = XNEWVEC (int, last_basic_block);
-          extended_rgn_header = sbitmap_alloc (last_basic_block);
+          degree1 = XNEWVEC (int, last_basic_block_for_fn (cfun));
+          extended_rgn_header =
+           sbitmap_alloc (last_basic_block_for_fn (cfun));
           bitmap_clear (extended_rgn_header);
        }
 
       /* Find blocks which are inner loop headers.  We still have non-reducible
         loops to consider at this point.  */
-      FOR_EACH_BB (bb)
+      FOR_EACH_BB_FN (bb, cfun)
        {
          if (bitmap_bit_p (header, bb->index) && bitmap_bit_p (inner, bb->index))
            {
@@ -824,7 +838,7 @@ haifa_find_rgns (void)
                 If there exists a block that is not dominated by the loop
                 header, then the block is reachable from outside the loop
                 and thus the loop is not a natural loop.  */
-             FOR_EACH_BB (jbb)
+             FOR_EACH_BB_FN (jbb, cfun)
                {
                  /* First identify blocks in the loop, except for the loop
                     entry block.  */
@@ -853,7 +867,8 @@ haifa_find_rgns (void)
                 /* We save degree in case when we meet a too_large region
                   and cancel it.  We need a correct degree later when
                    calling extend_rgns.  */
-                memcpy (degree1, degree, last_basic_block * sizeof (int));
+                memcpy (degree1, degree,
+                       last_basic_block_for_fn (cfun) * sizeof (int));
 
              /* Decrease degree of all I's successors for topological
                 ordering.  */
@@ -871,7 +886,7 @@ haifa_find_rgns (void)
                 Place those blocks into the queue.  */
              if (no_loops)
                {
-                 FOR_EACH_BB (jbb)
+                 FOR_EACH_BB_FN (jbb, cfun)
                    /* Leaf nodes have only a single successor which must
                       be EXIT_BLOCK.  */
                    if (single_succ_p (jbb)
@@ -948,7 +963,8 @@ haifa_find_rgns (void)
                  edge e;
                  child = queue[++head];
 
-                 FOR_EACH_EDGE (e, ei, BASIC_BLOCK (child)->preds)
+                 FOR_EACH_EDGE (e, ei,
+                                BASIC_BLOCK_FOR_FN (cfun, child)->preds)
                    {
                      node = e->src->index;
 
@@ -1005,7 +1021,9 @@ haifa_find_rgns (void)
                          CONTAINING_RGN (child) = nr_regions;
                          queue[head] = queue[tail--];
 
-                         FOR_EACH_EDGE (e, ei, BASIC_BLOCK (child)->succs)
+                         FOR_EACH_EDGE (e, ei,
+                                        BASIC_BLOCK_FOR_FN (cfun,
+                                                            child)->succs)
                            if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
                              --degree[e->dest->index];
                        }
@@ -1046,7 +1064,7 @@ haifa_find_rgns (void)
 
   /* Any block that did not end up in a region is placed into a region
      by itself.  */
-  FOR_EACH_BB (bb)
+  FOR_EACH_BB_FN (bb, cfun)
     if (degree[bb->index] >= 0)
       {
        rgn_bb_table[idx] = bb->index;
@@ -1157,9 +1175,9 @@ extend_rgns (int *degree, int *idxp, sbitmap header, int *loop_hdr)
 
   max_iter = PARAM_VALUE (PARAM_MAX_SCHED_EXTEND_REGIONS_ITERS);
 
-  max_hdr = XNEWVEC (int, last_basic_block);
+  max_hdr = XNEWVEC (int, last_basic_block_for_fn (cfun));
 
-  order = XNEWVEC (int, last_basic_block);
+  order = XNEWVEC (int, last_basic_block_for_fn (cfun));
   post_order_compute (order, false, false);
 
   for (i = nblocks - 1; i >= 0; i--)
@@ -1200,7 +1218,7 @@ extend_rgns (int *degree, int *idxp, sbitmap header, int *loop_hdr)
            {
              int hdr = -1;
 
-             FOR_EACH_EDGE (e, ei, BASIC_BLOCK (bbn)->preds)
+             FOR_EACH_EDGE (e, ei, BASIC_BLOCK_FOR_FN (cfun, bbn)->preds)
                {
                  int predn = e->src->index;
 
@@ -1304,7 +1322,7 @@ extend_rgns (int *degree, int *idxp, sbitmap header, int *loop_hdr)
              CONTAINING_RGN (bbn) = nr_regions;
              BLOCK_TO_BB (bbn) = 0;
 
-             FOR_EACH_EDGE (e, ei, BASIC_BLOCK (bbn)->succs)
+             FOR_EACH_EDGE (e, ei, BASIC_BLOCK_FOR_FN (cfun, bbn)->succs)
                if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
                  degree[e->dest->index]--;
 
@@ -1361,7 +1379,8 @@ extend_rgns (int *degree, int *idxp, sbitmap header, int *loop_hdr)
 
                      idx++;
 
-                     FOR_EACH_EDGE (e, ei, BASIC_BLOCK (succn)->succs)
+                     FOR_EACH_EDGE (e, ei,
+                                    BASIC_BLOCK_FOR_FN (cfun, succn)->succs)
                        if (e->dest != EXIT_BLOCK_PTR_FOR_FN (cfun))
                          degree[e->dest->index]--;
                    }
@@ -1420,7 +1439,8 @@ compute_dom_prob_ps (int bb)
   /* Initialize dom[bb] to '111..1'.  */
   bitmap_ones (dom[bb]);
 
-  FOR_EACH_EDGE (in_edge, in_ei, BASIC_BLOCK (BB_TO_BLOCK (bb))->preds)
+  FOR_EACH_EDGE (in_edge, in_ei,
+                BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (bb))->preds)
     {
       int pred_bb;
       edge out_edge;
@@ -1508,7 +1528,7 @@ compute_trg_info (int trg)
   sp->is_speculative = 0;
   sp->src_prob = REG_BR_PROB_BASE;
 
-  visited = sbitmap_alloc (last_basic_block);
+  visited = sbitmap_alloc (last_basic_block_for_fn (cfun));
 
   for (i = trg + 1; i < current_nr_blocks; i++)
     {
@@ -1696,7 +1716,7 @@ check_live_1 (int src, rtx x)
       if (regno < FIRST_PSEUDO_REGISTER)
        {
          /* Check for hard registers.  */
-         int j = hard_regno_nregs[regno][GET_MODE (reg)];
+         int j = REG_NREGS (reg);
          while (--j >= 0)
            {
              for (i = 0; i < candidate_table[src].split_bbs.nr_members; i++)
@@ -1777,12 +1797,7 @@ update_live_1 (int src, rtx x)
       for (i = 0; i < candidate_table[src].update_bbs.nr_members; i++)
        {
          basic_block b = candidate_table[src].update_bbs.first_member[i];
-
-         if (HARD_REGISTER_NUM_P (regno))
-           bitmap_set_range (df_get_live_in (b), regno,
-                             hard_regno_nregs[regno][GET_MODE (reg)]);
-         else
-           bitmap_set_bit (df_get_live_in (b), regno);
+         bitmap_set_range (df_get_live_in (b), regno, REG_NREGS (reg));
        }
     }
 }
@@ -1792,7 +1807,7 @@ update_live_1 (int src, rtx x)
    ready-list or before the scheduling.  */
 
 static int
-check_live (rtx insn, int src)
+check_live (rtx_insn *insn, int src)
 {
   /* Find the registers set by instruction.  */
   if (GET_CODE (PATTERN (insn)) == SET
@@ -1817,7 +1832,7 @@ check_live (rtx insn, int src)
    block src to trg.  */
 
 static void
-update_live (rtx insn, int src)
+update_live (rtx_insn *insn, int src)
 {
   /* Find the registers set by instruction.  */
   if (GET_CODE (PATTERN (insn)) == SET
@@ -1838,7 +1853,8 @@ update_live (rtx insn, int src)
   (bb_from == bb_to                                                    \
    || IS_RGN_ENTRY (bb_from)                                           \
    || (bitmap_bit_p (ancestor_edges[bb_to],                                    \
-        EDGE_TO_BIT (single_pred_edge (BASIC_BLOCK (BB_TO_BLOCK (bb_from)))))))
+        EDGE_TO_BIT (single_pred_edge (BASIC_BLOCK_FOR_FN (cfun, \
+                                                           BB_TO_BLOCK (bb_from)))))))
 
 /* Turns on the fed_by_spec_load flag for insns fed by load_insn.  */
 
@@ -1857,7 +1873,7 @@ set_spec_fed (rtx load_insn)
 branch depending on insn, that guards the speculative load.  */
 
 static int
-find_conditional_protection (rtx insn, int load_insn_bb)
+find_conditional_protection (rtx_insn *insn, int load_insn_bb)
 {
   sd_iterator_def sd_it;
   dep_t dep;
@@ -1865,7 +1881,7 @@ find_conditional_protection (rtx insn, int load_insn_bb)
   /* Iterate through DEF-USE forward dependences.  */
   FOR_EACH_DEP (insn, SD_LIST_FORW, sd_it, dep)
     {
-      rtx next = DEP_CON (dep);
+      rtx_insn *next = DEP_CON (dep);
 
       if ((CONTAINING_RGN (BLOCK_NUM (next)) ==
           CONTAINING_RGN (BB_TO_BLOCK (load_insn_bb)))
@@ -1901,7 +1917,7 @@ is_conditionally_protected (rtx load_insn, int bb_src, int bb_trg)
 
   FOR_EACH_DEP (load_insn, SD_LIST_BACK, sd_it, dep)
     {
-      rtx insn1 = DEP_PRO (dep);
+      rtx_insn *insn1 = DEP_PRO (dep);
 
       /* Must be a DEF-USE dependence upon non-branch.  */
       if (DEP_TYPE (dep) != REG_DEP_TRUE
@@ -1957,7 +1973,7 @@ is_pfree (rtx load_insn, int bb_src, int bb_trg)
 
   FOR_EACH_DEP (load_insn, SD_LIST_BACK, back_sd_it, back_dep)
     {
-      rtx insn1 = DEP_PRO (back_dep);
+      rtx_insn *insn1 = DEP_PRO (back_dep);
 
       if (DEP_TYPE (back_dep) == REG_DEP_TRUE)
        /* Found a DEF-USE dependence (insn1, load_insn).  */
@@ -1967,7 +1983,7 @@ is_pfree (rtx load_insn, int bb_src, int bb_trg)
 
          FOR_EACH_DEP (insn1, SD_LIST_FORW, fore_sd_it, fore_dep)
            {
-             rtx insn2 = DEP_CON (fore_dep);
+             rtx_insn *insn2 = DEP_CON (fore_dep);
 
              if (DEP_TYPE (fore_dep) == REG_DEP_TRUE)
                {
@@ -2017,7 +2033,7 @@ is_prisky (rtx load_insn, int bb_src, int bb_trg)
    and 0 otherwise.  */
 
 static int
-is_exception_free (rtx insn, int bb_src, int bb_trg)
+is_exception_free (rtx_insn *insn, int bb_src, int bb_trg)
 {
   int insn_class = haifa_classify_insn (insn);
 
@@ -2065,19 +2081,19 @@ static int sched_n_insns;
 
 /* Implementations of the sched_info functions for region scheduling.  */
 static void init_ready_list (void);
-static int can_schedule_ready_p (rtx);
-static void begin_schedule_ready (rtx);
-static ds_t new_ready (rtx, ds_t);
+static int can_schedule_ready_p (rtx_insn *);
+static void begin_schedule_ready (rtx_insn *);
+static ds_t new_ready (rtx_insn *, ds_t);
 static int schedule_more_p (void);
-static const char *rgn_print_insn (const_rtx, int);
-static int rgn_rank (rtx, rtx);
+static const char *rgn_print_insn (const rtx_insn *, int);
+static int rgn_rank (rtx_insn *, rtx_insn *);
 static void compute_jump_reg_dependencies (rtx, regset);
 
 /* Functions for speculative scheduling.  */
-static void rgn_add_remove_insn (rtx, int);
+static void rgn_add_remove_insn (rtx_insn *, int);
 static void rgn_add_block (basic_block, basic_block);
 static void rgn_fix_recovery_cfg (int, int, int);
-static basic_block advance_target_bb (basic_block, rtx);
+static basic_block advance_target_bb (basic_block, rtx_insn *);
 
 /* Return nonzero if there are more insns that should be scheduled.  */
 
@@ -2093,10 +2109,10 @@ schedule_more_p (void)
 static void
 init_ready_list (void)
 {
-  rtx prev_head = current_sched_info->prev_head;
-  rtx next_tail = current_sched_info->next_tail;
+  rtx_insn *prev_head = current_sched_info->prev_head;
+  rtx_insn *next_tail = current_sched_info->next_tail;
   int bb_src;
-  rtx insn;
+  rtx_insn *insn;
 
   target_n_insns = 0;
   sched_target_n_insns = 0;
@@ -2128,9 +2144,9 @@ init_ready_list (void)
   for (bb_src = target_bb + 1; bb_src < current_nr_blocks; bb_src++)
     if (IS_VALID (bb_src))
       {
-       rtx src_head;
-       rtx src_next_tail;
-       rtx tail, head;
+       rtx_insn *src_head;
+       rtx_insn *src_next_tail;
+       rtx_insn *tail, *head;
 
        get_ebb_head_tail (EBB_FIRST_BB (bb_src), EBB_LAST_BB (bb_src),
                           &head, &tail);
@@ -2151,7 +2167,7 @@ init_ready_list (void)
    insn can be scheduled, nonzero if we should silently discard it.  */
 
 static int
-can_schedule_ready_p (rtx insn)
+can_schedule_ready_p (rtx_insn *insn)
 {
   /* An interblock motion?  */
   if (INSN_BB (insn) != target_bb
@@ -2167,7 +2183,7 @@ can_schedule_ready_p (rtx insn)
    can_schedule_ready_p () differs from the one passed to
    begin_schedule_ready ().  */
 static void
-begin_schedule_ready (rtx insn)
+begin_schedule_ready (rtx_insn *insn)
 {
   /* An interblock motion?  */
   if (INSN_BB (insn) != target_bb)
@@ -2199,7 +2215,7 @@ begin_schedule_ready (rtx insn)
    Return nonzero if it should be moved to the ready list or the queue, or zero
    if we should silently discard it.  */
 static ds_t
-new_ready (rtx next, ds_t ts)
+new_ready (rtx_insn *next, ds_t ts)
 {
   if (INSN_BB (next) != target_bb)
     {
@@ -2252,7 +2268,7 @@ new_ready (rtx next, ds_t ts)
    to be formatted so that multiple output lines will line up nicely.  */
 
 static const char *
-rgn_print_insn (const_rtx insn, int aligned)
+rgn_print_insn (const rtx_insn *insn, int aligned)
 {
   static char tmp[80];
 
@@ -2273,7 +2289,7 @@ rgn_print_insn (const_rtx insn, int aligned)
    is to be preferred.  Zero if they are equally good.  */
 
 static int
-rgn_rank (rtx insn1, rtx insn2)
+rgn_rank (rtx_insn *insn1, rtx_insn *insn2)
 {
   /* Some comparison make sense in interblock scheduling only.  */
   if (INSN_BB (insn1) != INSN_BB (insn2))
@@ -2304,7 +2320,7 @@ rgn_rank (rtx insn1, rtx insn2)
    calculations.  */
 
 int
-contributes_to_priority (rtx next, rtx insn)
+contributes_to_priority (rtx_insn *next, rtx_insn *insn)
 {
   /* NEXT and INSN reside in one ebb.  */
   return BLOCK_TO_BB (BLOCK_NUM (next)) == BLOCK_TO_BB (BLOCK_NUM (insn));
@@ -2350,7 +2366,7 @@ static const struct sched_deps_info_def rgn_const_sel_sched_deps_info =
 /* Return true if scheduling INSN will trigger finish of scheduling
    current block.  */
 static bool
-rgn_insn_finishes_block_p (rtx insn)
+rgn_insn_finishes_block_p (rtx_insn *insn)
 {
   if (INSN_BB (insn) == target_bb
       && sched_target_n_insns + 1 == target_n_insns)
@@ -2427,9 +2443,9 @@ static sbitmap insn_referenced;
 /* Add dependences so that branches are scheduled to run last in their
    block.  */
 static void
-add_branch_dependences (rtx head, rtx tail)
+add_branch_dependences (rtx_insn *head, rtx_insn *tail)
 {
-  rtx insn, last;
+  rtx_insn *insn, *last;
 
   /* For all branches, calls, uses, clobbers, cc0 setters, and instructions
      that can throw exceptions, force them to remain in order at the end of
@@ -2462,9 +2478,7 @@ add_branch_dependences (rtx head, rtx tail)
             && (GET_CODE (PATTERN (insn)) == USE
                 || GET_CODE (PATTERN (insn)) == CLOBBER
                 || can_throw_internal (insn)
-#ifdef HAVE_cc0
-                || sets_cc0_p (PATTERN (insn))
-#endif
+                || (HAVE_cc0 && sets_cc0_p (PATTERN (insn)))
                 || (!reload_completed
                     && sets_likely_spilled (PATTERN (insn)))))
         || NOTE_P (insn)
@@ -2571,18 +2585,20 @@ add_branch_dependences (rtx head, rtx tail)
 static struct deps_desc *bb_deps;
 
 static void
-concat_insn_mem_list (rtx copy_insns, rtx copy_mems, rtx *old_insns_p,
-                     rtx *old_mems_p)
+concat_insn_mem_list (rtx_insn_list *copy_insns,
+                     rtx_expr_list *copy_mems,
+                     rtx_insn_list **old_insns_p,
+                     rtx_expr_list **old_mems_p)
 {
-  rtx new_insns = *old_insns_p;
-  rtx new_mems = *old_mems_p;
+  rtx_insn_list *new_insns = *old_insns_p;
+  rtx_expr_list *new_mems = *old_mems_p;
 
   while (copy_insns)
     {
-      new_insns = alloc_INSN_LIST (XEXP (copy_insns, 0), new_insns);
-      new_mems = alloc_EXPR_LIST (VOIDmode, XEXP (copy_mems, 0), new_mems);
-      copy_insns = XEXP (copy_insns, 1);
-      copy_mems = XEXP (copy_mems, 1);
+      new_insns = alloc_INSN_LIST (copy_insns->insn (), new_insns);
+      new_mems = alloc_EXPR_LIST (VOIDmode, copy_mems->element (), new_mems);
+      copy_insns = copy_insns->next ();
+      copy_mems = copy_mems->next ();
     }
 
   *old_insns_p = new_insns;
@@ -2655,7 +2671,7 @@ deps_join (struct deps_desc *succ_deps, struct deps_desc *pred_deps)
 static void
 propagate_deps (int bb, struct deps_desc *pred_deps)
 {
-  basic_block block = BASIC_BLOCK (BB_TO_BLOCK (bb));
+  basic_block block = BASIC_BLOCK_FOR_FN (cfun, BB_TO_BLOCK (bb));
   edge_iterator ei;
   edge e;
 
@@ -2709,7 +2725,7 @@ propagate_deps (int bb, struct deps_desc *pred_deps)
 static void
 compute_block_dependences (int bb)
 {
-  rtx head, tail;
+  rtx_insn *head, *tail;
   struct deps_desc tmp_deps;
 
   tmp_deps = bb_deps[bb];
@@ -2738,8 +2754,8 @@ compute_block_dependences (int bb)
 static void
 free_block_dependencies (int bb)
 {
-  rtx head;
-  rtx tail;
+  rtx_insn *head;
+  rtx_insn *tail;
 
   get_ebb_head_tail (EBB_FIRST_BB (bb), EBB_LAST_BB (bb), &head, &tail);
 
@@ -2781,7 +2797,7 @@ debug_rgn_dependencies (int from_bb)
 
   for (bb = from_bb; bb < current_nr_blocks; bb++)
     {
-      rtx head, tail;
+      rtx_insn *head, *tail;
 
       get_ebb_head_tail (EBB_FIRST_BB (bb), EBB_LAST_BB (bb), &head, &tail);
       fprintf (sched_dump, "\n;;   --- Region Dependences --- b %d bb %d \n",
@@ -2793,10 +2809,10 @@ debug_rgn_dependencies (int from_bb)
 
 /* Print dependencies information for instructions between HEAD and TAIL.
    ??? This function would probably fit best in haifa-sched.c.  */
-void debug_dependencies (rtx head, rtx tail)
+void debug_dependencies (rtx_insn *head, rtx_insn *tail)
 {
-  rtx insn;
-  rtx next_tail = NEXT_INSN (tail);
+  rtx_insn *insn;
+  rtx_insn *next_tail = NEXT_INSN (tail);
 
   fprintf (sched_dump, ";;   %7s%6s%6s%6s%6s%6s%14s\n",
           "insn", "code", "bb", "dep", "prio", "cost",
@@ -2864,7 +2880,8 @@ sched_is_disabled_for_current_region_p (void)
   int bb;
 
   for (bb = 0; bb < current_nr_blocks; bb++)
-    if (!(BASIC_BLOCK (BB_TO_BLOCK (bb))->flags & BB_DISABLE_SCHEDULE))
+    if (!(BASIC_BLOCK_FOR_FN (cfun,
+                             BB_TO_BLOCK (bb))->flags & BB_DISABLE_SCHEDULE))
       return false;
 
   return true;
@@ -2881,7 +2898,7 @@ free_rgn_deps (void)
 
   for (bb = 0; bb < current_nr_blocks; bb++)
     {
-      rtx head, tail;
+      rtx_insn *head, *tail;
 
       gcc_assert (EBB_FIRST_BB (bb) == EBB_LAST_BB (bb));
       get_ebb_head_tail (EBB_FIRST_BB (bb), EBB_LAST_BB (bb), &head, &tail);
@@ -2901,7 +2918,7 @@ compute_priorities (void)
   current_sched_info->sched_max_insns_priority = 0;
   for (bb = 0; bb < current_nr_blocks; bb++)
     {
-      rtx head, tail;
+      rtx_insn *head, *tail;
 
       gcc_assert (EBB_FIRST_BB (bb) == EBB_LAST_BB (bb));
       get_ebb_head_tail (EBB_FIRST_BB (bb), EBB_LAST_BB (bb), &head, &tail);
@@ -2928,11 +2945,11 @@ static void
 realloc_bb_state_array (int saved_last_basic_block)
 {
   char *old_bb_state_array = bb_state_array;
-  size_t lbb = (size_t) last_basic_block;
+  size_t lbb = (size_t) last_basic_block_for_fn (cfun);
   size_t slbb = (size_t) saved_last_basic_block;
 
   /* Nothing to do if nothing changed since the last time this was called.  */
-  if (saved_last_basic_block == last_basic_block)
+  if (saved_last_basic_block == last_basic_block_for_fn (cfun))
     return;
 
   /* The selective scheduler doesn't use the state arrays.  */
@@ -2981,6 +2998,15 @@ schedule_region (int rgn)
 
   rgn_n_insns = 0;
 
+  /* Do not support register pressure sensitive scheduling for the new regions
+     as we don't update the liveness info for them.  */
+  if (sched_pressure != SCHED_PRESSURE_NONE
+      && rgn >= nr_regions_initial)
+    {
+      free_global_sched_pressure_data ();
+      sched_pressure = SCHED_PRESSURE_NONE;
+    }
+
   rgn_setup_region (rgn);
 
   /* Don't schedule region that is marked by
@@ -3003,7 +3029,7 @@ schedule_region (int rgn)
       for (bb = 0; bb < current_nr_blocks; bb++)
        {
          basic_block first_bb, last_bb;
-         rtx head, tail;
+         rtx_insn *head, *tail;
 
          first_bb = EBB_FIRST_BB (bb);
          last_bb = EBB_LAST_BB (bb);
@@ -3023,7 +3049,7 @@ schedule_region (int rgn)
   for (bb = 0; bb < current_nr_blocks; bb++)
     {
       basic_block first_bb, last_bb, curr_bb;
-      rtx head, tail;
+      rtx_insn *head, *tail;
 
       first_bb = EBB_FIRST_BB (bb);
       last_bb = EBB_LAST_BB (bb);
@@ -3052,7 +3078,7 @@ schedule_region (int rgn)
       if (dbg_cnt (sched_block))
         {
          edge f;
-         int saved_last_basic_block = last_basic_block;
+         int saved_last_basic_block = last_basic_block_for_fn (cfun);
 
          schedule_block (&curr_bb, bb_state[first_bb->index]);
          gcc_assert (EBB_FIRST_BB (bb) == first_bb);
@@ -3143,6 +3169,7 @@ sched_rgn_init (bool single_blocks_p)
 
   RGN_BLOCKS (nr_regions) = (RGN_BLOCKS (nr_regions - 1) +
                             RGN_NR_BLOCKS (nr_regions - 1));
+  nr_regions_initial = nr_regions;
 }
 
 /* Free data structures for region scheduling.  */
@@ -3271,7 +3298,7 @@ sched_rgn_local_init (int rgn)
 
       /* Use ->aux to implement EDGE_TO_BIT mapping.  */
       rgn_nr_edges = 0;
-      FOR_EACH_BB (block)
+      FOR_EACH_BB_FN (block, cfun)
        {
          if (CONTAINING_RGN (block->index) != rgn)
            continue;
@@ -3281,7 +3308,7 @@ sched_rgn_local_init (int rgn)
 
       rgn_edges = XNEWVEC (edge, rgn_nr_edges);
       rgn_nr_edges = 0;
-      FOR_EACH_BB (block)
+      FOR_EACH_BB_FN (block, cfun)
        {
          if (CONTAINING_RGN (block->index) != rgn)
            continue;
@@ -3302,7 +3329,7 @@ sched_rgn_local_init (int rgn)
       /* Cleanup ->aux used for EDGE_TO_BIT mapping.  */
       /* We don't need them anymore.  But we want to avoid duplication of
         aux fields in the newly created edges.  */
-      FOR_EACH_BB (block)
+      FOR_EACH_BB_FN (block, cfun)
        {
          if (CONTAINING_RGN (block->index) != rgn)
            continue;
@@ -3401,7 +3428,7 @@ schedule_insns (void)
 
 /* INSN has been added to/removed from current region.  */
 static void
-rgn_add_remove_insn (rtx insn, int remove_p)
+rgn_add_remove_insn (rtx_insn *insn, int remove_p)
 {
   if (!remove_p)
     rgn_n_insns++;
@@ -3422,9 +3449,12 @@ void
 extend_regions (void)
 {
   rgn_table = XRESIZEVEC (region, rgn_table, n_basic_blocks_for_fn (cfun));
-  rgn_bb_table = XRESIZEVEC (int, rgn_bb_table, n_basic_blocks_for_fn (cfun));
-  block_to_bb = XRESIZEVEC (int, block_to_bb, last_basic_block);
-  containing_rgn = XRESIZEVEC (int, containing_rgn, last_basic_block);
+  rgn_bb_table = XRESIZEVEC (int, rgn_bb_table,
+                            n_basic_blocks_for_fn (cfun));
+  block_to_bb = XRESIZEVEC (int, block_to_bb,
+                           last_basic_block_for_fn (cfun));
+  containing_rgn = XRESIZEVEC (int, containing_rgn,
+                              last_basic_block_for_fn (cfun));
 }
 
 void
@@ -3553,7 +3583,7 @@ rgn_fix_recovery_cfg (int bbi, int check_bbi, int check_bb_nexti)
 /* Return next block in ebb chain.  For parameter meaning please refer to
    sched-int.h: struct sched_info: advance_target_bb.  */
 static basic_block
-advance_target_bb (basic_block bb, rtx insn)
+advance_target_bb (basic_block bb, rtx_insn *insn)
 {
   if (insn)
     return 0;
@@ -3565,16 +3595,6 @@ advance_target_bb (basic_block bb, rtx insn)
 
 #endif
 \f
-static bool
-gate_handle_live_range_shrinkage (void)
-{
-#ifdef INSN_SCHEDULING
-  return flag_live_range_shrinkage;
-#else
-  return 0;
-#endif
-}
-
 /* Run instruction scheduler.  */
 static unsigned int
 rest_of_handle_live_range_shrinkage (void)
@@ -3592,16 +3612,6 @@ rest_of_handle_live_range_shrinkage (void)
   return 0;
 }
 
-static bool
-gate_handle_sched (void)
-{
-#ifdef INSN_SCHEDULING
-  return optimize > 0 && flag_schedule_insns && dbg_cnt (sched_func);
-#else
-  return 0;
-#endif
-}
-
 /* Run instruction scheduler.  */
 static unsigned int
 rest_of_handle_sched (void)
@@ -3616,17 +3626,6 @@ rest_of_handle_sched (void)
   return 0;
 }
 
-static bool
-gate_handle_sched2 (void)
-{
-#ifdef INSN_SCHEDULING
-  return optimize > 0 && flag_schedule_insns_after_reload
-    && !targetm.delay_sched2 && dbg_cnt (sched2_func);
-#else
-  return 0;
-#endif
-}
-
 /* Run second scheduling pass after reload.  */
 static unsigned int
 rest_of_handle_sched2 (void)
@@ -3648,6 +3647,17 @@ rest_of_handle_sched2 (void)
   return 0;
 }
 
+static unsigned int
+rest_of_handle_sched_fusion (void)
+{
+#ifdef INSN_SCHEDULING
+  sched_fusion = true;
+  schedule_insns ();
+  sched_fusion = false;
+#endif
+  return 0;
+}
+
 namespace {
 
 const pass_data pass_data_live_range_shrinkage =
@@ -3655,15 +3665,12 @@ const pass_data pass_data_live_range_shrinkage =
   RTL_PASS, /* type */
   "lr_shrinkage", /* name */
   OPTGROUP_NONE, /* optinfo_flags */
-  true, /* has_gate */
-  true, /* has_execute */
   TV_LIVE_RANGE_SHRINKAGE, /* tv_id */
   0, /* properties_required */
   0, /* properties_provided */
   0, /* properties_destroyed */
   0, /* todo_flags_start */
-  ( TODO_df_finish | TODO_verify_rtl_sharing
-    | TODO_verify_flow ), /* todo_flags_finish */
+  TODO_df_finish, /* todo_flags_finish */
 };
 
 class pass_live_range_shrinkage : public rtl_opt_pass
@@ -3674,8 +3681,19 @@ public:
   {}
 
   /* opt_pass methods: */
-  bool gate () { return gate_handle_live_range_shrinkage (); }
-  unsigned int execute () { return rest_of_handle_live_range_shrinkage (); }
+  virtual bool gate (function *)
+    {
+#ifdef INSN_SCHEDULING
+      return flag_live_range_shrinkage;
+#else
+      return 0;
+#endif
+    }
+
+  virtual unsigned int execute (function *)
+    {
+      return rest_of_handle_live_range_shrinkage ();
+    }
 
 }; // class pass_live_range_shrinkage
 
@@ -3694,15 +3712,12 @@ const pass_data pass_data_sched =
   RTL_PASS, /* type */
   "sched1", /* name */
   OPTGROUP_NONE, /* optinfo_flags */
-  true, /* has_gate */
-  true, /* has_execute */
   TV_SCHED, /* tv_id */
   0, /* properties_required */
   0, /* properties_provided */
   0, /* properties_destroyed */
   0, /* todo_flags_start */
-  ( TODO_df_finish | TODO_verify_rtl_sharing
-    | TODO_verify_flow ), /* todo_flags_finish */
+  TODO_df_finish, /* todo_flags_finish */
 };
 
 class pass_sched : public rtl_opt_pass
@@ -3713,11 +3728,21 @@ public:
   {}
 
   /* opt_pass methods: */
-  bool gate () { return gate_handle_sched (); }
-  unsigned int execute () { return rest_of_handle_sched (); }
+  virtual bool gate (function *);
+  virtual unsigned int execute (function *) { return rest_of_handle_sched (); }
 
 }; // class pass_sched
 
+bool
+pass_sched::gate (function *)
+{
+#ifdef INSN_SCHEDULING
+  return optimize > 0 && flag_schedule_insns && dbg_cnt (sched_func);
+#else
+  return 0;
+#endif
+}
+
 } // anon namespace
 
 rtl_opt_pass *
@@ -3733,15 +3758,12 @@ const pass_data pass_data_sched2 =
   RTL_PASS, /* type */
   "sched2", /* name */
   OPTGROUP_NONE, /* optinfo_flags */
-  true, /* has_gate */
-  true, /* has_execute */
   TV_SCHED2, /* tv_id */
   0, /* properties_required */
   0, /* properties_provided */
   0, /* properties_destroyed */
   0, /* todo_flags_start */
-  ( TODO_df_finish | TODO_verify_rtl_sharing
-    | TODO_verify_flow ), /* todo_flags_finish */
+  TODO_df_finish, /* todo_flags_finish */
 };
 
 class pass_sched2 : public rtl_opt_pass
@@ -3752,11 +3774,25 @@ public:
   {}
 
   /* opt_pass methods: */
-  bool gate () { return gate_handle_sched2 (); }
-  unsigned int execute () { return rest_of_handle_sched2 (); }
+  virtual bool gate (function *);
+  virtual unsigned int execute (function *)
+    {
+      return rest_of_handle_sched2 ();
+    }
 
 }; // class pass_sched2
 
+bool
+pass_sched2::gate (function *)
+{
+#ifdef INSN_SCHEDULING
+  return optimize > 0 && flag_schedule_insns_after_reload
+    && !targetm.delay_sched2 && dbg_cnt (sched2_func);
+#else
+  return 0;
+#endif
+}
+
 } // anon namespace
 
 rtl_opt_pass *
@@ -3764,3 +3800,55 @@ make_pass_sched2 (gcc::context *ctxt)
 {
   return new pass_sched2 (ctxt);
 }
+
+namespace {
+
+const pass_data pass_data_sched_fusion =
+{
+  RTL_PASS, /* type */
+  "sched_fusion", /* name */
+  OPTGROUP_NONE, /* optinfo_flags */
+  TV_SCHED_FUSION, /* tv_id */
+  0, /* properties_required */
+  0, /* properties_provided */
+  0, /* properties_destroyed */
+  0, /* todo_flags_start */
+  TODO_df_finish, /* todo_flags_finish */
+};
+
+class pass_sched_fusion : public rtl_opt_pass
+{
+public:
+  pass_sched_fusion (gcc::context *ctxt)
+    : rtl_opt_pass (pass_data_sched_fusion, ctxt)
+  {}
+
+  /* opt_pass methods: */
+  virtual bool gate (function *);
+  virtual unsigned int execute (function *)
+    {
+      return rest_of_handle_sched_fusion ();
+    }
+
+}; // class pass_sched2
+
+bool
+pass_sched_fusion::gate (function *)
+{
+#ifdef INSN_SCHEDULING
+  /* Scheduling fusion relies on peephole2 to do real fusion work,
+     so only enable it if peephole2 is in effect.  */
+  return (optimize > 0 && flag_peephole2
+    && flag_schedule_fusion && targetm.sched.fusion_priority != NULL);
+#else
+  return 0;
+#endif
+}
+
+} // anon namespace
+
+rtl_opt_pass *
+make_pass_sched_fusion (gcc::context *ctxt)
+{
+  return new pass_sched_fusion (ctxt);
+}