From fd326ba823f7a8cbb2f7c47a2a3d15a8e098a976 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Thu, 28 Oct 2004 12:47:21 +0000 Subject: [PATCH] re PR target/15286 (ICE cause by reload) 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. From-SVN: r89752 --- gcc/ChangeLog | 10 ++++++++++ gcc/final.c | 19 ++++++++++++++++++- gcc/recog.c | 6 ++++-- gcc/simplify-rtx.c | 3 ++- 4 files changed, 34 insertions(+), 4 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4eb71fbc149..e4de1ded60c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2004-10-28 Ulrich Weigand + + 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. + 2004-10-28 Aldy Hernandez * function.c (assign_parm_setup_block): Handle parallels correctly. 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), diff --git a/gcc/recog.c b/gcc/recog.c index 61e1186d07a..eeb37afe9bb 100644 --- a/gcc/recog.c +++ b/gcc/recog.c @@ -936,8 +936,10 @@ general_operand (rtx op, enum machine_mode mode) #ifdef INSN_SCHEDULING /* On machines that have insn scheduling, we want all memory - reference to be explicit, so outlaw paradoxical SUBREGs. */ - if (MEM_P (sub) + reference to be explicit, so outlaw paradoxical SUBREGs. + However, we must allow them after reload so that they can + get cleaned up by cleanup_subreg_operands. */ + if (!reload_completed && MEM_P (sub) && GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (sub))) return 0; #endif diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index 4af468a40ca..e463fef1efe 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -3789,7 +3789,8 @@ simplify_gen_subreg (enum machine_mode outermode, rtx op, if (newx) return newx; - if (GET_CODE (op) == SUBREG || GET_MODE (op) == VOIDmode) + if (GET_CODE (op) == SUBREG || GET_MODE (op) == VOIDmode + || (REG_P (op) && REGNO (op) < FIRST_PSEUDO_REGISTER)) return NULL_RTX; return gen_rtx_SUBREG (outermode, op, byte);