summaryrefslogtreecommitdiff
path: root/gcc/regclass.c
diff options
context:
space:
mode:
authorhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2007-07-25 05:58:40 +0000
committerhubicka <hubicka@138bc75d-0d04-0410-961f-82ee72b054a4>2007-07-25 05:58:40 +0000
commit099d85c47996e2f2e39b8bb8c35a97e67593f982 (patch)
tree4f078700c58382b243b88aba5e79983488568e87 /gcc/regclass.c
parentfe6e8926c6c1ff1fe1a830e273bf6c1fa186b95f (diff)
downloadgcc-099d85c47996e2f2e39b8bb8c35a97e67593f982.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@126901 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/regclass.c')
-rw-r--r--gcc/regclass.c257
1 files changed, 169 insertions, 88 deletions
diff --git a/gcc/regclass.c b/gcc/regclass.c
index 1baccf68979..b35dc1823a2 100644
--- a/gcc/regclass.c
+++ b/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 = &reg_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 = &reg_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 = &reg_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 = &reg_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];
-
- 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));
+ 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++)
+ 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];
-
- 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));
+ 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++)
+ 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;
}