OSDN Git Service

gcc/fortran:
[pf3gnuchains/gcc-fork.git] / gcc / haifa-sched.c
index cf02644..809d934 100644 (file)
@@ -144,6 +144,7 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
 #include "target.h"
 #include "output.h"
 #include "params.h"
+#include "dbgcnt.h"
 
 #ifdef INSN_SCHEDULING
 
@@ -215,9 +216,6 @@ static bool added_recovery_block_p;
 /* Counters of different types of speculative instructions.  */
 static int nr_begin_data, nr_be_in_data, nr_begin_control, nr_be_in_control;
 
-/* Pointers to GLAT data.  See init_glat for more information.  */
-regset *glat_start, *glat_end;
-
 /* Array used in {unlink, restore}_bb_notes.  */
 static rtx *bb_header = 0;
 
@@ -541,7 +539,7 @@ static rtx ready_remove (struct ready_list *, int);
 static void ready_remove_insn (rtx);
 static int max_issue (struct ready_list *, int *, int);
 
-static rtx choose_ready (struct ready_list *);
+static int choose_ready (struct ready_list *, rtx *);
 
 static void fix_inter_tick (rtx, rtx);
 static int fix_tick_ready (rtx);
@@ -573,10 +571,6 @@ static void extend_bb (void);
 static void fix_jump_move (rtx);
 static void move_block_after_check (rtx);
 static void move_succs (VEC(edge,gc) **, basic_block);
-static void init_glat (void);
-static void init_glat1 (basic_block);
-static void attach_life_info1 (basic_block);
-static void free_glat (void);
 static void sched_remove_insn (rtx);
 static void clear_priorities (rtx, rtx_vec_t *);
 static void calc_priorities (rtx_vec_t);
@@ -1489,9 +1483,17 @@ queue_to_ready (struct ready_list *ready)
 {
   rtx insn;
   rtx link;
+  rtx skip_insn;
 
   q_ptr = NEXT_Q (q_ptr);
 
+  if (dbg_cnt (sched_insn) == false)
+    /* If debug counter is activated do not requeue insn next after
+       last_scheduled_insn.  */
+    skip_insn = next_nonnote_insn (last_scheduled_insn);
+  else
+    skip_insn = NULL_RTX;
+
   /* Add all pending insns that can be scheduled without stalls to the
      ready list.  */
   for (link = insn_queue[q_ptr]; link; link = XEXP (link, 1))
@@ -1507,7 +1509,8 @@ queue_to_ready (struct ready_list *ready)
         See the comment in schedule_block for the rationale.  */
       if (!reload_completed
          && ready->n_ready > MAX_SCHED_READY_INSNS
-         && !SCHED_GROUP_P (insn))
+         && !SCHED_GROUP_P (insn)
+         && insn != skip_insn)
        {
          if (sched_verbose >= 2)
            fprintf (sched_dump, "requeued because ready full\n");
@@ -1840,6 +1843,7 @@ move_insn (rtx insn)
        }
 
       set_block_for_insn (insn, bb);    
+      df_insn_change_bb (insn);
   
       /* Update BB_END, if needed.  */
       if (BB_END (bb) == last)
@@ -1985,17 +1989,43 @@ max_issue (struct ready_list *ready, int *index, int max_points)
 
 /* The following function chooses insn from READY and modifies
    *N_READY and READY.  The following function is used only for first
-   cycle multipass scheduling.  */
-
-static rtx
-choose_ready (struct ready_list *ready)
+   cycle multipass scheduling.
+   Return:
+   -1 if cycle should be advanced,
+   0 if INSN_PTR is set to point to the desirable insn,
+   1 if choose_ready () should be restarted without advancing the cycle.  */
+static int
+choose_ready (struct ready_list *ready, rtx *insn_ptr)
 {
-  int lookahead = 0;
+  int lookahead;
+
+  if (dbg_cnt (sched_insn) == false)
+    {
+      rtx insn;
+
+      insn = next_nonnote_insn (last_scheduled_insn);
+
+      if (QUEUE_INDEX (insn) == QUEUE_READY)
+       /* INSN is in the ready_list.  */
+       {
+         ready_remove_insn (insn);
+         *insn_ptr = insn;
+         return 0;
+       }
+
+      /* INSN is in the queue.  Advance cycle to move it to the ready list.  */
+      return -1;
+    }
+
+  lookahead = 0;
 
   if (targetm.sched.first_cycle_multipass_dfa_lookahead)
     lookahead = targetm.sched.first_cycle_multipass_dfa_lookahead ();
   if (lookahead <= 0 || SCHED_GROUP_P (ready_element (ready, 0)))
-    return ready_remove_first (ready);
+    {
+      *insn_ptr = ready_remove_first (ready);
+      return 0;
+    }
   else
     {
       /* Try to choose the better insn.  */
@@ -2012,7 +2042,10 @@ choose_ready (struct ready_list *ready)
        }
       insn = ready_element (ready, 0);
       if (INSN_CODE (insn) < 0)
-       return ready_remove_first (ready);
+       {
+         *insn_ptr = ready_remove_first (ready);
+         return 0;
+       }
 
       if (spec_info
          && spec_info->flags & (PREFER_NON_DATA_SPEC
@@ -2054,7 +2087,7 @@ choose_ready (struct ready_list *ready)
           list.  */
        {
          change_queue_index (insn, 1);
-         return 0;
+         return 1;
        }
 
       max_points = ISSUE_POINTS (insn);
@@ -2076,9 +2109,15 @@ choose_ready (struct ready_list *ready)
        }
 
       if (max_issue (ready, &index, max_points) == 0)
-       return ready_remove_first (ready);
+       {
+         *insn_ptr = ready_remove_first (ready);
+         return 0;
+       }
       else
-       return ready_remove (ready, index);
+       {
+         *insn_ptr = ready_remove (ready, index);
+         return 0;
+       }
     }
 }
 
@@ -2177,9 +2216,27 @@ schedule_block (basic_block *target_bb, int rgn_n_insns1)
                   ";;\t\t before reload => truncated to %d insns\n", i);
        }
 
-      /* Delay all insns past it for 1 cycle.  */
-      while (i < ready.n_ready)
-       queue_insn (ready_remove (&ready, i), 1);
+      /* Delay all insns past it for 1 cycle.  If debug counter is
+        activated make an exception for the insn right after
+        last_scheduled_insn.  */
+      {
+       rtx skip_insn;
+
+       if (dbg_cnt (sched_insn) == false)
+         skip_insn = next_nonnote_insn (last_scheduled_insn);
+       else
+         skip_insn = NULL_RTX;
+
+       while (i < ready.n_ready)
+         {
+           rtx insn;
+
+           insn = ready_remove (&ready, i);
+
+           if (insn != skip_insn)
+             queue_insn (insn, 1);
+         }
+      }
     }
 
   /* Now we can restore basic block notes and maintain precise cfg.  */
@@ -2279,9 +2336,19 @@ schedule_block (basic_block *target_bb, int rgn_n_insns1)
          /* Select and remove the insn from the ready list.  */
          if (sort_p)
            {
-             insn = choose_ready (&ready);
-             if (!insn)
+             int res;
+
+             insn = NULL_RTX;
+             res = choose_ready (&ready, &insn);
+
+             if (res < 0)
+               /* Finish cycle.  */
+               break;
+             if (res > 0)
+               /* Restart choose_ready ().  */
                continue;
+
+             gcc_assert (insn != NULL_RTX);
            }
          else
            insn = ready_remove_first (&ready);
@@ -2359,7 +2426,7 @@ schedule_block (basic_block *target_bb, int rgn_n_insns1)
             generate_recovery_code (insn);
 
          if (control_flow_insn_p (last_scheduled_insn)      
-             /* This is used to to switch basic blocks by request
+             /* This is used to switch basic blocks by request
                 from scheduler front-end (actually, sched-ebb.c only).
                 This is used to process blocks with single fallthru
                 edge.  If succeeding block has jump, it [jump] will try
@@ -2680,13 +2747,8 @@ sched_init (void)
   init_alias_analysis ();
 
   old_last_basic_block = 0;
-  glat_start = 0;  
-  glat_end = 0;
   extend_bb ();
 
-  if (current_sched_info->flags & USE_GLAT)
-    init_glat ();
-
   /* Compute INSN_REG_WEIGHT for all blocks.  We must do this before
      removing death notes.  */
   FOR_EACH_BB_REVERSE (b)
@@ -2714,7 +2776,6 @@ sched_finish (void)
   dfa_finish ();
   free_dependency_caches ();
   end_alias_analysis ();
-  free_glat ();
 
   if (targetm.sched.md_finish_global)
     targetm.sched.md_finish_global (sched_dump, sched_verbose);
@@ -3297,7 +3358,7 @@ add_to_speculative_block (rtx insn)
       
       rec = BLOCK_FOR_INSN (check);
       
-      twin = emit_insn_before (copy_rtx (PATTERN (insn)), BB_END (rec));
+      twin = emit_insn_before (copy_insn (PATTERN (insn)), BB_END (rec));
       extend_global (twin);
 
       copy_deps_list_change_con (INSN_RESOLVED_BACK_DEPS (twin),
@@ -4064,13 +4125,6 @@ extend_bb (void)
 
   old_last_basic_block = last_basic_block;
 
-  if (current_sched_info->flags & USE_GLAT)
-    {
-      glat_start = xrealloc (glat_start,
-                             last_basic_block * sizeof (*glat_start));
-      glat_end = xrealloc (glat_end, last_basic_block * sizeof (*glat_end));
-    }
-
   /* The following is done to keep current_sched_info->next_tail non null.  */
 
   insn = BB_END (EXIT_BLOCK_PTR->prev_bb);
@@ -4093,15 +4147,10 @@ extend_bb (void)
 void
 add_block (basic_block bb, basic_block ebb)
 {
-  gcc_assert (current_sched_info->flags & DETACH_LIFE_INFO
-             && bb->il.rtl->global_live_at_start == 0
-             && bb->il.rtl->global_live_at_end == 0);
+  gcc_assert (current_sched_info->flags & NEW_BBS);
 
   extend_bb ();
 
-  glat_start[bb->index] = 0;
-  glat_end[bb->index] = 0;
-
   if (current_sched_info->add_block)
     /* This changes only data structures of the front-end.  */
     current_sched_info->add_block (bb, ebb);
@@ -4164,6 +4213,8 @@ move_block_after_check (rtx jump)
   move_succs (&(jump_bb->succs), bb);
   move_succs (&(jump_bb_next->succs), jump_bb);
   move_succs (&t, jump_bb_next);
+
+  df_mark_solutions_dirty ();
   
   if (current_sched_info->fix_recovery_cfg)
     current_sched_info->fix_recovery_cfg 
@@ -4189,115 +4240,6 @@ move_succs (VEC(edge,gc) **succsp, basic_block to)
   *succsp = 0;
 }
 
-/* Initialize GLAT (global_live_at_{start, end}) structures.
-   GLAT structures are used to substitute global_live_{start, end}
-   regsets during scheduling.  This is necessary to use such functions as
-   split_block (), as they assume consistency of register live information.  */
-static void
-init_glat (void)
-{
-  basic_block bb;
-
-  FOR_ALL_BB (bb)
-    init_glat1 (bb);
-}
-
-/* Helper function for init_glat.  */
-static void
-init_glat1 (basic_block bb)
-{
-  gcc_assert (bb->il.rtl->global_live_at_start != 0
-             && bb->il.rtl->global_live_at_end != 0);
-
-  glat_start[bb->index] = bb->il.rtl->global_live_at_start;
-  glat_end[bb->index] = bb->il.rtl->global_live_at_end;
-  
-  if (current_sched_info->flags & DETACH_LIFE_INFO)
-    {
-      bb->il.rtl->global_live_at_start = 0;
-      bb->il.rtl->global_live_at_end = 0;
-    }
-}
-
-/* Attach reg_live_info back to basic blocks.
-   Also save regsets, that should not have been changed during scheduling,
-   for checking purposes (see check_reg_live).  */
-void
-attach_life_info (void)
-{
-  basic_block bb;
-
-  FOR_ALL_BB (bb)
-    attach_life_info1 (bb);
-}
-
-/* Helper function for attach_life_info.  */
-static void
-attach_life_info1 (basic_block bb)
-{
-  gcc_assert (bb->il.rtl->global_live_at_start == 0
-             && bb->il.rtl->global_live_at_end == 0);
-
-  if (glat_start[bb->index])
-    {
-      gcc_assert (glat_end[bb->index]);    
-
-      bb->il.rtl->global_live_at_start = glat_start[bb->index];
-      bb->il.rtl->global_live_at_end = glat_end[bb->index];
-
-      /* Make them NULL, so they won't be freed in free_glat.  */
-      glat_start[bb->index] = 0;
-      glat_end[bb->index] = 0;
-
-#ifdef ENABLE_CHECKING
-      if (bb->index < NUM_FIXED_BLOCKS
-         || current_sched_info->region_head_or_leaf_p (bb, 0))
-       {
-         glat_start[bb->index] = ALLOC_REG_SET (&reg_obstack);
-         COPY_REG_SET (glat_start[bb->index],
-                       bb->il.rtl->global_live_at_start);
-       }
-
-      if (bb->index < NUM_FIXED_BLOCKS
-         || current_sched_info->region_head_or_leaf_p (bb, 1))
-       {       
-         glat_end[bb->index] = ALLOC_REG_SET (&reg_obstack);
-         COPY_REG_SET (glat_end[bb->index], bb->il.rtl->global_live_at_end);
-       }
-#endif
-    }
-  else
-    {
-      gcc_assert (!glat_end[bb->index]);
-
-      bb->il.rtl->global_live_at_start = ALLOC_REG_SET (&reg_obstack);
-      bb->il.rtl->global_live_at_end = ALLOC_REG_SET (&reg_obstack);
-    }
-}
-
-/* Free GLAT information.  */
-static void
-free_glat (void)
-{
-#ifdef ENABLE_CHECKING
-  if (current_sched_info->flags & DETACH_LIFE_INFO)
-    {
-      basic_block bb;
-
-      FOR_ALL_BB (bb)
-       {
-         if (glat_start[bb->index])
-           FREE_REG_SET (glat_start[bb->index]);
-         if (glat_end[bb->index])
-           FREE_REG_SET (glat_end[bb->index]);
-       }
-    }
-#endif
-
-  free (glat_start);
-  free (glat_end);
-}
-
 /* Remove INSN from the instruction stream.
    INSN should have any dependencies.  */
 static void
@@ -4536,54 +4478,8 @@ check_sched_flags (void)
     gcc_assert (!(f & DO_SPECULATION));
   if (f & DO_SPECULATION)
     gcc_assert (!flag_sched_stalled_insns
-               && (f & DETACH_LIFE_INFO)
                && spec_info
                && spec_info->mask);
-  if (f & DETACH_LIFE_INFO)
-    gcc_assert (f & USE_GLAT);
-}
-
-/* Check global_live_at_{start, end} regsets.
-   If FATAL_P is TRUE, then abort execution at the first failure.
-   Otherwise, print diagnostics to STDERR (this mode is for calling
-   from debugger).  */
-void
-check_reg_live (bool fatal_p)
-{
-  basic_block bb;
-
-  FOR_ALL_BB (bb)
-    {
-      int i;
-
-      i = bb->index;
-
-      if (glat_start[i])
-       {
-         bool b = bitmap_equal_p (bb->il.rtl->global_live_at_start,
-                                  glat_start[i]);
-
-         if (!b)
-           {
-             gcc_assert (!fatal_p);
-
-             fprintf (stderr, ";; check_reg_live_at_start (%d) failed.\n", i);
-           }
-       }
-
-      if (glat_end[i])
-       {
-         bool b = bitmap_equal_p (bb->il.rtl->global_live_at_end,
-                                  glat_end[i]);
-
-         if (!b)
-           {
-             gcc_assert (!fatal_p);
-
-             fprintf (stderr, ";; check_reg_live_at_end (%d) failed.\n", i);
-           }
-       }
-    }
 }
 #endif /* ENABLE_CHECKING */