diff options
author | Ian Lance Taylor <iant@google.com> | 2007-04-27 04:11:47 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2007-04-27 04:11:47 +0000 |
commit | f5c3dc96c341e300248c37f76067b5a02d61bffb (patch) | |
tree | 8c11ae004937c006a4b4b23a9a29439c32f3beee /gcc/reload.c | |
parent | d333b74f9446e22d8c35a6713b3934f97e96a8aa (diff) | |
download | gcc-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.c | 27 |
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. */ |