aboutsummaryrefslogtreecommitdiff
path: root/gcc/final.c
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2004-10-28 12:47:21 +0000
committerUlrich Weigand <uweigand@de.ibm.com>2004-10-28 12:47:21 +0000
commit326fe9d2039bacea2b8ca3a7de7151450dd259bc (patch)
treea9bda2464d7b200ebd679487ccda3fef16f416b1 /gcc/final.c
parent183998957b06d74f5080ad6939bbc619f56253be (diff)
PR target/15286
* final.c (alter_subreg): Compute correct offset to use with paradoxical SUBREGs of memory operands. * recog.c (general_operand): Allow paradoxical SUBREGs of memory operands after reload. * simplify-rtx.c (simplify_gen_subreg): Fail if simplify_subreg has failed when passed a hard register. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@89752 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/final.c')
-rw-r--r--gcc/final.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/gcc/final.c b/gcc/final.c
index bf4f521bcf5..3952b9ff82c 100644
--- a/gcc/final.c
+++ b/gcc/final.c
@@ -2608,7 +2608,24 @@ alter_subreg (rtx *xp)
/* simplify_subreg does not remove subreg from volatile references.
We are required to. */
if (MEM_P (y))
- *xp = adjust_address (y, GET_MODE (x), SUBREG_BYTE (x));
+ {
+ int offset = SUBREG_BYTE (x);
+
+ /* For paradoxical subregs on big-endian machines, SUBREG_BYTE
+ contains 0 instead of the proper offset. See simplify_subreg. */
+ if (offset == 0
+ && GET_MODE_SIZE (GET_MODE (y)) < GET_MODE_SIZE (GET_MODE (x)))
+ {
+ int difference = GET_MODE_SIZE (GET_MODE (y))
+ - GET_MODE_SIZE (GET_MODE (x));
+ if (WORDS_BIG_ENDIAN)
+ offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
+ if (BYTES_BIG_ENDIAN)
+ offset += difference % UNITS_PER_WORD;
+ }
+
+ *xp = adjust_address (y, GET_MODE (x), offset);
+ }
else
{
rtx new = simplify_subreg (GET_MODE (x), y, GET_MODE (y),