aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Henderson <rth@cygnus.com>1998-04-19 18:22:13 -0700
committerJeff Law <law@gcc.gnu.org>1998-04-19 19:22:13 -0600
commit495bf6087a2fe026ed0155b32a43407d7b3f7900 (patch)
tree9e17381983b35c279acf88988171541427aadf68
parent620a5a20ec15115bb7e1ebf3a2f3ac416d10a1ab (diff)
reload1.c (eliminate_regs): Delete LOAD_EXTENDED_OP code that boiled down to && ! 0.
* 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. Co-Authored-By: J"orn Rennecke <amylaar@cygnus.co.uk> Co-Authored-By: Jim Wilson <wilson@cygnus.com> From-SVN: r19336
-rw-r--r--gcc/ChangeLog26
-rw-r--r--gcc/reload.c60
-rw-r--r--gcc/reload1.c43
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);
}