OSDN Git Service

gcc/testsuite/
[pf3gnuchains/gcc-fork.git] / gcc / haifa-sched.c
index d9a8f78..0f12cd0 100644 (file)
@@ -1,6 +1,7 @@
 /* Instruction scheduling pass.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+   Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
    and currently maintained by, Jim Wilson (wilson@cygnus.com)
 
@@ -328,7 +329,7 @@ static int clock_var;
 /* Number of instructions in current scheduling region.  */
 static int rgn_n_insns;
 
-static int may_trap_exp (rtx, int);
+static int may_trap_exp (const_rtx, int);
 
 /* Nonzero iff the address is comprised from at most 1 register.  */
 #define CONST_BASED_ADDRESS_P(x)                       \
@@ -342,7 +343,7 @@ static int may_trap_exp (rtx, int);
    as found by analyzing insn's expression.  */
 
 static int
-may_trap_exp (rtx x, int is_store)
+may_trap_exp (const_rtx x, int is_store)
 {
   enum rtx_code code;
 
@@ -405,8 +406,9 @@ may_trap_exp (rtx x, int is_store)
     }
 }
 
-/* Classifies insn for the purpose of verifying that it can be
-   moved speculatively, by examining it's patterns, returning:
+/* Classifies rtx X of an insn for the purpose of verifying that X can be
+   executed speculatively (and consequently the insn can be moved
+   speculatively), by examining X, returning:
    TRAP_RISKY: store, or risky non-load insn (e.g. division by variable).
    TRAP_FREE: non-load insn.
    IFREE: load from a globally safe location.
@@ -414,45 +416,20 @@ may_trap_exp (rtx x, int is_store)
    PFREE_CANDIDATE, PRISKY_CANDIDATE: load that need to be checked for
    being either PFREE or PRISKY.  */
 
-int
-haifa_classify_insn (rtx insn)
+static int
+haifa_classify_rtx (const_rtx x)
 {
-  rtx pat = PATTERN (insn);
   int tmp_class = TRAP_FREE;
   int insn_class = TRAP_FREE;
   enum rtx_code code;
 
-  if (GET_CODE (pat) == PARALLEL)
+  if (GET_CODE (x) == PARALLEL)
     {
-      int i, len = XVECLEN (pat, 0);
+      int i, len = XVECLEN (x, 0);
 
       for (i = len - 1; i >= 0; i--)
        {
-         code = GET_CODE (XVECEXP (pat, 0, i));
-         switch (code)
-           {
-           case CLOBBER:
-             /* Test if it is a 'store'.  */
-             tmp_class = may_trap_exp (XEXP (XVECEXP (pat, 0, i), 0), 1);
-             break;
-           case SET:
-             /* Test if it is a store.  */
-             tmp_class = may_trap_exp (SET_DEST (XVECEXP (pat, 0, i)), 1);
-             if (tmp_class == TRAP_RISKY)
-               break;
-             /* Test if it is a load.  */
-             tmp_class
-               = WORST_CLASS (tmp_class,
-                              may_trap_exp (SET_SRC (XVECEXP (pat, 0, i)),
-                                            0));
-             break;
-           case COND_EXEC:
-           case TRAP_IF:
-             tmp_class = TRAP_RISKY;
-             break;
-           default:
-             ;
-           }
+         tmp_class = haifa_classify_rtx (XVECEXP (x, 0, i));
          insn_class = WORST_CLASS (insn_class, tmp_class);
          if (insn_class == TRAP_RISKY || insn_class == IRISKY)
            break;
@@ -460,24 +437,30 @@ haifa_classify_insn (rtx insn)
     }
   else
     {
-      code = GET_CODE (pat);
+      code = GET_CODE (x);
       switch (code)
        {
        case CLOBBER:
          /* Test if it is a 'store'.  */
-         tmp_class = may_trap_exp (XEXP (pat, 0), 1);
+         tmp_class = may_trap_exp (XEXP (x, 0), 1);
          break;
        case SET:
          /* Test if it is a store.  */
-         tmp_class = may_trap_exp (SET_DEST (pat), 1);
+         tmp_class = may_trap_exp (SET_DEST (x), 1);
          if (tmp_class == TRAP_RISKY)
            break;
          /* Test if it is a load.  */
          tmp_class =
            WORST_CLASS (tmp_class,
-                        may_trap_exp (SET_SRC (pat), 0));
+                        may_trap_exp (SET_SRC (x), 0));
          break;
        case COND_EXEC:
+         tmp_class = haifa_classify_rtx (COND_EXEC_CODE (x));
+         if (tmp_class == TRAP_RISKY)
+           break;
+         tmp_class = WORST_CLASS (tmp_class,
+                                  may_trap_exp (COND_EXEC_TEST (x), 0));
+         break;
        case TRAP_IF:
          tmp_class = TRAP_RISKY;
          break;
@@ -489,6 +472,13 @@ haifa_classify_insn (rtx insn)
   return insn_class;
 }
 
+int
+haifa_classify_insn (const_rtx insn)
+{
+  return haifa_classify_rtx (PATTERN (insn));
+}
+
+
 /* A typedef for rtx vector.  */
 typedef VEC(rtx, heap) *rtx_vec_t;
 
@@ -499,7 +489,7 @@ static int rank_for_schedule (const void *, const void *);
 static void swap_sort (rtx *, int);
 static void queue_insn (rtx, int);
 static int schedule_insn (rtx);
-static int find_set_reg_weight (rtx);
+static int find_set_reg_weight (const_rtx);
 static void find_insn_reg_weight (basic_block);
 static void find_insn_reg_weight1 (rtx);
 static void adjust_priority (rtx);
@@ -582,7 +572,6 @@ static void add_jump_dependencies (rtx, rtx);
 #ifdef ENABLE_CHECKING
 static int has_edge_p (VEC(edge,gc) *, int);
 static void check_cfg (rtx, rtx);
-static void check_sched_flags (void);
 #endif
 
 #endif /* INSN_SCHEDULING */
@@ -1142,6 +1131,9 @@ adjust_priority (rtx prev)
 HAIFA_INLINE static void
 advance_one_cycle (void)
 {
+  if (targetm.sched.dfa_pre_advance_cycle)
+    targetm.sched.dfa_pre_advance_cycle ();
+
   if (targetm.sched.dfa_pre_cycle_insn)
     state_transition (curr_state,
                      targetm.sched.dfa_pre_cycle_insn ());
@@ -1151,6 +1143,9 @@ advance_one_cycle (void)
   if (targetm.sched.dfa_post_cycle_insn)
     state_transition (curr_state,
                      targetm.sched.dfa_post_cycle_insn ());
+
+  if (targetm.sched.dfa_post_advance_cycle)
+    targetm.sched.dfa_post_advance_cycle ();
 }
 
 /* Clock at which the previous instruction was issued.  */
@@ -1352,7 +1347,7 @@ get_ebb_head_tail (basic_block beg, basic_block end, rtx *headp, rtx *tailp)
 /* Return nonzero if there are no real insns in the range [ HEAD, TAIL ].  */
 
 int
-no_real_insns_p (rtx head, rtx tail)
+no_real_insns_p (const_rtx head, const_rtx tail)
 {
   while (head != NEXT_INSN (tail))
     {
@@ -1402,7 +1397,7 @@ rm_other_notes (rtx head, rtx tail)
    a new register is not needed.  */
 
 static int
-find_set_reg_weight (rtx x)
+find_set_reg_weight (const_rtx x)
 {
   if (GET_CODE (x) == CLOBBER
       && register_operand (SET_DEST (x), VOIDmode))
@@ -1584,6 +1579,12 @@ ok_for_early_queue_removal (rtx insn)
            {
              int cost;
 
+             if (prev_insn == current_sched_info->prev_head)
+               {
+                 prev_insn = NULL;
+                 break;
+               }
+
              if (!NOTE_P (prev_insn))
                {
                  dep_t dep;
@@ -1835,8 +1836,7 @@ move_insn (rtx insn)
          gcc_assert (BB_END (bb) == last);
        }
 
-      set_block_for_insn (insn, bb);    
-      df_insn_change_bb (insn);
+      df_insn_change_bb (insn, bb);
   
       /* Update BB_END, if needed.  */
       if (BB_END (bb) == last)
@@ -2680,9 +2680,6 @@ sched_init (void)
       else
        /* So we won't read anything accidentally.  */
        spec_info = 0;
-#ifdef ENABLE_CHECKING
-      check_sched_flags ();
-#endif
     }
   else
     /* So we won't read anything accidentally.  */
@@ -2918,7 +2915,7 @@ try_ready (rtx next)
   else
     {
       /* One of the NEXT's dependencies has been resolved.
-        Recalcute NEXT's status.  */
+        Recalculate NEXT's status.  */
 
       *ts &= ~SPECULATIVE & ~HARD_DEP;
 
@@ -3286,8 +3283,17 @@ process_insn_forw_deps_be_in_spec (rtx insn, rtx twin, ds_t fs)
                     due to backend decision.  Hence we can't let the
                     probability of the speculative dep to decrease.  */
                  dep_weak (ds) <= dep_weak (fs))
-               /* Transform it to be in speculative.  */
-               ds = (ds & ~BEGIN_SPEC) | fs;
+               {
+                 ds_t new_ds;
+
+                 new_ds = (ds & ~BEGIN_SPEC) | fs;
+                 
+                 if (/* consumer can 'be in speculative'.  */
+                     sched_insn_is_legitimate_for_speculation_p (consumer,
+                                                                 new_ds))
+                   /* Transform it to be in speculative.  */
+                   ds = new_ds;
+               }
            }
          else
            /* Mark the dep as 'be in speculative'.  */
@@ -3851,7 +3857,7 @@ create_check_block_twin (rtx insn, bool mutate_p)
       DONE_SPEC (insn) = ts & BEGIN_SPEC;
       CHECK_SPEC (check) = ts & BEGIN_SPEC;
 
-      /* Luckyness of future speculations solely depends upon initial
+      /* Luckiness of future speculations solely depends upon initial
         BEGIN speculation.  */
       if (ts & BEGIN_DATA)
        fs = set_dep_weak (fs, BE_IN_DATA, get_dep_weak (ts, BEGIN_DATA));
@@ -4011,7 +4017,7 @@ change_pattern (rtx insn, rtx new_pat)
 
 /* Return true if INSN can potentially be speculated with type DS.  */
 bool
-sched_insn_is_legitimate_for_speculation_p (rtx insn, ds_t ds)
+sched_insn_is_legitimate_for_speculation_p (const_rtx insn, ds_t ds)
 {
   if (HAS_INTERNAL_DEP (insn))
     return false;
@@ -4496,20 +4502,6 @@ check_cfg (rtx head, rtx tail)
 
   gcc_assert (bb == 0);
 }
-
-/* Perform a few consistency checks of flags in different data structures.  */
-static void
-check_sched_flags (void)
-{
-  unsigned int f = current_sched_info->flags;
-
-  if (flag_sched_stalled_insns)
-    gcc_assert (!(f & DO_SPECULATION));
-  if (f & DO_SPECULATION)
-    gcc_assert (!flag_sched_stalled_insns
-               && spec_info
-               && spec_info->mask);
-}
 #endif /* ENABLE_CHECKING */
 
 #endif /* INSN_SCHEDULING */