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>
|
2007-07-24 Daniel Berlin <dberlin@dberlin.org>
|
||||||
|
|
||||||
* config/darwin.c (darwin_override_options): Don't force on
|
* config/darwin.c (darwin_override_options): Don't force on
|
||||||
|
|
237
gcc/regclass.c
237
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];
|
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
|
/* Maximum cost of moving from a register in one class to a register in
|
||||||
another class. Based on REGISTER_MOVE_COST. */
|
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
|
/* 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. */
|
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
|
/* 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. */
|
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
|
#ifdef FORBIDDEN_INC_DEC_CLASSES
|
||||||
|
|
||||||
|
@ -312,6 +314,96 @@ init_reg_sets (void)
|
||||||
#endif
|
#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
|
/* After switches have been processed, which perhaps alter
|
||||||
`fixed_regs' and `call_used_regs', convert them to HARD_REG_SETs. */
|
`fixed_regs' and `call_used_regs', convert them to HARD_REG_SETs. */
|
||||||
|
|
||||||
|
@ -476,71 +568,19 @@ init_reg_sets_1 (void)
|
||||||
memset (have_regs_of_mode, 0, sizeof (have_regs_of_mode));
|
memset (have_regs_of_mode, 0, sizeof (have_regs_of_mode));
|
||||||
memset (contains_reg_of_mode, 0, sizeof (contains_reg_of_mode));
|
memset (contains_reg_of_mode, 0, sizeof (contains_reg_of_mode));
|
||||||
for (m = 0; m < (unsigned int) MAX_MACHINE_MODE; m++)
|
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])
|
HARD_REG_SET ok_regs;
|
||||||
|
CLEAR_HARD_REG_SET (ok_regs);
|
||||||
for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
|
for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
|
||||||
if (!fixed_regs [j] && TEST_HARD_REG_BIT (reg_class_contents[i], j)
|
if (!fixed_regs [j] && HARD_REGNO_MODE_OK (j, m))
|
||||||
&& 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;
|
contains_reg_of_mode [i][m] = 1;
|
||||||
have_regs_of_mode [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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1465,15 +1505,33 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops,
|
||||||
copy, which is one instruction. */
|
copy, which is one instruction. */
|
||||||
|
|
||||||
struct costs *pp = &this_op_costs[i];
|
struct costs *pp = &this_op_costs[i];
|
||||||
|
move_table *intable = NULL;
|
||||||
|
move_table *outtable = NULL;
|
||||||
|
int op_class = (int) classes[i];
|
||||||
|
|
||||||
|
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++)
|
for (class = 0; class < N_REG_CLASSES; class++)
|
||||||
pp->cost[class]
|
pp->cost[class] = (intable[class][op_class]
|
||||||
= ((recog_data.operand_type[i] != OP_OUT
|
+ outtable[op_class][class]);
|
||||||
? may_move_in_cost[mode][class][(int) classes[i]]
|
break;
|
||||||
: 0)
|
case OP_IN:
|
||||||
+ (recog_data.operand_type[i] != OP_IN
|
for (class = 0; class < N_REG_CLASSES; class++)
|
||||||
? may_move_out_cost[mode][(int) classes[i]][class]
|
pp->cost[class] = intable[class][op_class];
|
||||||
: 0));
|
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
|
/* If the alternative actually allows memory, make things
|
||||||
a bit cheaper since we won't need an extra insn to
|
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
|
else
|
||||||
{
|
{
|
||||||
struct costs *pp = &this_op_costs[i];
|
struct costs *pp = &this_op_costs[i];
|
||||||
|
move_table *intable = NULL;
|
||||||
|
move_table *outtable = NULL;
|
||||||
|
int op_class = (int) classes[i];
|
||||||
|
|
||||||
|
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++)
|
for (class = 0; class < N_REG_CLASSES; class++)
|
||||||
pp->cost[class]
|
pp->cost[class] = (intable[class][op_class]
|
||||||
= ((recog_data.operand_type[i] != OP_OUT
|
+ outtable[op_class][class]);
|
||||||
? may_move_in_cost[mode][class][(int) classes[i]]
|
break;
|
||||||
: 0)
|
case OP_IN:
|
||||||
+ (recog_data.operand_type[i] != OP_IN
|
for (class = 0; class < N_REG_CLASSES; class++)
|
||||||
? may_move_out_cost[mode][(int) classes[i]][class]
|
pp->cost[class] = intable[class][op_class];
|
||||||
: 0));
|
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
|
/* If the alternative actually allows memory, make things
|
||||||
a bit cheaper since we won't need an extra insn to
|
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;
|
sri.extra_cost = 0;
|
||||||
secondary_class = targetm.secondary_reload (to_p, x, class, mode, &sri);
|
secondary_class = targetm.secondary_reload (to_p, x, class, mode, &sri);
|
||||||
|
|
||||||
|
if (!move_cost[mode])
|
||||||
|
init_move_cost (mode);
|
||||||
|
|
||||||
if (secondary_class != NO_REGS)
|
if (secondary_class != NO_REGS)
|
||||||
return (move_cost[mode][(int) secondary_class][(int) class]
|
return (move_cost[mode][(int) secondary_class][(int) class]
|
||||||
+ sri.extra_cost
|
+ 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;
|
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++)
|
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) class] * scale) / 2;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue