OSDN Git Service

PR c++/27292
[pf3gnuchains/gcc-fork.git] / gcc / modulo-sched.c
index a2443c1..5a27033 100644 (file)
@@ -1,5 +1,5 @@
 /* Swing Modulo Scheduling implementation.
-   Copyright (C) 2004, 2005
+   Copyright (C) 2004, 2005, 2006
    Free Software Foundation, Inc.
    Contributed by Ayal Zaks and Mustafa Hagog <zaks,mustafa@il.ibm.com>
 
@@ -17,8 +17,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 
 #include "config.h"
@@ -47,6 +47,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "gcov-io.h"
 #include "df.h"
 #include "ddg.h"
+#include "timevar.h"
+#include "tree-pass.h"
 
 #ifdef INSN_SCHEDULING
 
@@ -105,8 +107,6 @@ typedef struct ps_insn *ps_insn_ptr;
 #define PS_STAGE_COUNT(ps) ((PS_MAX_CYCLE (ps) - PS_MIN_CYCLE (ps) \
                             + 1 + (ps)->ii - 1) / (ps)->ii)
 
-#define CFG_HOOKS cfg_layout_rtl_cfg_hooks
-
 /* A single instruction in the partial schedule.  */
 struct ps_insn
 {
@@ -157,9 +157,9 @@ struct undo_replace_buff_elem
 
 
   
-partial_schedule_ptr create_partial_schedule (int ii, ddg_ptr, int history);
-void free_partial_schedule (partial_schedule_ptr);
-void reset_partial_schedule (partial_schedule_ptr, int new_ii);
+static partial_schedule_ptr create_partial_schedule (int ii, ddg_ptr, int history);
+static void free_partial_schedule (partial_schedule_ptr);
+static void reset_partial_schedule (partial_schedule_ptr, int new_ii);
 void print_partial_schedule (partial_schedule_ptr, FILE *);
 static int kernel_number_of_cycles (rtx first_insn, rtx last_insn);
 static ps_insn_ptr ps_add_node_check_conflicts (partial_schedule_ptr,
@@ -181,13 +181,9 @@ static bool ps_unschedule_node (partial_schedule_ptr, ddg_node_ptr );
 
 static int issue_rate;
 
-/* For printing statistics.  */
-static FILE *stats_file;
-
 static int sms_order_nodes (ddg_ptr, int, int * result);
 static void set_node_sched_params (ddg_ptr);
-static partial_schedule_ptr sms_schedule_by_order (ddg_ptr, int, int,
-                                                  int *, FILE*);
+static partial_schedule_ptr sms_schedule_by_order (ddg_ptr, int, int, int *);
 static void permute_partial_schedule (partial_schedule_ptr ps, rtx last);
 static void generate_prolog_epilog (partial_schedule_ptr ,struct loop * loop, rtx);
 static void duplicate_insns_of_cycles (partial_schedule_ptr ps,
@@ -241,12 +237,6 @@ sms_print_insn (rtx insn, int aligned ATTRIBUTE_UNUSED)
   return tmp;
 }
 
-static int
-contributes_to_priority (rtx next, rtx insn)
-{
-  return BLOCK_NUM (next) == BLOCK_NUM (insn);
-}
-
 static void
 compute_jump_reg_dependencies (rtx insn ATTRIBUTE_UNUSED,
                               regset cond_exec ATTRIBUTE_UNUSED,
@@ -263,82 +253,49 @@ static struct sched_info sms_sched_info =
   NULL,
   NULL,
   sms_print_insn,
-  contributes_to_priority,
+  NULL,
   compute_jump_reg_dependencies,
   NULL, NULL,
   NULL, NULL,
-  0, 0, 0
+  0, 0, 0,
+
+  NULL, NULL, NULL, NULL, NULL,
+#ifdef ENABLE_CHECKING
+  NULL,
+#endif
+  0
 };
 
 
-/* Return the register decremented and tested or zero if it is not a decrement
-   and branch jump insn (similar to doloop_condition_get).  */
+/* Return the register decremented and tested in INSN,
+   or zero if it is not a decrement-and-branch insn.  */
+
 static rtx
-doloop_register_get (rtx insn, rtx *comp)
+doloop_register_get (rtx insn ATTRIBUTE_UNUSED)
 {
-  rtx pattern, cmp, inc, reg, condition;
-
-  if (!JUMP_P (insn))
-    return NULL_RTX;
-  pattern = PATTERN (insn);
-
-  /* The canonical doloop pattern we expect is:
-
-     (parallel [(set (pc) (if_then_else (condition)
-                                       (label_ref (label))
-                                       (pc)))
-               (set (reg) (plus (reg) (const_int -1)))
-               (additional clobbers and uses)])
-
-    where condition is further restricted to be
-      (ne (reg) (const_int 1)).  */
-
-  if (GET_CODE (pattern) != PARALLEL)
-    return NULL_RTX;
-
-  cmp = XVECEXP (pattern, 0, 0);
-  inc = XVECEXP (pattern, 0, 1);
-  /* Return the compare rtx.  */
-  *comp = cmp;
+#ifdef HAVE_doloop_end
+  rtx pattern, reg, condition;
 
-  /* Check for (set (reg) (something)).  */
-  if (GET_CODE (inc) != SET || ! REG_P (SET_DEST (inc)))
+  if (! JUMP_P (insn))
     return NULL_RTX;
 
-  /* Extract loop counter register.  */
-  reg = SET_DEST (inc);
-
-  /* Check if something = (plus (reg) (const_int -1)).  */
-  if (GET_CODE (SET_SRC (inc)) != PLUS
-      || XEXP (SET_SRC (inc), 0) != reg
-      || XEXP (SET_SRC (inc), 1) != constm1_rtx)
-    return NULL_RTX;
-
-  /* Check for (set (pc) (if_then_else (condition)
-                                      (label_ref (label))
-                                      (pc))).  */
-  if (GET_CODE (cmp) != SET
-      || SET_DEST (cmp) != pc_rtx
-      || GET_CODE (SET_SRC (cmp)) != IF_THEN_ELSE
-      || GET_CODE (XEXP (SET_SRC (cmp), 1)) != LABEL_REF
-      || XEXP (SET_SRC (cmp), 2) != pc_rtx)
-    return NULL_RTX;
-
-  /* Extract loop termination condition.  */
-  condition = XEXP (SET_SRC (cmp), 0);
-
-  /* Check if condition = (ne (reg) (const_int 1)), which is more
-     restrictive than the check in doloop_condition_get:
-     if ((GET_CODE (condition) != GE && GET_CODE (condition) != NE)
-        || GET_CODE (XEXP (condition, 1)) != CONST_INT).  */
-  if (GET_CODE (condition) != NE
-      || XEXP (condition, 1) != const1_rtx)
+  pattern = PATTERN (insn);
+  condition = doloop_condition_get (pattern);
+  if (! condition)
     return NULL_RTX;
 
-  if (XEXP (condition, 0) == reg)
-    return reg;
+  if (REG_P (XEXP (condition, 0)))
+    reg = XEXP (condition, 0);
+  else if (GET_CODE (XEXP (condition, 0)) == PLUS
+          && REG_P (XEXP (XEXP (condition, 0), 0)))
+    reg = XEXP (XEXP (condition, 0), 0);
+  else
+    gcc_unreachable ();
 
+  return reg;
+#else
   return NULL_RTX;
+#endif
 }
 
 /* Check if COUNT_REG is set to a constant in the PRE_HEADER block, so
@@ -355,7 +312,7 @@ const_iteration_count (rtx count_reg, basic_block pre_header,
   if (! pre_header)
     return NULL_RTX;
 
-  get_block_head_tail (pre_header->index, &head, &tail);
+  get_ebb_head_tail (pre_header, pre_header, &head, &tail);
 
   for (insn = tail; insn != PREV_INSN (head); insn = PREV_INSN (insn))
     if (INSN_P (insn) && single_set (insn) &&
@@ -413,11 +370,11 @@ set_node_sched_params (ddg_ptr g)
 }
 
 static void
-print_node_sched_params (FILE * dump_file, int num_nodes)
+print_node_sched_params (FILE * file, int num_nodes)
 {
   int i;
 
-  if (! dump_file)
+  if (! file)
     return;
   for (i = 0; i < num_nodes; i++)
     {
@@ -425,14 +382,14 @@ print_node_sched_params (FILE * dump_file, int num_nodes)
       rtx reg_move = nsp->first_reg_move;
       int j;
 
-      fprintf (dump_file, "Node %d:\n", i);
-      fprintf (dump_file, " asap = %d:\n", nsp->asap);
-      fprintf (dump_file, " time = %d:\n", nsp->time);
-      fprintf (dump_file, " nreg_moves = %d:\n", nsp->nreg_moves);
+      fprintf (file, "Node %d:\n", i);
+      fprintf (file, " asap = %d:\n", nsp->asap);
+      fprintf (file, " time = %d:\n", nsp->time);
+      fprintf (file, " nreg_moves = %d:\n", nsp->nreg_moves);
       for (j = 0; j < nsp->nreg_moves; j++)
        {
-         fprintf (dump_file, " reg_move = ");
-         print_rtl_single (dump_file, reg_move);
+         fprintf (file, " reg_move = ");
+         print_rtl_single (file, reg_move);
          reg_move = PREV_INSN (reg_move);
        }
     }
@@ -540,9 +497,10 @@ generate_reg_moves (partial_schedule_ptr ps)
 
       for (i_reg_move = 0; i_reg_move < nreg_moves; i_reg_move++)
        {
-         int i_use;
+         unsigned int i_use = 0;
          rtx new_reg = gen_reg_rtx (GET_MODE (prev_reg));
          rtx reg_move = gen_move_insn (new_reg, prev_reg);
+         sbitmap_iterator sbi;
 
          add_insn_before (reg_move, last_reg_move);
          last_reg_move = reg_move;
@@ -550,7 +508,7 @@ generate_reg_moves (partial_schedule_ptr ps)
          if (!SCHED_FIRST_REG_MOVE (u))
            SCHED_FIRST_REG_MOVE (u) = reg_move;
 
-         EXECUTE_IF_SET_IN_SBITMAP (uses_of_defs[i_reg_move], 0, i_use,
+         EXECUTE_IF_SET_IN_SBITMAP (uses_of_defs[i_reg_move], 0, i_use, sbi)
            {
              struct undo_replace_buff_elem *rep;
 
@@ -569,10 +527,11 @@ generate_reg_moves (partial_schedule_ptr ps)
                }
 
              replace_rtx (g->nodes[i_use].insn, old_reg, new_reg);
-           });
+           }
 
          prev_reg = new_reg;
        }
+      sbitmap_vector_free (uses_of_defs);
     }
   return reg_move_replaces;
 }
@@ -599,6 +558,7 @@ undo_generate_reg_moves (partial_schedule_ptr ps,
          delete_insn (crr);
          crr = prev;
        }
+      SCHED_FIRST_REG_MOVE (u) = NULL_RTX;
     }
 
   while (reg_move_replaces)
@@ -640,8 +600,7 @@ normalize_sched_times (partial_schedule_ptr ps)
       ddg_node_ptr u = &g->nodes[i];
       int normalized_time = SCHED_TIME (u) - amount;
 
-      if (normalized_time < 0)
-       abort ();
+      gcc_assert (normalized_time >= 0);
 
       SCHED_TIME (u) = normalized_time;
       SCHED_ROW (u) = normalized_time % ii;
@@ -833,7 +792,7 @@ loop_single_full_bb_p (struct loop *loop)
 
       /* Make sure that basic blocks other than the header
          have only notes labels or jumps.  */
-      get_block_head_tail (bbs[i]->index, &head, &tail);
+      get_ebb_head_tail (bbs[i], bbs[i], &head, &tail);
       for (; head != NEXT_INSN (tail); head = NEXT_INSN (head))
         {
           if (NOTE_P (head) || LABEL_P (head)
@@ -862,7 +821,7 @@ loop_single_full_bb_p (struct loop *loop)
 /* 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, FILE *dump_file)
+loop_canon_p (struct loop *loop)
 {
 
   if (loop->inner || ! loop->outer)
@@ -879,7 +838,7 @@ loop_canon_p (struct loop *loop, FILE *dump_file)
            {
              expanded_location xloc;
              NOTE_EXPANDED_LOCATION (xloc, line_note);
-             fprintf (stats_file, " %s %d (file, line)\n",
+             fprintf (dump_file, " %s %d (file, line)\n",
                       xloc.file, xloc.line);
            }
        }
@@ -897,7 +856,7 @@ loop_canon_p (struct loop *loop, FILE *dump_file)
            {
              expanded_location xloc;
              NOTE_EXPANDED_LOCATION (xloc, line_note);
-             fprintf (stats_file, " %s %d (file, line)\n",
+             fprintf (dump_file, " %s %d (file, line)\n",
                       xloc.file, xloc.line);
            }
        }
@@ -932,48 +891,10 @@ canon_loop (struct loop *loop)
     }
 }
 
-/* Build the loop information without loop
-   canonization, the loop canonization will
-   be perfromed if the loop is SMSable.  */
-static struct loops *
-build_loops_structure (FILE *dumpfile)
-{
-  struct loops *loops = xcalloc (1, sizeof (struct loops));
-
-  /* Find the loops.  */
-
-  if (flow_loops_find (loops) <= 1)
-    {
-      /* No loops.  */
-      flow_loops_free (loops);
-      free (loops);
-
-      return NULL;
-    }
-
-  /* Not going to update these.  */
-  free (loops->cfg.rc_order);
-  loops->cfg.rc_order = NULL;
-  free (loops->cfg.dfs_order);
-  loops->cfg.dfs_order = NULL;
-
-  create_preheaders (loops, CP_SIMPLE_PREHEADERS);
-  mark_single_exit_loops (loops);
-  /* Dump loops.  */
-  flow_loops_dump (loops, dumpfile, NULL, 1);
-
-#ifdef ENABLE_CHECKING
-  verify_dominators (CDI_DOMINATORS);
-  verify_loop_structure (loops);
-#endif
-
-  return loops;
-}
-
 /* Main entry point, perform SMS scheduling on the loops of the function
    that consist of single basic blocks.  */
-void
-sms_schedule (FILE *dump_file)
+static void
+sms_schedule (void)
 {
   static int passes = 0;
   rtx insn;
@@ -991,19 +912,18 @@ sms_schedule (FILE *dump_file)
   edge latch_edge;
   gcov_type trip_count = 0;
 
-  if (! (loops = build_loops_structure (dump_file)))
+  loops = loop_optimizer_init (LOOPS_HAVE_PREHEADERS
+                              | LOOPS_HAVE_MARKED_SINGLE_EXITS);
+  if (!loops)
     return;  /* There is no loops to schedule.  */
 
-
-  stats_file = dump_file;
-
   /* Initialize issue_rate.  */
   if (targetm.sched.issue_rate)
     {
       int temp = reload_completed;
 
       reload_completed = 1;
-      issue_rate = (*targetm.sched.issue_rate) ();
+      issue_rate = targetm.sched.issue_rate ();
       reload_completed = temp;
     }
   else
@@ -1011,15 +931,18 @@ sms_schedule (FILE *dump_file)
 
   /* Initialize the scheduler.  */
   current_sched_info = &sms_sched_info;
-  sched_init (NULL);
+  sched_init ();
 
   /* Init Data Flow analysis, to be used in interloop dep calculation.  */
-  df = df_init ();
-  df_analyze (df, 0, DF_ALL);
+  df = df_init (DF_HARD_REGS | DF_EQUIV_NOTES |        DF_SUBREGS);
+  df_rd_add_problem (df);
+  df_ru_add_problem (df);
+  df_chain_add_problem (df, DF_DU_CHAIN | DF_UD_CHAIN);
+  df_analyze (df);
 
   /* Allocate memory to hold the DDG array one entry for each loop.
      We use loop->num as index into this array.  */
-  g_arr = xcalloc (loops->num, sizeof (ddg_ptr));
+  g_arr = XCNEWVEC (ddg_ptr, loops->num);
 
 
   /* Build DDGs for all the relevant loops and hold them in G_ARR
@@ -1027,7 +950,7 @@ sms_schedule (FILE *dump_file)
   for (i = 0; i < loops->num; i++)
     {
       rtx head, tail;
-      rtx count_reg, comp;
+      rtx count_reg;
       struct loop *loop = loops->parray[i];
 
       /* For debugging.  */
@@ -1039,7 +962,7 @@ sms_schedule (FILE *dump_file)
           break;
         }
 
-      if (! loop_canon_p (loop, dump_file))
+      if (! loop_canon_p (loop))
         continue;
 
       if (! loop_single_full_bb_p (loop))
@@ -1047,7 +970,7 @@ sms_schedule (FILE *dump_file)
 
       bb = loop->header;
 
-      get_block_head_tail (bb->index, &head, &tail);
+      get_ebb_head_tail (bb, bb, &head, &tail);
       latch_edge = loop_latch_edge (loop);
       gcc_assert (loop->single_exit);
       if (loop->single_exit->count)
@@ -1058,7 +981,7 @@ sms_schedule (FILE *dump_file)
       if ( latch_edge->count
           && (latch_edge->count < loop->single_exit->count * SMS_LOOP_AVERAGE_COUNT_THRESHOLD))
        {
-         if (stats_file)
+         if (dump_file)
            {
              rtx line_note = find_line_note (tail);
 
@@ -1066,31 +989,31 @@ sms_schedule (FILE *dump_file)
                {
                  expanded_location xloc;
                  NOTE_EXPANDED_LOCATION (xloc, line_note);
-                 fprintf (stats_file, "SMS bb %s %d (file, line)\n",
+                 fprintf (dump_file, "SMS bb %s %d (file, line)\n",
                           xloc.file, xloc.line);
                }
-             fprintf (stats_file, "SMS single-bb-loop\n");
+             fprintf (dump_file, "SMS single-bb-loop\n");
              if (profile_info && flag_branch_probabilities)
                {
-                 fprintf (stats_file, "SMS loop-count ");
-                 fprintf (stats_file, HOST_WIDEST_INT_PRINT_DEC,
+                 fprintf (dump_file, "SMS loop-count ");
+                 fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
                           (HOST_WIDEST_INT) bb->count);
-                 fprintf (stats_file, "\n");
-                  fprintf (stats_file, "SMS trip-count ");
-                  fprintf (stats_file, HOST_WIDEST_INT_PRINT_DEC,
+                 fprintf (dump_file, "\n");
+                  fprintf (dump_file, "SMS trip-count ");
+                  fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
                            (HOST_WIDEST_INT) trip_count);
-                  fprintf (stats_file, "\n");
-                 fprintf (stats_file, "SMS profile-sum-max ");
-                 fprintf (stats_file, HOST_WIDEST_INT_PRINT_DEC,
+                  fprintf (dump_file, "\n");
+                 fprintf (dump_file, "SMS profile-sum-max ");
+                 fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
                           (HOST_WIDEST_INT) profile_info->sum_max);
-                 fprintf (stats_file, "\n");
+                 fprintf (dump_file, "\n");
                }
            }
           continue;
         }
 
       /* Make sure this is a doloop.  */
-      if ( !(count_reg = doloop_register_get (tail, &comp)))
+      if ( !(count_reg = doloop_register_get (tail)))
        continue;
 
       /* Don't handle BBs with calls or barriers, or !single_set insns.  */
@@ -1103,15 +1026,15 @@ sms_schedule (FILE *dump_file)
 
       if (insn != NEXT_INSN (tail))
        {
-         if (stats_file)
+         if (dump_file)
            {
              if (CALL_P (insn))
-               fprintf (stats_file, "SMS loop-with-call\n");
+               fprintf (dump_file, "SMS loop-with-call\n");
              else if (BARRIER_P (insn))
-               fprintf (stats_file, "SMS loop-with-barrier\n");
+               fprintf (dump_file, "SMS loop-with-barrier\n");
              else
-               fprintf (stats_file, "SMS loop-with-not-single-set\n");
-             print_rtl_single (stats_file, insn);
+               fprintf (dump_file, "SMS loop-with-not-single-set\n");
+             print_rtl_single (dump_file, insn);
            }
 
          continue;
@@ -1119,8 +1042,8 @@ sms_schedule (FILE *dump_file)
 
       if (! (g = create_ddg (bb, df, 0)))
         {
-          if (stats_file)
-           fprintf (stats_file, "SMS doloop\n");
+          if (dump_file)
+           fprintf (dump_file, "SMS doloop\n");
          continue;
         }
 
@@ -1129,6 +1052,7 @@ sms_schedule (FILE *dump_file)
 
   /* Release Data Flow analysis data structures.  */
   df_finish (df);
+  df = NULL;
 
   /* We don't want to perform SMS on new loops - created by versioning.  */
   num_loops = loops->num;
@@ -1136,7 +1060,7 @@ sms_schedule (FILE *dump_file)
   for (i = 0; i < num_loops; i++)
     {
       rtx head, tail;
-      rtx count_reg, count_init, comp;
+      rtx count_reg, count_init;
       int mii, rec_mii;
       unsigned stage_count = 0;
       HOST_WIDEST_INT loop_count = 0;
@@ -1148,14 +1072,14 @@ sms_schedule (FILE *dump_file)
       if (dump_file)
        print_ddg (dump_file, g);
 
-      get_block_head_tail (loop->header->index, &head, &tail);
+      get_ebb_head_tail (loop->header, loop->header, &head, &tail);
 
       latch_edge = loop_latch_edge (loop);
       gcc_assert (loop->single_exit);
       if (loop->single_exit->count)
        trip_count = latch_edge->count / loop->single_exit->count;
 
-      if (stats_file)
+      if (dump_file)
        {
          rtx line_note = find_line_note (tail);
 
@@ -1163,32 +1087,32 @@ sms_schedule (FILE *dump_file)
            {
              expanded_location xloc;
              NOTE_EXPANDED_LOCATION (xloc, line_note);
-             fprintf (stats_file, "SMS bb %s %d (file, line)\n",
+             fprintf (dump_file, "SMS bb %s %d (file, line)\n",
                       xloc.file, xloc.line);
            }
-         fprintf (stats_file, "SMS single-bb-loop\n");
+         fprintf (dump_file, "SMS single-bb-loop\n");
          if (profile_info && flag_branch_probabilities)
            {
-             fprintf (stats_file, "SMS loop-count ");
-             fprintf (stats_file, HOST_WIDEST_INT_PRINT_DEC,
+             fprintf (dump_file, "SMS loop-count ");
+             fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
                       (HOST_WIDEST_INT) bb->count);
-             fprintf (stats_file, "\n");
-             fprintf (stats_file, "SMS profile-sum-max ");
-             fprintf (stats_file, HOST_WIDEST_INT_PRINT_DEC,
+             fprintf (dump_file, "\n");
+             fprintf (dump_file, "SMS profile-sum-max ");
+             fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
                       (HOST_WIDEST_INT) profile_info->sum_max);
-             fprintf (stats_file, "\n");
+             fprintf (dump_file, "\n");
            }
-         fprintf (stats_file, "SMS doloop\n");
-         fprintf (stats_file, "SMS built-ddg %d\n", g->num_nodes);
-          fprintf (stats_file, "SMS num-loads %d\n", g->num_loads);
-          fprintf (stats_file, "SMS num-stores %d\n", g->num_stores);
+         fprintf (dump_file, "SMS doloop\n");
+         fprintf (dump_file, "SMS built-ddg %d\n", g->num_nodes);
+          fprintf (dump_file, "SMS num-loads %d\n", g->num_loads);
+          fprintf (dump_file, "SMS num-stores %d\n", g->num_stores);
        }
 
 
       /* In case of th loop have doloop register it gets special
         handling.  */
       count_init = NULL_RTX;
-      if ((count_reg = doloop_register_get (tail, &comp)))
+      if ((count_reg = doloop_register_get (tail)))
        {
          basic_block pre_header;
 
@@ -1198,30 +1122,30 @@ sms_schedule (FILE *dump_file)
        }
       gcc_assert (count_reg);
 
-      if (stats_file && count_init)
+      if (dump_file && count_init)
         {
-          fprintf (stats_file, "SMS const-doloop ");
-          fprintf (stats_file, HOST_WIDEST_INT_PRINT_DEC,
+          fprintf (dump_file, "SMS const-doloop ");
+          fprintf (dump_file, HOST_WIDEST_INT_PRINT_DEC,
                     loop_count);
-          fprintf (stats_file, "\n");
+          fprintf (dump_file, "\n");
         }
 
-      node_order = (int *) xmalloc (sizeof (int) * g->num_nodes);
+      node_order = XNEWVEC (int, g->num_nodes);
 
       mii = 1; /* Need to pass some estimate of mii.  */
       rec_mii = sms_order_nodes (g, mii, node_order);
       mii = MAX (res_MII (g), rec_mii);
       maxii = (calculate_maxii (g) * SMS_MAX_II_FACTOR) / 100;
 
-      if (stats_file)
-       fprintf (stats_file, "SMS iis %d %d %d (rec_mii, mii, maxii)\n",
+      if (dump_file)
+       fprintf (dump_file, "SMS iis %d %d %d (rec_mii, mii, maxii)\n",
                 rec_mii, mii, maxii);
 
       /* After sms_order_nodes and before sms_schedule_by_order, to copy over
         ASAP.  */
       set_node_sched_params (g);
 
-      ps = sms_schedule_by_order (g, mii, maxii, node_order, dump_file);
+      ps = sms_schedule_by_order (g, mii, maxii, node_order);
 
       if (ps)
        stage_count = PS_STAGE_COUNT (ps);
@@ -1249,13 +1173,13 @@ sms_schedule (FILE *dump_file)
          int new_cycles;
          struct undo_replace_buff_elem *reg_move_replaces;
 
-         if (stats_file)
+         if (dump_file)
            {
-             fprintf (stats_file,
+             fprintf (dump_file,
                       "SMS succeeded %d %d (with ii, sc)\n", ps->ii,
                       stage_count);
-             print_partial_schedule (ps, stats_file);
-             fprintf (stats_file,
+             print_partial_schedule (ps, dump_file);
+             fprintf (dump_file,
                       "SMS Branch (%d) will later be scheduled at cycle %d.\n",
                       g->closing_branch->cuid, PS_MIN_CYCLE (ps) - 1);
            }
@@ -1286,7 +1210,7 @@ sms_schedule (FILE *dump_file)
              /* SMS is not profitable so undo the permutation and reg move generation
                 and return the kernel to its original state.  */
              if (dump_file)
-               fprintf (dump_file, "Undoing SMS becuase it is not profitable.\n");
+               fprintf (dump_file, "Undoing SMS because it is not profitable.\n");
 
            }
          else
@@ -1299,7 +1223,8 @@ sms_schedule (FILE *dump_file)
                  rtx comp_rtx = gen_rtx_fmt_ee (GT, VOIDmode, count_reg,
                                                 GEN_INT(stage_count));
 
-                 nloop = loop_version (loops, loop, comp_rtx, &condition_bb);
+                 nloop = loop_version (loops, loop, comp_rtx, &condition_bb,
+                                       true);
                }
 
              /* Set new iteration count of loop kernel.  */
@@ -1335,9 +1260,11 @@ sms_schedule (FILE *dump_file)
       free_ddg (g);
     }
 
+  free (g_arr);
+
   /* Release scheduler data, needed until now because of DFA.  */
   sched_finish ();
-  loop_optimizer_finalize (loops, dump_file);
+  loop_optimizer_finalize (loops);
 }
 
 /* The SMS scheduling algorithm itself
@@ -1417,11 +1344,11 @@ sms_schedule (FILE *dump_file)
 #define DFA_HISTORY SMS_DFA_HISTORY
 
 /* Given the partial schedule PS, this function calculates and returns the
-   cycles in wich we can schedule the node with the given index I.
+   cycles in which we can schedule the node with the given index I.
    NOTE: Here we do the backtracking in SMS, in some special cases. We have
    noticed that there are several cases in which we fail    to SMS the loop
    because the sched window of a node is empty    due to tight data-deps. In
-   such cases we want to unschedule    some of the predecssors/successors
+   such cases we want to unschedule    some of the predecessors/successors
    until we get non-empty    scheduling window.  It returns -1 if the
    scheduling window is empty and zero otherwise.  */
 
@@ -1551,7 +1478,7 @@ get_sched_window (partial_schedule_ptr ps, int *nodes_order, int i,
 /* This function implements the scheduling algorithm for SMS according to the
    above algorithm.  */
 static partial_schedule_ptr
-sms_schedule_by_order (ddg_ptr g, int mii, int maxii, int *nodes_order, FILE *dump_file)
+sms_schedule_by_order (ddg_ptr g, int mii, int maxii, int *nodes_order)
 {
   int ii = mii;
   int i, c, success;
@@ -1683,6 +1610,9 @@ sms_schedule_by_order (ddg_ptr g, int mii, int maxii, int *nodes_order, FILE *du
     } /* While try_again_with_larger_ii.  */
 
   sbitmap_free (sched_nodes);
+  sbitmap_free (must_precede);
+  sbitmap_free (must_follow);
+  sbitmap_free (tobe_scheduled);
 
   if (ii >= maxii)
     {
@@ -1735,8 +1665,7 @@ check_nodes_order (int *node_order, int num_nodes)
     {
       int u = node_order[i];
 
-      if (u >= num_nodes || u < 0 || TEST_BIT (tmp, u))
-       abort ();
+      gcc_assert (u < num_nodes && u >= 0 && !TEST_BIT (tmp, u));
 
       SET_BIT (tmp, u);
     }
@@ -1884,11 +1813,12 @@ calculate_order_params (ddg_ptr g, int mii ATTRIBUTE_UNUSED)
 static int
 find_max_asap (ddg_ptr g, sbitmap nodes)
 {
-  int u;
+  unsigned int u = 0;
   int max_asap = -1;
   int result = -1;
+  sbitmap_iterator sbi;
 
-  EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u,
+  EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u, sbi)
     {
       ddg_node_ptr u_node = &g->nodes[u];
 
@@ -1897,19 +1827,20 @@ find_max_asap (ddg_ptr g, sbitmap nodes)
          max_asap = ASAP (u_node);
          result = u;
        }
-    });
+    }
   return result;
 }
 
 static int
 find_max_hv_min_mob (ddg_ptr g, sbitmap nodes)
 {
-  int u;
+  unsigned int u = 0;
   int max_hv = -1;
   int min_mob = INT_MAX;
   int result = -1;
+  sbitmap_iterator sbi;
 
-  EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u,
+  EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u, sbi)
     {
       ddg_node_ptr u_node = &g->nodes[u];
 
@@ -1925,19 +1856,20 @@ find_max_hv_min_mob (ddg_ptr g, sbitmap nodes)
          min_mob = MOB (u_node);
          result = u;
        }
-    });
+    }
   return result;
 }
 
 static int
 find_max_dv_min_mob (ddg_ptr g, sbitmap nodes)
 {
-  int u;
+  unsigned int u = 0;
   int max_dv = -1;
   int min_mob = INT_MAX;
   int result = -1;
+  sbitmap_iterator sbi;
 
-  EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u,
+  EXECUTE_IF_SET_IN_SBITMAP (nodes, 0, u, sbi)
     {
       ddg_node_ptr u_node = &g->nodes[u];
 
@@ -1953,7 +1885,7 @@ find_max_dv_min_mob (ddg_ptr g, sbitmap nodes)
          min_mob = MOB (u_node);
          result = u;
        }
-    });
+    }
   return result;
 }
 
@@ -2064,11 +1996,11 @@ order_nodes_in_scc (ddg_ptr g, sbitmap nodes_ordered, sbitmap scc,
    modulo scheduling.  */
 
 /* Create a partial schedule and allocate a memory to hold II rows.  */
-partial_schedule_ptr
+
+static partial_schedule_ptr
 create_partial_schedule (int ii, ddg_ptr g, int history)
 {
-  partial_schedule_ptr ps = (partial_schedule_ptr)
-                            xmalloc (sizeof (struct partial_schedule));
+  partial_schedule_ptr ps = XNEW (struct partial_schedule);
   ps->rows = (ps_insn_ptr *) xcalloc (ii, sizeof (ps_insn_ptr));
   ps->ii = ii;
   ps->history = history;
@@ -2100,7 +2032,8 @@ free_ps_insns (partial_schedule_ptr ps)
 }
 
 /* Free all the memory allocated to the partial schedule.  */
-void
+
+static void
 free_partial_schedule (partial_schedule_ptr ps)
 {
   if (!ps)
@@ -2112,7 +2045,8 @@ free_partial_schedule (partial_schedule_ptr ps)
 
 /* Clear the rows array with its PS_INSNs, and create a new one with
    NEW_II rows.  */
-void
+
+static void
 reset_partial_schedule (partial_schedule_ptr ps, int new_ii)
 {
   if (!ps)
@@ -2153,7 +2087,7 @@ print_partial_schedule (partial_schedule_ptr ps, FILE *dump)
 static ps_insn_ptr
 create_ps_insn (ddg_node_ptr node, int rest_count, int cycle)
 {
-  ps_insn_ptr ps_i = xmalloc (sizeof (struct ps_insn));
+  ps_insn_ptr ps_i = XNEW (struct ps_insn);
 
   ps_i->node = node;
   ps_i->next_in_row = NULL;
@@ -2346,13 +2280,13 @@ advance_one_cycle (void)
 {
   if (targetm.sched.dfa_pre_cycle_insn)
     state_transition (curr_state,
-                     (*targetm.sched.dfa_pre_cycle_insn) ());
+                     targetm.sched.dfa_pre_cycle_insn ());
 
   state_transition (curr_state, NULL);
 
   if (targetm.sched.dfa_post_cycle_insn)
     state_transition (curr_state,
-                     (*targetm.sched.dfa_post_cycle_insn) ());
+                     targetm.sched.dfa_post_cycle_insn ());
 }
 
 /* Given the kernel of a loop (from FIRST_INSN to LAST_INSN), finds
@@ -2396,8 +2330,8 @@ kernel_number_of_cycles (rtx first_insn, rtx last_insn)
 
       if (targetm.sched.variable_issue)
        can_issue_more =
-         (*targetm.sched.variable_issue) (sched_dump, sched_verbose,
-                                          insn, can_issue_more);
+         targetm.sched.variable_issue (sched_dump, sched_verbose,
+                                       insn, can_issue_more);
       /* A naked CLOBBER or USE generates no instruction, so don't
         let them consume issue slots.  */
       else if (GET_CODE (PATTERN (insn)) != USE
@@ -2444,8 +2378,8 @@ ps_has_conflicts (partial_schedule_ptr ps, int from, int to)
 
          if (targetm.sched.variable_issue)
            can_issue_more =
-             (*targetm.sched.variable_issue) (sched_dump, sched_verbose,
-                                              insn, can_issue_more);
+             targetm.sched.variable_issue (sched_dump, sched_verbose,
+                                           insn, can_issue_more);
          /* A naked CLOBBER or USE generates no instruction, so don't
             let them consume issue slots.  */
          else if (GET_CODE (PATTERN (insn)) != USE
@@ -2535,8 +2469,8 @@ rotate_partial_schedule (partial_schedule_ptr ps, int start_cycle)
   ps->min_cycle -= start_cycle;
 }
 
-/* Remove the node N from the partial schedule PS; becuase we restart the DFA
-   each time we want to check for resuorce conflicts; this is equivalent to
+/* Remove the node N from the partial schedule PS; because we restart the DFA
+   each time we want to check for resource conflicts; this is equivalent to
    unscheduling the node N.  */
 static bool
 ps_unschedule_node (partial_schedule_ptr ps, ddg_node_ptr n)
@@ -2555,5 +2489,65 @@ ps_unschedule_node (partial_schedule_ptr ps, ddg_node_ptr n)
 
   return remove_node_from_ps (ps, ps_i);
 }
-#endif /* INSN_SCHEDULING*/
+#endif /* INSN_SCHEDULING */
+\f
+static bool
+gate_handle_sms (void)
+{
+  return (optimize > 0 && flag_modulo_sched);
+}
+
+
+/* Run instruction scheduler.  */
+/* Perform SMS module scheduling.  */
+static unsigned int
+rest_of_handle_sms (void)
+{
+#ifdef INSN_SCHEDULING
+  basic_block bb;
+
+  /* We want to be able to create new pseudos.  */
+  no_new_pseudos = 0;
+  /* Collect loop information to be used in SMS.  */
+  cfg_layout_initialize (CLEANUP_UPDATE_LIFE);
+  sms_schedule ();
+
+  /* Update the life information, because we add pseudos.  */
+  max_regno = max_reg_num ();
+  allocate_reg_info (max_regno, FALSE, FALSE);
+  update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES,
+                    (PROP_DEATH_NOTES
+                     | PROP_REG_INFO
+                     | PROP_KILL_DEAD_CODE
+                     | PROP_SCAN_DEAD_CODE));
+
+  no_new_pseudos = 1;
+
+  /* Finalize layout changes.  */
+  FOR_EACH_BB (bb)
+    if (bb->next_bb != EXIT_BLOCK_PTR)
+      bb->aux = bb->next_bb;
+  cfg_layout_finalize ();
+  free_dominance_info (CDI_DOMINATORS);
+#endif /* INSN_SCHEDULING */
+  return 0;
+}
+
+struct tree_opt_pass pass_sms =
+{
+  "sms",                                /* name */
+  gate_handle_sms,                      /* gate */
+  rest_of_handle_sms,                   /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_SMS,                               /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  TODO_dump_func |
+  TODO_ggc_collect,                     /* todo_flags_finish */
+  'm'                                   /* letter */
+};