X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fregclass.c;h=78951cfd3dac4909a32f2b37a9bde3ed54089674;hb=dc820f84d22b9e29b94f4c416d29c858079ac46f;hp=a73d8865bac3ba11f0f435918de97c7392513d3c;hpb=04e579b6fdd5e00f2367ee4282d097bee5efeadc;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/regclass.c b/gcc/regclass.c index a73d8865bac..78951cfd3da 100644 --- a/gcc/regclass.c +++ b/gcc/regclass.c @@ -1,6 +1,6 @@ /* Compute register class preferences for pseudo-registers. Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996 - 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 + 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. This file is part of GCC. @@ -45,6 +45,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "output.h" #include "ggc.h" #include "timevar.h" +#include "hashtab.h" static void init_reg_sets_1 (void); static void init_reg_autoinc (void); @@ -104,6 +105,13 @@ static const char initial_call_used_regs[] = CALL_USED_REGISTERS; char call_really_used_regs[] = CALL_REALLY_USED_REGISTERS; #endif +#ifdef CALL_REALLY_USED_REGISTERS +#define CALL_REALLY_USED_REGNO_P(X) call_really_used_regs[X] +#else +#define CALL_REALLY_USED_REGNO_P(X) call_used_regs[X] +#endif + + /* Indexed by hard register number, contains 1 for registers that are fixed use or call used registers that cannot hold quantities across calls even if we are willing to save and restore them. call fixed @@ -164,11 +172,11 @@ unsigned int reg_class_size[N_REG_CLASSES]; /* For each reg class, table listing all the containing classes. */ -enum reg_class reg_class_superclasses[N_REG_CLASSES][N_REG_CLASSES]; +static enum reg_class reg_class_superclasses[N_REG_CLASSES][N_REG_CLASSES]; /* For each reg class, table listing all the classes contained in it. */ -enum reg_class reg_class_subclasses[N_REG_CLASSES][N_REG_CLASSES]; +static enum reg_class reg_class_subclasses[N_REG_CLASSES][N_REG_CLASSES]; /* For each pair of reg classes, a largest reg class contained in their union. */ @@ -184,6 +192,10 @@ enum reg_class reg_class_superunion[N_REG_CLASSES][N_REG_CLASSES]; const char * reg_names[] = REGISTER_NAMES; +/* Array containing all of the register class names. */ + +const char * reg_class_names[] = REG_CLASS_NAMES; + /* 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 @@ -228,12 +240,6 @@ static char *in_inc_dec; #endif /* FORBIDDEN_INC_DEC_CLASSES */ -#ifdef CANNOT_CHANGE_MODE_CLASS -/* All registers that have been subreged. Indexed by regno * MAX_MACHINE_MODE - + mode. */ -bitmap_head subregs_of_mode; -#endif - /* Sample MEM values for use by memory_move_secondary_cost. */ static GTY(()) rtx top_of_stack[MAX_MACHINE_MODE]; @@ -291,9 +297,6 @@ init_reg_sets (void) memcpy (call_used_regs, initial_call_used_regs, sizeof call_used_regs); memset (global_regs, 0, sizeof global_regs); - /* Do any additional initialization regsets may need. */ - INIT_ONCE_REG_SET (); - #ifdef REG_ALLOC_ORDER for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) inv_reg_alloc_order[reg_alloc_order[i]] = i; @@ -454,7 +457,11 @@ init_reg_sets_1 (void) If we are generating PIC code, the PIC offset table register is preserved across calls, though the target can override that. */ - if (i == STACK_POINTER_REGNUM || i == FRAME_POINTER_REGNUM) + if (i == STACK_POINTER_REGNUM) + ; + else if (global_regs[i]) + SET_HARD_REG_BIT (regs_invalidated_by_call, i); + else if (i == FRAME_POINTER_REGNUM) ; #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM else if (i == HARD_FRAME_POINTER_REGNUM) @@ -468,13 +475,7 @@ init_reg_sets_1 (void) else if (i == (unsigned) PIC_OFFSET_TABLE_REGNUM && fixed_regs[i]) ; #endif - else if (0 -#ifdef CALL_REALLY_USED_REGISTERS - || call_really_used_regs[i] -#else - || call_used_regs[i] -#endif - || global_regs[i]) + else if (CALL_REALLY_USED_REGNO_P (i)) SET_HARD_REG_BIT (regs_invalidated_by_call, i); } @@ -800,6 +801,12 @@ globalize_reg (int i) global_regs[i] = 1; + /* If we're globalizing the frame pointer, we need to set the + appropriate regs_invalidated_by_call bit, even if it's already + set in fixed_regs. */ + if (i != STACK_POINTER_REGNUM) + SET_HARD_REG_BIT (regs_invalidated_by_call, i); + /* If already fixed, nothing else to do. */ if (fixed_regs[i]) return; @@ -813,7 +820,6 @@ globalize_reg (int i) SET_HARD_REG_BIT (fixed_reg_set, i); SET_HARD_REG_BIT (call_used_reg_set, i); SET_HARD_REG_BIT (call_fixed_reg_set, i); - SET_HARD_REG_BIT (regs_invalidated_by_call, i); } /* Now the data and code for the `regclass' pass, which happens @@ -923,7 +929,6 @@ regclass_init (void) static void dump_regclass (FILE *dump) { - static const char *const reg_class_names[] = REG_CLASS_NAMES; int i; for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) { @@ -1346,7 +1351,6 @@ regclass (rtx f, int nregs, FILE *dump) && (reg_pref[i].prefclass != (int) best || reg_pref[i].altclass != (int) alt)) { - static const char *const reg_class_names[] = REG_CLASS_NAMES; fprintf (dump, " Register %i", i); if (alt == ALL_REGS || best == ALL_REGS) fprintf (dump, " pref %s\n", reg_class_names[(int) best]); @@ -1572,7 +1576,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, win = address_operand (op, GET_MODE (op)); /* We know this operand is an address, so we want it to be allocated to a register that can be the base of an - address, ie BASE_REG_CLASS. */ + address, i.e. BASE_REG_CLASS. */ classes[i] = reg_class_subunion[(int) classes[i]] [(int) MODE_BASE_REG_CLASS (VOIDmode)]; @@ -1686,7 +1690,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, win = 1; /* We know this operand is an address, so we want it to be allocated to a register that can be the base of an - address, ie BASE_REG_CLASS. */ + address, i.e. BASE_REG_CLASS. */ classes[i] = reg_class_subunion[(int) classes[i]] [(int) MODE_BASE_REG_CLASS (VOIDmode)]; @@ -2006,25 +2010,27 @@ record_address_regs (rtx x, enum reg_class class, int scale) record_address_regs (arg0, INDEX_REG_CLASS, scale); /* If both operands are registers but one is already a hard register - of index or base class, give the other the class that the hard - register is not. */ + of index or reg-base class, give the other the class that the + hard register is not. */ -#ifdef REG_OK_FOR_BASE_P else if (code0 == REG && code1 == REG && REGNO (arg0) < FIRST_PSEUDO_REGISTER - && (REG_OK_FOR_BASE_P (arg0) || REG_OK_FOR_INDEX_P (arg0))) + && (REG_MODE_OK_FOR_REG_BASE_P (arg0, VOIDmode) + || REG_OK_FOR_INDEX_P (arg0))) record_address_regs (arg1, - REG_OK_FOR_BASE_P (arg0) - ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (VOIDmode), + REG_MODE_OK_FOR_REG_BASE_P (arg0, VOIDmode) + ? INDEX_REG_CLASS + : MODE_BASE_REG_REG_CLASS (VOIDmode), scale); else if (code0 == REG && code1 == REG && REGNO (arg1) < FIRST_PSEUDO_REGISTER - && (REG_OK_FOR_BASE_P (arg1) || REG_OK_FOR_INDEX_P (arg1))) + && (REG_MODE_OK_FOR_REG_BASE_P (arg1, VOIDmode) + || REG_OK_FOR_INDEX_P (arg1))) record_address_regs (arg0, - REG_OK_FOR_BASE_P (arg1) - ? INDEX_REG_CLASS : MODE_BASE_REG_CLASS (VOIDmode), + REG_MODE_OK_FOR_REG_BASE_P (arg1, VOIDmode) + ? INDEX_REG_CLASS + : MODE_BASE_REG_REG_CLASS (VOIDmode), scale); -#endif /* If one operand is known to be a pointer, it must be the base with the other operand the index. Likewise if the other operand @@ -2033,14 +2039,16 @@ record_address_regs (rtx x, enum reg_class class, int scale) else if ((code0 == REG && REG_POINTER (arg0)) || code1 == MULT) { - record_address_regs (arg0, MODE_BASE_REG_CLASS (VOIDmode), scale); + record_address_regs (arg0, MODE_BASE_REG_REG_CLASS (VOIDmode), + scale); record_address_regs (arg1, INDEX_REG_CLASS, scale); } else if ((code1 == REG && REG_POINTER (arg1)) || code0 == MULT) { record_address_regs (arg0, INDEX_REG_CLASS, scale); - record_address_regs (arg1, MODE_BASE_REG_CLASS (VOIDmode), scale); + record_address_regs (arg1, MODE_BASE_REG_REG_CLASS (VOIDmode), + scale); } /* Otherwise, count equal chances that each might be a base @@ -2048,10 +2056,10 @@ record_address_regs (rtx x, enum reg_class class, int scale) else { - record_address_regs (arg0, MODE_BASE_REG_CLASS (VOIDmode), + record_address_regs (arg0, MODE_BASE_REG_REG_CLASS (VOIDmode), scale / 2); record_address_regs (arg0, INDEX_REG_CLASS, scale / 2); - record_address_regs (arg1, MODE_BASE_REG_CLASS (VOIDmode), + record_address_regs (arg1, MODE_BASE_REG_REG_CLASS (VOIDmode), scale / 2); record_address_regs (arg1, INDEX_REG_CLASS, scale / 2); } @@ -2172,7 +2180,6 @@ allocate_reg_info (size_t num_regs, int new_p, int renumber_p) reg_pref_buffer = xmalloc (regno_allocated * sizeof (struct reg_pref)); } - else { VARRAY_GROW (reg_n_info, regno_allocated); @@ -2248,9 +2255,6 @@ allocate_reg_info (size_t num_regs, int new_p, int renumber_p) if (renumber_p) reg_renumber = renumber; - - /* Tell the regset code about the new number of registers. */ - MAX_REGNO_REG_SET (num_regs, new_p, renumber_p); } /* Free up the space allocated by allocate_reg_info. */ @@ -2301,7 +2305,7 @@ int max_parallel; static int max_set_parallel; void -reg_scan (rtx f, unsigned int nregs, int repeat ATTRIBUTE_UNUSED) +reg_scan (rtx f, unsigned int nregs) { rtx insn; @@ -2390,7 +2394,6 @@ reg_scan_mark_refs (rtx x, rtx insn, int note_flag, unsigned int min_regno) if (regno >= min_regno) { - REGNO_LAST_NOTE_UID (regno) = INSN_UID (insn); if (!note_flag) REGNO_LAST_UID (regno) = INSN_UID (insn); if (REGNO_FIRST_UID (regno) == 0) @@ -2575,15 +2578,71 @@ reg_classes_intersect_p (enum reg_class c1, enum reg_class c2) return 0; } -/* Release any memory allocated by register sets. */ +#ifdef CANNOT_CHANGE_MODE_CLASS + +struct subregs_of_mode_node +{ + unsigned int block; + unsigned char modes[MAX_MACHINE_MODE]; +}; + +static htab_t subregs_of_mode; + +static hashval_t +som_hash (const void *x) +{ + const struct subregs_of_mode_node *a = x; + return a->block; +} + +static int +som_eq (const void *x, const void *y) +{ + const struct subregs_of_mode_node *a = x; + const struct subregs_of_mode_node *b = y; + return a->block == b->block; +} void -regset_release_memory (void) +init_subregs_of_mode (void) { - bitmap_release_memory (); + if (subregs_of_mode) + htab_empty (subregs_of_mode); + else + subregs_of_mode = htab_create (100, som_hash, som_eq, free); +} + +void +record_subregs_of_mode (rtx subreg) +{ + struct subregs_of_mode_node dummy, *node; + enum machine_mode mode; + unsigned int regno; + void **slot; + + if (!REG_P (SUBREG_REG (subreg))) + return; + + regno = REGNO (SUBREG_REG (subreg)); + mode = GET_MODE (subreg); + + if (regno < FIRST_PSEUDO_REGISTER) + return; + + dummy.block = regno & -8; + slot = htab_find_slot_with_hash (subregs_of_mode, &dummy, + dummy.block, INSERT); + node = *slot; + if (node == NULL) + { + node = xcalloc (1, sizeof (*node)); + node->block = regno & -8; + *slot = node; + } + + node->modes[mode] |= 1 << (regno & 7); } -#ifdef CANNOT_CHANGE_MODE_CLASS /* Set bits in *USED which correspond to registers which can't change their mode from FROM to any mode in which REGNO was encountered. */ @@ -2591,19 +2650,23 @@ void cannot_change_mode_set_regs (HARD_REG_SET *used, enum machine_mode from, unsigned int regno) { + struct subregs_of_mode_node dummy, *node; enum machine_mode to; - int n, i; - int start = regno * MAX_MACHINE_MODE; + unsigned char mask; + unsigned int i; - EXECUTE_IF_SET_IN_BITMAP (&subregs_of_mode, start, n, - if (n >= MAX_MACHINE_MODE + start) - return; - to = n - start; - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (! TEST_HARD_REG_BIT (*used, i) - && REG_CANNOT_CHANGE_MODE_P (i, from, to)) - SET_HARD_REG_BIT (*used, i); - ); + dummy.block = regno & -8; + node = htab_find_with_hash (subregs_of_mode, &dummy, dummy.block); + if (node == NULL) + return; + + mask = 1 << (regno & 7); + for (to = VOIDmode; to < NUM_MACHINE_MODES; to++) + if (node->modes[to] & mask) + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (!TEST_HARD_REG_BIT (*used, i) + && REG_CANNOT_CHANGE_MODE_P (i, from, to)) + SET_HARD_REG_BIT (*used, i); } /* Return 1 if REGNO has had an invalid mode change in CLASS from FROM @@ -2611,20 +2674,24 @@ cannot_change_mode_set_regs (HARD_REG_SET *used, enum machine_mode from, bool invalid_mode_change_p (unsigned int regno, enum reg_class class, - enum machine_mode from_mode) + enum machine_mode from) { - enum machine_mode to_mode; - int n; - int start = regno * MAX_MACHINE_MODE; - - EXECUTE_IF_SET_IN_BITMAP (&subregs_of_mode, start, n, - if (n >= MAX_MACHINE_MODE + start) - return 0; - to_mode = n - start; - if (CANNOT_CHANGE_MODE_CLASS (from_mode, to_mode, class)) - return 1; - ); - return 0; + struct subregs_of_mode_node dummy, *node; + enum machine_mode to; + unsigned char mask; + + dummy.block = regno & -8; + node = htab_find_with_hash (subregs_of_mode, &dummy, dummy.block); + if (node == NULL) + return false; + + mask = 1 << (regno & 7); + for (to = VOIDmode; to < NUM_MACHINE_MODES; to++) + if (node->modes[to] & mask) + if (CANNOT_CHANGE_MODE_CLASS (from, to, class)) + return true; + + return false; } #endif /* CANNOT_CHANGE_MODE_CLASS */