Commit 61719ba7 by Bernd Schmidt Committed by Jeff Law

regclass.c (regclass): Break out some code into new function scan_one_insn, and into regclass_init.

        * regclass.c (regclass): Break out some code into new function
        scan_one_insn, and into regclass_init.
        (init_cost): New static variable, moved out of regclass.
        (regclass_init): Initialize it here, not in .
        (scan_one_insn): New static function, broken out of regclass.
        * recog.c (apply_change_group): Break out some code into new
        function insn_invalid_p.
        (insn_invalid_p): New static fn, broken out of apply_change_group.

From-SVN: r23236
parent 04bbb0c5
Fri Oct 23 00:07:01 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
* regclass.c (regclass): Break out some code into new function
scan_one_insn, and into regclass_init.
(init_cost): New static variable, moved out of regclass.
(regclass_init): Initialize it here, not in .
(scan_one_insn): New static function, broken out of regclass.
* recog.c (apply_change_group): Break out some code into new
function insn_invalid_p.
(insn_invalid_p): New static fn, broken out of apply_change_group.
Thu Oct 22 22:34:42 1998 Jim Wilson <wilson@cygnus.com> Thu Oct 22 22:34:42 1998 Jim Wilson <wilson@cygnus.com>
* reload1.c (reload_as_needed): When rewrite POST_INC, verify * reload1.c (reload_as_needed): When rewrite POST_INC, verify
......
...@@ -43,6 +43,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -43,6 +43,7 @@ Boston, MA 02111-1307, USA. */
static void validate_replace_rtx_1 PROTO((rtx *, rtx, rtx, rtx)); static void validate_replace_rtx_1 PROTO((rtx *, rtx, rtx, rtx));
static rtx *find_single_use_1 PROTO((rtx, rtx *)); static rtx *find_single_use_1 PROTO((rtx, rtx *));
static rtx *find_constant_term_loc PROTO((rtx *)); static rtx *find_constant_term_loc PROTO((rtx *));
static int insn_invalid_p PROTO((rtx));
/* Nonzero means allow operands to be volatile. /* Nonzero means allow operands to be volatile.
This should be 0 if you are generating rtl, such as if you are calling This should be 0 if you are generating rtl, such as if you are calling
...@@ -252,6 +253,41 @@ validate_change (object, loc, new, in_group) ...@@ -252,6 +253,41 @@ validate_change (object, loc, new, in_group)
return apply_change_group (); return apply_change_group ();
} }
/* This subroutine of apply_change_group verifies whether the changes to INSN
were valid; i.e. whether INSN can still be recognized. */
static int
insn_invalid_p (insn)
rtx insn;
{
int icode = recog_memoized (insn);
int is_asm = icode < 0 && asm_noperands (PATTERN (insn)) >= 0;
if (is_asm)
{
if (! check_asm_operands (PATTERN (insn)))
return 1;
/* Disallow modification of ASM_OPERANDS after reload; verifying the
constraints is too difficult. */
if (reload_completed)
return 1;
}
else if (icode < 0)
return 1;
/* After reload, verify that all constraints are satisfied. */
if (reload_completed)
{
insn_extract (insn);
if (! constrain_operands (INSN_CODE (insn), 1))
return 1;
}
return 0;
}
/* Apply a group of changes previously issued with `validate_change'. /* Apply a group of changes previously issued with `validate_change'.
Return 1 if all changes are valid, zero otherwise. */ Return 1 if all changes are valid, zero otherwise. */
...@@ -282,13 +318,7 @@ apply_change_group () ...@@ -282,13 +318,7 @@ apply_change_group ()
if (! memory_address_p (GET_MODE (object), XEXP (object, 0))) if (! memory_address_p (GET_MODE (object), XEXP (object, 0)))
break; break;
} }
else if ((recog_memoized (object) < 0 else if (insn_invalid_p (object))
&& (asm_noperands (PATTERN (object)) < 0
|| ! check_asm_operands (PATTERN (object))
|| reload_completed))
|| (reload_completed
&& (insn_extract (object),
! constrain_operands (INSN_CODE (object), 1))))
{ {
rtx pat = PATTERN (object); rtx pat = PATTERN (object);
......
...@@ -648,6 +648,10 @@ struct costs ...@@ -648,6 +648,10 @@ struct costs
static struct costs *costs; static struct costs *costs;
/* Initialized once, and used to initialize cost values for each insn. */
static struct costs init_cost;
/* Record the same data by operand number, accumulated for each alternative /* 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 in an insn. The contribution to a pseudo is that of the minimum-cost
alternative. */ alternative. */
...@@ -685,6 +689,7 @@ static int loop_depth; ...@@ -685,6 +689,7 @@ static int loop_depth;
static int loop_cost; static int loop_cost;
static int n_occurrences PROTO((int, char *)); static int n_occurrences PROTO((int, char *));
static rtx scan_one_insn PROTO((rtx, int));
static void record_reg_classes PROTO((int, int, rtx *, enum machine_mode *, static void record_reg_classes PROTO((int, int, rtx *, enum machine_mode *,
char **, rtx)); char **, rtx));
static int copy_cost PROTO((rtx, enum machine_mode, static int copy_cost PROTO((rtx, enum machine_mode,
...@@ -718,12 +723,19 @@ reg_alternate_class (regno) ...@@ -718,12 +723,19 @@ reg_alternate_class (regno)
return (enum reg_class) altclass[regno]; return (enum reg_class) altclass[regno];
} }
/* This prevents dump_flow_info from losing if called /* Initialize some global data for this pass. */
before regclass is run. */
void void
regclass_init () regclass_init ()
{ {
int i;
init_cost.mem_cost = 10000;
for (i = 0; i < N_REG_CLASSES; i++)
init_cost.cost[i] = 10000;
/* This prevents dump_flow_info from losing if called
before regclass is run. */
prefclass = 0; prefclass = 0;
} }
...@@ -739,132 +751,55 @@ n_occurrences (c, s) ...@@ -739,132 +751,55 @@ n_occurrences (c, s)
return n; return n;
} }
/* This is a pass of the compiler that scans all instructions /* Subroutine of regclass, processes one insn INSN. Scan it and record each
and calculates the preferred class for each pseudo-register. time it would save code to put a certain register in a certain class.
This information can be accessed later by calling `reg_preferred_class'. PASS, when nonzero, inhibits some optimizations which need only be done
This pass comes just before local register allocation. */ once.
Return the last insn processed, so that the scan can be continued from
there. */
void static rtx
regclass (f, nregs) scan_one_insn (insn, pass)
rtx f; rtx insn;
int nregs;
{
#ifdef REGISTER_CONSTRAINTS
register rtx insn;
register int i, j;
struct costs init_cost;
rtx set;
int pass; int pass;
{
enum rtx_code code = GET_CODE (insn);
enum rtx_code pat_code;
init_recog ();
costs = (struct costs *) xmalloc (nregs * sizeof (struct costs));
#ifdef FORBIDDEN_INC_DEC_CLASSES
in_inc_dec = (char *) alloca (nregs);
/* Initialize information about which register classes can be used for
pseudos that are auto-incremented or auto-decremented. It would
seem better to put this in init_reg_sets, but we need to be able
to allocate rtx, which we can't do that early. */
for (i = 0; i < N_REG_CLASSES; i++)
{
rtx r = gen_rtx_REG (VOIDmode, 0);
enum machine_mode m;
for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
if (TEST_HARD_REG_BIT (reg_class_contents[i], j))
{
REGNO (r) = j;
for (m = VOIDmode; (int) m < (int) MAX_MACHINE_MODE;
m = (enum machine_mode) ((int) m + 1))
if (HARD_REGNO_MODE_OK (j, m))
{
PUT_MODE (r, m);
/* If a register is not directly suitable for an
auto-increment or decrement addressing mode and
requires secondary reloads, disallow its class from
being used in such addresses. */
if ((0
#ifdef SECONDARY_RELOAD_CLASS
|| (SECONDARY_RELOAD_CLASS (BASE_REG_CLASS, m, r)
!= NO_REGS)
#else
#ifdef SECONDARY_INPUT_RELOAD_CLASS
|| (SECONDARY_INPUT_RELOAD_CLASS (BASE_REG_CLASS, m, r)
!= NO_REGS)
#endif
#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
|| (SECONDARY_OUTPUT_RELOAD_CLASS (BASE_REG_CLASS, m, r)
!= NO_REGS)
#endif
#endif
)
&& ! auto_inc_dec_reg_p (r, m))
forbidden_inc_dec_class[i] = 1;
}
}
}
#endif /* FORBIDDEN_INC_DEC_CLASSES */
init_cost.mem_cost = 10000;
for (i = 0; i < N_REG_CLASSES; i++)
init_cost.cost[i] = 10000;
/* Normally we scan the insns once and determine the best class to use for
each register. However, if -fexpensive_optimizations are on, we do so
twice, the second time using the tentative best classes to guide the
selection. */
for (pass = 0; pass <= flag_expensive_optimizations; pass++)
{
/* Zero out our accumulation of the cost of each class for each reg. */
bzero ((char *) costs, nregs * sizeof (struct costs));
#ifdef FORBIDDEN_INC_DEC_CLASSES
bzero (in_inc_dec, nregs);
#endif
loop_depth = 0, loop_cost = 1;
/* Scan the instructions and record each time it would
save code to put a certain register in a certain class. */
for (insn = f; insn; insn = NEXT_INSN (insn))
{
char *constraints[MAX_RECOG_OPERANDS]; char *constraints[MAX_RECOG_OPERANDS];
enum machine_mode modes[MAX_RECOG_OPERANDS]; enum machine_mode modes[MAX_RECOG_OPERANDS];
int nalternatives; int nalternatives;
int noperands; int noperands;
rtx set;
int i, j;
/* Show that an insn inside a loop is likely to be executed three /* Show that an insn inside a loop is likely to be executed three
times more than insns outside a loop. This is much more aggressive times more than insns outside a loop. This is much more aggressive
than the assumptions made elsewhere and is being tried as an than the assumptions made elsewhere and is being tried as an
experiment. */ experiment. */
if (GET_CODE (insn) == NOTE if (code == NOTE)
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG) {
if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_BEG)
loop_depth++, loop_cost = 1 << (2 * MIN (loop_depth, 5)); loop_depth++, loop_cost = 1 << (2 * MIN (loop_depth, 5));
else if (GET_CODE (insn) == NOTE else if (NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_LOOP_END)
loop_depth--, loop_cost = 1 << (2 * MIN (loop_depth, 5)); loop_depth--, loop_cost = 1 << (2 * MIN (loop_depth, 5));
else if ((GET_CODE (insn) == INSN return insn;
&& GET_CODE (PATTERN (insn)) != USE }
&& GET_CODE (PATTERN (insn)) != CLOBBER
&& GET_CODE (PATTERN (insn)) != ASM_INPUT) if (GET_RTX_CLASS (code) != 'i')
|| (GET_CODE (insn) == JUMP_INSN return insn;
&& GET_CODE (PATTERN (insn)) != ADDR_VEC
&& GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC) pat_code = GET_CODE (PATTERN (insn));
|| GET_CODE (insn) == CALL_INSN) if (pat_code == USE
{ || pat_code == CLOBBER
if (GET_CODE (insn) == INSN || pat_code == ASM_INPUT
|| pat_code == ADDR_VEC
|| pat_code == ADDR_DIFF_VEC)
return insn;
if (code == INSN
&& (noperands = asm_noperands (PATTERN (insn))) >= 0) && (noperands = asm_noperands (PATTERN (insn))) >= 0)
{ {
decode_asm_operands (PATTERN (insn), recog_operand, NULL_PTR, decode_asm_operands (PATTERN (insn), recog_operand, NULL_PTR,
...@@ -899,7 +834,7 @@ regclass (f, nregs) ...@@ -899,7 +834,7 @@ regclass (f, nregs)
* loop_cost); * loop_cost);
record_address_regs (XEXP (SET_SRC (set), 0), record_address_regs (XEXP (SET_SRC (set), 0),
BASE_REG_CLASS, loop_cost * 2); BASE_REG_CLASS, loop_cost * 2);
continue; return insn;
} }
/* Improve handling of two-address insns such as /* Improve handling of two-address insns such as
...@@ -955,8 +890,7 @@ regclass (f, nregs) ...@@ -955,8 +890,7 @@ regclass (f, nregs)
if (recog_dup_num[i] == 1) if (recog_dup_num[i] == 1)
*recog_dup_loc[i] = recog_operand[0]; *recog_dup_loc[i] = recog_operand[0];
insn = PREV_INSN (newinsn); return PREV_INSN (newinsn);
continue;
} }
for (i = 0; i < noperands; i++) for (i = 0; i < noperands; i++)
...@@ -1028,7 +962,104 @@ regclass (f, nregs) ...@@ -1028,7 +962,104 @@ regclass (f, nregs)
for (j = 0; j < N_REG_CLASSES; j++) for (j = 0; j < N_REG_CLASSES; j++)
p->cost[j] += q->cost[j] * loop_cost; p->cost[j] += q->cost[j] * loop_cost;
} }
return insn;
}
/* This is a pass of the compiler that scans all instructions
and calculates the preferred class for each pseudo-register.
This information can be accessed later by calling `reg_preferred_class'.
This pass comes just before local register allocation. */
void
regclass (f, nregs)
rtx f;
int nregs;
{
#ifdef REGISTER_CONSTRAINTS
register rtx insn;
register int i;
int pass;
init_recog ();
costs = (struct costs *) xmalloc (nregs * sizeof (struct costs));
#ifdef FORBIDDEN_INC_DEC_CLASSES
in_inc_dec = (char *) alloca (nregs);
/* Initialize information about which register classes can be used for
pseudos that are auto-incremented or auto-decremented. It would
seem better to put this in init_reg_sets, but we need to be able
to allocate rtx, which we can't do that early. */
for (i = 0; i < N_REG_CLASSES; i++)
{
rtx r = gen_rtx_REG (VOIDmode, 0);
enum machine_mode m;
for (j = 0; j < FIRST_PSEUDO_REGISTER; j++)
if (TEST_HARD_REG_BIT (reg_class_contents[i], j))
{
REGNO (r) = j;
for (m = VOIDmode; (int) m < (int) MAX_MACHINE_MODE;
m = (enum machine_mode) ((int) m + 1))
if (HARD_REGNO_MODE_OK (j, m))
{
PUT_MODE (r, m);
/* If a register is not directly suitable for an
auto-increment or decrement addressing mode and
requires secondary reloads, disallow its class from
being used in such addresses. */
if ((0
#ifdef SECONDARY_RELOAD_CLASS
|| (SECONDARY_RELOAD_CLASS (BASE_REG_CLASS, m, r)
!= NO_REGS)
#else
#ifdef SECONDARY_INPUT_RELOAD_CLASS
|| (SECONDARY_INPUT_RELOAD_CLASS (BASE_REG_CLASS, m, r)
!= NO_REGS)
#endif
#ifdef SECONDARY_OUTPUT_RELOAD_CLASS
|| (SECONDARY_OUTPUT_RELOAD_CLASS (BASE_REG_CLASS, m, r)
!= NO_REGS)
#endif
#endif
)
&& ! auto_inc_dec_reg_p (r, m))
forbidden_inc_dec_class[i] = 1;
}
}
} }
#endif /* FORBIDDEN_INC_DEC_CLASSES */
/* Normally we scan the insns once and determine the best class to use for
each register. However, if -fexpensive_optimizations are on, we do so
twice, the second time using the tentative best classes to guide the
selection. */
for (pass = 0; pass <= flag_expensive_optimizations; pass++)
{
/* Zero out our accumulation of the cost of each class for each reg. */
bzero ((char *) costs, nregs * sizeof (struct costs));
#ifdef FORBIDDEN_INC_DEC_CLASSES
bzero (in_inc_dec, nregs);
#endif
loop_depth = 0, loop_cost = 1;
/* Scan the instructions and record each time it would
save code to put a certain register in a certain class. */
for (insn = f; insn; insn = NEXT_INSN (insn))
{
insn = scan_one_insn (insn, pass);
} }
/* Now for each register look at how desirable each class is /* Now for each register look at how desirable each class is
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment