aboutsummaryrefslogtreecommitdiff
path: root/gcc/reload.c
diff options
context:
space:
mode:
authorRichard Stallman <rms@gnu.org>1993-05-24 07:51:12 +0000
committerRichard Stallman <rms@gnu.org>1993-05-24 07:51:12 +0000
commit86c31b2d150ede7efba5e394716e341396a8b450 (patch)
treeaa9a246bf0f71d538854ec00e7f679cdb4b95c7f /gcc/reload.c
parent8908158db387544f2bf19409617455766be8511f (diff)
downloadgcc-86c31b2d150ede7efba5e394716e341396a8b450.zip
gcc-86c31b2d150ede7efba5e394716e341396a8b450.tar.gz
gcc-86c31b2d150ede7efba5e394716e341396a8b450.tar.bz2
(push_reload): Fix NULL arg in last change.
(push_reload): When IN is a subreg of a multiword reg that uses a funny number of registers, and SUBREG_WORD is nonzero, and IN must match an output, reload both the reg and the subreg. From-SVN: r4556
Diffstat (limited to 'gcc/reload.c')
-rw-r--r--gcc/reload.c35
1 files changed, 32 insertions, 3 deletions
diff --git a/gcc/reload.c b/gcc/reload.c
index c2555b0..08a21c6 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -616,9 +616,12 @@ push_reload (in, out, inloc, outloc, class,
really reload just the inside expression in its own mode.
If we have (SUBREG:M1 (REG:M2 ...) ...) with M1 wider than M2 and the
register is a pseudo, this will become the same as the above case.
- Do the same for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
+ Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
either M1 is not valid for R or M2 is wider than a word but we only
need one word to store an M2-sized quantity in R.
+ (However, if OUT is nonzero, we need to reload the reg *and*
+ the subreg, so do nothing here, and let following statement handle it.)
+
Note that the case of (SUBREG (CONST_INT...)...) is handled elsewhere;
we can't handle it here because CONST_INT does not indicate a mode.
@@ -635,8 +638,10 @@ push_reload (in, out, inloc, outloc, class,
&& REGNO (SUBREG_REG (in)) >= FIRST_PSEUDO_REGISTER
&& (GET_MODE_SIZE (inmode)
> GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))))
- || (GET_CODE (SUBREG_REG (in)) == REG
- && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
+ || (REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
+ /* The case where out is nonzero
+ is handled differently in the following statement. */
+ && (out == 0 || SUBREG_WORD (in) == 0)
&& (! HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (in)), inmode)
|| (GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
&& (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
@@ -667,6 +672,30 @@ push_reload (in, out, inloc, outloc, class,
inmode = GET_MODE (in);
}
+ /* Similar issue for (SUBREG:M1 (REG:M2 ...) ...) for a hard register R where
+ either M1 is not valid for R or M2 is wider than a word but we only
+ need one word to store an M2-sized quantity in R.
+
+ However, we must reload the inner reg *as well as* the subreg in
+ that case. */
+
+ if (in != 0 && GET_CODE (in) == SUBREG
+ && GET_CODE (SUBREG_REG (in)) == REG
+ && REGNO (SUBREG_REG (in)) < FIRST_PSEUDO_REGISTER
+ && (! HARD_REGNO_MODE_OK (REGNO (SUBREG_REG (in)), inmode)
+ || (GET_MODE_SIZE (inmode) <= UNITS_PER_WORD
+ && (GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
+ > UNITS_PER_WORD)
+ && ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (in)))
+ / UNITS_PER_WORD)
+ != HARD_REGNO_NREGS (REGNO (SUBREG_REG (in)),
+ GET_MODE (SUBREG_REG (in)))))))
+ {
+ push_reload (SUBREG_REG (in), NULL_RTX, &SUBREG_REG (in), NULL_PTR,
+ GENERAL_REGS, VOIDmode, VOIDmode, 0, 0, opnum, type);
+ }
+
+
/* Similarly for paradoxical and problematical SUBREGs on the output.
Note that there is no reason we need worry about the previous value
of SUBREG_REG (out); even if wider than out,