OSDN Git Service

PR middle-end/27332
[pf3gnuchains/gcc-fork.git] / gcc / reorg.c
index 763f07b..7781d27 100644 (file)
@@ -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)
@@ -960,9 +963,8 @@ static int
 mostly_true_jump (rtx jump_insn, rtx condition)
 {
   rtx target_label = JUMP_LABEL (jump_insn);
-  rtx insn, note;
-  int rare_dest = rare_destination (target_label);
-  int rare_fallthrough = rare_destination (NEXT_INSN (jump_insn));
+  rtx note;
+  int rare_dest, rare_fallthrough;
 
   /* If branch probabilities are available, then use that number since it
      always gives a correct answer.  */
@@ -981,32 +983,10 @@ mostly_true_jump (rtx jump_insn, rtx condition)
        return -1;
     }
 
-  /* ??? Ought to use estimate_probability instead.  */
-
-  /* If this is a branch outside a loop, it is highly unlikely.  */
-  if (GET_CODE (PATTERN (jump_insn)) == SET
-      && GET_CODE (SET_SRC (PATTERN (jump_insn))) == IF_THEN_ELSE
-      && ((GET_CODE (XEXP (SET_SRC (PATTERN (jump_insn)), 1)) == LABEL_REF
-          && LABEL_OUTSIDE_LOOP_P (XEXP (SET_SRC (PATTERN (jump_insn)), 1)))
-         || (GET_CODE (XEXP (SET_SRC (PATTERN (jump_insn)), 2)) == LABEL_REF
-             && LABEL_OUTSIDE_LOOP_P (XEXP (SET_SRC (PATTERN (jump_insn)), 2)))))
-    return -1;
-
-  if (target_label)
-    {
-      /* If this is the test of a loop, it is very likely true.  We scan
-        backwards from the target label.  If we find a NOTE_INSN_LOOP_BEG
-        before the next real insn, we assume the branch is to the top of
-        the loop.  */
-      for (insn = PREV_INSN (target_label);
-          insn && NOTE_P (insn);
-          insn = PREV_INSN (insn))
-       if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
-         return 2;
-    }
-
   /* Look at the relative rarities of the fallthrough and destination.  If
      they differ, we can predict the branch that way.  */
+  rare_dest = rare_destination (target_label);
+  rare_fallthrough = rare_destination (NEXT_INSN (jump_insn));
 
   switch (rare_fallthrough - rare_dest)
     {
@@ -1027,33 +1007,6 @@ mostly_true_jump (rtx jump_insn, rtx condition)
   if (condition == 0)
     return 0;
 
-  /* EQ tests are usually false and NE tests are usually true.  Also,
-     most quantities are positive, so we can make the appropriate guesses
-     about signed comparisons against zero.  */
-  switch (GET_CODE (condition))
-    {
-    case CONST_INT:
-      /* Unconditional branch.  */
-      return 1;
-    case EQ:
-      return 0;
-    case NE:
-      return 1;
-    case LE:
-    case LT:
-      if (XEXP (condition, 1) == const0_rtx)
-       return 0;
-      break;
-    case GE:
-    case GT:
-      if (XEXP (condition, 1) == const0_rtx)
-       return 1;
-      break;
-
-    default:
-      break;
-    }
-
   /* Predict backward branches usually take, forward branches usually not.  If
      we don't know whether this is forward or backward, assume the branch
      will be taken, since most are.  */
@@ -1334,7 +1287,7 @@ steal_delay_list_from_target (rtx insn, rtx condition, rtx seq,
       if (! must_annul
          && ((condition == const_true_rtx
               || (! insn_sets_resource_p (trial, other_needed, 0)
-                  && ! may_trap_p (PATTERN (trial)))))
+                  && ! may_trap_or_fault_p (PATTERN (trial)))))
          ? eligible_for_delay (insn, total_slots_filled, trial, flags)
          : (must_annul || (delay_list == NULL && new_delay_list == NULL))
             && (must_annul = 1,
@@ -1428,7 +1381,7 @@ steal_delay_list_from_fallthrough (rtx insn, rtx condition, rtx seq,
       if (! must_annul
          && ((condition == const_true_rtx
               || (! insn_sets_resource_p (trial, other_needed, 0)
-                  && ! may_trap_p (PATTERN (trial)))))
+                  && ! may_trap_or_fault_p (PATTERN (trial)))))
          ? eligible_for_delay (insn, *pslots_filled, trial, flags)
          : (must_annul || delay_list == NULL) && (must_annul = 1,
             check_annul_list_true_false (1, delay_list)
@@ -1931,7 +1884,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
@@ -2320,7 +2273,7 @@ fill_simple_delay_slots (int non_jumps_p)
 #ifdef HAVE_cc0
                    && ! (reg_mentioned_p (cc0_rtx, pat) && ! sets_cc0_p (pat))
 #endif
-                   && ! (maybe_never && may_trap_p (pat))
+                   && ! (maybe_never && may_trap_or_fault_p (pat))
                    && (trial = try_split (pat, trial, 0))
                    && eligible_for_delay (insn, slots_filled, trial, flags)
                    && ! can_throw_internal(trial))
@@ -2373,7 +2326,7 @@ fill_simple_delay_slots (int non_jumps_p)
 #ifdef HAVE_cc0
              && ! reg_mentioned_p (cc0_rtx, PATTERN (next_trial))
 #endif
-             && ! (maybe_never && may_trap_p (PATTERN (next_trial)))
+             && ! (maybe_never && may_trap_or_fault_p (PATTERN (next_trial)))
              && (next_trial = try_split (PATTERN (next_trial), next_trial, 0))
              && eligible_for_delay (insn, slots_filled, next_trial, flags)
              && ! can_throw_internal (trial))
@@ -2653,7 +2606,7 @@ fill_slots_from_thread (rtx insn, rtx condition, rtx thread,
          if (!must_annul
              && (condition == const_true_rtx
                  || (! insn_sets_resource_p (trial, &opposite_needed, 1)
-                     && ! may_trap_p (pat))))
+                     && ! may_trap_or_fault_p (pat))))
            {
              old_trial = trial;
              trial = try_split (pat, trial, 0);
@@ -3120,10 +3073,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)
@@ -3169,7 +3123,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,
@@ -3379,6 +3333,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)
@@ -3577,25 +3532,14 @@ make_return_insns (rtx first)
 /* Try to find insns to place in delay slots.  */
 
 void
-dbr_schedule (rtx first, FILE *file)
+dbr_schedule (rtx first)
 {
   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.  */
-  if (n_basic_blocks == 0)
+  if (n_basic_blocks == NUM_FIXED_BLOCKS)
     return;
 
   /* Find the highest INSN_UID and allocate and initialize our map from
@@ -3694,7 +3638,7 @@ dbr_schedule (rtx first, FILE *file)
   /* It is not clear why the line below is needed, but it does seem to be.  */
   unfilled_firstobj = obstack_alloc (&unfilled_slots_obstack, 0);
 
-  if (file)
+  if (dump_file)
     {
       int i, j, need_comma;
       int total_delay_slots[MAX_DELAY_HISTOGRAM + 1];
@@ -3704,25 +3648,25 @@ dbr_schedule (rtx first, FILE *file)
           reorg_pass_number < MAX_REORG_PASSES;
           reorg_pass_number++)
        {
-         fprintf (file, ";; Reorg pass #%d:\n", reorg_pass_number + 1);
+         fprintf (dump_file, ";; Reorg pass #%d:\n", reorg_pass_number + 1);
          for (i = 0; i < NUM_REORG_FUNCTIONS; i++)
            {
              need_comma = 0;
-             fprintf (file, ";; Reorg function #%d\n", i);
+             fprintf (dump_file, ";; Reorg function #%d\n", i);
 
-             fprintf (file, ";; %d insns needing delay slots\n;; ",
+             fprintf (dump_file, ";; %d insns needing delay slots\n;; ",
                       num_insns_needing_delays[i][reorg_pass_number]);
 
              for (j = 0; j < MAX_DELAY_HISTOGRAM + 1; j++)
                if (num_filled_delays[i][j][reorg_pass_number])
                  {
                    if (need_comma)
-                     fprintf (file, ", ");
+                     fprintf (dump_file, ", ");
                    need_comma = 1;
-                   fprintf (file, "%d got %d delays",
+                   fprintf (dump_file, "%d got %d delays",
                             num_filled_delays[i][j][reorg_pass_number], j);
                  }
-             fprintf (file, "\n");
+             fprintf (dump_file, "\n");
            }
        }
       memset (total_delay_slots, 0, sizeof total_delay_slots);
@@ -3748,35 +3692,35 @@ dbr_schedule (rtx first, FILE *file)
                total_delay_slots[0]++;
            }
        }
-      fprintf (file, ";; Reorg totals: ");
+      fprintf (dump_file, ";; Reorg totals: ");
       need_comma = 0;
       for (j = 0; j < MAX_DELAY_HISTOGRAM + 1; j++)
        {
          if (total_delay_slots[j])
            {
              if (need_comma)
-               fprintf (file, ", ");
+               fprintf (dump_file, ", ");
              need_comma = 1;
-             fprintf (file, "%d got %d delays", total_delay_slots[j], j);
+             fprintf (dump_file, "%d got %d delays", total_delay_slots[j], j);
            }
        }
-      fprintf (file, "\n");
+      fprintf (dump_file, "\n");
 #if defined (ANNUL_IFTRUE_SLOTS) || defined (ANNUL_IFFALSE_SLOTS)
-      fprintf (file, ";; Reorg annuls: ");
+      fprintf (dump_file, ";; Reorg annuls: ");
       need_comma = 0;
       for (j = 0; j < MAX_DELAY_HISTOGRAM + 1; j++)
        {
          if (total_annul_slots[j])
            {
              if (need_comma)
-               fprintf (file, ", ");
+               fprintf (dump_file, ", ");
              need_comma = 1;
-             fprintf (file, "%d got %d delays", total_annul_slots[j], j);
+             fprintf (dump_file, "%d got %d delays", total_annul_slots[j], j);
            }
        }
-      fprintf (file, "\n");
+      fprintf (dump_file, "\n");
 #endif
-      fprintf (file, "\n");
+      fprintf (dump_file, "\n");
     }
 
   /* For all JUMP insns, fill in branch prediction notes, so that during
@@ -3819,3 +3763,75 @@ 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 unsigned int
+rest_of_handle_delay_slots (void)
+{
+#ifdef DELAY_SLOTS
+  dbr_schedule (get_insns ());
+#endif
+  return 0;
+}   
+
+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 unsigned int
+rest_of_handle_machine_reorg (void)
+{
+  targetm.machine_dependent_reorg ();
+  return 0;
+}
+
+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 */
+};
+