OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / reorg.c
index fbaf968..8b9d7ef 100644 (file)
@@ -1,6 +1,6 @@
 /* Perform instruction reorganizations for delay slot filling.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
    Contributed by Richard Kenner (kenner@vlsi1.ultra.nyu.edu).
    Hacked by Michael Tiemann (tiemann@cygnus.com).
 
@@ -18,8 +18,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.  */
 
 /* Instruction reorganization pass.
 
@@ -133,6 +133,9 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "resource.h"
 #include "except.h"
 #include "params.h"
+#include "timevar.h"
+#include "target.h"
+#include "tree-pass.h"
 
 #ifdef DELAY_SLOTS
 
@@ -384,7 +387,7 @@ find_end_label (void)
       /* If the basic block reorder pass moves the return insn to
         some other place try to locate it again and put our
         end_of_function_label there.  */
-      while (insn && ! (GET_CODE (insn) == JUMP_INSN
+      while (insn && ! (JUMP_P (insn)
                        && (GET_CODE (PATTERN (insn)) == RETURN)))
        insn = PREV_INSN (insn);
       if (insn)
@@ -420,7 +423,12 @@ find_end_label (void)
             if needed.  */
          emit_label (end_of_function_label);
 #ifdef HAVE_return
-         if (HAVE_return)
+         /* We don't bother trying to create a return insn if the
+            epilogue has filled delay-slots; we would have to try and
+            move the delay-slot fillers to the delay-slots for the new
+            return insn or in front of the new return insn.  */
+         if (current_function_epilogue_delay_list == NULL
+             && HAVE_return)
            {
              /* The return we make may have delay slots too.  */
              rtx insn = gen_return ();
@@ -1926,7 +1934,7 @@ reorg_redirect_jump (rtx jump, rtx nlabel)
    that reference values used in INSN.  If we find one, then we move the
    REG_DEAD note to INSN.
 
-   This is needed to handle the case where an later insn (after INSN) has a
+   This is needed to handle the case where a later insn (after INSN) has a
    REG_DEAD note for a register used by INSN, and this later insn subsequently
    gets moved before a CODE_LABEL because it is a redundant insn.  In this
    case, mark_target_live_regs may be confused into thinking the register
@@ -3115,10 +3123,11 @@ relax_delay_slots (rtx first)
          if (target_label && target_label != JUMP_LABEL (insn))
            reorg_redirect_jump (insn, target_label);
 
-         /* See if this jump branches around an unconditional jump.
-            If so, invert this jump and point it to the target of the
+         /* See if this jump conditionally branches around an unconditional
+            jump.  If so, invert this jump and point it to the target of the
             second jump.  */
          if (next && JUMP_P (next)
+             && any_condjump_p (insn)
              && (simplejump_p (next) || GET_CODE (PATTERN (next)) == RETURN)
              && target_label
              && next_active_insn (target_label) == next_active_insn (next)
@@ -3164,7 +3173,7 @@ relax_delay_slots (rtx first)
       if (JUMP_P (insn)
          && (simplejump_p (insn) || GET_CODE (PATTERN (insn)) == RETURN)
          && (other = prev_active_insn (insn)) != 0
-         && (condjump_p (other) || condjump_in_parallel_p (other))
+         && any_condjump_p (other)
          && no_labels_between_p (other, insn)
          && 0 > mostly_true_jump (other,
                                   get_branch_condition (other,
@@ -3374,6 +3383,7 @@ relax_delay_slots (rtx first)
         annulled jumps, though.  Again, don't convert a jump to a RETURN
         here.  */
       if (! INSN_ANNULLED_BRANCH_P (delay_insn)
+         && any_condjump_p (delay_insn)
          && next && JUMP_P (next)
          && (simplejump_p (next) || GET_CODE (PATTERN (next)) == RETURN)
          && next_active_insn (target_label) == next_active_insn (next)
@@ -3576,17 +3586,6 @@ dbr_schedule (rtx first, FILE *file)
 {
   rtx insn, next, epilogue_insn = 0;
   int i;
-#if 0
-  int old_flag_no_peephole = flag_no_peephole;
-
-  /* Execute `final' once in prescan mode to delete any insns that won't be
-     used.  Don't let final try to do any peephole optimization--it will
-     ruin dataflow information for this pass.  */
-
-  flag_no_peephole = 1;
-  final (first, 0, NO_DEBUG, 1, 1);
-  flag_no_peephole = old_flag_no_peephole;
-#endif
 
   /* If the current function has no insns other than the prologue and
      epilogue, then do not try to fill any delay slots.  */
@@ -3814,3 +3813,73 @@ dbr_schedule (rtx first, FILE *file)
 #endif
 }
 #endif /* DELAY_SLOTS */
+\f
+static bool
+gate_handle_delay_slots (void)
+{
+#ifdef DELAY_SLOTS
+  return flag_delayed_branch;
+#else 
+  return 0;
+#endif
+}
+
+/* Run delay slot optimization.  */
+static void
+rest_of_handle_delay_slots (void)
+{
+#ifdef DELAY_SLOTS
+  dbr_schedule (get_insns (), dump_file);
+#endif
+}   
+
+struct tree_opt_pass pass_delay_slots =
+{
+  "dbr",                                /* name */
+  gate_handle_delay_slots,              /* gate */
+  rest_of_handle_delay_slots,           /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_DBR_SCHED,                         /* tv_id */
+  0,                                    /* properties_required */
+  0,                                    /* properties_provided */
+  0,                                    /* properties_destroyed */
+  0,                                    /* todo_flags_start */
+  TODO_dump_func |
+  TODO_ggc_collect,                     /* todo_flags_finish */
+  'd'                                   /* letter */
+};
+
+/* Machine dependent reorg pass.  */
+static bool
+gate_handle_machine_reorg (void)
+{
+  return targetm.machine_dependent_reorg != 0;
+}
+
+
+static void
+rest_of_handle_machine_reorg (void)
+{
+  targetm.machine_dependent_reorg ();
+}
+
+struct tree_opt_pass pass_machine_reorg =
+{
+  "mach",                               /* name */
+  gate_handle_machine_reorg,            /* gate */
+  rest_of_handle_machine_reorg,         /* execute */
+  NULL,                                 /* sub */
+  NULL,                                 /* next */
+  0,                                    /* static_pass_number */
+  TV_MACH_DEP,                          /* 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 */
+};
+