diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 5cc14f3d28b..532a9c6bfd5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2000-11-10 Bernd Schmidt + + * reload.c (find_reloads_address_1, case POST_MODIFY): Use RELOAD_OTHER + for address reloads. Push replacements for REG_INC notes. + (regno_clobbered_p): New arg SETS. Examine SETs if it's nonzero. All + callers changed. + * reload1.c (choose_reload_regs): Registers set in the insn can't be + used for RELOAD_OTHER reloads. + 2000-11-10 Mark Mitchell * c-dump.h: New file. diff --git a/gcc/reload.c b/gcc/reload.c index 65a5e731b41..86d80c1af23 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -4536,7 +4536,7 @@ find_reloads_address (mode, memrefloc, ad, loc, opnum, type, ind_levels, insn) else if (regno < FIRST_PSEUDO_REGISTER && REGNO_MODE_OK_FOR_BASE_P (regno, mode) - && ! regno_clobbered_p (regno, this_insn, mode)) + && ! regno_clobbered_p (regno, this_insn, mode, 0)) return 0; /* If we do not have one of the cases above, we must do the reload. */ @@ -5155,7 +5155,9 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn) if (REG_P (XEXP (op1, 0))) { - register int regno = REGNO (XEXP (op1, 0)); + rtx link; + int regno = REGNO (XEXP (op1, 0)); + int reloadnum; /* A register that is incremented cannot be constant! */ if (regno >= FIRST_PSEUDO_REGISTER @@ -5178,15 +5180,17 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn) write back the value after reading it, hence we actually need two registers. */ find_reloads_address (GET_MODE (tem), 0, XEXP (tem, 0), - &XEXP (tem, 0), opnum, type, + &XEXP (tem, 0), opnum, + RELOAD_OTHER, ind_levels, insn); /* Then reload the memory location into a base register. */ - push_reload (tem, tem, &XEXP (x, 0), &XEXP (op1, 0), - BASE_REG_CLASS, GET_MODE (x), GET_MODE (x), - 0, 0, opnum, RELOAD_OTHER); - break; + reloadnum = push_reload (tem, tem, &XEXP (x, 0), + &XEXP (op1, 0), BASE_REG_CLASS, + GET_MODE (x), GET_MODE (x), 0, + 0, opnum, RELOAD_OTHER); + goto reg_inc; } } @@ -5196,12 +5200,19 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn) /* We require a base register here... */ if (!REGNO_MODE_OK_FOR_BASE_P (regno, GET_MODE (x))) { - push_reload (XEXP (op1, 0), XEXP (x, 0), - &XEXP (op1, 0), &XEXP (x, 0), - BASE_REG_CLASS, - GET_MODE (x), GET_MODE (x), 0, 0, - opnum, RELOAD_OTHER); + reloadnum = push_reload (XEXP (op1, 0), XEXP (x, 0), + &XEXP (op1, 0), &XEXP (x, 0), + BASE_REG_CLASS, + GET_MODE (x), GET_MODE (x), 0, 0, + opnum, RELOAD_OTHER); } + + /* Update the REG_INC notes. */ + reg_inc: + for (link = REG_NOTES (this_insn); link; link = XEXP (link, 1)) + if (REG_NOTE_KIND (link) == REG_INC + && REGNO (XEXP (link, 0)) == regno) + push_replacement (&XEXP (link, 0), reloadnum, VOIDmode); } else abort (); @@ -5441,7 +5452,7 @@ find_reloads_address_1 (mode, x, context, loc, opnum, type, ind_levels, insn) in this insn, reload it into some other register to be safe. The CLOBBER is supposed to make the register unavailable from before this insn to after it. */ - if (regno_clobbered_p (regno, this_insn, GET_MODE (x))) + if (regno_clobbered_p (regno, this_insn, GET_MODE (x), 0)) { push_reload (x, NULL_RTX, loc, NULL_PTR, (context ? INDEX_REG_CLASS : BASE_REG_CLASS), @@ -6552,18 +6563,21 @@ find_inc_amount (x, inced) return 0; } -/* Return 1 if register REGNO is the subject of a clobber in insn INSN. */ +/* Return 1 if register REGNO is the subject of a clobber in insn INSN. + If SETS is nonzero, also consider SETs. */ int -regno_clobbered_p (regno, insn, mode) +regno_clobbered_p (regno, insn, mode, sets) unsigned int regno; rtx insn; enum machine_mode mode; + int sets; { int nregs = HARD_REGNO_NREGS (regno, mode); int endregno = regno + nregs; - if (GET_CODE (PATTERN (insn)) == CLOBBER + if ((GET_CODE (PATTERN (insn)) == CLOBBER + || (sets && GET_CODE (PATTERN (insn)) == SET)) && GET_CODE (XEXP (PATTERN (insn), 0)) == REG) { int test = REGNO (XEXP (PATTERN (insn), 0)); @@ -6578,7 +6592,9 @@ regno_clobbered_p (regno, insn, mode) for (; i >= 0; i--) { rtx elt = XVECEXP (PATTERN (insn), 0, i); - if (GET_CODE (elt) == CLOBBER && GET_CODE (XEXP (elt, 0)) == REG) + if ((GET_CODE (elt) == CLOBBER + || (sets && GET_CODE (PATTERN (insn)) == SET)) + && GET_CODE (XEXP (elt, 0)) == REG) { int test = REGNO (XEXP (elt, 0)); diff --git a/gcc/reload.h b/gcc/reload.h index a2df3b1caa5..7841c7ad7d1 100644 --- a/gcc/reload.h +++ b/gcc/reload.h @@ -335,7 +335,8 @@ extern rtx find_equiv_reg PARAMS ((rtx, rtx, enum reg_class, int, short *, int, enum machine_mode)); /* Return 1 if register REGNO is the subject of a clobber in insn INSN. */ -extern int regno_clobbered_p PARAMS ((unsigned int, rtx, enum machine_mode)); +extern int regno_clobbered_p PARAMS ((unsigned int, rtx, enum machine_mode, + int)); /* Return 1 if X is an operand of an insn that is being earlyclobbered. */ int earlyclobber_operand_p PARAMS ((rtx)); diff --git a/gcc/reload1.c b/gcc/reload1.c index dbe13fa6f51..fe749293dbf 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -5544,25 +5544,44 @@ choose_reload_regs (chain) In particular, we then can't use EQUIV for a RELOAD_FOR_OUTPUT_ADDRESS reload. */ - if (equiv != 0 && regno_clobbered_p (regno, insn, rld[r].mode)) - { - switch (rld[r].when_needed) - { - case RELOAD_FOR_OTHER_ADDRESS: - case RELOAD_FOR_INPADDR_ADDRESS: - case RELOAD_FOR_INPUT_ADDRESS: - case RELOAD_FOR_OPADDR_ADDR: - break; - case RELOAD_OTHER: - case RELOAD_FOR_INPUT: - case RELOAD_FOR_OPERAND_ADDRESS: - if (! rld[r].optional) - reload_override_in[r] = equiv; - /* Fall through. */ - default: - equiv = 0; - break; - } + if (equiv != 0) + { + if (regno_clobbered_p (regno, insn, rld[r].mode, 0)) + switch (rld[r].when_needed) + { + case RELOAD_FOR_OTHER_ADDRESS: + case RELOAD_FOR_INPADDR_ADDRESS: + case RELOAD_FOR_INPUT_ADDRESS: + case RELOAD_FOR_OPADDR_ADDR: + break; + case RELOAD_OTHER: + case RELOAD_FOR_INPUT: + case RELOAD_FOR_OPERAND_ADDRESS: + if (! rld[r].optional) + reload_override_in[r] = equiv; + /* Fall through. */ + default: + equiv = 0; + break; + } + else if (regno_clobbered_p (regno, insn, rld[r].mode, 1)) + switch (rld[r].when_needed) + { + case RELOAD_FOR_OTHER_ADDRESS: + case RELOAD_FOR_INPADDR_ADDRESS: + case RELOAD_FOR_INPUT_ADDRESS: + case RELOAD_FOR_OPADDR_ADDR: + case RELOAD_FOR_OPERAND_ADDRESS: + case RELOAD_FOR_INPUT: + break; + case RELOAD_OTHER: + if (! rld[r].optional) + reload_override_in[r] = equiv; + /* Fall through. */ + default: + equiv = 0; + break; + } } /* If we found an equivalent reg, say no code need be generated @@ -6567,7 +6586,7 @@ emit_output_reload_insns (chain, rl, j) || !(set = single_set (insn)) || rtx_equal_p (old, SET_DEST (set)) || !reg_mentioned_p (old, SET_SRC (set)) - || !regno_clobbered_p (REGNO (old), insn, rl->mode)) + || !regno_clobbered_p (REGNO (old), insn, rl->mode, 0)) gen_reload (old, reloadreg, rl->opnum, rl->when_needed); }