mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-10 17:11:01 +08:00
regclass.c (move_table): New type.
* regclass.c (move_table): New type. (move_cost, may_move_in_cost, may_move_out_cost): Use it. (init_move_cost): Break out from ... (init_reg_sets_1): ... here; simplify computation of have_regs-of_mode and contains_reg_of_mode. (record_reg_classes): Unswitch internal loops. (copy_cost): Trigger lazy initialization of move cost (record_address_regs): Likewise. From-SVN: r126901
This commit is contained in:
parent
a857cbfbbf
commit
779d7a1a92
@ -1,3 +1,14 @@
|
||||
2007-07-24 Jan Hubicka <jh@suse.cz>
|
||||
|
||||
* regclass.c (move_table): New type.
|
||||
(move_cost, may_move_in_cost, may_move_out_cost): Use it.
|
||||
(init_move_cost): Break out from ...
|
||||
(init_reg_sets_1): ... here; simplify computation of
|
||||
have_regs-of_mode and contains_reg_of_mode.
|
||||
(record_reg_classes): Unswitch internal loops.
|
||||
(copy_cost): Trigger lazy initialization of move cost
|
||||
(record_address_regs): Likewise.
|
||||
|
||||
2007-07-24 Daniel Berlin <dberlin@dberlin.org>
|
||||
|
||||
* config/darwin.c (darwin_override_options): Don't force on
|
||||
|
253
gcc/regclass.c
253
gcc/regclass.c
@ -214,20 +214,22 @@ bool have_regs_of_mode [MAX_MACHINE_MODE];
|
||||
|
||||
static char contains_reg_of_mode [N_REG_CLASSES] [MAX_MACHINE_MODE];
|
||||
|
||||
typedef unsigned short move_table[N_REG_CLASSES];
|
||||
|
||||
/* Maximum cost of moving from a register in one class to a register in
|
||||
another class. Based on REGISTER_MOVE_COST. */
|
||||
|
||||
static int move_cost[MAX_MACHINE_MODE][N_REG_CLASSES][N_REG_CLASSES];
|
||||
static 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 int may_move_in_cost[MAX_MACHINE_MODE][N_REG_CLASSES][N_REG_CLASSES];
|
||||
static 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 int may_move_out_cost[MAX_MACHINE_MODE][N_REG_CLASSES][N_REG_CLASSES];
|
||||
static move_table *may_move_out_cost[MAX_MACHINE_MODE];
|
||||
|
||||
#ifdef FORBIDDEN_INC_DEC_CLASSES
|
||||
|
||||
@ -312,6 +314,96 @@ init_reg_sets (void)
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Initialize may_move_cost and friends for mode M. */
|
||||
|
||||
static void
|
||||
init_move_cost (enum machine_mode m)
|
||||
{
|
||||
static unsigned short last_move_cost[N_REG_CLASSES][N_REG_CLASSES];
|
||||
static int last_mode = -1;
|
||||
bool all_match = true;
|
||||
unsigned int i, j;
|
||||
|
||||
gcc_assert (have_regs_of_mode[m]);
|
||||
for (i = 0; i < N_REG_CLASSES; i++)
|
||||
if (contains_reg_of_mode[i][m])
|
||||
for (j = 0; j < N_REG_CLASSES; j++)
|
||||
{
|
||||
int cost;
|
||||
if (!contains_reg_of_mode[j][m])
|
||||
cost = 65535;
|
||||
else
|
||||
{
|
||||
cost = REGISTER_MOVE_COST (m, i, j);
|
||||
gcc_assert (cost < 65535);
|
||||
}
|
||||
all_match &= (last_move_cost[i][j] == cost);
|
||||
last_move_cost[i][j] = cost;
|
||||
}
|
||||
if (all_match && last_mode != -1)
|
||||
{
|
||||
move_cost[m] = move_cost[last_mode];
|
||||
may_move_in_cost[m] = may_move_in_cost[last_mode];
|
||||
may_move_out_cost[m] = may_move_out_cost[last_mode];
|
||||
return;
|
||||
}
|
||||
last_mode = m;
|
||||
move_cost[m] = (move_table *)xmalloc (sizeof (move_table)
|
||||
* N_REG_CLASSES);
|
||||
may_move_in_cost[m] = (move_table *)xmalloc (sizeof (move_table)
|
||||
* N_REG_CLASSES);
|
||||
may_move_out_cost[m] = (move_table *)xmalloc (sizeof (move_table)
|
||||
* N_REG_CLASSES);
|
||||
for (i = 0; i < N_REG_CLASSES; i++)
|
||||
if (contains_reg_of_mode[i][m])
|
||||
for (j = 0; j < N_REG_CLASSES; j++)
|
||||
{
|
||||
int cost;
|
||||
enum reg_class *p1, *p2;
|
||||
|
||||
if (last_move_cost[i][j] == 65535)
|
||||
{
|
||||
move_cost[m][i][j] = 65535;
|
||||
may_move_in_cost[m][i][j] = 65535;
|
||||
may_move_out_cost[m][i][j] = 65535;
|
||||
}
|
||||
else
|
||||
{
|
||||
cost = last_move_cost[i][j];
|
||||
|
||||
for (p2 = ®_class_subclasses[j][0];
|
||||
*p2 != LIM_REG_CLASSES; p2++)
|
||||
if (*p2 != i && contains_reg_of_mode[*p2][m])
|
||||
cost = MAX (cost, move_cost[m][i][*p2]);
|
||||
|
||||
for (p1 = ®_class_subclasses[i][0];
|
||||
*p1 != LIM_REG_CLASSES; p1++)
|
||||
if (*p1 != j && contains_reg_of_mode[*p1][m])
|
||||
cost = MAX (cost, move_cost[m][*p1][j]);
|
||||
|
||||
gcc_assert (cost <= 65535);
|
||||
move_cost[m][i][j] = cost;
|
||||
|
||||
if (reg_class_subset_p (i, j))
|
||||
may_move_in_cost[m][i][j] = 0;
|
||||
else
|
||||
may_move_in_cost[m][i][j] = cost;
|
||||
|
||||
if (reg_class_subset_p (j, i))
|
||||
may_move_out_cost[m][i][j] = 0;
|
||||
else
|
||||
may_move_out_cost[m][i][j] = cost;
|
||||
}
|
||||
}
|
||||
else
|
||||
for (j = 0; j < N_REG_CLASSES; j++)
|
||||
{
|
||||
move_cost[m][i][j] = 65535;
|
||||
may_move_in_cost[m][i][j] = 65535;
|
||||
may_move_out_cost[m][i][j] = 65535;
|
||||
}
|
||||
}
|
||||
|
||||
/* After switches have been processed, which perhaps alter
|
||||
`fixed_regs' and `call_used_regs', convert them to HARD_REG_SETs. */
|
||||
|
||||
@ -476,73 +568,21 @@ init_reg_sets_1 (void)
|
||||
memset (have_regs_of_mode, 0, sizeof (have_regs_of_mode));
|
||||
memset (contains_reg_of_mode, 0, sizeof (contains_reg_of_mode));
|
||||
for (m = 0; m < (unsigned int) MAX_MACHINE_MODE; m++)
|
||||
for (i = 0; i < N_REG_CLASSES; i++)
|
||||
if ((unsigned) CLASS_MAX_NREGS (i, m) <= reg_class_size[i])
|
||||
for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
|
||||
if (!fixed_regs [j] && TEST_HARD_REG_BIT (reg_class_contents[i], j)
|
||||
&& HARD_REGNO_MODE_OK (j, m))
|
||||
{
|
||||
contains_reg_of_mode [i][m] = 1;
|
||||
have_regs_of_mode [m] = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Initialize the move cost table. Find every subset of each class
|
||||
and take the maximum cost of moving any subset to any other. */
|
||||
|
||||
for (m = 0; m < (unsigned int) MAX_MACHINE_MODE; m++)
|
||||
if (have_regs_of_mode [m])
|
||||
{
|
||||
for (i = 0; i < N_REG_CLASSES; i++)
|
||||
if (contains_reg_of_mode [i][m])
|
||||
for (j = 0; j < N_REG_CLASSES; j++)
|
||||
{
|
||||
int cost;
|
||||
enum reg_class *p1, *p2;
|
||||
|
||||
if (!contains_reg_of_mode [j][m])
|
||||
{
|
||||
move_cost[m][i][j] = 65536;
|
||||
may_move_in_cost[m][i][j] = 65536;
|
||||
may_move_out_cost[m][i][j] = 65536;
|
||||
}
|
||||
else
|
||||
{
|
||||
cost = REGISTER_MOVE_COST (m, i, j);
|
||||
|
||||
for (p2 = ®_class_subclasses[j][0];
|
||||
*p2 != LIM_REG_CLASSES;
|
||||
p2++)
|
||||
if (*p2 != i && contains_reg_of_mode [*p2][m])
|
||||
cost = MAX (cost, move_cost [m][i][*p2]);
|
||||
|
||||
for (p1 = ®_class_subclasses[i][0];
|
||||
*p1 != LIM_REG_CLASSES;
|
||||
p1++)
|
||||
if (*p1 != j && contains_reg_of_mode [*p1][m])
|
||||
cost = MAX (cost, move_cost [m][*p1][j]);
|
||||
|
||||
move_cost[m][i][j] = cost;
|
||||
|
||||
if (reg_class_subset_p (i, j))
|
||||
may_move_in_cost[m][i][j] = 0;
|
||||
else
|
||||
may_move_in_cost[m][i][j] = cost;
|
||||
|
||||
if (reg_class_subset_p (j, i))
|
||||
may_move_out_cost[m][i][j] = 0;
|
||||
else
|
||||
may_move_out_cost[m][i][j] = cost;
|
||||
}
|
||||
}
|
||||
else
|
||||
for (j = 0; j < N_REG_CLASSES; j++)
|
||||
{
|
||||
move_cost[m][i][j] = 65536;
|
||||
may_move_in_cost[m][i][j] = 65536;
|
||||
may_move_out_cost[m][i][j] = 65536;
|
||||
}
|
||||
}
|
||||
{
|
||||
HARD_REG_SET ok_regs;
|
||||
CLEAR_HARD_REG_SET (ok_regs);
|
||||
for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
|
||||
if (!fixed_regs [j] && HARD_REGNO_MODE_OK (j, m))
|
||||
SET_HARD_REG_BIT (ok_regs, j);
|
||||
|
||||
for (i = 0; i < N_REG_CLASSES; i++)
|
||||
if ((unsigned) CLASS_MAX_NREGS (i, m) <= reg_class_size[i]
|
||||
&& hard_reg_set_intersect_p (ok_regs, reg_class_contents[i]))
|
||||
{
|
||||
contains_reg_of_mode [i][m] = 1;
|
||||
have_regs_of_mode [m] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Compute the table of register modes.
|
||||
@ -1465,15 +1505,33 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
|
||||
copy, which is one instruction. */
|
||||
|
||||
struct costs *pp = &this_op_costs[i];
|
||||
move_table *intable = NULL;
|
||||
move_table *outtable = NULL;
|
||||
int op_class = (int) classes[i];
|
||||
|
||||
for (class = 0; class < N_REG_CLASSES; class++)
|
||||
pp->cost[class]
|
||||
= ((recog_data.operand_type[i] != OP_OUT
|
||||
? may_move_in_cost[mode][class][(int) classes[i]]
|
||||
: 0)
|
||||
+ (recog_data.operand_type[i] != OP_IN
|
||||
? may_move_out_cost[mode][(int) classes[i]][class]
|
||||
: 0));
|
||||
if (!move_cost[mode])
|
||||
init_move_cost (mode);
|
||||
intable = may_move_in_cost[mode];
|
||||
outtable = may_move_out_cost[mode];
|
||||
|
||||
/* The loop is performance critical, so unswitch it manually.
|
||||
*/
|
||||
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]);
|
||||
break;
|
||||
case OP_IN:
|
||||
for (class = 0; class < N_REG_CLASSES; class++)
|
||||
pp->cost[class] = intable[class][op_class];
|
||||
break;
|
||||
case OP_OUT:
|
||||
for (class = 0; class < N_REG_CLASSES; class++)
|
||||
pp->cost[class] = outtable[op_class][class];
|
||||
break;
|
||||
}
|
||||
|
||||
/* If the alternative actually allows memory, make things
|
||||
a bit cheaper since we won't need an extra insn to
|
||||
@ -1691,15 +1749,33 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
|
||||
else
|
||||
{
|
||||
struct costs *pp = &this_op_costs[i];
|
||||
move_table *intable = NULL;
|
||||
move_table *outtable = NULL;
|
||||
int op_class = (int) classes[i];
|
||||
|
||||
for (class = 0; class < N_REG_CLASSES; class++)
|
||||
pp->cost[class]
|
||||
= ((recog_data.operand_type[i] != OP_OUT
|
||||
? may_move_in_cost[mode][class][(int) classes[i]]
|
||||
: 0)
|
||||
+ (recog_data.operand_type[i] != OP_IN
|
||||
? may_move_out_cost[mode][(int) classes[i]][class]
|
||||
: 0));
|
||||
if (!move_cost[mode])
|
||||
init_move_cost (mode);
|
||||
intable = may_move_in_cost[mode];
|
||||
outtable = may_move_out_cost[mode];
|
||||
|
||||
/* The loop is performance critical, so unswitch it manually.
|
||||
*/
|
||||
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]);
|
||||
break;
|
||||
case OP_IN:
|
||||
for (class = 0; class < N_REG_CLASSES; class++)
|
||||
pp->cost[class] = intable[class][op_class];
|
||||
break;
|
||||
case OP_OUT:
|
||||
for (class = 0; class < N_REG_CLASSES; class++)
|
||||
pp->cost[class] = outtable[op_class][class];
|
||||
break;
|
||||
}
|
||||
|
||||
/* If the alternative actually allows memory, make things
|
||||
a bit cheaper since we won't need an extra insn to
|
||||
@ -1856,6 +1932,9 @@ copy_cost (rtx x, enum machine_mode mode, enum reg_class class, int to_p,
|
||||
sri.extra_cost = 0;
|
||||
secondary_class = targetm.secondary_reload (to_p, x, class, mode, &sri);
|
||||
|
||||
if (!move_cost[mode])
|
||||
init_move_cost (mode);
|
||||
|
||||
if (secondary_class != NO_REGS)
|
||||
return (move_cost[mode][(int) secondary_class][(int) class]
|
||||
+ sri.extra_cost
|
||||
@ -2056,6 +2135,8 @@ record_address_regs (enum machine_mode mode, rtx x, int context,
|
||||
|
||||
pp->mem_cost += (MEMORY_MOVE_COST (Pmode, class, 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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user