HARD_REG_SET regs_invalidated_by_call;
+/* Same information as REGS_INVALIDATED_BY_CALL but in regset form to be used
+ in dataflow more conveniently. */
+
+regset regs_invalidated_by_call_regset;
+
+/* The bitmap_obstack is used to hold some static variables that
+ should not be reset after each function is compiled. */
+
+static bitmap_obstack persistent_obstack;
+
/* Table of register numbers in the order in which to try to use them. */
#ifdef REG_ALLOC_ORDER
int reg_alloc_order[FIRST_PSEUDO_REGISTER] = REG_ALLOC_ORDER;
/* For each reg class, table listing all the classes contained in it. */
-static enum reg_class reg_class_subclasses[N_REG_CLASSES][N_REG_CLASSES];
+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. */
/* 1 if class does contain register of given mode. */
-static char contains_reg_of_mode [N_REG_CLASSES] [MAX_MACHINE_MODE];
-
-typedef unsigned short move_table[N_REG_CLASSES];
+char 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 REGISTER_MOVE_COST. */
-static move_table *move_cost[MAX_MACHINE_MODE];
+move_table *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. */
-static move_table *may_move_in_cost[MAX_MACHINE_MODE];
+move_table *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. */
-static move_table *may_move_out_cost[MAX_MACHINE_MODE];
+move_table *may_move_out_cost[MAX_MACHINE_MODE];
/* Keep track of the last mode we initialized move costs for. */
static int last_mode_for_init_move_cost;
/* Initialize may_move_cost and friends for mode M. */
-static void
+void
init_move_cost (enum machine_mode m)
{
static unsigned short last_move_cost[N_REG_CLASSES][N_REG_CLASSES];
CLEAR_HARD_REG_SET (call_fixed_reg_set);
CLEAR_HARD_REG_SET (regs_invalidated_by_call);
CLEAR_HARD_REG_SET (losing_caller_save_reg_set);
+ if (!regs_invalidated_by_call_regset)
+ {
+ bitmap_obstack_initialize (&persistent_obstack);
+ regs_invalidated_by_call_regset = ALLOC_REG_SET (&persistent_obstack);
+ }
+ else
+ CLEAR_REG_SET (regs_invalidated_by_call_regset);
memcpy (call_fixed_regs, fixed_regs, sizeof call_fixed_regs);
if (i == STACK_POINTER_REGNUM)
;
else if (global_regs[i])
- SET_HARD_REG_BIT (regs_invalidated_by_call, i);
+ {
+ SET_HARD_REG_BIT (regs_invalidated_by_call, i);
+ SET_REGNO_REG_SET (regs_invalidated_by_call_regset, i);
+ }
else if (i == FRAME_POINTER_REGNUM)
;
#if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM
;
#endif
else if (CALL_REALLY_USED_REGNO_P (i))
- SET_HARD_REG_BIT (regs_invalidated_by_call, i);
+ {
+ SET_HARD_REG_BIT (regs_invalidated_by_call, i);
+ SET_REGNO_REG_SET (regs_invalidated_by_call_regset, i);
+ }
}
/* Preserve global registers if called more than once. */
Only needed if secondary reloads are required for memory moves. */
int
-memory_move_secondary_cost (enum machine_mode mode, enum reg_class class, int in)
+memory_move_secondary_cost (enum machine_mode mode, enum reg_class rclass, int in)
{
enum reg_class altclass;
int partial_cost = 0;
rtx mem ATTRIBUTE_UNUSED = top_of_stack[(int) mode];
- altclass = secondary_reload_class (in ? 1 : 0, class, mode, mem);
+ altclass = secondary_reload_class (in ? 1 : 0, rclass, mode, mem);
if (altclass == NO_REGS)
return 0;
if (in)
- partial_cost = REGISTER_MOVE_COST (mode, altclass, class);
+ partial_cost = REGISTER_MOVE_COST (mode, altclass, rclass);
else
- partial_cost = REGISTER_MOVE_COST (mode, class, altclass);
+ partial_cost = REGISTER_MOVE_COST (mode, rclass, altclass);
- if (class == altclass)
+ if (rclass == altclass)
/* This isn't simply a copy-to-temporary situation. Can't guess
what it is, so MEMORY_MOVE_COST really ought not to be calling
here in that case.
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);
+ {
+ SET_HARD_REG_BIT (regs_invalidated_by_call, i);
+ SET_REGNO_REG_SET (regs_invalidated_by_call_regset, i);
+ }
/* If already fixed, nothing else to do. */
if (fixed_regs[i])
{
if (reg_pref == 0)
return GENERAL_REGS;
+
return (enum reg_class) reg_pref[regno].prefclass;
}
int i;
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
{
- int /* enum reg_class */ class;
+ int /* enum reg_class */ rclass;
if (REG_N_REFS (i))
{
fprintf (dump, " Register %i costs:", i);
- for (class = 0; class < (int) N_REG_CLASSES; class++)
- if (contains_reg_of_mode [(enum reg_class) class][PSEUDO_REGNO_MODE (i)]
+ for (rclass = 0; rclass < (int) N_REG_CLASSES; rclass++)
+ if (contains_reg_of_mode [(enum reg_class) rclass][PSEUDO_REGNO_MODE (i)]
#ifdef FORBIDDEN_INC_DEC_CLASSES
&& (!in_inc_dec[i]
- || !forbidden_inc_dec_class[(enum reg_class) class])
+ || !forbidden_inc_dec_class[(enum reg_class) rclass])
#endif
#ifdef CANNOT_CHANGE_MODE_CLASS
- && ! invalid_mode_change_p (i, (enum reg_class) class,
+ && ! invalid_mode_change_p (i, (enum reg_class) rclass,
PSEUDO_REGNO_MODE (i))
#endif
)
- fprintf (dump, " %s:%i", reg_class_names[class],
- costs[i].cost[(enum reg_class) class]);
+ fprintf (dump, " %s:%i", reg_class_names[rclass],
+ costs[i].cost[(enum reg_class) rclass]);
fprintf (dump, " MEM:%i\n", costs[i].mem_cost);
}
}
record_address_regs (GET_MODE (recog_data.operand[i]),
XEXP (recog_data.operand[i], 0),
0, MEM, SCRATCH, frequency * 2);
- else if (constraints[i][0] == 'p'
- || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i]))
+ else if (recog_data.alternative_enabled_p[0]
+ && (constraints[i][0] == 'p'
+ || EXTRA_ADDRESS_CONSTRAINT (constraints[i][0], constraints[i])))
record_address_regs (VOIDmode, recog_data.operand[i], 0, ADDRESS,
SCRATCH, frequency * 2);
}
init_recog ();
- reg_renumber = xmalloc (max_regno * sizeof (short));
+ reg_renumber = XNEWVEC (short, max_regno);
reg_pref = XCNEWVEC (struct reg_pref, max_regno);
memset (reg_renumber, -1, max_regno * sizeof (short));
enum reg_class best = ALL_REGS, alt = NO_REGS;
/* This is an enum reg_class, but we call it an int
to save lots of casts. */
- int class;
+ int rclass;
struct costs *p = &costs[i];
if (regno_reg_rtx[i] == NULL)
if (optimize && !REG_N_REFS (i) && !REG_N_SETS (i))
continue;
- for (class = (int) ALL_REGS - 1; class > 0; class--)
+ for (rclass = (int) ALL_REGS - 1; rclass > 0; rclass--)
{
/* Ignore classes that are too small for this operand or
invalid for an operand that was auto-incremented. */
- if (!contains_reg_of_mode [class][PSEUDO_REGNO_MODE (i)]
+ if (!contains_reg_of_mode [rclass][PSEUDO_REGNO_MODE (i)]
#ifdef FORBIDDEN_INC_DEC_CLASSES
- || (in_inc_dec[i] && forbidden_inc_dec_class[class])
+ || (in_inc_dec[i] && forbidden_inc_dec_class[rclass])
#endif
#ifdef CANNOT_CHANGE_MODE_CLASS
- || invalid_mode_change_p (i, (enum reg_class) class,
+ || invalid_mode_change_p (i, (enum reg_class) rclass,
PSEUDO_REGNO_MODE (i))
#endif
)
;
- else if (p->cost[class] < best_cost)
+ else if (p->cost[rclass] < best_cost)
{
- best_cost = p->cost[class];
- best = (enum reg_class) class;
+ best_cost = p->cost[rclass];
+ best = (enum reg_class) rclass;
}
- else if (p->cost[class] == best_cost)
- best = reg_class_subunion[(int) best][class];
+ else if (p->cost[rclass] == best_cost)
+ best = reg_class_subunion[(int) best][rclass];
}
/* If no register class is better than memory, use memory. */
will be doing it again later. */
if ((pass == 1 || dump_file) || ! flag_expensive_optimizations)
- for (class = 0; class < N_REG_CLASSES; class++)
- if (p->cost[class] < p->mem_cost
- && (reg_class_size[(int) reg_class_subunion[(int) alt][class]]
+ for (rclass = 0; rclass < N_REG_CLASSES; rclass++)
+ if (p->cost[rclass] < p->mem_cost
+ && (reg_class_size[(int) reg_class_subunion[(int) alt][rclass]]
> reg_class_size[(int) alt])
#ifdef FORBIDDEN_INC_DEC_CLASSES
- && ! (in_inc_dec[i] && forbidden_inc_dec_class[class])
+ && ! (in_inc_dec[i] && forbidden_inc_dec_class[rclass])
#endif
#ifdef CANNOT_CHANGE_MODE_CLASS
- && ! invalid_mode_change_p (i, (enum reg_class) class,
+ && ! invalid_mode_change_p (i, (enum reg_class) rclass,
PSEUDO_REGNO_MODE (i))
#endif
)
- alt = reg_class_subunion[(int) alt][class];
+ alt = reg_class_subunion[(int) alt][rclass];
/* If we don't add any classes, nothing to try. */
if (alt == best)
int alt_cost = 0;
enum reg_class classes[MAX_RECOG_OPERANDS];
int allows_mem[MAX_RECOG_OPERANDS];
- int class;
+ int rclass;
for (i = 0; i < n_ops; i++)
{
switch (recog_data.operand_type[i])
{
case OP_INOUT:
- for (class = 0; class < N_REG_CLASSES; class++)
- pp->cost[class] = (intable[class][op_class]
- + outtable[op_class][class]);
+ for (rclass = 0; rclass < N_REG_CLASSES; rclass++)
+ pp->cost[rclass] = (intable[rclass][op_class]
+ + outtable[op_class][rclass]);
break;
case OP_IN:
- for (class = 0; class < N_REG_CLASSES; class++)
- pp->cost[class] = intable[class][op_class];
+ for (rclass = 0; rclass < N_REG_CLASSES; rclass++)
+ pp->cost[rclass] = intable[rclass][op_class];
break;
case OP_OUT:
- for (class = 0; class < N_REG_CLASSES; class++)
- pp->cost[class] = outtable[op_class][class];
+ for (rclass = 0; rclass < N_REG_CLASSES; rclass++)
+ pp->cost[rclass] = outtable[op_class][rclass];
break;
}
[(int) base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
break;
- case 'm': case 'o': case 'V':
+ case TARGET_MEM_CONSTRAINT: case 'o': case 'V':
/* It doesn't seem worth distinguishing between offsettable
and non-offsettable addresses here. */
allows_mem[i] = 1;
switch (recog_data.operand_type[i])
{
case OP_INOUT:
- for (class = 0; class < N_REG_CLASSES; class++)
- pp->cost[class] = (intable[class][op_class]
- + outtable[op_class][class]);
+ for (rclass = 0; rclass < N_REG_CLASSES; rclass++)
+ pp->cost[rclass] = (intable[rclass][op_class]
+ + outtable[op_class][rclass]);
break;
case OP_IN:
- for (class = 0; class < N_REG_CLASSES; class++)
- pp->cost[class] = intable[class][op_class];
+ for (rclass = 0; rclass < N_REG_CLASSES; rclass++)
+ pp->cost[rclass] = intable[rclass][op_class];
break;
case OP_OUT:
- for (class = 0; class < N_REG_CLASSES; class++)
- pp->cost[class] = outtable[op_class][class];
+ for (rclass = 0; rclass < N_REG_CLASSES; rclass++)
+ pp->cost[rclass] = outtable[op_class][rclass];
break;
}
if (alt_fail)
continue;
+ if (!recog_data.alternative_enabled_p[alt])
+ continue;
+
/* Finally, update the costs with the information we've calculated
about this alternative. */
pp->mem_cost = MIN (pp->mem_cost,
(qq->mem_cost + alt_cost) * scale);
- for (class = 0; class < N_REG_CLASSES; class++)
- pp->cost[class] = MIN (pp->cost[class],
- (qq->cost[class] + alt_cost) * scale);
+ for (rclass = 0; rclass < N_REG_CLASSES; rclass++)
+ pp->cost[rclass] = MIN (pp->cost[rclass],
+ (qq->cost[rclass] + alt_cost) * scale);
}
}
we may want to adjust the cost of that register class to -1.
Avoid the adjustment if the source does not die to avoid stressing of
- register allocator by preferrencing two colliding registers into single
+ register allocator by preferencing two colliding registers into single
class.
Also avoid the adjustment if a copy between registers of the class
{
unsigned int regno = REGNO (ops[!i]);
enum machine_mode mode = GET_MODE (ops[!i]);
- int class;
+ int rclass;
if (regno >= FIRST_PSEUDO_REGISTER && reg_pref != 0
&& reg_pref[regno].prefclass != NO_REGS)
op_costs[i].cost[(unsigned char) pref] = -1;
}
else if (regno < FIRST_PSEUDO_REGISTER)
- for (class = 0; class < N_REG_CLASSES; class++)
- if (TEST_HARD_REG_BIT (reg_class_contents[class], regno)
- && reg_class_size[class] == (unsigned) CLASS_MAX_NREGS (class, mode))
+ for (rclass = 0; rclass < N_REG_CLASSES; rclass++)
+ if (TEST_HARD_REG_BIT (reg_class_contents[rclass], regno)
+ && reg_class_size[rclass] == (unsigned) CLASS_MAX_NREGS (rclass, mode))
{
- if (reg_class_size[class] == 1)
- op_costs[i].cost[class] = -1;
- else if (in_hard_reg_set_p (reg_class_contents[class],
+ if (reg_class_size[rclass] == 1)
+ op_costs[i].cost[rclass] = -1;
+ else if (in_hard_reg_set_p (reg_class_contents[rclass],
mode, regno))
- op_costs[i].cost[class] = -1;
+ op_costs[i].cost[rclass] = -1;
}
}
}
X must not be a pseudo. */
static int
-copy_cost (rtx x, enum machine_mode mode, enum reg_class class, int to_p,
+copy_cost (rtx x, enum machine_mode mode, enum reg_class rclass, int to_p,
secondary_reload_info *prev_sri)
{
enum reg_class secondary_class = NO_REGS;
return 0;
/* Get the class we will actually use for a reload. */
- class = PREFERRED_RELOAD_CLASS (x, class);
+ rclass = PREFERRED_RELOAD_CLASS (x, rclass);
/* If we need a secondary reload for an intermediate, the
cost is that to load the input into the intermediate register, then
sri.prev_sri = prev_sri;
sri.extra_cost = 0;
- secondary_class = targetm.secondary_reload (to_p, x, class, mode, &sri);
+ secondary_class = targetm.secondary_reload (to_p, x, rclass, mode, &sri);
if (!move_cost[mode])
init_move_cost (mode);
if (secondary_class != NO_REGS)
- return (move_cost[mode][(int) secondary_class][(int) class]
+ return (move_cost[mode][(int) secondary_class][(int) rclass]
+ sri.extra_cost
+ copy_cost (x, mode, secondary_class, to_p, &sri));
cost to move between the register classes, and use 2 for everything
else (constants). */
- if (MEM_P (x) || class == NO_REGS)
- return sri.extra_cost + MEMORY_MOVE_COST (mode, class, to_p);
+ if (MEM_P (x) || rclass == NO_REGS)
+ return sri.extra_cost + MEMORY_MOVE_COST (mode, rclass, to_p);
else if (REG_P (x))
return (sri.extra_cost
- + move_cost[mode][(int) REGNO_REG_CLASS (REGNO (x))][(int) class]);
+ + move_cost[mode][(int) REGNO_REG_CLASS (REGNO (x))][(int) rclass]);
else
/* If this is a constant, we may eventually want to call rtx_cost here. */
int scale)
{
enum rtx_code code = GET_CODE (x);
- enum reg_class class;
+ enum reg_class rclass;
if (context == 1)
- class = INDEX_REG_CLASS;
+ rclass = INDEX_REG_CLASS;
else
- class = base_reg_class (mode, outer_code, index_code);
+ rclass = base_reg_class (mode, outer_code, index_code);
switch (code)
{
struct costs *pp = &costs[REGNO (x)];
int i;
- pp->mem_cost += (MEMORY_MOVE_COST (Pmode, class, 1) * scale) / 2;
+ pp->mem_cost += (MEMORY_MOVE_COST (Pmode, rclass, 1) * scale) / 2;
if (!move_cost[Pmode])
init_move_cost (Pmode);
for (i = 0; i < N_REG_CLASSES; i++)
- pp->cost[i] += (may_move_in_cost[Pmode][i][(int) class] * scale) / 2;
+ pp->cost[i] += (may_move_in_cost[Pmode][i][(int) rclass] * scale) / 2;
}
break;
}
#endif
\f
+
+/* Allocate space for reg info. */
+void
+allocate_reg_info (void)
+{
+ int size = max_reg_num ();
+
+ gcc_assert (! reg_pref && ! reg_renumber);
+ reg_renumber = XNEWVEC (short, size);
+ reg_pref = XCNEWVEC (struct reg_pref, size);
+ memset (reg_renumber, -1, size * sizeof (short));
+}
+
+
+/* Resize reg info. The new elements will be uninitialized. */
+void
+resize_reg_info (void)
+{
+ int size = max_reg_num ();
+
+ gcc_assert (reg_pref && reg_renumber);
+ reg_renumber = XRESIZEVEC (short, reg_renumber, size);
+ reg_pref = XRESIZEVEC (struct reg_pref, reg_pref, size);
+}
+
+
/* Free up the space allocated by allocate_reg_info. */
void
free_reg_info (void)
}
}
+
+\f
+
+/* Set up preferred and alternate classes for REGNO as PREFCLASS and
+ ALTCLASS. */
+void
+setup_reg_classes (int regno,
+ enum reg_class prefclass, enum reg_class altclass)
+{
+ if (reg_pref == NULL)
+ return;
+ reg_pref[regno].prefclass = prefclass;
+ reg_pref[regno].altclass = altclass;
+}
+
\f
/* This is the `regscan' pass of the compiler, run just before cse and
again just before loop. It finds the first and last use of each
static hashval_t
som_hash (const void *x)
{
- const struct subregs_of_mode_node *a = x;
+ const struct subregs_of_mode_node *const a =
+ (const struct subregs_of_mode_node *) 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;
+ const struct subregs_of_mode_node *const a =
+ (const struct subregs_of_mode_node *) x;
+ const struct subregs_of_mode_node *const b =
+ (const struct subregs_of_mode_node *) y;
return a->block == b->block;
}
dummy.block = regno & -8;
slot = htab_find_slot_with_hash (subregs_of_mode, &dummy,
dummy.block, INSERT);
- node = *slot;
+ node = (struct subregs_of_mode_node *) *slot;
if (node == NULL)
{
node = XCNEW (struct subregs_of_mode_node);
gcc_assert (subregs_of_mode);
dummy.block = regno & -8;
- node = htab_find_with_hash (subregs_of_mode, &dummy, dummy.block);
+ node = (struct subregs_of_mode_node *)
+ htab_find_with_hash (subregs_of_mode, &dummy, dummy.block);
if (node == NULL)
return;
bool
invalid_mode_change_p (unsigned int regno,
- enum reg_class class ATTRIBUTE_UNUSED,
+ enum reg_class rclass ATTRIBUTE_UNUSED,
enum machine_mode from)
{
struct subregs_of_mode_node dummy, *node;
gcc_assert (subregs_of_mode);
dummy.block = regno & -8;
- node = htab_find_with_hash (subregs_of_mode, &dummy, dummy.block);
+ node = (struct subregs_of_mode_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))
+ if (CANNOT_CHANGE_MODE_CLASS (from, to, rclass))
return true;
return false;