aboutsummaryrefslogtreecommitdiff
path: root/gcc/reload.c
diff options
context:
space:
mode:
authorIan Lance Taylor <iant@google.com>2007-04-27 04:11:47 +0000
committerIan Lance Taylor <ian@gcc.gnu.org>2007-04-27 04:11:47 +0000
commitf5c3dc96c341e300248c37f76067b5a02d61bffb (patch)
tree8c11ae004937c006a4b4b23a9a29439c32f3beee /gcc/reload.c
parentd333b74f9446e22d8c35a6713b3934f97e96a8aa (diff)
downloadgcc-f5c3dc96c341e300248c37f76067b5a02d61bffb.zip
gcc-f5c3dc96c341e300248c37f76067b5a02d61bffb.tar.gz
gcc-f5c3dc96c341e300248c37f76067b5a02d61bffb.tar.bz2
re PR target/28675 (ICE in extract_insn, at recog.c:2084 (unrecognizable insn) [arm])
gcc/: PR target/28675 * reload.c (find_reloads_subreg_address): If the address was valid in the original mode but not in the new mode, reload the whole address. testsuite/: PR target/28675 * gcc.c-torture/compile/pr28675.c: New test. From-SVN: r124211
Diffstat (limited to 'gcc/reload.c')
-rw-r--r--gcc/reload.c27
1 files changed, 24 insertions, 3 deletions
diff --git a/gcc/reload.c b/gcc/reload.c
index b0374d8..de6093b 100644
--- a/gcc/reload.c
+++ b/gcc/reload.c
@@ -6006,6 +6006,8 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
unsigned inner_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (x)));
int offset;
rtx orig = tem;
+ enum machine_mode orig_mode = GET_MODE (orig);
+ int reloaded;
/* For big-endian paradoxical subregs, SUBREG_BYTE does not
hold the correct (negative) byte offset. */
@@ -6038,13 +6040,32 @@ find_reloads_subreg_address (rtx x, int force_replace, int opnum,
return x;
}
- find_reloads_address (GET_MODE (tem), &tem, XEXP (tem, 0),
- &XEXP (tem, 0), opnum, type,
- ind_levels, insn);
+ reloaded = find_reloads_address (GET_MODE (tem), &tem,
+ XEXP (tem, 0), &XEXP (tem, 0),
+ opnum, type, ind_levels, insn);
/* ??? Do we need to handle nonzero offsets somehow? */
if (!offset && !rtx_equal_p (tem, orig))
push_reg_equiv_alt_mem (regno, tem);
+ /* For some processors an address may be valid in the
+ original mode but not in a smaller mode. For
+ example, ARM accepts a scaled index register in
+ SImode but not in HImode. find_reloads_address
+ assumes that we pass it a valid address, and doesn't
+ force a reload. This will probably be fine if
+ find_reloads_address finds some reloads. But if it
+ doesn't find any, then we may have just converted a
+ valid address into an invalid one. Check for that
+ here. */
+ if (reloaded != 1
+ && strict_memory_address_p (orig_mode, XEXP (tem, 0))
+ && !strict_memory_address_p (GET_MODE (tem),
+ XEXP (tem, 0)))
+ push_reload (XEXP (tem, 0), NULL_RTX, &XEXP (tem, 0), (rtx*) 0,
+ base_reg_class (GET_MODE (tem), MEM, SCRATCH),
+ GET_MODE (XEXP (tem, 0)), VOIDmode, 0, 0,
+ opnum, type);
+
/* If this is not a toplevel operand, find_reloads doesn't see
this substitution. We have to emit a USE of the pseudo so
that delete_output_reload can see it. */