OSDN Git Service

* reorg.c (mostly_true_jump): Clean up code depending on
[pf3gnuchains/gcc-fork.git] / gcc / reorg.c
index 6d0db45..104ad8e 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)
@@ -961,8 +964,7 @@ 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));
+  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,
@@ -3809,3 +3763,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 */
+};
+