OSDN Git Service

don't use build_function_type in the ObjC/C++ frontends
[pf3gnuchains/gcc-fork.git] / gcc / sched-deps.c
index 21632c3..09bf65d 100644 (file)
@@ -1,7 +1,8 @@
 /* Instruction scheduling pass.  This file computes dependencies between
    instructions.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+   2011
    Free Software Foundation, Inc.
    Contributed by Michael Tiemann (tiemann@cygnus.com) Enhanced by,
    and currently maintained by, Jim Wilson (wilson@cygnus.com)
@@ -26,7 +27,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "system.h"
 #include "coretypes.h"
 #include "tm.h"
-#include "toplev.h"
+#include "diagnostic-core.h"
 #include "rtl.h"
 #include "tm_p.h"
 #include "hard-reg-set.h"
@@ -36,7 +37,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 "params.h"
@@ -52,6 +52,12 @@ along with GCC; see the file COPYING3.  If not see
 #define CHECK (false)
 #endif
 
+/* In deps->last_pending_memory_flush marks JUMP_INSNs that weren't
+   added to the list because of flush_pending_lists, stands just
+   for itself and not for any other pending memory reads/writes.  */
+#define NON_FLUSH_JUMP_KIND REG_DEP_ANTI
+#define NON_FLUSH_JUMP_P(x) (REG_NOTE_KIND (x) == NON_FLUSH_JUMP_KIND)
+
 /* Holds current parameters for the dependency analyzer.  */
 struct sched_deps_info_def *sched_deps_info;
 
@@ -442,15 +448,15 @@ static int cache_size;
 
 static int deps_may_trap_p (const_rtx);
 static void add_dependence_list (rtx, rtx, int, enum reg_note);
-static void add_dependence_list_and_free (struct deps *, rtx,
+static void add_dependence_list_and_free (struct deps_desc *, rtx,
                                          rtx *, int, enum reg_note);
 static void delete_all_dependences (rtx);
 static void fixup_sched_groups (rtx);
 
-static void flush_pending_lists (struct deps *, rtx, int, int);
-static void sched_analyze_1 (struct deps *, rtx, rtx);
-static void sched_analyze_2 (struct deps *, rtx, rtx);
-static void sched_analyze_insn (struct deps *, rtx, rtx);
+static void flush_pending_lists (struct deps_desc *, rtx, int, int);
+static void sched_analyze_1 (struct deps_desc *, rtx, rtx);
+static void sched_analyze_2 (struct deps_desc *, rtx, rtx);
+static void sched_analyze_insn (struct deps_desc *, rtx, rtx);
 
 static bool sched_has_condition_p (const_rtx);
 static int conditions_mutex_p (const_rtx, const_rtx, bool, bool);
@@ -597,8 +603,8 @@ sched_insn_is_legitimate_for_speculation_p (const_rtx insn, ds_t ds)
     /* The following instructions, which depend on a speculatively scheduled
        instruction, cannot be speculatively scheduled along.  */
     {
-      if (may_trap_p (PATTERN (insn)))
-       /* If instruction might trap, it cannot be speculatively scheduled.
+      if (may_trap_or_fault_p (PATTERN (insn)))
+       /* If instruction might fault, it cannot be speculatively scheduled.
           For control speculation it's obvious why and for data speculation
           it's because the insn might get wrong input if speculation
           wasn't successful.  */
@@ -710,9 +716,6 @@ sd_init_insn (rtx insn)
   INSN_FORW_DEPS (insn) = create_deps_list ();
   INSN_RESOLVED_FORW_DEPS (insn) = create_deps_list ();
 
-  if (DEBUG_INSN_P (insn))
-    DEBUG_INSN_SCHED_P (insn) = TRUE;
-
   /* ??? It would be nice to allocate dependency caches here.  */
 }
 
@@ -722,12 +725,6 @@ sd_finish_insn (rtx insn)
 {
   /* ??? It would be nice to deallocate dependency caches here.  */
 
-  if (DEBUG_INSN_P (insn))
-    {
-      gcc_assert (DEBUG_INSN_SCHED_P (insn));
-      DEBUG_INSN_SCHED_P (insn) = FALSE;
-    }
-
   free_deps_list (INSN_HARD_BACK_DEPS (insn));
   INSN_HARD_BACK_DEPS (insn) = NULL;
 
@@ -1402,12 +1399,15 @@ add_dependence_list (rtx insn, rtx list, int uncond, enum reg_note dep_type)
    is not readonly.  */
 
 static void
-add_dependence_list_and_free (struct deps *deps, rtx insn, rtx *listp,
+add_dependence_list_and_free (struct deps_desc *deps, rtx insn, rtx *listp,
                               int uncond, enum reg_note dep_type)
 {
   rtx list, next;
 
-  if (deps->readonly)
+  /* We don't want to short-circuit dependencies involving debug
+     insns, because they may cause actual dependencies to be
+     disregarded.  */
+  if (deps->readonly || DEBUG_INSN_P (insn))
     {
       add_dependence_list (insn, *listp, uncond, dep_type);
       return;
@@ -1517,9 +1517,7 @@ fixup_sched_groups (rtx insn)
 
   delete_all_dependences (insn);
 
-  prev_nonnote = prev_nonnote_insn (insn);
-  while (DEBUG_INSN_P (prev_nonnote))
-    prev_nonnote = prev_nonnote_insn (prev_nonnote);
+  prev_nonnote = prev_nonnote_nondebug_insn (insn);
   if (BLOCK_FOR_INSN (insn) == BLOCK_FOR_INSN (prev_nonnote)
       && ! sched_insns_conditions_mutex_p (insn, prev_nonnote))
     add_dependence (insn, prev_nonnote, REG_DEP_ANTI);
@@ -1541,7 +1539,7 @@ fixup_sched_groups (rtx insn)
    so that we can do memory aliasing on it.  */
 
 static void
-add_insn_mem_dependence (struct deps *deps, bool read_p,
+add_insn_mem_dependence (struct deps_desc *deps, bool read_p,
                         rtx insn, rtx mem)
 {
   rtx *insn_list;
@@ -1569,7 +1567,7 @@ add_insn_mem_dependence (struct deps *deps, bool read_p,
   if (sched_deps_info->use_cselib)
     {
       mem = shallow_copy_rtx (mem);
-      XEXP (mem, 0) = cselib_subst_to_values (XEXP (mem, 0));
+      XEXP (mem, 0) = cselib_subst_to_values (XEXP (mem, 0), GET_MODE (mem));
     }
   link = alloc_EXPR_LIST (VOIDmode, canon_rtx (mem), *mem_list);
   *mem_list = link;
@@ -1580,7 +1578,7 @@ add_insn_mem_dependence (struct deps *deps, bool read_p,
    dependencies for a read operation, similarly with FOR_WRITE.  */
 
 static void
-flush_pending_lists (struct deps *deps, rtx insn, int for_read,
+flush_pending_lists (struct deps_desc *deps, rtx insn, int for_read,
                     int for_write)
 {
   if (for_write)
@@ -1764,7 +1762,7 @@ create_insn_reg_set (int regno, rtx insn)
 
 /* Set up insn register uses for INSN and dependency context DEPS.  */
 static void
-setup_insn_reg_uses (struct deps *deps, rtx insn)
+setup_insn_reg_uses (struct deps_desc *deps, rtx insn)
 {
   unsigned i;
   reg_set_iterator rsi;
@@ -1824,10 +1822,10 @@ mark_insn_pseudo_birth (rtx insn, int regno, bool clobber_p, bool unused_p)
   enum reg_class cl;
 
   gcc_assert (regno >= FIRST_PSEUDO_REGISTER);
-  cl = sched_regno_cover_class[regno];
+  cl = sched_regno_pressure_class[regno];
   if (cl != NO_REGS)
     {
-      incr = ira_reg_class_nregs[cl][PSEUDO_REGNO_MODE (regno)];
+      incr = ira_reg_class_max_nregs[cl][PSEUDO_REGNO_MODE (regno)];
       if (clobber_p)
        {
          new_incr = reg_pressure_info[cl].clobber_increase + incr;
@@ -1864,7 +1862,7 @@ mark_insn_hard_regno_birth (rtx insn, int regno, int nregs,
       gcc_assert (regno < FIRST_PSEUDO_REGISTER);
       if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno))
        {
-         cl = sched_regno_cover_class[regno];
+         cl = sched_regno_pressure_class[regno];
          if (cl != NO_REGS)
            {
              if (clobber_p)
@@ -1925,10 +1923,10 @@ mark_pseudo_death (int regno)
   enum reg_class cl;
 
   gcc_assert (regno >= FIRST_PSEUDO_REGISTER);
-  cl = sched_regno_cover_class[regno];
+  cl = sched_regno_pressure_class[regno];
   if (cl != NO_REGS)
     {
-      incr = ira_reg_class_nregs[cl][PSEUDO_REGNO_MODE (regno)];
+      incr = ira_reg_class_max_nregs[cl][PSEUDO_REGNO_MODE (regno)];
       reg_pressure_info[cl].change -= incr;
     }
 }
@@ -1946,7 +1944,7 @@ mark_hard_regno_death (int regno, int nregs)
       gcc_assert (regno < FIRST_PSEUDO_REGISTER);
       if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno))
        {
-         cl = sched_regno_cover_class[regno];
+         cl = sched_regno_pressure_class[regno];
          if (cl != NO_REGS)
            reg_pressure_info[cl].change -= 1;
        }
@@ -1994,8 +1992,8 @@ mark_insn_reg_clobber (rtx reg, const_rtx setter, void *data)
 }
 
 /* Set up reg pressure info related to INSN.  */
-static void
-setup_insn_reg_pressure_info (rtx insn)
+void
+init_insn_reg_pressure_info (rtx insn)
 {
   int i, len;
   enum reg_class cl;
@@ -2007,9 +2005,9 @@ setup_insn_reg_pressure_info (rtx insn)
   if (! INSN_P (insn))
     return;
 
-  for (i = 0; i < ira_reg_class_cover_size; i++)
+  for (i = 0; i < ira_pressure_classes_num; i++)
     {
-      cl = ira_reg_class_cover[i];
+      cl = ira_pressure_classes[i];
       reg_pressure_info[cl].clobber_increase = 0;
       reg_pressure_info[cl].set_increase = 0;
       reg_pressure_info[cl].unused_set_increase = 0;
@@ -2030,14 +2028,14 @@ setup_insn_reg_pressure_info (rtx insn)
     if (REG_NOTE_KIND (link) == REG_DEAD)
       mark_reg_death (XEXP (link, 0));
 
-  len = sizeof (struct reg_pressure_data) * ira_reg_class_cover_size;
+  len = sizeof (struct reg_pressure_data) * ira_pressure_classes_num;
   pressure_info
     = INSN_REG_PRESSURE (insn) = (struct reg_pressure_data *) xmalloc (len);
-  INSN_MAX_REG_PRESSURE (insn) = (int *) xmalloc (ira_reg_class_cover_size
-                                                 * sizeof (int));
-  for (i = 0; i < ira_reg_class_cover_size; i++)
+  INSN_MAX_REG_PRESSURE (insn) = (int *) xcalloc (ira_pressure_classes_num
+                                                 * sizeof (int), 1);
+  for (i = 0; i < ira_pressure_classes_num; i++)
     {
-      cl = ira_reg_class_cover[i];
+      cl = ira_pressure_classes[i];
       pressure_info[i].clobber_increase
        = reg_pressure_info[cl].clobber_increase;
       pressure_info[i].set_increase = reg_pressure_info[cl].set_increase;
@@ -2058,7 +2056,7 @@ static bool can_start_lhs_rhs_p;
 /* Extend reg info for the deps context DEPS given that
    we have just generated a register numbered REGNO.  */
 static void
-extend_deps_reg_info (struct deps *deps, int regno)
+extend_deps_reg_info (struct deps_desc *deps, int regno)
 {
   int max_regno = regno + 1;
 
@@ -2107,7 +2105,7 @@ maybe_extend_reg_info_p (void)
    CLOBBER, PRE_DEC, POST_DEC, PRE_INC, POST_INC or USE.  */
 
 static void
-sched_analyze_reg (struct deps *deps, int regno, enum machine_mode mode,
+sched_analyze_reg (struct deps_desc *deps, int regno, enum machine_mode mode,
                   enum rtx_code ref, rtx insn)
 {
   /* We could emit new pseudos in renaming.  Extend the reg structures.  */
@@ -2186,7 +2184,7 @@ sched_analyze_reg (struct deps *deps, int regno, enum machine_mode mode,
    destination of X, and reads of everything mentioned.  */
 
 static void
-sched_analyze_1 (struct deps *deps, rtx x, rtx insn)
+sched_analyze_1 (struct deps_desc *deps, rtx x, rtx insn)
 {
   rtx dest = XEXP (x, 0);
   enum rtx_code code = GET_CODE (x);
@@ -2262,16 +2260,12 @@ sched_analyze_1 (struct deps *deps, rtx x, rtx insn)
       /* Treat all writes to a stack register as modifying the TOS.  */
       if (regno >= FIRST_STACK_REG && regno <= LAST_STACK_REG)
        {
-         int nregs;
-
          /* Avoid analyzing the same register twice.  */
          if (regno != FIRST_STACK_REG)
            sched_analyze_reg (deps, FIRST_STACK_REG, mode, code, insn);
 
-         nregs = hard_regno_nregs[FIRST_STACK_REG][mode];
-         while (--nregs >= 0)
-           SET_HARD_REG_BIT (implicit_reg_pending_uses,
-                             FIRST_STACK_REG + nregs);
+         add_to_hard_reg_set (&implicit_reg_pending_uses, mode,
+                              FIRST_STACK_REG);
        }
 #endif
     }
@@ -2286,8 +2280,9 @@ sched_analyze_1 (struct deps *deps, rtx x, rtx insn)
            = targetm.addr_space.address_mode (MEM_ADDR_SPACE (dest));
 
          t = shallow_copy_rtx (dest);
-         cselib_lookup (XEXP (t, 0), address_mode, 1);
-         XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0));
+         cselib_lookup_from_insn (XEXP (t, 0), address_mode, 1,
+                                  GET_MODE (t), insn);
+         XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0), GET_MODE (t));
        }
       t = canon_rtx (t);
 
@@ -2358,7 +2353,7 @@ sched_analyze_1 (struct deps *deps, rtx x, rtx insn)
 
 /* Analyze the uses of memory and registers in rtx X in INSN.  */
 static void
-sched_analyze_2 (struct deps *deps, rtx x, rtx insn)
+sched_analyze_2 (struct deps_desc *deps, rtx x, rtx insn)
 {
   int i;
   int j;
@@ -2443,8 +2438,9 @@ sched_analyze_2 (struct deps *deps, rtx x, rtx insn)
              = targetm.addr_space.address_mode (MEM_ADDR_SPACE (t));
 
            t = shallow_copy_rtx (t);
-           cselib_lookup (XEXP (t, 0), address_mode, 1);
-           XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0));
+           cselib_lookup_from_insn (XEXP (t, 0), address_mode, 1,
+                                    GET_MODE (t), insn);
+           XEXP (t, 0) = cselib_subst_to_values (XEXP (t, 0), GET_MODE (t));
          }
 
        if (!DEBUG_INSN_P (insn))
@@ -2482,7 +2478,7 @@ sched_analyze_2 (struct deps *deps, rtx x, rtx insn)
 
            for (u = deps->last_pending_memory_flush; u; u = XEXP (u, 1))
              {
-               if (! JUMP_P (XEXP (u, 0)))
+               if (! NON_FLUSH_JUMP_P (u))
                  add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
                else if (deps_may_trap_p (x))
                  {
@@ -2609,7 +2605,7 @@ sched_analyze_2 (struct deps *deps, rtx x, rtx insn)
 
 /* Analyze an INSN with pattern X to find all dependencies.  */
 static void
-sched_analyze_insn (struct deps *deps, rtx x, rtx insn)
+sched_analyze_insn (struct deps_desc *deps, rtx x, rtx insn)
 {
   RTX_CODE code = GET_CODE (x);
   rtx link;
@@ -2623,6 +2619,7 @@ sched_analyze_insn (struct deps *deps, rtx x, rtx insn)
       extract_insn (insn);
       preprocess_constraints ();
       ira_implicitly_set_insn_hard_regs (&temp);
+      AND_COMPL_HARD_REG_SET (temp, ira_no_alloc_regs);
       IOR_HARD_REG_SET (implicit_reg_pending_clobbers, temp);
     }
 
@@ -2694,9 +2691,7 @@ sched_analyze_insn (struct deps *deps, rtx x, rtx insn)
   if (JUMP_P (insn))
     {
       rtx next;
-      next = next_nonnote_insn (insn);
-      while (next && DEBUG_INSN_P (next))
-       next = next_nonnote_insn (next);
+      next = next_nonnote_nondebug_insn (insn);
       if (next && BARRIER_P (next))
        reg_pending_barrier = MOVE_BARRIER;
       else
@@ -2776,7 +2771,7 @@ sched_analyze_insn (struct deps *deps, rtx x, rtx insn)
   if (sched_pressure_p)
     {
       setup_insn_reg_uses (deps, insn);
-      setup_insn_reg_pressure_info (insn);
+      init_insn_reg_pressure_info (insn);
     }
 
   /* Add register dependencies for insn.  */
@@ -2795,8 +2790,7 @@ sched_analyze_insn (struct deps *deps, rtx x, rtx insn)
                           REG_DEP_ANTI);
 
       for (u = deps->last_pending_memory_flush; u; u = XEXP (u, 1))
-       if (! JUMP_P (XEXP (u, 0))
-           || !sel_sched_p ())
+       if (! NON_FLUSH_JUMP_P (u) || !sel_sched_p ())
          add_dependence (insn, XEXP (u, 0), REG_DEP_ANTI);
 
       EXECUTE_IF_SET_IN_REG_SET (reg_pending_uses, 0, i, rsi)
@@ -3055,8 +3049,8 @@ sched_analyze_insn (struct deps *deps, rtx x, rtx insn)
      This insn must be a simple move of a hard reg to a pseudo or
      vice-versa.
 
-     We must avoid moving these insns for correctness on
-     SMALL_REGISTER_CLASS machines, and for special registers like
+     We must avoid moving these insns for correctness on targets
+     with small register classes, and for special registers like
      PIC_OFFSET_TABLE_REGNUM.  For simplicity, extend this to all
      hard regs for all targets.  */
 
@@ -3223,7 +3217,7 @@ call_may_noreturn_p (rtx insn)
 
 /* Analyze INSN with DEPS as a context.  */
 void
-deps_analyze_insn (struct deps *deps, rtx insn)
+deps_analyze_insn (struct deps_desc *deps, rtx insn)
 {
   if (sched_deps_info->start_insn)
     sched_deps_info->start_insn (insn);
@@ -3241,8 +3235,15 @@ deps_analyze_insn (struct deps *deps, rtx insn)
           if (deps->pending_flush_length++ > MAX_PENDING_LIST_LENGTH)
             flush_pending_lists (deps, insn, true, true);
           else
-            deps->last_pending_memory_flush
-              = alloc_INSN_LIST (insn, deps->last_pending_memory_flush);
+           {
+             deps->last_pending_memory_flush
+               = alloc_INSN_LIST (insn, deps->last_pending_memory_flush);
+             /* Signal to sched_analyze_insn that this jump stands
+                just for its own, not any other pending memory
+                reads/writes flush_pending_lists had to flush.  */
+             PUT_REG_NOTE_KIND (deps->last_pending_memory_flush,
+                                NON_FLUSH_JUMP_KIND);
+           }
         }
 
       sched_analyze_insn (deps, PATTERN (insn), insn);
@@ -3356,7 +3357,7 @@ deps_analyze_insn (struct deps *deps, rtx insn)
 
 /* Initialize DEPS for the new block beginning with HEAD.  */
 void
-deps_start_bb (struct deps *deps, rtx head)
+deps_start_bb (struct deps_desc *deps, rtx head)
 {
   gcc_assert (!deps->readonly);
 
@@ -3365,10 +3366,8 @@ deps_start_bb (struct deps *deps, rtx head)
      hard registers correct.  */
   if (! reload_completed && !LABEL_P (head))
     {
-      rtx insn = prev_nonnote_insn (head);
+      rtx insn = prev_nonnote_nondebug_insn (head);
 
-      while (insn && DEBUG_INSN_P (insn))
-       insn = prev_nonnote_insn (insn);
       if (insn && CALL_P (insn))
        deps->in_post_call_group_p = post_call_initial;
     }
@@ -3377,12 +3376,12 @@ deps_start_bb (struct deps *deps, rtx head)
 /* Analyze every insn between HEAD and TAIL inclusive, creating backward
    dependencies for each insn.  */
 void
-sched_analyze (struct deps *deps, rtx head, rtx tail)
+sched_analyze (struct deps_desc *deps, rtx head, rtx tail)
 {
   rtx insn;
 
   if (sched_deps_info->use_cselib)
-    cselib_init (true);
+    cselib_init (CSELIB_RECORD_MEMORY);
 
   deps_start_bb (deps, head);
 
@@ -3462,10 +3461,10 @@ sched_free_deps (rtx head, rtx tail, bool resolved_p)
 \f
 /* Initialize variables for region data dependence analysis.
    When LAZY_REG_LAST is true, do not allocate reg_last array
-   of struct deps immediately.  */
+   of struct deps_desc immediately.  */
 
 void
-init_deps (struct deps *deps, bool lazy_reg_last)
+init_deps (struct deps_desc *deps, bool lazy_reg_last)
 {
   int max_reg = (reload_completed ? FIRST_PSEUDO_REGISTER : max_reg_num ());
 
@@ -3497,7 +3496,7 @@ init_deps (struct deps *deps, bool lazy_reg_last)
 /* Init only reg_last field of DEPS, which was not allocated before as
    we inited DEPS lazily.  */
 void
-init_deps_reg_last (struct deps *deps)
+init_deps_reg_last (struct deps_desc *deps)
 {
   gcc_assert (deps && deps->max_reg > 0);
   gcc_assert (deps->reg_last == NULL);
@@ -3509,7 +3508,7 @@ init_deps_reg_last (struct deps *deps)
 /* Free insn lists found in DEPS.  */
 
 void
-free_deps (struct deps *deps)
+free_deps (struct deps_desc *deps)
 {
   unsigned i;
   reg_set_iterator rsi;
@@ -3548,8 +3547,7 @@ free_deps (struct deps *deps)
 
   /* As we initialize reg_last lazily, it is possible that we didn't allocate
      it at all.  */
-  if (deps->reg_last)
-    free (deps->reg_last);
+  free (deps->reg_last);
   deps->reg_last = NULL;
 
   deps = NULL;
@@ -3558,7 +3556,7 @@ free_deps (struct deps *deps)
 /* Remove INSN from dependence contexts DEPS.  Caution: reg_conditional_sets
    is not handled.  */
 void
-remove_from_deps (struct deps *deps, rtx insn)
+remove_from_deps (struct deps_desc *deps, rtx insn)
 {
   int removed;
   unsigned i;
@@ -4076,7 +4074,7 @@ dump_ds (FILE *f, ds_t s)
   fprintf (f, "}");
 }
 
-void
+DEBUG_FUNCTION void
 debug_ds (ds_t s)
 {
   dump_ds (stderr, s);