diff options
author | Bernd Schmidt <crux@pool.informatik.rwth-aachen.de> | 1998-10-14 01:21:06 +0000 |
---|---|---|
committer | Jeff Law <law@gcc.gnu.org> | 1998-10-13 19:21:06 -0600 |
commit | 18a90182e3204fe9418addfd3824d7ca68007128 (patch) | |
tree | c4a397994dfab113e27e01b53436dba983f876f2 /gcc | |
parent | 7609e7209a9078fec27fa04108cb5b8173911cbe (diff) | |
download | gcc-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/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/reload1.c | 116 |
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. */ |