#include "toplev.h"
#include "output.h"
#include "ggc.h"
+#include "timevar.h"
#ifndef REGISTER_MOVE_COST
#define REGISTER_MOVE_COST(m, x, y) 2
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
#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. */
;
#endif
#ifndef PIC_OFFSET_TABLE_REG_CALL_CLOBBERED
- else if (i == PIC_OFFSET_TABLE_REGNUM && fixed_regs[i])
+ else if (i == (unsigned) PIC_OFFSET_TABLE_REGNUM && fixed_regs[i])
;
#endif
else if (0
init_reg_sets_1 ();
init_reg_modes ();
+
+ init_reg_autoinc ();
}
/* Initialize some fake stack-frame MEM references for use in
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;
}
}
#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
max_parallel = 3;
max_set_parallel = 0;
+ timevar_push (TV_REG_SCAN);
+
for (insn = f; insn; insn = NEXT_INSN (insn))
if (GET_CODE (insn) == INSN
|| GET_CODE (insn) == CALL_INSN
}
max_parallel += max_set_parallel;
+
+ timevar_pop (TV_REG_SCAN);
}
/* Update 'regscan' information by looking at the insns
REG_POINTER (SET_DEST (x)) = 1;
/* If this is setting a register from a register or from a simple
- conversion of a register, propagate REG_DECL. */
+ conversion of a register, propagate REG_EXPR. */
if (GET_CODE (dest) == REG)
{
rtx src = SET_SRC (x);
|| (GET_CODE (src) == SUBREG && subreg_lowpart_p (src)))
src = XEXP (src, 0);
- if (GET_CODE (src) == REG && REGNO_DECL (REGNO (src)) == 0)
- REGNO_DECL (REGNO (src)) = REGNO_DECL (REGNO (dest));
- else if (GET_CODE (src) == REG && REGNO_DECL (REGNO (dest)) == 0)
- REGNO_DECL (REGNO (dest)) = REGNO_DECL (REGNO (src));
+ if (!REG_ATTRS (dest) && REG_P (src))
+ REG_ATTRS (dest) = REG_ATTRS (src);
+ if (!REG_ATTRS (dest) && GET_CODE (src) == MEM)
+ set_reg_attrs_from_mem (dest, src);
}
/* ... fall through ... */
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
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 */