OSDN Git Service

2009-09-23 Yuri Gribov <tetra2005@googlemail.com>
[pf3gnuchains/gcc-fork.git] / gcc / sched-int.h
index aa5007b..4d60ece 100644 (file)
@@ -181,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;
@@ -439,6 +441,7 @@ struct deps_reg
 {
   rtx uses;
   rtx sets;
+  rtx implicit_sets;
   rtx clobbers;
   int uses_length;
   int clobbers_length;
@@ -499,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
@@ -509,6 +518,9 @@ struct deps
      the call.  */
   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.  */
   int max_reg;
@@ -637,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.  */
 
@@ -682,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
@@ -707,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;
@@ -735,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;
@@ -750,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;
@@ -800,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.
@@ -1131,7 +1235,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);
@@ -1141,6 +1247,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;
@@ -1342,7 +1449,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;