OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / regs.h
index f0679f7..328b839 100644 (file)
@@ -1,6 +1,7 @@
 /* Define per-register tables for data flow info and register allocation.
    Copyright (C) 1987, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   1999, 2000, 2003, 2004, 2005, 2006, 2007, 2008, 2010 Free Software
+   Foundation, Inc.
 
 This file is part of GCC.
 
@@ -21,10 +22,8 @@ along with GCC; see the file COPYING3.  If not see
 #ifndef GCC_REGS_H
 #define GCC_REGS_H
 
-#include "varray.h"
-#include "obstack.h"
+#include "machmode.h"
 #include "hard-reg-set.h"
-#include "basic-block.h"
 
 #define REG_BYTES(R) mode_size[(int) GET_MODE (R)]
 
@@ -37,10 +36,6 @@ along with GCC; see the file COPYING3.  If not see
 #define REGMODE_NATURAL_SIZE(MODE)     UNITS_PER_WORD
 #endif
 
-#ifndef SMALL_REGISTER_CLASSES
-#define SMALL_REGISTER_CLASSES 0
-#endif
-
 /* Maximum register number used in this function, plus one.  */
 
 extern int max_regno;
@@ -49,11 +44,11 @@ extern int max_regno;
    regstat_init_n_sets_and_refs from the current values of
    DF_REG_DEF_COUNT and DF_REG_USE_COUNT.  REG_N_REFS and REG_N_SETS
    should only be used if a pass need to change these values in some
-   magical way or or the pass needs to have accurate values for these
+   magical way or the pass needs to have accurate values for these
    and is not using incremental df scanning.
 
    At the end of a pass that uses REG_N_REFS and REG_N_SETS, a call
-   should be made to regstat_free_n_sets_and_refs.  
+   should be made to regstat_free_n_sets_and_refs.
 
    Local alloc seems to play pretty loose with these values.
    REG_N_REFS is set to 0 if the register is used in an asm.
@@ -129,7 +124,7 @@ extern size_t reg_info_p_size;
 
 #define REG_FREQ(N) (reg_info_p[N].freq)
 
-/* The weights for each insn varries from 0 to REG_FREQ_BASE.
+/* The weights for each insn varies from 0 to REG_FREQ_BASE.
    This constant does not need to be high, as in infrequently executed
    regions we want to count instructions equivalently to optimize for
    size instead of speed.  */
@@ -219,17 +214,6 @@ extern size_t reg_info_p_size;
 
 extern short *reg_renumber;
 
-/* Vector indexed by machine mode saying whether there are regs of that mode.  */
-
-extern bool have_regs_of_mode [MAX_MACHINE_MODE];
-
-/* For each hard register, the widest mode object that it can contain.
-   This will be a MODE_INT mode if the register can hold integers.  Otherwise
-   it will be a MODE_FLOAT or a MODE_CC mode, whichever is valid for the
-   register.  */
-
-extern enum machine_mode reg_raw_mode[FIRST_PSEUDO_REGISTER];
-
 /* Flag set by local-alloc or global-alloc if they decide to allocate
    something in a call-clobbered register.  */
 
@@ -243,12 +227,6 @@ extern int caller_save_needed;
 #define CALLER_SAVE_PROFITABLE(REFS, CALLS)  (4 * (CALLS) < (REFS))
 #endif
 
-/* On most machines a register class is likely to be spilled if it
-   only has one register.  */
-#ifndef CLASS_LIKELY_SPILLED_P
-#define CLASS_LIKELY_SPILLED_P(CLASS) (reg_class_size[(int) (CLASS)] == 1)
-#endif
-
 /* Select a register mode required for caller save of hard regno REGNO.  */
 #ifndef HARD_REGNO_CALLER_SAVE_MODE
 #define HARD_REGNO_CALLER_SAVE_MODE(REGNO, NREGS, MODE) \
@@ -261,8 +239,79 @@ extern int caller_save_needed;
 #define HARD_REGNO_CALL_PART_CLOBBERED(REGNO, MODE) 0
 #endif
 
-/* Specify number of hard registers given machine mode occupy.  */
-extern unsigned char hard_regno_nregs[FIRST_PSEUDO_REGISTER][MAX_MACHINE_MODE];
+typedef unsigned short move_table[N_REG_CLASSES];
+
+/* Target-dependent globals.  */
+struct target_regs {
+  /* For each starting hard register, the number of consecutive hard
+     registers that a given machine mode occupies.  */
+  unsigned char x_hard_regno_nregs[FIRST_PSEUDO_REGISTER][MAX_MACHINE_MODE];
+
+  /* For each hard register, the widest mode object that it can contain.
+     This will be a MODE_INT mode if the register can hold integers.  Otherwise
+     it will be a MODE_FLOAT or a MODE_CC mode, whichever is valid for the
+     register.  */
+  enum machine_mode x_reg_raw_mode[FIRST_PSEUDO_REGISTER];
+
+  /* Vector indexed by machine mode saying whether there are regs of
+     that mode.  */
+  bool x_have_regs_of_mode[MAX_MACHINE_MODE];
+
+  /* 1 if the corresponding class contains a register of the given mode.  */
+  char x_contains_reg_of_mode[N_REG_CLASSES][MAX_MACHINE_MODE];
+
+  /* Maximum cost of moving from a register in one class to a register
+     in another class.  Based on TARGET_REGISTER_MOVE_COST.  */
+  move_table *x_move_cost[MAX_MACHINE_MODE];
+
+  /* Similar, but here we don't have to move if the first index is a
+     subset of the second so in that case the cost is zero.  */
+  move_table *x_may_move_in_cost[MAX_MACHINE_MODE];
+
+  /* Similar, but here we don't have to move if the first index is a
+     superset of the second so in that case the cost is zero.  */
+  move_table *x_may_move_out_cost[MAX_MACHINE_MODE];
+
+  /* Keep track of the last mode we initialized move costs for.  */
+  int x_last_mode_for_init_move_cost;
+
+  /* Record for each mode whether we can move a register directly to or
+     from an object of that mode in memory.  If we can't, we won't try
+     to use that mode directly when accessing a field of that mode.  */
+  char x_direct_load[NUM_MACHINE_MODES];
+  char x_direct_store[NUM_MACHINE_MODES];
+
+  /* Record for each mode whether we can float-extend from memory.  */
+  bool x_float_extend_from_mem[NUM_MACHINE_MODES][NUM_MACHINE_MODES];
+};
+
+extern struct target_regs default_target_regs;
+#if SWITCHABLE_TARGET
+extern struct target_regs *this_target_regs;
+#else
+#define this_target_regs (&default_target_regs)
+#endif
+
+#define hard_regno_nregs \
+  (this_target_regs->x_hard_regno_nregs)
+#define reg_raw_mode \
+  (this_target_regs->x_reg_raw_mode)
+#define have_regs_of_mode \
+  (this_target_regs->x_have_regs_of_mode)
+#define contains_reg_of_mode \
+  (this_target_regs->x_contains_reg_of_mode)
+#define move_cost \
+  (this_target_regs->x_move_cost)
+#define may_move_in_cost \
+  (this_target_regs->x_may_move_in_cost)
+#define may_move_out_cost \
+  (this_target_regs->x_may_move_out_cost)
+#define direct_load \
+  (this_target_regs->x_direct_load)
+#define direct_store \
+  (this_target_regs->x_direct_store)
+#define float_extend_from_mem \
+  (this_target_regs->x_float_extend_from_mem)
 
 /* Return an exclusive upper bound on the registers occupied by hard
    register (reg:MODE REGNO).  */
@@ -348,4 +397,48 @@ overlaps_hard_reg_set_p (const HARD_REG_SET regs, enum machine_mode mode,
   return false;
 }
 
+/* Like add_to_hard_reg_set, but use a REGNO/NREGS range instead of
+   REGNO and MODE.  */
+
+static inline void
+add_range_to_hard_reg_set (HARD_REG_SET *regs, unsigned int regno,
+                          int nregs)
+{
+  while (nregs-- > 0)
+    SET_HARD_REG_BIT (*regs, regno + nregs);
+}
+
+/* Likewise, but remove the registers.  */
+
+static inline void
+remove_range_from_hard_reg_set (HARD_REG_SET *regs, unsigned int regno,
+                               int nregs)
+{
+  while (nregs-- > 0)
+    CLEAR_HARD_REG_BIT (*regs, regno + nregs);
+}
+
+/* Like overlaps_hard_reg_set_p, but use a REGNO/NREGS range instead of
+   REGNO and MODE.  */
+static inline bool
+range_overlaps_hard_reg_set_p (const HARD_REG_SET set, unsigned regno,
+                              int nregs)
+{
+  while (nregs-- > 0)
+    if (TEST_HARD_REG_BIT (set, regno + nregs))
+      return true;
+  return false;
+}
+
+/* Like in_hard_reg_set_p, but use a REGNO/NREGS range instead of
+   REGNO and MODE.  */
+static inline bool
+range_in_hard_reg_set_p (const HARD_REG_SET set, unsigned regno, int nregs)
+{
+  while (nregs-- > 0)
+    if (!TEST_HARD_REG_BIT (set, regno + nregs))
+      return false;
+  return true;
+}
+
 #endif /* GCC_REGS_H */