aboutsummaryrefslogtreecommitdiff
path: root/gcc/regclass.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/regclass.c')
-rw-r--r--gcc/regclass.c101
1 files changed, 59 insertions, 42 deletions
diff --git a/gcc/regclass.c b/gcc/regclass.c
index 20c7d3b03d1..45c69d8b89a 100644
--- a/gcc/regclass.c
+++ b/gcc/regclass.c
@@ -48,6 +48,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
static void init_reg_sets_1 PARAMS ((void));
static void init_reg_modes PARAMS ((void));
+static void init_reg_autoinc PARAMS ((void));
/* If we have auto-increment or auto-decrement and we can have secondary
reloads, we are not allowed to use classes requiring secondary
@@ -228,9 +229,9 @@ static char *in_inc_dec;
#endif /* FORBIDDEN_INC_DEC_CLASSES */
#ifdef CANNOT_CHANGE_MODE_CLASS
-/* All registers that have been subreged. Indexed by mode, where each
- entry is a regset of registers. */
-regset_head subregs_of_mode [NUM_MACHINE_MODES];
+/* 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. */
@@ -576,6 +577,8 @@ init_regs ()
init_reg_sets_1 ();
init_reg_modes ();
+
+ init_reg_autoinc ();
}
/* Initialize some fake stack-frame MEM references for use in
@@ -1141,37 +1144,18 @@ scan_one_insn (insn, pass)
return insn;
}
-/* This is a pass of the compiler that scans all instructions
- and calculates the preferred class for each pseudo-register.
- This information can be accessed later by calling `reg_preferred_class'.
- This pass comes just before local register allocation. */
+/* Initialize information about which register classes can be used for
+ pseudos that are auto-incremented or auto-decremented. */
-void
-regclass (f, nregs, dump)
- rtx f;
- int nregs;
- FILE *dump;
+static void
+init_reg_autoinc ()
{
- rtx insn;
- int i;
- int pass;
-
- init_recog ();
-
- costs = (struct costs *) xmalloc (nregs * sizeof (struct costs));
-
#ifdef FORBIDDEN_INC_DEC_CLASSES
-
- in_inc_dec = (char *) xmalloc (nregs);
-
- /* Initialize information about which register classes can be used for
- pseudos that are auto-incremented or auto-decremented. It would
- seem better to put this in init_reg_sets, but we need to be able
- to allocate rtx, which we can't do that early. */
+ int i;
for (i = 0; i < N_REG_CLASSES; i++)
{
- rtx r = gen_rtx_REG (VOIDmode, 0);
+ rtx r = gen_rtx_raw_REG (VOIDmode, 0);
enum machine_mode m;
int j;
@@ -1212,6 +1196,32 @@ regclass (f, nregs, dump)
}
}
#endif /* FORBIDDEN_INC_DEC_CLASSES */
+}
+
+/* This is a pass of the compiler that scans all instructions
+ and calculates the preferred class for each pseudo-register.
+ This information can be accessed later by calling `reg_preferred_class'.
+ This pass comes just before local register allocation. */
+
+void
+regclass (f, nregs, dump)
+ rtx f;
+ int nregs;
+ FILE *dump;
+{
+ rtx insn;
+ int i;
+ int pass;
+
+ init_recog ();
+
+ costs = (struct costs *) xmalloc (nregs * sizeof (struct costs));
+
+#ifdef FORBIDDEN_INC_DEC_CLASSES
+
+ in_inc_dec = (char *) xmalloc (nregs);
+
+#endif /* FORBIDDEN_INC_DEC_CLASSES */
/* Normally we scan the insns once and determine the best class to use for
each register. However, if -fexpensive_optimizations are on, we do so
@@ -1678,7 +1688,7 @@ record_reg_classes (n_alts, n_ops, ops, modes,
if (GET_CODE (op) == MEM)
win = 1;
}
- if (EXTRA_ADDRESS_CONSTRAINT (op))
+ if (EXTRA_ADDRESS_CONSTRAINT (c))
{
/* Every address can be reloaded to fit. */
allows_addr = 1;
@@ -2614,15 +2624,18 @@ cannot_change_mode_set_regs (used, from, regno)
unsigned int regno;
{
enum machine_mode to;
- enum reg_class class;
+ int n, i;
+ int start = regno * MAX_MACHINE_MODE;
- for (to = VOIDmode; to < MAX_MACHINE_MODE; ++to)
- if (REGNO_REG_SET_P (&subregs_of_mode[to], regno))
- {
- class = CANNOT_CHANGE_MODE_CLASS (from, to);
- if (class != NO_REGS)
- IOR_HARD_REG_SET (*used, reg_class_contents [(int) class]);
- }
+ 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);
+ );
}
/* Return 1 if REGNO has had an invalid mode change in CLASS from FROM
@@ -2635,12 +2648,16 @@ invalid_mode_change_p (regno, class, from_mode)
enum machine_mode from_mode;
{
enum machine_mode to_mode;
-
- for (to_mode = 0; to_mode < NUM_MACHINE_MODES; ++to_mode)
- if (REGNO_REG_SET_P (&subregs_of_mode[(int) to_mode], regno)
- && reg_classes_intersect_p
- (class, CANNOT_CHANGE_MODE_CLASS (from_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;
}
#endif /* CANNOT_CHANGE_MODE_CLASS */