diff options
author | law <law@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-04-20 01:22:13 +0000 |
---|---|---|
committer | law <law@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-04-20 01:22:13 +0000 |
commit | 296b222fcd1c8a9a231d8355ee7cd585fd5dfe0a (patch) | |
tree | 9e17381983b35c279acf88988171541427aadf68 | |
parent | 9f0b5d2fc5a50cc5d45e3ed86b2c66ef703aecf4 (diff) | |
download | gcc-296b222fcd1c8a9a231d8355ee7cd585fd5dfe0a.tar.gz |
* reload1.c (eliminate_regs): Delete LOAD_EXTENDED_OP code that
boiled down to && ! 0.
* reload.c (find_reloads): Always force (subreg (mem)) to be
reloaded if WORD_REGISTER_OPERATIONS.
* reload.c (find_reloads_toplev): Handle arbitrary non-paradoxical
SUBREGs of CONST_INTs.
* reload.c (push_reload): If WORD_REGISTER_OPERATIONS, reload the
SUBREG_REG if the word count is unchanged, also in the input reload
case. Disable non-applicable sanity checks.
* reload.c (push_reload): In WORD_REGISTER_OPERATIONS code, add test
to require the SUBREG mode to be smaller than the SUBREG_REG mode.
* reload1.c (eliminate_regs): Likewise.
* reload.c (push_reload): If WORD_REGISTER_OPERATIONS, reload the
SUBREG_REG if the word count is unchanged.
* reload1.c (eliminate_regs) [case SET]: If W_R_O, preserve
subregs of identical word size for push_reload.
Various alpha fixes from the mainline sources.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/egcs_1_00_branch@19336 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r-- | gcc/ChangeLog | 26 | ||||
-rw-r--r-- | gcc/reload.c | 60 | ||||
-rw-r--r-- | gcc/reload1.c | 43 |
3 files changed, 95 insertions, 34 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e1ca3cf3e5b..4b5c39d1b51 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +Mon Apr 20 02:17:37 1998 Richard Henderson <rth@cygnus.com> + Jim Wilson <wilson@cygnus.com> + J"orn Rennecke <amylaar@cygnus.co.uk> + + * reload1.c (eliminate_regs): Delete LOAD_EXTENDED_OP code that + boiled down to && ! 0. + + * reload.c (find_reloads): Always force (subreg (mem)) to be + reloaded if WORD_REGISTER_OPERATIONS. + + * reload.c (find_reloads_toplev): Handle arbitrary non-paradoxical + SUBREGs of CONST_INTs. + + * reload.c (push_reload): If WORD_REGISTER_OPERATIONS, reload the + SUBREG_REG if the word count is unchanged, also in the input reload + case. Disable non-applicable sanity checks. + + * reload.c (push_reload): In WORD_REGISTER_OPERATIONS code, add test + to require the SUBREG mode to be smaller than the SUBREG_REG mode. + * reload1.c (eliminate_regs): Likewise. + + * reload.c (push_reload): If WORD_REGISTER_OPERATIONS, reload the + SUBREG_REG if the word count is unchanged. + * reload1.c (eliminate_regs) [case SET]: If W_R_O, preserve + subregs of identical word size for push_reload. + Mon Apr 20 00:58:48 1998 H.J. Lu (hjl@gnu.org) * reg-stack.c (subst_asm_stack_regs): Change to return the last diff --git a/gcc/reload.c b/gcc/reload.c index 4b48a6c3171..a979550d793 100644 --- a/gcc/reload.c +++ b/gcc/reload.c @@ -890,6 +890,13 @@ push_reload (in, out, inloc, outloc, class, && INTEGRAL_MODE_P (GET_MODE (SUBREG_REG (in))) && LOAD_EXTEND_OP (GET_MODE (SUBREG_REG (in))) != NIL) #endif +#ifdef WORD_REGISTER_OPERATIONS + || ((GET_MODE_SIZE (inmode) + < GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))) + && ((GET_MODE_SIZE (inmode) - 1) / UNITS_PER_WORD == + ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in))) - 1) + / UNITS_PER_WORD))) +#endif )) || (GET_CODE (SUBREG_REG (in)) == REG && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER @@ -927,7 +934,7 @@ push_reload (in, out, inloc, outloc, class, in_subreg_loc = inloc; inloc = &SUBREG_REG (in); in = *inloc; -#ifndef LOAD_EXTEND_OP +#if ! defined (LOAD_EXTEND_OP) && ! defined (WORD_REGISTER_OPERATIONS) if (GET_CODE (in) == MEM) /* This is supposed to happen only for paradoxical subregs made by combine.c. (SUBREG (MEM)) isn't supposed to occur other ways. */ @@ -989,7 +996,15 @@ push_reload (in, out, inloc, outloc, class, && REGNO (SUBREG_REG (out)) >= FIRST_PSEUDO_REGISTER) || GET_CODE (SUBREG_REG (out)) == MEM) && ((GET_MODE_SIZE (outmode) - > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))))) + > GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))) +#ifdef WORD_REGISTER_OPERATIONS + || ((GET_MODE_SIZE (outmode) + < GET_MODE_SIZE (GET_MODE (SUBREG_REG (out)))) + && ((GET_MODE_SIZE (outmode) - 1) / UNITS_PER_WORD == + ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (out))) - 1) + / UNITS_PER_WORD))) +#endif + )) || (GET_CODE (SUBREG_REG (out)) == REG && REGNO (SUBREG_REG (out)) < FIRST_PSEUDO_REGISTER && ((GET_MODE_SIZE (outmode) <= UNITS_PER_WORD @@ -1023,7 +1038,7 @@ push_reload (in, out, inloc, outloc, class, out_subreg_loc = outloc; outloc = &SUBREG_REG (out); out = *outloc; -#ifndef LOAD_EXTEND_OP +#if ! defined (LOAD_EXTEND_OP) && ! defined (WORD_REGISTER_OPERATIONS) if (GET_CODE (out) == MEM && GET_MODE_SIZE (GET_MODE (out)) > GET_MODE_SIZE (outmode)) abort (); @@ -2757,10 +2772,20 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) register access. If the data is, in fact, in memory we must always load using the size assumed to be in the register and let the insn do the different-sized - accesses. */ + accesses. + + This is doubly true if WORD_REGISTER_OPERATIONS. In + this case eliminate_regs has left non-paradoxical + subregs for push_reloads to see. Make sure it does + by forcing the reload. + + ??? When is it right at this stage to have a subreg + of a mem that is _not_ to be handled specialy? IMO + those should have been reduced to just a mem. */ || ((GET_CODE (operand) == MEM || (GET_CODE (operand)== REG && REGNO (operand) >= FIRST_PSEUDO_REGISTER)) +#ifndef WORD_REGISTER_OPERATIONS && (((GET_MODE_BITSIZE (GET_MODE (operand)) < BIGGEST_ALIGNMENT) && (GET_MODE_SIZE (operand_mode[i]) @@ -2775,7 +2800,9 @@ find_reloads (insn, replace, ind_levels, live_known, reload_reg_p) && INTEGRAL_MODE_P (GET_MODE (operand)) && LOAD_EXTEND_OP (GET_MODE (operand)) != NIL) #endif - )) + ) +#endif + ) /* Subreg of a hard reg which can't handle the subreg's mode or which would handle that mode in the wrong number of registers for subregging to work. */ @@ -4162,6 +4189,29 @@ find_reloads_toplev (x, opnum, type, ind_levels, is_set_dest) GET_MODE (SUBREG_REG (x)))) != 0) return tem; + /* If the SUBREG is wider than a word, the above test will fail. + For example, we might have a SImode SUBREG of a DImode SUBREG_REG + for a 16 bit target, or a DImode SUBREG of a TImode SUBREG_REG for + a 32 bit target. We still can - and have to - handle this + for non-paradoxical subregs of CONST_INTs. */ + if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0 + && reg_equiv_constant[regno] != 0 + && GET_CODE (reg_equiv_constant[regno]) == CONST_INT + && (GET_MODE_SIZE (GET_MODE (x)) + < GET_MODE_SIZE (GET_MODE (SUBREG_REG (x))))) + { + int shift = SUBREG_WORD (x) * BITS_PER_WORD; + if (WORDS_BIG_ENDIAN) + shift = (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) + - GET_MODE_BITSIZE (GET_MODE (x)) + - shift); + /* Here we use the knowledge that CONST_INTs have a + HOST_WIDE_INT field. */ + if (shift >= HOST_BITS_PER_WIDE_INT) + shift = HOST_BITS_PER_WIDE_INT - 1; + return GEN_INT (INTVAL (reg_equiv_constant[regno]) >> shift); + } + if (regno >= FIRST_PSEUDO_REGISTER && reg_renumber[regno] < 0 && reg_equiv_constant[regno] != 0 && GET_MODE (reg_equiv_constant[regno]) == VOIDmode) diff --git a/gcc/reload1.c b/gcc/reload1.c index cbb41308ddb..565ba4b7802 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -3108,30 +3108,21 @@ eliminate_regs (x, mem_mode, insn, storing) int x_size = GET_MODE_SIZE (GET_MODE (x)); int new_size = GET_MODE_SIZE (GET_MODE (new)); - /* When asked to spill a partial word subreg, we need to go - ahead and spill the whole thing against the possibility - that we reload the whole reg and find garbage at the top. */ - if (storing - && GET_CODE (new) == MEM - && x_size < new_size - && ((x_size + UNITS_PER_WORD-1) / UNITS_PER_WORD - == (new_size + UNITS_PER_WORD-1) / UNITS_PER_WORD)) - return new; - else if (GET_CODE (new) == MEM - && x_size <= new_size -#ifdef LOAD_EXTEND_OP - /* On these machines we will be reloading what is - inside the SUBREG if it originally was a pseudo and - the inner and outer modes are both a word or - smaller. So leave the SUBREG then. */ - && ! (GET_CODE (SUBREG_REG (x)) == REG - && x_size <= UNITS_PER_WORD - && new_size <= UNITS_PER_WORD - && x_size > new_size - && INTEGRAL_MODE_P (GET_MODE (new)) - && LOAD_EXTEND_OP (GET_MODE (new)) != NIL) + if (GET_CODE (new) == MEM + && ((x_size < new_size +#ifdef WORD_REGISTER_OPERATIONS + /* On these machines, combine can create rtl of the form + (set (subreg:m1 (reg:m2 R) 0) ...) + where m1 < m2, and expects something interesting to + happen to the entire word. Moreover, it will use the + (reg:m2 R) later, expecting all bits to be preserved. + So if the number of words is the same, preserve the + subreg so that push_reloads can see it. */ + && ! ((x_size-1)/UNITS_PER_WORD == (new_size-1)/UNITS_PER_WORD) #endif - ) + ) + || (x_size == new_size)) + ) { int offset = SUBREG_WORD (x) * UNITS_PER_WORD; enum machine_mode mode = GET_MODE (x); @@ -3271,12 +3262,6 @@ eliminate_regs (x, mem_mode, insn, storing) && GET_CODE (insn) != INSN_LIST) emit_insn_after (gen_rtx (CLOBBER, VOIDmode, SET_DEST (x)), insn); - /* If SET_DEST was a partial-word subreg, NEW0 may have been widened - to spill the entire register (see SUBREG case above). If the - widths of SET_DEST and NEW0 no longer match, adjust NEW1. */ - if (GET_MODE (SET_DEST (x)) != GET_MODE (new0)) - new1 = gen_rtx (SUBREG, GET_MODE (new0), new1, 0); - if (new0 != SET_DEST (x) || new1 != SET_SRC (x)) return gen_rtx (SET, VOIDmode, new0, new1); } |