OSDN Git Service

2009-09-27 Sebastian Pop <sebastian.pop@amd.com>
[pf3gnuchains/gcc-fork.git] / gcc / sched-int.h
index e332c61..35a517e 100644 (file)
@@ -1,7 +1,8 @@
 /* Instruction scheduling pass.  This file contains definitions used
    internally in the scheduler.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   2001, 2003, 2004, 2005, 2006, 2007, 2008, 2009
+   Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -180,13 +181,15 @@ extern bool sel_insn_is_speculation_check (rtx);
    FIRST is the index of the element with the highest priority; i.e. the
    last one in the ready list, since elements are ordered by ascending
    priority.
-   N_READY determines how many insns are on the ready list.  */
+   N_READY determines how many insns are on the ready list.
+   N_DEBUG determines how many debug insns are on the ready list.  */
 struct ready_list
 {
   rtx *vec;
   int veclen;
   int first;
   int n_ready;
+  int n_debug;
 };
 
 extern char *ready_try;
@@ -425,6 +428,25 @@ enum reg_pending_barrier_mode
   TRUE_BARRIER
 };
 
+/* Whether a register movement is associated with a call.  */
+enum post_call_group
+{
+  not_post_call,
+  post_call,
+  post_call_initial
+};
+
+/* Insns which affect pseudo-registers.  */
+struct deps_reg
+{
+  rtx uses;
+  rtx sets;
+  rtx implicit_sets;
+  rtx clobbers;
+  int uses_length;
+  int clobbers_length;
+};
+
 /* Describe state of dependencies used during sched_analyze phase.  */
 struct deps
 {
@@ -480,6 +502,12 @@ struct deps
      Used to prevent register lifetimes from expanding unnecessarily.  */
   rtx last_function_call;
 
+  /* A list of the last function calls that may not return normally
+     we have seen.  We use a list to represent last function calls from
+     multiple predecessor blocks.  Used to prevent moving trapping insns
+     across such calls.  */
+  rtx last_function_call_may_noreturn;
+
   /* A list of insns which use a pseudo register that does not already
      cross a call.  We create dependencies between each of those insn
      and the next call insn, to ensure that they won't cross a call after
@@ -488,7 +516,10 @@ struct deps
 
   /* Used to keep post-call pseudo/hard reg movements together with
      the call.  */
-  enum { not_post_call, post_call, post_call_initial } in_post_call_group_p;
+  enum post_call_group in_post_call_group_p;
+
+  /* The last debug insn we've seen.  */
+  rtx last_debug_insn;
 
   /* The maximum register number for the following arrays.  Before reload
      this is max_reg_num; after reload it is FIRST_PSEUDO_REGISTER.  */
@@ -498,14 +529,7 @@ struct deps
      N within the current basic block; or zero, if there is no
      such insn.  Needed for new registers which may be introduced
      by splitting insns.  */
-  struct deps_reg
-    {
-      rtx uses;
-      rtx sets;
-      rtx clobbers;
-      int uses_length;
-      int clobbers_length;
-    } *reg_last;
+  struct deps_reg *reg_last;
 
   /* Element N is set for each register that has any nonzero element
      in reg_last[N].{uses,sets,clobbers}.  */
@@ -558,6 +582,10 @@ struct haifa_sched_info
      calculations.  */
   int (*contributes_to_priority) (rtx, rtx);
 
+  /* Return true if scheduling insn (passed as the parameter) will trigger
+     finish of scheduling current block.  */
+  bool (*insn_finishes_block_p) (rtx);
+
   /* The boundaries of the set of insns to be scheduled.  */
   rtx prev_head, next_tail;
 
@@ -621,6 +649,14 @@ extern spec_info_t spec_info;
 
 extern struct haifa_sched_info *current_sched_info;
 
+/* Do register pressure sensitive insn scheduling if the flag is set
+   up.  */
+extern bool sched_pressure_p;
+
+/* Map regno -> its cover class.  The map defined only when
+   SCHED_PRESSURE_P is true.  */
+extern enum reg_class *sched_regno_cover_class;
+
 /* Indexed by INSN_UID, the collection of all data associated with
    a single instruction.  */
 
@@ -666,6 +702,52 @@ struct _haifa_deps_insn_data
   unsigned int cant_move : 1;
 };
 
+/* Bits used for storing values of the fields in the following
+   structure.  */
+#define INCREASE_BITS 8
+
+/* The structure describes how the corresponding insn increases the
+   register pressure for each cover class.  */
+struct reg_pressure_data
+{
+  /* Pressure increase for given class because of clobber.  */
+  unsigned int clobber_increase : INCREASE_BITS;
+  /* Increase in register pressure for given class because of register
+     sets. */
+  unsigned int set_increase : INCREASE_BITS;
+  /* Pressure increase for given class because of unused register
+     set.  */
+  unsigned int unused_set_increase : INCREASE_BITS;
+  /* Pressure change: #sets - #deaths.  */
+  int change : INCREASE_BITS;
+};
+
+/* The following structure describes usage of registers by insns.  */
+struct reg_use_data
+{
+  /* Regno used in the insn.  */
+  int regno;
+  /* Insn using the regno.  */
+  rtx insn;
+  /* Cyclic list of elements with the same regno.  */
+  struct reg_use_data *next_regno_use;
+  /* List of elements with the same insn.  */
+  struct reg_use_data *next_insn_use;
+};
+
+/* The following structure describes used sets of registers by insns.
+   Registers are pseudos whose cover class is not NO_REGS or hard
+   registers available for allocations.  */
+struct reg_set_data
+{
+  /* Regno used in the insn.  */
+  int regno;
+  /* Insn setting the regno.  */
+  rtx insn;
+  /* List of elements with the same insn.  */
+  struct reg_set_data *next_insn_set;
+};
+
 struct _haifa_insn_data
 {
   /* We can't place 'struct _deps_list' into h_i_d instead of deps_list_t
@@ -691,10 +773,6 @@ struct _haifa_insn_data
 
   short cost;
 
-  /* This weight is an estimation of the insn's contribution to
-     register pressure.  */
-  short reg_weight;
-
   /* Set if there's DEF-USE dependence between some speculatively
      moved load insn and this one.  */
   unsigned int fed_by_spec_load : 1;
@@ -719,6 +797,26 @@ struct _haifa_insn_data
 
   /* Original pattern of the instruction.  */
   rtx orig_pat;
+
+  /* The following array contains info how the insn increases register
+     pressure.  There is an element for each cover class of pseudos
+     referenced in insns.  */
+  struct reg_pressure_data *reg_pressure;
+  /* The following array contains maximal reg pressure between last
+     scheduled insn and given insn.  There is an element for each
+     cover class of pseudos referenced in insns.  This info updated
+     after scheduling each insn for each insn between the two
+     mentioned insns.  */
+  int *max_reg_pressure;
+  /* The following list contains info about used pseudos and hard
+     registers available for allocation.  */
+  struct reg_use_data *reg_use_list;
+  /* The following list contains info about set pseudos and hard
+     registers available for allocation.  */
+  struct reg_set_data *reg_set_list;
+  /* Info about how scheduling the insn changes cost of register
+     pressure excess (between source and target).  */
+  int reg_pressure_excess_cost_change;
 };
 
 typedef struct _haifa_insn_data haifa_insn_data_def;
@@ -734,7 +832,12 @@ extern VEC(haifa_insn_data_def, heap) *h_i_d;
 /* Accessor macros for h_i_d.  There are more in haifa-sched.c and
    sched-rgn.c.  */
 #define INSN_PRIORITY(INSN) (HID (INSN)->priority)
-#define INSN_REG_WEIGHT(INSN) (HID (INSN)->reg_weight)
+#define INSN_REG_PRESSURE(INSN) (HID (INSN)->reg_pressure)
+#define INSN_MAX_REG_PRESSURE(INSN) (HID (INSN)->max_reg_pressure)
+#define INSN_REG_USE_LIST(INSN) (HID (INSN)->reg_use_list)
+#define INSN_REG_SET_LIST(INSN) (HID (INSN)->reg_set_list)
+#define INSN_REG_PRESSURE_EXCESS_COST_CHANGE(INSN) \
+  (HID (INSN)->reg_pressure_excess_cost_change)
 #define INSN_PRIORITY_STATUS(INSN) (HID (INSN)->priority_status)
 
 typedef struct _haifa_deps_insn_data haifa_deps_insn_data_def;
@@ -784,6 +887,23 @@ extern VEC(haifa_deps_insn_data_def, heap) *h_d_i_d;
 #define IS_SPECULATION_BRANCHY_CHECK_P(INSN) \
   (RECOVERY_BLOCK (INSN) != NULL && RECOVERY_BLOCK (INSN) != EXIT_BLOCK_PTR)
 
+/* The unchanging bit tracks whether a debug insn is to be handled
+   like an insn (i.e., schedule it) or like a note (e.g., it is next
+   to a basic block boundary.  */
+#define DEBUG_INSN_SCHED_P(insn) \
+  (RTL_FLAG_CHECK1("DEBUG_INSN_SCHED_P", (insn), DEBUG_INSN)->unchanging)
+
+/* True if INSN is a debug insn that is next to a basic block
+   boundary, i.e., it is to be handled by the scheduler like a
+   note.  */
+#define BOUNDARY_DEBUG_INSN_P(insn) \
+  (DEBUG_INSN_P (insn) && !DEBUG_INSN_SCHED_P (insn))
+/* True if INSN is a debug insn that is not next to a basic block
+   boundary, i.e., it is to be handled by the scheduler like an
+   insn.  */
+#define SCHEDULE_DEBUG_INSN_P(insn) \
+  (DEBUG_INSN_P (insn) && DEBUG_INSN_SCHED_P (insn))
+
 /* Dep status (aka ds_t) of the link encapsulates information, that is needed
    for speculative scheduling.  Namely, it is 4 integers in the range
    [0, MAX_DEP_WEAK] and 3 bits.
@@ -1079,7 +1199,8 @@ extern bool sched_insns_conditions_mutex_p (const_rtx, const_rtx);
 extern bool sched_insn_is_legitimate_for_speculation_p (const_rtx, ds_t);
 extern void add_dependence (rtx, rtx, enum reg_note);
 extern void sched_analyze (struct deps *, rtx, rtx);
-extern void init_deps (struct deps *);
+extern void init_deps (struct deps *, bool);
+extern void init_deps_reg_last (struct deps *);
 extern void free_deps (struct deps *);
 extern void init_deps_global (void);
 extern void finish_deps_global (void);
@@ -1115,7 +1236,9 @@ extern void extend_dependency_caches (int, bool);
 
 extern void debug_ds (ds_t);
 
+
 /* Functions in haifa-sched.c.  */
+extern void sched_init_region_reg_pressure_info (void);
 extern int haifa_classify_insn (const_rtx);
 extern void get_ebb_head_tail (basic_block, basic_block, rtx *, rtx *);
 extern int no_real_insns_p (const_rtx, const_rtx);
@@ -1125,6 +1248,7 @@ extern int dep_cost_1 (dep_t, dw_t);
 extern int dep_cost (dep_t);
 extern int set_priorities (rtx, rtx);
 
+extern void sched_setup_bb_reg_pressure_info (basic_block, rtx);
 extern void schedule_block (basic_block *);
 
 extern int cycle_issued_insns;
@@ -1326,7 +1450,8 @@ sd_iterator_cond (sd_iterator_def *it_ptr, dep_t *dep_ptr)
 
          it_ptr->linkp = &DEPS_LIST_FIRST (list);
 
-         return sd_iterator_cond (it_ptr, dep_ptr);
+         if (list)
+           return sd_iterator_cond (it_ptr, dep_ptr);
        }
 
       *dep_ptr = NULL;