tree-optimization/95495 - use SLP_TREE_REPRESENTATIVE in assertion
[gcc.git] / gcc / modulo-sched.c
index 5604ddefc18f3cbb9cfd8771bffbc9be37aa7672..77254b31b422099b8e852ab8a3706092f0e1f0ed 100644 (file)
@@ -1,5 +1,5 @@
 /* Swing Modulo Scheduling implementation.
-   Copyright (C) 2004-2015 Free Software Foundation, Inc.
+   Copyright (C) 2004-2020 Free Software Foundation, Inc.
    Contributed by Ayal Zaks and Mustafa Hagog <zaks,mustafa@il.ibm.com>
 
 This file is part of GCC.
@@ -23,36 +23,22 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "backend.h"
-#include "cfghooks.h"
-#include "tree.h"
+#include "target.h"
 #include "rtl.h"
+#include "tree.h"
+#include "cfghooks.h"
 #include "df.h"
-#include "diagnostic-core.h"
-#include "tm_p.h"
+#include "memmodel.h"
+#include "optabs.h"
 #include "regs.h"
+#include "emit-rtl.h"
+#include "gcov-io.h"
 #include "profile.h"
-#include "flags.h"
-#include "insn-config.h"
 #include "insn-attr.h"
-#include "except.h"
-#include "recog.h"
 #include "cfgrtl.h"
 #include "sched-int.h"
-#include "target.h"
 #include "cfgloop.h"
-#include "alias.h"
-#include "insn-codes.h"
-#include "optabs.h"
-#include "expmed.h"
-#include "dojump.h"
-#include "explow.h"
-#include "calls.h"
-#include "emit-rtl.h"
-#include "varasm.h"
-#include "stmt.h"
 #include "expr.h"
-#include "params.h"
-#include "gcov-io.h"
 #include "ddg.h"
 #include "tree-pass.h"
 #include "dbgcnt.h"
@@ -224,7 +210,7 @@ static int sms_order_nodes (ddg_ptr, int, int *, int *);
 static void set_node_sched_params (ddg_ptr);
 static partial_schedule_ptr sms_schedule_by_order (ddg_ptr, int, int, int *);
 static void permute_partial_schedule (partial_schedule_ptr, rtx_insn *);
-static void generate_prolog_epilog (partial_schedule_ptr, struct loop *,
+static void generate_prolog_epilog (partial_schedule_ptr, class loop *,
                                     rtx, rtx);
 static int calculate_stage_count (partial_schedule_ptr, int);
 static void calculate_must_precede_follow (ddg_node_ptr, int, int,
@@ -383,7 +369,7 @@ doloop_register_get (rtx_insn *head, rtx_insn *tail)
                              : prev_nondebug_insn (tail));
 
   for (insn = head; insn != first_insn_not_to_check; insn = NEXT_INSN (insn))
-    if (!DEBUG_INSN_P (insn) && reg_mentioned_p (reg, insn))
+    if (NONDEBUG_INSN_P (insn) && reg_mentioned_p (reg, insn))
       {
         if (dump_file)
         {
@@ -442,7 +428,7 @@ res_MII (ddg_ptr g)
   if (targetm.sched.sms_res_mii)
     return targetm.sched.sms_res_mii (g);
 
-  return ((g->num_nodes - g->num_debug) / issue_rate);
+  return g->num_nodes / issue_rate;
 }
 
 
@@ -696,14 +682,13 @@ schedule_reg_moves (partial_schedule_ptr ps)
       rtx prev_reg, old_reg;
       int first_move;
       int distances[2];
-      sbitmap must_follow;
       sbitmap distance1_uses;
       rtx set = single_set (u->insn);
       
       /* Skip instructions that do not set a register.  */
-      if ((set && !REG_P (SET_DEST (set))))
+      if (set && !REG_P (SET_DEST (set)))
         continue;
+
       /* Compute the number of reg_moves needed for u, by looking at life
         ranges started at u (excluding self-loops).  */
       distances[0] = distances[1] = false;
@@ -757,7 +742,10 @@ schedule_reg_moves (partial_schedule_ptr ps)
       first_move += ps->g->num_nodes;
 
       /* Generate each move.  */
-      old_reg = prev_reg = SET_DEST (single_set (u->insn));
+      old_reg = prev_reg = SET_DEST (set);
+      if (HARD_REGISTER_P (old_reg))
+       return false;
+
       for (i_reg_move = 0; i_reg_move < nreg_moves; i_reg_move++)
        {
          ps_reg_move_info *move = ps_reg_move (ps, first_move + i_reg_move);
@@ -806,12 +794,11 @@ schedule_reg_moves (partial_schedule_ptr ps)
              }
          }
 
-      must_follow = sbitmap_alloc (first_move + nreg_moves);
+      auto_sbitmap must_follow (first_move + nreg_moves);
       for (i_reg_move = 0; i_reg_move < nreg_moves; i_reg_move++)
        if (!schedule_reg_move (ps, first_move + i_reg_move,
                                distance1_uses, must_follow))
          break;
-      sbitmap_free (must_follow);
       if (distance1_uses)
        sbitmap_free (distance1_uses);
       if (i_reg_move < nreg_moves)
@@ -820,7 +807,7 @@ schedule_reg_moves (partial_schedule_ptr ps)
   return true;
 }
 
-/* Emit the moves associatied with PS.  Apply the substitutions
+/* Emit the moves associated with PS.  Apply the substitutions
    associated with them.  */
 static void
 apply_reg_moves (partial_schedule_ptr ps)
@@ -941,7 +928,6 @@ static bool
 optimize_sc (partial_schedule_ptr ps, ddg_ptr g)
 {
   int amount = PS_MIN_CYCLE (ps);
-  sbitmap sched_nodes = sbitmap_alloc (g->num_nodes);
   int start, end, step;
   int ii = ps->ii;
   bool ok = false;
@@ -958,8 +944,7 @@ optimize_sc (partial_schedule_ptr ps, ddg_ptr g)
       if (dump_file)
        fprintf (dump_file, "SMS SC already optimized.\n");
 
-      ok = false;
-      goto clear;
+      return false;
     }
 
   if (dump_file)
@@ -981,11 +966,9 @@ optimize_sc (partial_schedule_ptr ps, ddg_ptr g)
     }
 
   if (SMODULO (SCHED_TIME (g->closing_branch->cuid), ii) == ii - 1)
-    {
-      ok = true;
-      goto clear;
-    }
+    return true;
 
+  auto_sbitmap sched_nodes (g->num_nodes);
   bitmap_ones (sched_nodes);
 
   /* Calculate the new placement of the branch.  It should be in row
@@ -998,8 +981,8 @@ optimize_sc (partial_schedule_ptr ps, ddg_ptr g)
       int branch_cycle = SCHED_TIME (g->closing_branch->cuid);
       int row = SMODULO (branch_cycle, ps->ii);
       int num_splits = 0;
-      sbitmap must_precede, must_follow, tmp_precede, tmp_follow;
-      int c;
+      sbitmap tmp_precede, tmp_follow;
+      int min_cycle, c;
 
       if (dump_file)
        fprintf (dump_file, "\nTrying to schedule node %d "
@@ -1014,11 +997,10 @@ optimize_sc (partial_schedule_ptr ps, ddg_ptr g)
          gcc_assert (c >= start);
          if (c >= end)
            {
-             ok = false;
              if (dump_file)
                fprintf (dump_file,
                         "SMS failed to schedule branch at cycle: %d\n", c);
-             goto clear;
+             return false;
            }
        }
       else
@@ -1031,13 +1013,12 @@ optimize_sc (partial_schedule_ptr ps, ddg_ptr g)
              if (dump_file)
                fprintf (dump_file,
                         "SMS failed to schedule branch at cycle: %d\n", c);
-             ok = false;
-             goto clear;
+             return false;
            }
        }
 
-      must_precede = sbitmap_alloc (g->num_nodes);
-      must_follow = sbitmap_alloc (g->num_nodes);
+      auto_sbitmap must_precede (g->num_nodes);
+      auto_sbitmap must_follow (g->num_nodes);
 
       /* Try to schedule the branch is it's new cycle.  */
       calculate_must_precede_follow (g->closing_branch, start, end,
@@ -1054,6 +1035,7 @@ optimize_sc (partial_schedule_ptr ps, ddg_ptr g)
        if (next_ps_i->id == g->closing_branch->cuid)
          break;
 
+      min_cycle = PS_MIN_CYCLE (ps) - SMODULO (PS_MIN_CYCLE (ps), ps->ii);
       remove_node_from_ps (ps, next_ps_i);
       success =
        try_scheduling_node_in_cycle (ps, g->closing_branch->cuid, c,
@@ -1093,12 +1075,11 @@ optimize_sc (partial_schedule_ptr ps, ddg_ptr g)
          ok = true;
        }
 
-      free (must_precede);
-      free (must_follow);
+      /* This might have been added to a new first stage.  */
+      if (PS_MIN_CYCLE (ps) < min_cycle)
+       reset_sched_times (ps, 0);
     }
 
-clear:
-  free (sched_nodes);
   return ok;
 }
 
@@ -1142,7 +1123,7 @@ duplicate_insns_of_cycles (partial_schedule_ptr ps, int from_stage,
 
 /* Generate the instructions (including reg_moves) for prolog & epilog.  */
 static void
-generate_prolog_epilog (partial_schedule_ptr ps, struct loop *loop,
+generate_prolog_epilog (partial_schedule_ptr ps, class loop *loop,
                         rtx count_reg, rtx count_init)
 {
   int i;
@@ -1199,7 +1180,7 @@ generate_prolog_epilog (partial_schedule_ptr ps, struct loop *loop,
 /* Mark LOOP as software pipelined so the later
    scheduling passes don't touch it.  */
 static void
-mark_loop_unsched (struct loop *loop)
+mark_loop_unsched (class loop *loop)
 {
   unsigned i;
   basic_block *bbs = get_loop_body (loop);
@@ -1213,7 +1194,7 @@ mark_loop_unsched (struct loop *loop)
 /* Return true if all the BBs of the loop are empty except the
    loop header.  */
 static bool
-loop_single_full_bb_p (struct loop *loop)
+loop_single_full_bb_p (class loop *loop)
 {
   unsigned i;
   basic_block *bbs = get_loop_body (loop);
@@ -1269,7 +1250,7 @@ dump_insn_location (rtx_insn *insn)
 /* Return true if the loop is in its canonical form and false if not.
    i.e. SIMPLE_SMS_LOOP_P and have one preheader block, and single exit.  */
 static bool
-loop_canon_p (struct loop *loop)
+loop_canon_p (class loop *loop)
 {
 
   if (loop->inner || !loop_outer (loop))
@@ -1312,7 +1293,7 @@ loop_canon_p (struct loop *loop)
    make it one by splitting the first entry edge and
    redirecting the others to the new BB.  */
 static void
-canon_loop (struct loop *loop)
+canon_loop (class loop *loop)
 {
   edge e;
   edge_iterator i;
@@ -1350,9 +1331,6 @@ setup_sched_infos (void)
    version may be entered.  Just a guess.  */
 #define PROB_SMS_ENOUGH_ITERATIONS 80
 
-/* Used to calculate the upper bound of ii.  */
-#define MAXII_FACTOR 2
-
 /* Main entry point, perform SMS scheduling on the loops of the function
    that consist of single basic blocks.  */
 static void
@@ -1364,10 +1342,10 @@ sms_schedule (void)
   int maxii, max_asap;
   partial_schedule_ptr ps;
   basic_block bb = NULL;
-  struct loop *loop;
+  class loop *loop;
   basic_block condition_bb = NULL;
   edge latch_edge;
-  gcov_type trip_count = 0;
+  HOST_WIDE_INT trip_count, max_trip_count;
 
   loop_optimizer_init (LOOPS_HAVE_PREHEADERS
                       | LOOPS_HAVE_RECORDED_EXITS);
@@ -1443,13 +1421,15 @@ sms_schedule (void)
       get_ebb_head_tail (bb, bb, &head, &tail);
       latch_edge = loop_latch_edge (loop);
       gcc_assert (single_exit (loop));
-      if (single_exit (loop)->count)
-       trip_count = latch_edge->count / single_exit (loop)->count;
+      trip_count = get_estimated_loop_iterations_int (loop);
+      max_trip_count = get_max_loop_iterations_int (loop);
 
       /* Perform SMS only on loops that their average count is above threshold.  */
 
-      if ( latch_edge->count
-          && (latch_edge->count < single_exit (loop)->count * SMS_LOOP_AVERAGE_COUNT_THRESHOLD))
+      if ( latch_edge->count () > profile_count::zero ()
+          && (latch_edge->count()
+             < single_exit (loop)->count ().apply_scale
+                                (param_sms_loop_average_count_threshold, 1)))
        {
          if (dump_file)
            {
@@ -1459,16 +1439,12 @@ sms_schedule (void)
                {
                  fprintf (dump_file, "SMS loop-count ");
                  fprintf (dump_file, "%" PRId64,
-                          (int64_t) bb->count);
+                          (int64_t) bb->count.to_gcov_type ());
                  fprintf (dump_file, "\n");
                   fprintf (dump_file, "SMS trip-count ");
-                  fprintf (dump_file, "%" PRId64,
-                           (int64_t) trip_count);
+                  fprintf (dump_file, "%" PRId64 "max %" PRId64,
+                           (int64_t) trip_count, (int64_t) max_trip_count);
                   fprintf (dump_file, "\n");
-                 fprintf (dump_file, "SMS profile-sum-max ");
-                 fprintf (dump_file, "%" PRId64,
-                          (int64_t) profile_info->sum_max);
-                 fprintf (dump_file, "\n");
                }
            }
           continue;
@@ -1570,8 +1546,8 @@ sms_schedule (void)
 
       latch_edge = loop_latch_edge (loop);
       gcc_assert (single_exit (loop));
-      if (single_exit (loop)->count)
-       trip_count = latch_edge->count / single_exit (loop)->count;
+      trip_count = get_estimated_loop_iterations_int (loop);
+      max_trip_count = get_max_loop_iterations_int (loop);
 
       if (dump_file)
        {
@@ -1581,11 +1557,7 @@ sms_schedule (void)
            {
              fprintf (dump_file, "SMS loop-count ");
              fprintf (dump_file, "%" PRId64,
-                      (int64_t) bb->count);
-             fprintf (dump_file, "\n");
-             fprintf (dump_file, "SMS profile-sum-max ");
-             fprintf (dump_file, "%" PRId64,
-                      (int64_t) profile_info->sum_max);
+                      (int64_t) bb->count.to_gcov_type ());
              fprintf (dump_file, "\n");
            }
          fprintf (dump_file, "SMS doloop\n");
@@ -1621,7 +1593,8 @@ sms_schedule (void)
       mii = 1; /* Need to pass some estimate of mii.  */
       rec_mii = sms_order_nodes (g, mii, node_order, &max_asap);
       mii = MAX (res_MII (g), rec_mii);
-      maxii = MAX (max_asap, MAXII_FACTOR * mii);
+      mii = MAX (mii, 1);
+      maxii = MAX (max_asap, param_sms_max_ii_factor * mii);
 
       if (dump_file)
        fprintf (dump_file, "SMS iis %d %d %d (rec_mii, mii, maxii)\n",
@@ -1660,12 +1633,13 @@ sms_schedule (void)
              gcc_assert (stage_count >= 1);
            }
 
-         /* The default value of PARAM_SMS_MIN_SC is 2 as stage count of
+         /* The default value of param_sms_min_sc is 2 as stage count of
             1 means that there is no interleaving between iterations thus
             we let the scheduling passes do the job in this case.  */
-         if (stage_count < PARAM_VALUE (PARAM_SMS_MIN_SC)
+         if (stage_count < param_sms_min_sc
              || (count_init && (loop_count <= stage_count))
-             || (flag_branch_probabilities && (trip_count <= stage_count)))
+             || (max_trip_count >= 0 && max_trip_count <= stage_count)
+             || (trip_count >= 0 && trip_count <= stage_count))
            {
              if (dump_file)
                {
@@ -1674,7 +1648,8 @@ sms_schedule (void)
                           " loop-count=", stage_count);
                  fprintf (dump_file, "%" PRId64, loop_count);
                  fprintf (dump_file, ", trip-count=");
-                 fprintf (dump_file, "%" PRId64, trip_count);
+                 fprintf (dump_file, "%" PRId64 "max %" PRId64,
+                          (int64_t) trip_count, (int64_t) max_trip_count);
                  fprintf (dump_file, ")\n");
                }
              break;
@@ -1730,12 +1705,12 @@ sms_schedule (void)
              rtx comp_rtx = gen_rtx_GT (VOIDmode, count_reg,
                                         gen_int_mode (stage_count,
                                                       GET_MODE (count_reg)));
-             unsigned prob = (PROB_SMS_ENOUGH_ITERATIONS
-                              * REG_BR_PROB_BASE) / 100;
+             profile_probability prob = profile_probability::guessed_always ()
+                               .apply_scale (PROB_SMS_ENOUGH_ITERATIONS, 100);
 
              loop_version (loop, comp_rtx, &condition_bb,
-                           prob, prob, REG_BR_PROB_BASE - prob,
-                           true);
+                           prob, prob.invert (),
+                           prob, prob.invert (), true);
             }
 
          /* Set new iteration count of loop kernel.  */
@@ -1850,11 +1825,6 @@ sms_schedule (void)
    The window would then start and end on the same row, but with
    different "must precede" and "must follow" requirements.  */
 
-/* A limit on the number of cycles that resource conflicts can span.  ??? Should
-   be provided by DFA, and be dependent on the type of insn scheduled.  Currently
-   set to 0 to save compile time.  */
-#define DFA_HISTORY SMS_DFA_HISTORY
-
 /* A threshold for the number of repeated unsuccessful attempts to insert
    an empty row, before we flush the partial schedule and start over.  */
 #define MAX_SPLIT_NUM 10
@@ -1875,8 +1845,8 @@ get_sched_window (partial_schedule_ptr ps, ddg_node_ptr u_node,
   int start, step, end;
   int early_start, late_start;
   ddg_edge_ptr e;
-  sbitmap psp = sbitmap_alloc (ps->g->num_nodes);
-  sbitmap pss = sbitmap_alloc (ps->g->num_nodes);
+  auto_sbitmap psp (ps->g->num_nodes);
+  auto_sbitmap pss (ps->g->num_nodes);
   sbitmap u_node_preds = NODE_PREDECESSORS (u_node);
   sbitmap u_node_succs = NODE_SUCCESSORS (u_node);
   int psp_not_empty;
@@ -2005,8 +1975,6 @@ get_sched_window (partial_schedule_ptr ps, ddg_node_ptr u_node,
   *start_p = start;
   *step_p = step;
   *end_p = end;
-  sbitmap_free (psp);
-  sbitmap_free (pss);
 
   if ((start >= end && step == 1) || (start <= end && step == -1))
     {
@@ -2155,12 +2123,17 @@ sms_schedule_by_order (ddg_ptr g, int mii, int maxii, int *nodes_order)
   int flush_and_start_over = true;
   int num_nodes = g->num_nodes;
   int start, end, step; /* Place together into one struct?  */
-  sbitmap sched_nodes = sbitmap_alloc (num_nodes);
-  sbitmap must_precede = sbitmap_alloc (num_nodes);
-  sbitmap must_follow = sbitmap_alloc (num_nodes);
-  sbitmap tobe_scheduled = sbitmap_alloc (num_nodes);
-
-  partial_schedule_ptr ps = create_partial_schedule (ii, g, DFA_HISTORY);
+  auto_sbitmap sched_nodes (num_nodes);
+  auto_sbitmap must_precede (num_nodes);
+  auto_sbitmap must_follow (num_nodes);
+  auto_sbitmap tobe_scheduled (num_nodes);
+
+  /* Value of param_sms_dfa_history is a limit on the number of cycles that
+     resource conflicts can span.  ??? Should be provided by DFA, and be
+     dependent on the type of insn scheduled.  Set to 0 by default to save
+     compile time.  */
+  partial_schedule_ptr ps = create_partial_schedule (ii, g,
+                                                    param_sms_dfa_history);
 
   bitmap_ones (tobe_scheduled);
   bitmap_clear (sched_nodes);
@@ -2179,11 +2152,7 @@ sms_schedule_by_order (ddg_ptr g, int mii, int maxii, int *nodes_order)
          ddg_node_ptr u_node = &ps->g->nodes[u];
          rtx_insn *insn = u_node->insn;
 
-         if (!NONDEBUG_INSN_P (insn))
-           {
-             bitmap_clear_bit (tobe_scheduled, u);
-             continue;
-           }
+         gcc_checking_assert (NONDEBUG_INSN_P (insn));
 
          if (bitmap_bit_p (sched_nodes, u))
            continue;
@@ -2269,11 +2238,6 @@ sms_schedule_by_order (ddg_ptr g, int mii, int maxii, int *nodes_order)
   else
     gcc_assert (bitmap_equal_p (tobe_scheduled, sched_nodes));
 
-  sbitmap_free (sched_nodes);
-  sbitmap_free (must_precede);
-  sbitmap_free (must_follow);
-  sbitmap_free (tobe_scheduled);
-
   return ps;
 }
 
@@ -2483,7 +2447,7 @@ static void
 check_nodes_order (int *node_order, int num_nodes)
 {
   int i;
-  sbitmap tmp = sbitmap_alloc (num_nodes);
+  auto_sbitmap tmp (num_nodes);
 
   bitmap_clear (tmp);
 
@@ -2503,8 +2467,6 @@ check_nodes_order (int *node_order, int num_nodes)
 
   if (dump_file)
     fprintf (dump_file, "\n");
-
-  sbitmap_free (tmp);
 }
 
 /* Order the nodes of G for scheduling and pass the result in
@@ -2548,10 +2510,10 @@ order_nodes_of_sccs (ddg_all_sccs_ptr all_sccs, int * node_order)
   int i, pos = 0;
   ddg_ptr g = all_sccs->ddg;
   int num_nodes = g->num_nodes;
-  sbitmap prev_sccs = sbitmap_alloc (num_nodes);
-  sbitmap on_path = sbitmap_alloc (num_nodes);
-  sbitmap tmp = sbitmap_alloc (num_nodes);
-  sbitmap ones = sbitmap_alloc (num_nodes);
+  auto_sbitmap prev_sccs (num_nodes);
+  auto_sbitmap on_path (num_nodes);
+  auto_sbitmap tmp (num_nodes);
+  auto_sbitmap ones (num_nodes);
 
   bitmap_clear (prev_sccs);
   bitmap_ones (ones);
@@ -2584,10 +2546,6 @@ order_nodes_of_sccs (ddg_all_sccs_ptr all_sccs, int * node_order)
       bitmap_and_compl (tmp, ones, prev_sccs);
       pos = order_nodes_in_scc (g, prev_sccs, tmp, node_order, pos);
     }
-  sbitmap_free (prev_sccs);
-  sbitmap_free (on_path);
-  sbitmap_free (tmp);
-  sbitmap_free (ones);
 }
 
 /* MII is needed if we consider backarcs (that do not close recursive cycles).  */
@@ -2748,11 +2706,11 @@ order_nodes_in_scc (ddg_ptr g, sbitmap nodes_ordered, sbitmap scc,
 {
   enum sms_direction dir;
   int num_nodes = g->num_nodes;
-  sbitmap workset = sbitmap_alloc (num_nodes);
-  sbitmap tmp = sbitmap_alloc (num_nodes);
+  auto_sbitmap workset (num_nodes);
+  auto_sbitmap tmp (num_nodes);
   sbitmap zero_bitmap = sbitmap_alloc (num_nodes);
-  sbitmap predecessors = sbitmap_alloc (num_nodes);
-  sbitmap successors = sbitmap_alloc (num_nodes);
+  auto_sbitmap predecessors (num_nodes);
+  auto_sbitmap successors (num_nodes);
 
   bitmap_clear (predecessors);
   find_predecessors (predecessors, g, nodes_ordered);
@@ -2832,11 +2790,7 @@ order_nodes_in_scc (ddg_ptr g, sbitmap nodes_ordered, sbitmap scc,
          bitmap_and (workset, successors, scc);
        }
     }
-  sbitmap_free (tmp);
-  sbitmap_free (workset);
   sbitmap_free (zero_bitmap);
-  sbitmap_free (predecessors);
-  sbitmap_free (successors);
   return pos;
 }
 
@@ -3035,9 +2989,7 @@ ps_insn_find_column (partial_schedule_ptr ps, ps_insn_ptr ps_i,
             last_must_precede = next_ps_i;
         }
       /* The closing branch must be the last in the row.  */
-      if (must_precede 
-         && bitmap_bit_p (must_precede, next_ps_i->id)
-         && JUMP_P (ps_rtl_insn (ps, next_ps_i->id)))
+      if (JUMP_P (ps_rtl_insn (ps, next_ps_i->id)))
        return false;
              
        last_in_row = next_ps_i;
@@ -3202,9 +3154,6 @@ ps_has_conflicts (partial_schedule_ptr ps, int from, int to)
        {
          rtx_insn *insn = ps_rtl_insn (ps, crr_insn->id);
 
-         if (!NONDEBUG_INSN_P (insn))
-           continue;
-
          /* Check if there is room for the current insn.  */
          if (!can_issue_more || state_dead_lock_p (curr_state))
            return true;
@@ -3241,7 +3190,7 @@ ps_add_node_check_conflicts (partial_schedule_ptr ps, int n,
                             int c, sbitmap must_precede,
                             sbitmap must_follow)
 {
-  int has_conflicts = 0;
+  int i, first, amount, has_conflicts = 0;
   ps_insn_ptr ps_i;
 
   /* First add the node to the PS, if this succeeds check for
@@ -3249,23 +3198,32 @@ ps_add_node_check_conflicts (partial_schedule_ptr ps, int n,
   if (! (ps_i = add_node_to_ps (ps, n, c, must_precede, must_follow)))
     return NULL; /* Failed to insert the node at the given cycle.  */
 
-  has_conflicts = ps_has_conflicts (ps, c, c)
-                 || (ps->history > 0
-                     && ps_has_conflicts (ps,
-                                          c - ps->history,
-                                          c + ps->history));
-
-  /* Try different issue slots to find one that the given node can be
-     scheduled in without conflicts.  */
-  while (has_conflicts)
+  while (1)
     {
+      has_conflicts = ps_has_conflicts (ps, c, c);
+      if (ps->history > 0 && !has_conflicts)
+       {
+         /* Check all 2h+1 intervals, starting from c-2h..c up to c..2h,
+            but not more than ii intervals.  */
+         first = c - ps->history;
+         amount = 2 * ps->history + 1;
+         if (amount > ps->ii)
+           amount = ps->ii;
+         for (i = first; i < first + amount; i++)
+           {
+             has_conflicts = ps_has_conflicts (ps,
+                                               i - ps->history,
+                                               i + ps->history);
+             if (has_conflicts)
+               break;
+           }
+       }
+      if (!has_conflicts)
+       break;
+      /* Try different issue slots to find one that the given node can be
+        scheduled in without conflicts.  */
       if (! ps_insn_advance_column (ps, ps_i, must_follow))
        break;
-      has_conflicts = ps_has_conflicts (ps, c, c)
-                     || (ps->history > 0
-                         && ps_has_conflicts (ps,
-                                              c - ps->history,
-                                              c + ps->history));
     }
 
   if (has_conflicts)