reload1.c (maybe_fix_stack_asms): New static function.
* reload1.c (maybe_fix_stack_asms): New static function. (reload): Call it. From-SVN: r23075
This commit is contained in:
parent
7609e7209a
commit
18a90182e3
|
@ -1,5 +1,8 @@
|
|||
Tue Oct 13 22:12:11 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de>
|
||||
|
||||
* reload1.c (maybe_fix_stack_asms): New static function.
|
||||
(reload): Call it.
|
||||
|
||||
* reload.h (compute_use_by_pseudos): Declare.
|
||||
|
||||
* reload1.c (spilled_pseudos, insns_need_reload): New variables.
|
||||
|
|
116
gcc/reload1.c
116
gcc/reload1.c
|
@ -357,6 +357,7 @@ static int num_labels;
|
|||
struct hard_reg_n_uses { int regno; int uses; };
|
||||
|
||||
static void dump_needs PROTO((FILE *));
|
||||
static void maybe_fix_stack_asms PROTO((void));
|
||||
static int calculate_needs_all_insns PROTO((int));
|
||||
static int calculate_needs PROTO((struct insn_chain *, rtx, int));
|
||||
static int find_reload_regs PROTO((int, FILE *));
|
||||
|
@ -868,6 +869,8 @@ reload (first, global, dumpfile)
|
|||
|
||||
order_regs_for_reload ();
|
||||
|
||||
maybe_fix_stack_asms ();
|
||||
|
||||
/* So far, no hard regs have been spilled. */
|
||||
n_spills = 0;
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
|
@ -1280,6 +1283,119 @@ reload (first, global, dumpfile)
|
|||
return failure;
|
||||
}
|
||||
|
||||
/* Yet another special case. Unfortunately, reg-stack forces people to
|
||||
write incorrect clobbers in asm statements. These clobbers must not
|
||||
cause the register to appear in bad_spill_regs, otherwise we'll call
|
||||
fatal_insn later. We clear the corresponding regnos in the live
|
||||
register sets to avoid this.
|
||||
The whole thing is rather sick, I'm afraid. */
|
||||
static void
|
||||
maybe_fix_stack_asms ()
|
||||
{
|
||||
#ifdef STACK_REGS
|
||||
char *constraints[MAX_RECOG_OPERANDS];
|
||||
enum machine_mode operand_mode[MAX_RECOG_OPERANDS];
|
||||
struct insn_chain *chain;
|
||||
|
||||
for (chain = reload_insn_chain; chain != 0; chain = chain->next)
|
||||
{
|
||||
int i, noperands;
|
||||
HARD_REG_SET clobbered, allowed;
|
||||
rtx pat;
|
||||
|
||||
if (GET_RTX_CLASS (GET_CODE (chain->insn)) != 'i'
|
||||
|| (noperands = asm_noperands (PATTERN (chain->insn))) < 0)
|
||||
continue;
|
||||
pat = PATTERN (chain->insn);
|
||||
if (GET_CODE (pat) != PARALLEL)
|
||||
continue;
|
||||
|
||||
CLEAR_HARD_REG_SET (clobbered);
|
||||
CLEAR_HARD_REG_SET (allowed);
|
||||
|
||||
/* First, make a mask of all stack regs that are clobbered. */
|
||||
for (i = 0; i < XVECLEN (pat, 0); i++)
|
||||
{
|
||||
rtx t = XVECEXP (pat, 0, i);
|
||||
if (GET_CODE (t) == CLOBBER && STACK_REG_P (XEXP (t, 0)))
|
||||
SET_HARD_REG_BIT (clobbered, REGNO (XEXP (t, 0)));
|
||||
}
|
||||
|
||||
/* Get the operand values and constraints out of the insn. */
|
||||
decode_asm_operands (pat, recog_operand, recog_operand_loc,
|
||||
constraints, operand_mode);
|
||||
|
||||
/* For every operand, see what registers are allowed. */
|
||||
for (i = 0; i < noperands; i++)
|
||||
{
|
||||
char *p = constraints[i];
|
||||
/* For every alternative, we compute the class of registers allowed
|
||||
for reloading in CLS, and merge its contents into the reg set
|
||||
ALLOWED. */
|
||||
int cls = (int) NO_REGS;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
char c = *p++;
|
||||
|
||||
if (c == '\0' || c == ',' || c == '#')
|
||||
{
|
||||
/* End of one alternative - mark the regs in the current
|
||||
class, and reset the class. */
|
||||
IOR_HARD_REG_SET (allowed, reg_class_contents[cls]);
|
||||
cls = NO_REGS;
|
||||
if (c == '#')
|
||||
do {
|
||||
c = *p++;
|
||||
} while (c != '\0' && c != ',');
|
||||
if (c == '\0')
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (c)
|
||||
{
|
||||
case '=': case '+': case '*': case '%': case '?': case '!':
|
||||
case '0': case '1': case '2': case '3': case '4': case 'm':
|
||||
case '<': case '>': case 'V': case 'o': case '&': case 'E':
|
||||
case 'F': case 's': case 'i': case 'n': case 'X': case 'I':
|
||||
case 'J': case 'K': case 'L': case 'M': case 'N': case 'O':
|
||||
case 'P':
|
||||
#ifdef EXTRA_CONSTRAINT
|
||||
case 'Q': case 'R': case 'S': case 'T': case 'U':
|
||||
#endif
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
cls = (int) reg_class_subunion[cls][(int) BASE_REG_CLASS];
|
||||
break;
|
||||
|
||||
case 'g':
|
||||
case 'r':
|
||||
cls = (int) reg_class_subunion[cls][(int) GENERAL_REGS];
|
||||
break;
|
||||
|
||||
default:
|
||||
cls = (int) reg_class_subunion[cls][(int) REG_CLASS_FROM_LETTER (c)];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Those of the registers which are clobbered, but allowed by the
|
||||
constraints, must be usable as reload registers. So clear them
|
||||
out of the life information. */
|
||||
AND_HARD_REG_SET (allowed, clobbered);
|
||||
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
|
||||
if (TEST_HARD_REG_BIT (allowed, i))
|
||||
{
|
||||
CLEAR_REGNO_REG_SET (chain->live_before, i);
|
||||
CLEAR_REGNO_REG_SET (chain->live_after, i);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Walk the insns of the current function, starting with FIRST, and collect
|
||||
information about the need to do register elimination and the need to
|
||||
perform reloads. */
|
||||
|
|
Loading…
Reference in New Issue