Commit 18a90182 by Bernd Schmidt Committed by Jeff Law

reload1.c (maybe_fix_stack_asms): New static function.

	* reload1.c (maybe_fix_stack_asms): New static function.
	(reload): Call it.

From-SVN: r23075
parent 7609e720
Tue Oct 13 22:12:11 1998 Bernd Schmidt <crux@pool.informatik.rwth-aachen.de> 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. * reload.h (compute_use_by_pseudos): Declare.
* reload1.c (spilled_pseudos, insns_need_reload): New variables. * reload1.c (spilled_pseudos, insns_need_reload): New variables.
......
...@@ -357,6 +357,7 @@ static int num_labels; ...@@ -357,6 +357,7 @@ static int num_labels;
struct hard_reg_n_uses { int regno; int uses; }; struct hard_reg_n_uses { int regno; int uses; };
static void dump_needs PROTO((FILE *)); 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_all_insns PROTO((int));
static int calculate_needs PROTO((struct insn_chain *, rtx, int)); static int calculate_needs PROTO((struct insn_chain *, rtx, int));
static int find_reload_regs PROTO((int, FILE *)); static int find_reload_regs PROTO((int, FILE *));
...@@ -868,6 +869,8 @@ reload (first, global, dumpfile) ...@@ -868,6 +869,8 @@ reload (first, global, dumpfile)
order_regs_for_reload (); order_regs_for_reload ();
maybe_fix_stack_asms ();
/* So far, no hard regs have been spilled. */ /* So far, no hard regs have been spilled. */
n_spills = 0; n_spills = 0;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
...@@ -1280,6 +1283,119 @@ reload (first, global, dumpfile) ...@@ -1280,6 +1283,119 @@ reload (first, global, dumpfile)
return failure; 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 /* Walk the insns of the current function, starting with FIRST, and collect
information about the need to do register elimination and the need to information about the need to do register elimination and the need to
perform reloads. */ perform reloads. */
......
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