OSDN Git Service

* config/m32r/m32r.h (FUNCTION_ARG, FUNCTION_ARG_ADVANCE): Move
[pf3gnuchains/gcc-fork.git] / gcc / haifa-sched.c
index 204fab6..2787685 100644 (file)
@@ -1,6 +1,6 @@
 /* Instruction scheduling pass.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
    Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
    and currently maintained by, Jim Wilson (wilson@cygnus.com)
@@ -128,6 +128,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
+#include "diagnostic-core.h"
 #include "toplev.h"
 #include "rtl.h"
 #include "tm_p.h"
@@ -138,7 +139,6 @@ along with GCC; see the file COPYING3.  If not see
 #include "insn-config.h"
 #include "insn-attr.h"
 #include "except.h"
-#include "toplev.h"
 #include "recog.h"
 #include "sched-int.h"
 #include "target.h"
@@ -148,6 +148,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "dbgcnt.h"
 #include "cfgloop.h"
 #include "ira.h"
+#include "emit-rtl.h"  /* FIXME: Can go away once crtl is moved to rtl.h.  */
 
 #ifdef INSN_SCHEDULING
 
@@ -718,7 +719,7 @@ initiate_bb_reg_pressure_info (basic_block bb)
 
   if (current_nr_blocks > 1)
     FOR_BB_INSNS (bb, insn)
-      if (INSN_P (insn))
+      if (NONDEBUG_INSN_P (insn))
        setup_ref_regs (PATTERN (insn));
   initiate_reg_pressure_info (df_get_live_in (bb));
 #ifdef EH_RETURN_DATA_REGNO
@@ -766,7 +767,8 @@ dying_use_p (struct reg_use_data *use)
   struct reg_use_data *next;
 
   for (next = use->next_regno_use; next != use; next = next->next_regno_use)
-    if (QUEUE_INDEX (next->insn) != QUEUE_SCHEDULED)
+    if (NONDEBUG_INSN_P (next->insn)
+       && QUEUE_INDEX (next->insn) != QUEUE_SCHEDULED)
       return false;
   return true;
 }
@@ -1122,6 +1124,8 @@ setup_insn_reg_pressure_info (rtx insn)
   struct reg_use_data *use;
   static int death[N_REG_CLASSES];
 
+  gcc_checking_assert (!DEBUG_INSN_P (insn));
+
   excess_cost_change = 0;
   for (i = 0; i < ira_reg_class_cover_size; i++)
     death[ira_reg_class_cover[i]] = 0;
@@ -1498,7 +1502,8 @@ ready_sort (struct ready_list *ready)
   if (sched_pressure_p)
     {
       for (i = 0; i < ready->n_ready; i++)
-       setup_insn_reg_pressure_info (first[i]);
+       if (!DEBUG_INSN_P (first[i]))
+         setup_insn_reg_pressure_info (first[i]);
     }
   SCHED_SORT (first, ready->n_ready);
 }
@@ -1562,6 +1567,8 @@ update_register_pressure (rtx insn)
   struct reg_use_data *use;
   struct reg_set_data *set;
 
+  gcc_checking_assert (!DEBUG_INSN_P (insn));
+
   for (use = INSN_REG_USE_LIST (insn); use != NULL; use = use->next_insn_use)
     if (dying_use_p (use) && bitmap_bit_p (curr_reg_live, use->regno))
       mark_regno_birth_or_death (use->regno, false);
@@ -1585,7 +1592,8 @@ setup_insn_max_reg_pressure (rtx after, bool update_p)
     max_reg_pressure[ira_reg_class_cover[i]]
       = curr_reg_pressure[ira_reg_class_cover[i]];
   for (insn = NEXT_INSN (after);
-       insn != NULL_RTX && BLOCK_FOR_INSN (insn) == BLOCK_FOR_INSN (after);
+       insn != NULL_RTX && ! BARRIER_P (insn)
+        && BLOCK_FOR_INSN (insn) == BLOCK_FOR_INSN (after);
        insn = NEXT_INSN (insn))
     if (NONDEBUG_INSN_P (insn))
       {
@@ -1681,7 +1689,7 @@ schedule_insn (rtx insn)
       fputc ('\n', sched_dump);
     }
 
-  if (sched_pressure_p)
+  if (sched_pressure_p && !DEBUG_INSN_P (insn))
     update_reg_and_insn_max_reg_pressure (insn);
 
   /* Scheduling instruction should have all its dependencies resolved and
@@ -1694,6 +1702,7 @@ schedule_insn (rtx insn)
         sd_iterator_cond (&sd_it, &dep);)
       {
        rtx dbg = DEP_PRO (dep);
+       struct reg_use_data *use, *next;
 
        gcc_assert (DEBUG_INSN_P (dbg));
 
@@ -1715,6 +1724,20 @@ schedule_insn (rtx insn)
        INSN_VAR_LOCATION_LOC (dbg) = gen_rtx_UNKNOWN_VAR_LOC ();
        df_insn_rescan (dbg);
 
+       /* Unknown location doesn't use any registers.  */
+       for (use = INSN_REG_USE_LIST (dbg); use != NULL; use = next)
+         {
+           struct reg_use_data *prev = use;
+
+           /* Remove use from the cyclic next_regno_use chain first.  */
+           while (prev->next_regno_use != use)
+             prev = prev->next_regno_use;
+           prev->next_regno_use = use->next_regno_use;
+           next = use->next_insn_use;
+           free (use);
+         }
+       INSN_REG_USE_LIST (dbg) = NULL;
+
        /* We delete rather than resolve these deps, otherwise we
           crash in sched_free_deps(), because forward deps are
           expected to be released before backward deps.  */
@@ -1775,7 +1798,7 @@ schedule_insn (rtx insn)
      forward dependencies for INSN anymore.  Nevertheless they are used in
      heuristics in rank_for_schedule (), early_queue_to_ready () and in
      some targets (e.g. rs6000).  Thus the earliest place where we *can*
-     remove dependencies is after targetm.sched.md_finish () call in
+     remove dependencies is after targetm.sched.finish () call in
      schedule_block ().  But, on the other side, the safest place to remove
      dependencies is when we are finishing scheduling entire region.  As we
      don't generate [many] dependencies during scheduling itself, we won't
@@ -1803,89 +1826,82 @@ schedule_insn (rtx insn)
 
 /* Functions for handling of notes.  */
 
-/* Insert the INSN note at the end of the notes list.  */
-static void
-add_to_note_list (rtx insn, rtx *note_list_end_p)
-{
-  PREV_INSN (insn) = *note_list_end_p;
-  if (*note_list_end_p)
-    NEXT_INSN (*note_list_end_p) = insn;
-  *note_list_end_p = insn;
-}
-
 /* Add note list that ends on FROM_END to the end of TO_ENDP.  */
 void
 concat_note_lists (rtx from_end, rtx *to_endp)
 {
   rtx from_start;
 
+  /* It's easy when have nothing to concat.  */
   if (from_end == NULL)
-    /* It's easy when have nothing to concat.  */
     return;
 
+  /* It's also easy when destination is empty.  */
   if (*to_endp == NULL)
-    /* It's also easy when destination is empty.  */
     {
       *to_endp = from_end;
       return;
     }
 
   from_start = from_end;
-  /* A note list should be traversed via PREV_INSN.  */
   while (PREV_INSN (from_start) != NULL)
     from_start = PREV_INSN (from_start);
 
-  add_to_note_list (from_start, to_endp);
+  PREV_INSN (from_start) = *to_endp;
+  NEXT_INSN (*to_endp) = from_start;
   *to_endp = from_end;
 }
 
-/* Delete notes beginning with INSN and put them in the chain
-   of notes ended by NOTE_LIST.
-   Returns the insn following the notes.  */
-static rtx
-unlink_other_notes (rtx insn, rtx tail)
+/* Delete notes between HEAD and TAIL and put them in the chain
+   of notes ended by NOTE_LIST.  */
+void
+remove_notes (rtx head, rtx tail)
 {
-  rtx prev = PREV_INSN (insn);
-
-  while (insn != tail && NOTE_NOT_BB_P (insn))
-    {
-      rtx next = NEXT_INSN (insn);
-      basic_block bb = BLOCK_FOR_INSN (insn);
+  rtx next_tail, insn, next;
 
-      /* Delete the note from its current position.  */
-      if (prev)
-       NEXT_INSN (prev) = next;
-      if (next)
-       PREV_INSN (next) = prev;
+  note_list = 0;
+  if (head == tail && !INSN_P (head))
+    return;
 
-      if (bb)
-        {
-          /* Basic block can begin with either LABEL or
-             NOTE_INSN_BASIC_BLOCK.  */
-          gcc_assert (BB_HEAD (bb) != insn);
+  next_tail = NEXT_INSN (tail);
+  for (insn = head; insn != next_tail; insn = next)
+    {
+      next = NEXT_INSN (insn);
+      if (!NOTE_P (insn))
+       continue;
 
-          /* Check if we are removing last insn in the BB.  */
-          if (BB_END (bb) == insn)
-            BB_END (bb) = prev;
-        }
+      switch (NOTE_KIND (insn))
+       {
+       case NOTE_INSN_BASIC_BLOCK:
+         continue;
 
-      /* See sched_analyze to see how these are handled.  */
-      if (NOTE_KIND (insn) != NOTE_INSN_EH_REGION_BEG
-         && NOTE_KIND (insn) != NOTE_INSN_EH_REGION_END)
-        add_to_note_list (insn, &note_list);
+       case NOTE_INSN_EPILOGUE_BEG:
+         if (insn != tail)
+           {
+             remove_insn (insn);
+             add_reg_note (next, REG_SAVE_NOTE,
+                           GEN_INT (NOTE_INSN_EPILOGUE_BEG));
+             break;
+           }
+         /* FALLTHRU */
 
-      insn = next;
-    }
+       default:
+         remove_insn (insn);
+
+         /* Add the note to list that ends at NOTE_LIST.  */
+         PREV_INSN (insn) = note_list;
+         NEXT_INSN (insn) = NULL_RTX;
+         if (note_list)
+           NEXT_INSN (note_list) = insn;
+         note_list = insn;
+         break;
+       }
 
-  if (insn == tail)
-    {
-      gcc_assert (sel_sched_p ());
-      return prev;
+      gcc_assert ((sel_sched_p () || insn != tail) && insn != head);
     }
-
-  return insn;
 }
 
+
 /* Return the head and tail pointers of ebb starting at BEG and ending
    at END.  */
 void
@@ -1939,62 +1955,6 @@ no_real_insns_p (const_rtx head, const_rtx tail)
   return 1;
 }
 
-/* Delete notes between HEAD and TAIL and put them in the chain
-   of notes ended by NOTE_LIST.  */
-static void
-rm_other_notes (rtx head, rtx tail)
-{
-  rtx next_tail;
-  rtx insn;
-
-  note_list = 0;
-  if (head == tail && (! INSN_P (head)))
-    return;
-
-  next_tail = NEXT_INSN (tail);
-  for (insn = head; insn != next_tail; insn = NEXT_INSN (insn))
-    {
-      rtx prev;
-
-      /* Farm out notes, and maybe save them in NOTE_LIST.
-         This is needed to keep the debugger from
-         getting completely deranged.  */
-      if (NOTE_NOT_BB_P (insn))
-       {
-         prev = insn;
-         insn = unlink_other_notes (insn, next_tail);
-
-         gcc_assert ((sel_sched_p ()
-                      || prev != tail) && prev != head && insn != next_tail);
-       }
-    }
-}
-
-/* Same as above, but also process REG_SAVE_NOTEs of HEAD.  */
-void
-remove_notes (rtx head, rtx tail)
-{
-  /* rm_other_notes only removes notes which are _inside_ the
-     block---that is, it won't remove notes before the first real insn
-     or after the last real insn of the block.  So if the first insn
-     has a REG_SAVE_NOTE which would otherwise be emitted before the
-     insn, it is redundant with the note before the start of the
-     block, and so we have to take it out.  */
-  if (INSN_P (head))
-    {
-      rtx note;
-
-      for (note = REG_NOTES (head); note; note = XEXP (note, 1))
-       if (REG_NOTE_KIND (note) == REG_SAVE_NOTE)
-         remove_note (head, note);
-    }
-
-  /* Remove remaining note insns from the block, save them in
-     note_list.  These notes are restored at the end of
-     schedule_block ().  */
-  rm_other_notes (head, tail);
-}
-
 /* Restore-other-notes: NOTE_LIST is the end of a chain of notes
    previously found among the insns.  Insert them just before HEAD.  */
 rtx
@@ -2043,13 +2003,9 @@ queue_to_ready (struct ready_list *ready)
   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);
-      while (skip_insn && DEBUG_INSN_P (skip_insn))
-       skip_insn = next_nonnote_insn (skip_insn);
-    }
+    /* If debug counter is activated do not requeue insn next after
+       last_scheduled_insn.  */
+    skip_insn = next_nonnote_nondebug_insn (last_scheduled_insn);
   else
     skip_insn = NULL_RTX;
 
@@ -2315,11 +2271,9 @@ debug_ready_list (struct ready_list *ready)
   fprintf (sched_dump, "\n");
 }
 
-/* Search INSN for REG_SAVE_NOTE note pairs for
-   NOTE_INSN_EHREGION_{BEG,END}; and convert them back into
-   NOTEs.  The REG_SAVE_NOTE note following first one is contains the
-   saved value for NOTE_BLOCK_NUMBER which is useful for
-   NOTE_INSN_EH_REGION_{BEG,END} NOTEs.  */
+/* Search INSN for REG_SAVE_NOTE notes and convert them back into insn
+   NOTEs.  This is used for NOTE_INSN_EPILOGUE_BEG, so that sched-ebb
+   replaces the epilogue note in the correct basic block.  */
 void
 reemit_notes (rtx insn)
 {
@@ -2850,8 +2804,8 @@ schedule_block (basic_block *target_bb)
   /* It is used for first cycle multipass scheduling.  */
   temp_state = alloca (dfa_state_size);
 
-  if (targetm.sched.md_init)
-    targetm.sched.md_init (sched_dump, sched_verbose, ready.veclen);
+  if (targetm.sched.init)
+    targetm.sched.init (sched_dump, sched_verbose, ready.veclen);
 
   /* We start inserting insns after PREV_HEAD.  */
   last_scheduled_insn = prev_head;
@@ -3325,9 +3279,9 @@ schedule_block (basic_block *target_bb)
       fix_inter_tick (NEXT_INSN (prev_head), last_scheduled_insn);
     }
 
-  if (targetm.sched.md_finish)
+  if (targetm.sched.finish)
     {
-      targetm.sched.md_finish (sched_dump, sched_verbose);
+      targetm.sched.finish (sched_dump, sched_verbose);
       /* Target might have added some instructions to the scheduled block
         in its md_finish () hook.  These new insns don't have any data
         initialized and to identify them we extend h_i_d so that they'll
@@ -3486,9 +3440,8 @@ sched_init (void)
 
   regstat_compute_calls_crossed ();
 
-  if (targetm.sched.md_init_global)
-    targetm.sched.md_init_global (sched_dump, sched_verbose,
-                                 get_max_uid () + 1);
+  if (targetm.sched.init_global)
+    targetm.sched.init_global (sched_dump, sched_verbose, get_max_uid () + 1);
 
   if (sched_pressure_p)
     {
@@ -3613,8 +3566,8 @@ sched_finish (void)
     }
   free (curr_state);
 
-  if (targetm.sched.md_finish_global)
-    targetm.sched.md_finish_global (sched_dump, sched_verbose);
+  if (targetm.sched.finish_global)
+    targetm.sched.finish_global (sched_dump, sched_verbose);
 
   end_alias_analysis ();
 
@@ -3660,9 +3613,8 @@ fix_inter_tick (rtx head, rtx tail)
          gcc_assert (tick >= MIN_TICK);
 
          /* Fix INSN_TICK of instruction from just scheduled block.  */
-         if (!bitmap_bit_p (&processed, INSN_LUID (head)))
+         if (bitmap_set_bit (&processed, INSN_LUID (head)))
            {
-             bitmap_set_bit (&processed, INSN_LUID (head));
              tick -= next_clock;
 
              if (tick < MIN_TICK)
@@ -3682,9 +3634,8 @@ fix_inter_tick (rtx head, rtx tail)
                  /* If NEXT has its INSN_TICK calculated, fix it.
                     If not - it will be properly calculated from
                     scratch later in fix_tick_ready.  */
-                 && !bitmap_bit_p (&processed, INSN_LUID (next)))
+                 && bitmap_set_bit (&processed, INSN_LUID (next)))
                {
-                 bitmap_set_bit (&processed, INSN_LUID (next));
                  tick -= next_clock;
 
                  if (tick < MIN_TICK)
@@ -4803,11 +4754,8 @@ fix_recovery_deps (basic_block rec)
            {
              sd_delete_dep (sd_it);
 
-             if (!bitmap_bit_p (&in_ready, INSN_LUID (consumer)))
-               {
-                 ready_list = alloc_INSN_LIST (consumer, ready_list);
-                 bitmap_set_bit (&in_ready, INSN_LUID (consumer));
-               }
+             if (bitmap_set_bit (&in_ready, INSN_LUID (consumer)))
+               ready_list = alloc_INSN_LIST (consumer, ready_list);
            }
          else
            {
@@ -5145,7 +5093,7 @@ calc_priorities (rtx_vec_t roots)
   int i;
   rtx insn;
 
-  for (i = 0; VEC_iterate (rtx, roots, i, insn); i++)
+  FOR_EACH_VEC_ELT (rtx, roots, i, insn)
     priority (insn);
 }
 
@@ -5373,7 +5321,7 @@ sched_scan (const struct sched_scan_info_def *ssi,
          unsigned i;
          basic_block x;
 
-         for (i = 0; VEC_iterate (basic_block, bbs, i, x); i++)
+         FOR_EACH_VEC_ELT (basic_block, bbs, i, x)
            init_bb (x);
        }
 
@@ -5388,7 +5336,7 @@ sched_scan (const struct sched_scan_info_def *ssi,
       unsigned i;
       basic_block x;
 
-      for (i = 0; VEC_iterate (basic_block, bbs, i, x); i++)
+      FOR_EACH_VEC_ELT (basic_block, bbs, i, x)
        init_insns_in_bb (x);
     }
 
@@ -5400,7 +5348,7 @@ sched_scan (const struct sched_scan_info_def *ssi,
       unsigned i;
       rtx x;
 
-      for (i = 0; VEC_iterate (rtx, insns, i, x); i++)
+      FOR_EACH_VEC_ELT (rtx, insns, i, x)
        init_insn (x);
     }
 
@@ -5530,7 +5478,7 @@ haifa_finish_h_i_d (void)
   haifa_insn_data_t data;
   struct reg_use_data *use, *next;
 
-  for (i = 0; VEC_iterate (haifa_insn_data_def, h_i_d, i, data); i++)
+  FOR_EACH_VEC_ELT (haifa_insn_data_def, h_i_d, i, data)
     {
       if (data->reg_pressure != NULL)
        free (data->reg_pressure);