From: Bernd Schmidt Date: Mon, 18 Dec 2000 14:29:56 +0000 (+0000) Subject: Backport a bunch of reload fixes X-Git-Tag: prereleases/gcc-2.95.3-test1~29 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=55d5b23a3441e5f1e512c9750182415773506f15;p=thirdparty%2Fgcc.git Backport a bunch of reload fixes From-SVN: r38348 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 53de662c547b..8bc4f9f9c90f 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,25 @@ +2000-12-18 Bernd Schmidt + + 2000-12-02 Bernd Schmidt + * reload1.c (free_for_value_p): New function, frontend to + reload_reg_free_for_value_p. All callers of the latter now call + this function with an additional mode argument. + + 2000-11-10 Bernd Schmidt + (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-10-28 Bernd Schmidt + * reload1.c (choose_reload_regs): Never set reload_override_in for an + optional reload. + + 2000-09-07 Bernd Schmidt + * reload.c (regno_clobbered_p): Accept new arg, MODE, and use it + to handle multiword modes correctly. All callers and the declaration + changed. + 2000-12-18 David Edelsohn * rs6000.c (and64_operand): Use logical_u_operand. diff --git a/gcc/reload.c b/gcc/reload.c index 72b38f325165..7aa297150e80 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -4682,7 +4682,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)) + && ! regno_clobbered_p (regno, this_insn, GET_MODE (ad), 0)) return 0; /* If we do not have one of the cases above, we must do the reload. */ @@ -5514,7 +5514,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)) + 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), @@ -6627,13 +6627,23 @@ find_inc_amount (x, inced) /* Return 1 if register REGNO is the subject of a clobber in insn INSN. */ int -regno_clobbered_p (regno, insn) +regno_clobbered_p (regno, insn, mode, sets) int regno; rtx insn; + enum machine_mode mode; + int sets; { - if (GET_CODE (PATTERN (insn)) == CLOBBER + int nregs = HARD_REGNO_NREGS (regno, mode); + int endregno = regno + nregs; + + if ((GET_CODE (PATTERN (insn)) == CLOBBER + || (sets && GET_CODE (PATTERN (insn)) == SET)) && GET_CODE (XEXP (PATTERN (insn), 0)) == REG) - return REGNO (XEXP (PATTERN (insn), 0)) == regno; + { + int test = REGNO (XEXP (PATTERN (insn), 0)); + + return test >= regno && test < endregno; + } if (GET_CODE (PATTERN (insn)) == PARALLEL) { @@ -6642,9 +6652,15 @@ regno_clobbered_p (regno, insn) for (; i >= 0; i--) { rtx elt = XVECEXP (PATTERN (insn), 0, i); - if (GET_CODE (elt) == CLOBBER && GET_CODE (XEXP (elt, 0)) == REG - && REGNO (XEXP (elt, 0)) == regno) - return 1; + if ((GET_CODE (elt) == CLOBBER + || (sets && GET_CODE (PATTERN (insn)) == SET)) + && GET_CODE (XEXP (elt, 0)) == REG) + { + int test = REGNO (XEXP (elt, 0)); + + if (test >= regno && test < endregno) + return 1; + } } } diff --git a/gcc/reload.h b/gcc/reload.h index 50526db8566f..7bc6ccab89ae 100644 --- a/gcc/reload.h +++ b/gcc/reload.h @@ -296,7 +296,7 @@ extern rtx find_equiv_reg PROTO((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 PROTO((int, rtx)); +extern int regno_clobbered_p PROTO((int, rtx, enum machine_mode, int)); /* Functions in reload1.c: */ diff --git a/gcc/reload1.c b/gcc/reload1.c index 4011236f47b2..13e24ee67cfe 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -420,6 +420,9 @@ static void clear_reload_reg_in_use PROTO((int, int, enum reload_type, enum machine_mode)); static int reload_reg_free_p PROTO((int, int, enum reload_type)); static int reload_reg_free_for_value_p PROTO((int, int, enum reload_type, rtx, rtx, int, int)); +static int free_for_value_p PROTO((int, enum machine_mode, int, + enum reload_type, rtx, rtx, + int, int)); static int reload_reg_reaches_end_p PROTO((int, int, enum reload_type)); static int allocate_reload_reg PROTO((struct insn_chain *, int, int, int)); @@ -5177,25 +5180,8 @@ rtx reload_override_in[MAX_RELOADS]; or -1 if we did not need a register for this reload. */ int reload_spill_index[MAX_RELOADS]; -/* Return 1 if the value in reload reg REGNO, as used by a reload - needed for the part of the insn specified by OPNUM and TYPE, - may be used to load VALUE into it. - - Other read-only reloads with the same value do not conflict - unless OUT is non-zero and these other reloads have to live while - output reloads live. - If OUT is CONST0_RTX, this is a special case: it means that the - test should not be for using register REGNO as reload register, but - for copying from register REGNO into the reload register. +/* Subroutine of free_for_value_p, used to check a single register. */ - RELOADNUM is the number of the reload we want to load this value for; - a reload does not conflict with itself. - - When IGNORE_ADDRESS_RELOADS is set, we can not have conflicts with - reloads that load an address for the very reload we are considering. - - The caller has to make sure that there is no conflict with the return - register. */ static int reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum, ignore_address_reloads) @@ -5413,6 +5399,48 @@ reload_reg_free_for_value_p (regno, opnum, type, value, out, reloadnum, return 1; } +/* Return 1 if the value in reload reg REGNO, as used by a reload + needed for the part of the insn specified by OPNUM and TYPE, + may be used to load VALUE into it. + + MODE is the mode in which the register is used, this is needed to + determine how many hard regs to test. + + Other read-only reloads with the same value do not conflict + unless OUT is non-zero and these other reloads have to live while + output reloads live. + If OUT is CONST0_RTX, this is a special case: it means that the + test should not be for using register REGNO as reload register, but + for copying from register REGNO into the reload register. + + RELOADNUM is the number of the reload we want to load this value for; + a reload does not conflict with itself. + + When IGNORE_ADDRESS_RELOADS is set, we can not have conflicts with + reloads that load an address for the very reload we are considering. + + The caller has to make sure that there is no conflict with the return + register. */ + +static int +free_for_value_p (regno, mode, opnum, type, value, out, reloadnum, + ignore_address_reloads) + int regno; + enum machine_mode mode; + int opnum; + enum reload_type type; + rtx value, out; + int reloadnum; + int ignore_address_reloads; +{ + int nregs = HARD_REGNO_NREGS (regno, mode); + while (nregs-- > 0) + if (! reload_reg_free_for_value_p (regno, opnum, type, value, out, + reloadnum, ignore_address_reloads)) + return 0; + return 1; +} + /* Determine whether the reload reg X overlaps any rtx'es used for overriding inheritance. Return nonzero if so. */ @@ -5508,11 +5536,10 @@ allocate_reload_reg (chain, r, last_reload, noerror) /* We check reload_reg_used to make sure we don't clobber the return register. */ && ! TEST_HARD_REG_BIT (reload_reg_used, regnum) - && reload_reg_free_for_value_p (regnum, - reload_opnum[r], - reload_when_needed[r], - reload_in[r], - reload_out[r], r, 1))) + && free_for_value_p (regnum, reload_mode[r], + reload_opnum[r], + reload_when_needed[r], + reload_in[r], reload_out[r], r, 1))) && TEST_HARD_REG_BIT (reg_class_contents[class], regnum) && HARD_REGNO_MODE_OK (regnum, reload_mode[r]) /* Look first for regs to share, then for unshared. But @@ -5967,10 +5994,9 @@ choose_reload_regs (chain) && (reload_nregs[r] == max_group_size || ! TEST_HARD_REG_BIT (reg_class_contents[(int) group_class], i)) - && reload_reg_free_for_value_p (i, reload_opnum[r], - reload_when_needed[r], - reload_in[r], - const0_rtx, r, 1)) + && free_for_value_p (i, reload_mode[r], reload_opnum[r], + reload_when_needed[r], reload_in[r], + const0_rtx, r, 1)) { /* If a group is needed, verify that all the subsequent registers still have their values intact. */ @@ -6004,9 +6030,11 @@ choose_reload_regs (chain) break; if (i1 != n_earlyclobbers - || ! (reload_reg_free_for_value_p - (i, reload_opnum[r], reload_when_needed[r], - reload_in[r], reload_out[r], r, 1)) + || ! (free_for_value_p (i, reload_mode[r], + reload_opnum[r], + reload_when_needed[r], + reload_in[r], + reload_out[r], r, 1)) /* Don't use it if we'd clobber a pseudo reg. */ || (TEST_HARD_REG_BIT (reg_used_in_insn, i) && reload_out[r] @@ -6028,9 +6056,12 @@ choose_reload_regs (chain) && rtx_equal_p (reload_out[r], reload_reg_rtx[r]))) { - reload_override_in[r] = last_reg; - reload_inheritance_insn[r] - = reg_reloaded_insn[i]; + if (! reload_optional[r]) + { + reload_override_in[r] = last_reg; + reload_inheritance_insn[r] + = reg_reloaded_insn[i]; + } } else { @@ -6108,10 +6139,11 @@ choose_reload_regs (chain) and of the desired class. */ if (equiv != 0 && ((TEST_HARD_REG_BIT (reload_reg_used_at_all, regno) - && ! reload_reg_free_for_value_p (regno, reload_opnum[r], - reload_when_needed[r], - reload_in[r], - reload_out[r], r, 1)) + && ! free_for_value_p (regno, reload_mode[r], + reload_opnum[r], + reload_when_needed[r], + reload_in[r], reload_out[r], r, + 1)) || ! TEST_HARD_REG_BIT (reg_class_contents[(int) reload_reg_class[r]], regno))) equiv = 0; @@ -6129,7 +6161,8 @@ choose_reload_regs (chain) if (reg_overlap_mentioned_for_reload_p (equiv, reload_earlyclobbers[i])) { - reload_override_in[r] = equiv; + if (! reload_optional[r]) + reload_override_in[r] = equiv; equiv = 0; break; } @@ -6140,7 +6173,8 @@ 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)) + if (equiv != 0 && regno_clobbered_p (regno, insn, + reload_mode[r], 0)) { switch (reload_when_needed[r]) { @@ -6152,13 +6186,32 @@ choose_reload_regs (chain) case RELOAD_OTHER: case RELOAD_FOR_INPUT: case RELOAD_FOR_OPERAND_ADDRESS: - reload_override_in[r] = equiv; + if (! reload_optional[r]) + reload_override_in[r] = equiv; /* Fall through. */ default: equiv = 0; break; } } + else if (regno_clobbered_p (regno, insn, reload_mode[r], 1)) + switch (reload_when_needed[r]) + { + 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 (! reload_optional[r]) + reload_override_in[r] = equiv; + /* Fall through. */ + default: + equiv = 0; + break; + } /* If we found an equivalent reg, say no code need be generated to load it, and use it as our reload reg. */ @@ -6319,13 +6372,12 @@ choose_reload_regs (chain) check_reg = reload_override_in[r]; else continue; - if (! reload_reg_free_for_value_p (true_regnum (check_reg), - reload_opnum[r], - reload_when_needed[r], - reload_in[r], - (reload_inherited[r] - ? reload_out[r] : const0_rtx), - r, 1)) + if (! free_for_value_p (true_regnum (check_reg), reload_mode[r], + reload_opnum[r], reload_when_needed[r], + reload_in[r], + (reload_inherited[r] + ? reload_out[r] : const0_rtx), + r, 1)) { if (pass) continue; @@ -6682,10 +6734,10 @@ emit_reload_insns (chain) /* Don't use OLDEQUIV if any other reload changes it at an earlier stage of this insn or at this stage. */ - if (! reload_reg_free_for_value_p (regno, reload_opnum[j], - reload_when_needed[j], - reload_in[j], const0_rtx, j, - 0)) + if (! free_for_value_p (regno, reload_mode[j], + reload_opnum[j], + reload_when_needed[j], + reload_in[j], const0_rtx, j, 0)) oldequiv = 0; /* If it is no cheaper to copy from OLDEQUIV into the @@ -6836,11 +6888,9 @@ emit_reload_insns (chain) /* This is unsafe if some other reload uses the same reg first. */ && ! conflicts_with_override (reloadreg) - && reload_reg_free_for_value_p (REGNO (reloadreg), - reload_opnum[j], - reload_when_needed[j], - old, reload_out[j], - j, 0)) + && free_for_value_p (REGNO (reloadreg), reload_mode[j], + reload_opnum[j], reload_when_needed[j], + old, reload_out[j], j, 0)) { rtx temp = PREV_INSN (insn); while (temp && GET_CODE (temp) == NOTE) @@ -7326,7 +7376,7 @@ emit_reload_insns (chain) || !(set = single_set (insn)) || rtx_equal_p (old, SET_DEST (set)) || !reg_mentioned_p (old, SET_SRC (set)) - || !regno_clobbered_p (REGNO (old), insn)) + || !regno_clobbered_p (REGNO (old), insn, reload_mode[j], 0)) gen_reload (old, reloadreg, reload_opnum[j], reload_when_needed[j]); }