Regclass cleanups
Jan Hubicka
hubicka@atrey.karlin.mff.cuni.cz
Sat Jan 1 15:05:00 GMT 2000
Hi
This patch contains some preparation work necesary for my propagation patch.
Basically it just converts op_costs to local variable, adds new parameter to
record_reg_classes to specify reg_pref structure currently in use, breaks out
the operand cost calculations from scan_one_insn and improves dumps (prints the
preferences choosed and changes made in the second pass), makes regclass to
ignore unreferenced registers and fixes simple bug in scan_one_insn, that was
ignoring ASM_INPUT instructions for no purpose. I believe it is incorrect to
just ignore their preferrences.
Sat Jan 1 13:57:40 CET 2000 Jan Hubicka <hubicka@freesoft.cz>
* regclass.c (op_costs): Remove global variable.
(record_reg_classes): New parameter "op_costs" and "reg_pref".
(record_operand_costs): Break out from ...
(scan_one_insn): ... here; process ASM_INPUT insns.
(dump_regclass): Make dumps nicer.
(regclass): Dump preferrences choosed and changes done during passes.
*** regclass.c.nopro Sat Jan 1 12:16:55 2000
--- regclass.c Sat Jan 1 13:53:39 2000
*************** static struct costs *costs;
*** 703,714 ****
static struct costs init_cost;
- /* Record the same data by operand number, accumulated for each alternative
- in an insn. The contribution to a pseudo is that of the minimum-cost
- alternative. */
-
- static struct costs op_costs[MAX_RECOG_OPERANDS];
-
/* Record preferrences of each pseudo.
This is available after `regclass' is run. */
--- 703,708 ----
*************** static struct reg_pref *reg_pref_buffer;
*** 724,732 ****
static int loop_cost;
static rtx scan_one_insn PROTO((rtx, int));
static void dump_regclass PROTO((FILE *));
static void record_reg_classes PROTO((int, int, rtx *, enum machine_mode *,
! char *, const char **, rtx));
static int copy_cost PROTO((rtx, enum machine_mode,
enum reg_class, int));
static void record_address_regs PROTO((rtx, enum reg_class, int));
--- 718,728 ----
static int loop_cost;
static rtx scan_one_insn PROTO((rtx, int));
+ static void record_operand_costs PROTO((rtx, struct costs *, struct reg_pref *));
static void dump_regclass PROTO((FILE *));
static void record_reg_classes PROTO((int, int, rtx *, enum machine_mode *,
! char *, const char **, rtx,
! struct costs *, struct reg_pref *));
static int copy_cost PROTO((rtx, enum machine_mode,
enum reg_class, int));
static void record_address_regs PROTO((rtx, enum reg_class, int));
*************** dump_regclass (dump)
*** 789,803 ****
enum reg_class class;
if (REG_N_REFS (i))
{
! fprintf (dump, ";; Register %i costs:", i);
for (class = 0; class < N_REG_CLASSES; class++)
fprintf (dump, " %s:%i", reg_class_names[(int) class],
costs[i].cost[class]);
! fprintf (dump, " MEM:%i\n\n", costs[i].mem_cost);
}
}
}
/* Subroutine of regclass, processes one insn INSN. Scan it and record each
time it would save code to put a certain register in a certain class.
--- 785,873 ----
enum reg_class class;
if (REG_N_REFS (i))
{
! fprintf (dump, " Register %i costs:", i);
for (class = 0; class < N_REG_CLASSES; class++)
fprintf (dump, " %s:%i", reg_class_names[(int) class],
costs[i].cost[class]);
! fprintf (dump, " MEM:%i\n", costs[i].mem_cost);
}
}
}
+
+
+ /* Calculate the costs of insn operands. */
+
+ static void
+ record_operand_costs (insn, op_costs, reg_pref)
+ rtx insn;
+ struct costs *op_costs;
+ struct reg_pref *reg_pref;
+ {
+ const char *constraints[MAX_RECOG_OPERANDS];
+ enum machine_mode modes[MAX_RECOG_OPERANDS];
+ char subreg_changes_size[MAX_RECOG_OPERANDS];
+ int i;
+
+ for (i = 0; i < recog_data.n_operands; i++)
+ {
+ constraints[i] = recog_data.constraints[i];
+ modes[i] = recog_data.operand_mode[i];
+ }
+ memset (subreg_changes_size, 0, sizeof (subreg_changes_size));
+
+ /* If we get here, we are set up to record the costs of all the
+ operands for this insn. Start by initializing the costs.
+ Then handle any address registers. Finally record the desired
+ classes for any pseudos, doing it twice if some pair of
+ operands are commutative. */
+
+ for (i = 0; i < recog_data.n_operands; i++)
+ {
+ op_costs[i] = init_cost;
+
+ if (GET_CODE (recog_data.operand[i]) == SUBREG)
+ {
+ rtx inner = SUBREG_REG (recog_data.operand[i]);
+ if (GET_MODE_SIZE (modes[i]) != GET_MODE_SIZE (GET_MODE (inner)))
+ subreg_changes_size[i] = 1;
+ recog_data.operand[i] = inner;
+ }
+
+ if (GET_CODE (recog_data.operand[i]) == MEM)
+ record_address_regs (XEXP (recog_data.operand[i], 0),
+ BASE_REG_CLASS, loop_cost * 2);
+ else if (constraints[i][0] == 'p')
+ record_address_regs (recog_data.operand[i],
+ BASE_REG_CLASS, loop_cost * 2);
+ }
+
+ /* Check for commutative in a separate loop so everything will
+ have been initialized. We must do this even if one operand
+ is a constant--see addsi3 in m68k.md. */
+
+ for (i = 0; i < (int) recog_data.n_operands - 1; i++)
+ if (constraints[i][0] == '%')
+ {
+ const char *xconstraints[MAX_RECOG_OPERANDS];
+ int j;
+
+ /* Handle commutative operands by swapping the constraints.
+ We assume the modes are the same. */
+
+ for (j = 0; j < recog_data.n_operands; j++)
+ xconstraints[j] = constraints[j];
+
+ xconstraints[i] = constraints[i+1];
+ xconstraints[i+1] = constraints[i];
+ record_reg_classes (recog_data.n_alternatives, recog_data.n_operands,
+ recog_data.operand, modes, subreg_changes_size,
+ xconstraints, insn, op_costs, reg_pref);
+ }
+ record_reg_classes (recog_data.n_alternatives, recog_data.n_operands,
+ recog_data.operand, modes, subreg_changes_size,
+ constraints, insn, op_costs, reg_pref);
+ }
/* Subroutine of regclass, processes one insn INSN. Scan it and record each
time it would save code to put a certain register in a certain class.
*************** scan_one_insn (insn, pass)
*** 813,831 ****
{
enum rtx_code code = GET_CODE (insn);
enum rtx_code pat_code;
- const char *constraints[MAX_RECOG_OPERANDS];
- enum machine_mode modes[MAX_RECOG_OPERANDS];
- char subreg_changes_size[MAX_RECOG_OPERANDS];
rtx set, note;
int i, j;
if (GET_RTX_CLASS (code) != 'i')
return insn;
pat_code = GET_CODE (PATTERN (insn));
if (pat_code == USE
|| pat_code == CLOBBER
- || pat_code == ASM_INPUT
|| pat_code == ADDR_VEC
|| pat_code == ADDR_DIFF_VEC)
return insn;
--- 883,899 ----
{
enum rtx_code code = GET_CODE (insn);
enum rtx_code pat_code;
rtx set, note;
int i, j;
+ struct costs op_costs[MAX_RECOG_OPERANDS];
+
if (GET_RTX_CLASS (code) != 'i')
return insn;
pat_code = GET_CODE (PATTERN (insn));
if (pat_code == USE
|| pat_code == CLOBBER
|| pat_code == ADDR_VEC
|| pat_code == ADDR_DIFF_VEC)
return insn;
*************** scan_one_insn (insn, pass)
*** 833,845 ****
set = single_set (insn);
extract_insn (insn);
- for (i = 0; i < recog_data.n_operands; i++)
- {
- constraints[i] = recog_data.constraints[i];
- modes[i] = recog_data.operand_mode[i];
- }
- memset (subreg_changes_size, 0, sizeof (subreg_changes_size));
-
/* If this insn loads a parameter from its stack slot, then
it represents a savings, rather than a cost, if the
parameter is stored in memory. Record this fact. */
--- 901,906 ----
*************** scan_one_insn (insn, pass)
*** 911,968 ****
return PREV_INSN (newinsn);
}
! /* If we get here, we are set up to record the costs of all the
! operands for this insn. Start by initializing the costs.
! Then handle any address registers. Finally record the desired
! classes for any pseudos, doing it twice if some pair of
! operands are commutative. */
!
! for (i = 0; i < recog_data.n_operands; i++)
! {
! op_costs[i] = init_cost;
!
! if (GET_CODE (recog_data.operand[i]) == SUBREG)
! {
! rtx inner = SUBREG_REG (recog_data.operand[i]);
! if (GET_MODE_SIZE (modes[i]) != GET_MODE_SIZE (GET_MODE (inner)))
! subreg_changes_size[i] = 1;
! recog_data.operand[i] = inner;
! }
!
! if (GET_CODE (recog_data.operand[i]) == MEM)
! record_address_regs (XEXP (recog_data.operand[i], 0),
! BASE_REG_CLASS, loop_cost * 2);
! else if (constraints[i][0] == 'p')
! record_address_regs (recog_data.operand[i],
! BASE_REG_CLASS, loop_cost * 2);
! }
!
! /* Check for commutative in a separate loop so everything will
! have been initialized. We must do this even if one operand
! is a constant--see addsi3 in m68k.md. */
!
! for (i = 0; i < (int) recog_data.n_operands - 1; i++)
! if (constraints[i][0] == '%')
! {
! const char *xconstraints[MAX_RECOG_OPERANDS];
! int j;
!
! /* Handle commutative operands by swapping the constraints.
! We assume the modes are the same. */
!
! for (j = 0; j < recog_data.n_operands; j++)
! xconstraints[j] = constraints[j];
!
! xconstraints[i] = constraints[i+1];
! xconstraints[i+1] = constraints[i];
! record_reg_classes (recog_data.n_alternatives, recog_data.n_operands,
! recog_data.operand, modes, subreg_changes_size,
! xconstraints, insn);
! }
!
! record_reg_classes (recog_data.n_alternatives, recog_data.n_operands,
! recog_data.operand, modes, subreg_changes_size,
! constraints, insn);
/* Now add the cost for each operand to the total costs for
its register. */
--- 972,978 ----
return PREV_INSN (newinsn);
}
! record_operand_costs(insn, op_costs, reg_pref);
/* Now add the cost for each operand to the total costs for
its register. */
*************** regclass (f, nregs, dump)
*** 1062,1067 ****
--- 1072,1080 ----
for (pass = 0; pass <= flag_expensive_optimizations; pass++)
{
int index;
+
+ if (dump)
+ fprintf (dump, "\n\nPass %i\n\n",pass);
/* Zero out our accumulation of the cost of each class for each reg. */
bzero ((char *) costs, nregs * sizeof (struct costs));
*************** regclass (f, nregs, dump)
*** 1102,1107 ****
--- 1115,1125 ----
if (pass == 0)
reg_pref = reg_pref_buffer;
+ if (dump)
+ {
+ dump_regclass (dump);
+ fprintf(dump,"\n");
+ }
for (i = FIRST_PSEUDO_REGISTER; i < nregs; i++)
{
register int best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1;
*************** regclass (f, nregs, dump)
*** 1111,1116 ****
--- 1129,1137 ----
register int class;
register struct costs *p = &costs[i];
+ if (!REG_N_REFS (i))
+ continue;
+
for (class = (int) ALL_REGS - 1; class > 0; class--)
{
/* Ignore classes that are too small for this operand or
*************** regclass (f, nregs, dump)
*** 1138,1144 ****
should be provided as a register class. Don't do this if we
will be doing it again later. */
! if (pass == 1 || ! 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]]
--- 1159,1165 ----
should be provided as a register class. Don't do this if we
will be doing it again later. */
! if ((pass == 1 || dump) || ! 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]]
*************** regclass (f, nregs, dump)
*** 1153,1167 ****
if (alt == best)
alt = NO_REGS;
/* We cast to (int) because (char) hits bugs in some compilers. */
reg_pref[i].prefclass = (int) best;
reg_pref[i].altclass = (int) alt;
}
- if (dump)
- {
- fprintf (dump, "\nPass %i\n",pass);
- dump_regclass (dump);
- }
}
#ifdef FORBIDDEN_INC_DEC_CLASSES
--- 1174,1197 ----
if (alt == best)
alt = NO_REGS;
+ if (dump
+ && (reg_pref[i].prefclass != (int) best || reg_pref[i].altclass != (int) alt))
+ {
+ static const char *const reg_class_names[] = REG_CLASS_NAMES;
+ fprintf(dump, " Register %i", i);
+ if (alt == ALL_REGS || best == ALL_REGS)
+ fprintf (dump, " pref %s\n", reg_class_names[(int) best]);
+ else if (alt == NO_REGS)
+ fprintf (dump, " pref %s or none\n", reg_class_names[(int) best]);
+ else
+ fprintf (dump, " pref %s, else %s\n",
+ reg_class_names[(int) best],
+ reg_class_names[(int) alt]);
+ }
/* We cast to (int) because (char) hits bugs in some compilers. */
reg_pref[i].prefclass = (int) best;
reg_pref[i].altclass = (int) alt;
}
}
#ifdef FORBIDDEN_INC_DEC_CLASSES
*************** regclass (f, nregs, dump)
*** 1196,1202 ****
static void
record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size,
! constraints, insn)
int n_alts;
int n_ops;
rtx *ops;
--- 1226,1232 ----
static void
record_reg_classes (n_alts, n_ops, ops, modes, subreg_changes_size,
! constraints, insn, op_costs, reg_pref)
int n_alts;
int n_ops;
rtx *ops;
*************** record_reg_classes (n_alts, n_ops, ops,
*** 1204,1209 ****
--- 1234,1241 ----
char *subreg_changes_size ATTRIBUTE_UNUSED;
const char **constraints;
rtx insn;
+ struct costs *op_costs;
+ struct reg_pref *reg_pref;
{
int alt;
int i, j;
More information about the Gcc-patches
mailing list