aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorBernd Schmidt <crux@pool.informatik.rwth-aachen.de>1998-10-14 01:21:06 +0000
committerJeff Law <law@gcc.gnu.org>1998-10-13 19:21:06 -0600
commit18a90182e3204fe9418addfd3824d7ca68007128 (patch)
treec4a397994dfab113e27e01b53436dba983f876f2 /gcc
parent7609e7209a9078fec27fa04108cb5b8173911cbe (diff)
downloadgcc-18a90182e3204fe9418addfd3824d7ca68007128.zip
gcc-18a90182e3204fe9418addfd3824d7ca68007128.tar.gz
gcc-18a90182e3204fe9418addfd3824d7ca68007128.tar.bz2
reload1.c (maybe_fix_stack_asms): New static function.
* reload1.c (maybe_fix_stack_asms): New static function. (reload): Call it. From-SVN: r23075
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog3
-rw-r--r--gcc/reload1.c116
2 files changed, 119 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 2168f56..9351a57 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/reload1.c b/gcc/reload1.c
index a9925cb..34f4954 100644
--- a/gcc/reload1.c
+++ b/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. */