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 | |
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')
-rw-r--r-- | gcc/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/reload.c | 27 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gcc/testsuite/gcc.c-torture/compile/pr28675.c | 38 |
4 files changed, 75 insertions, 4 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 2b6d43c..526c390 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2007-04-26 Ian Lance Taylor <iant@google.com> + + 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. + 2007-04-27 Zdenek Dvorak <dvorakz@suse.cz> * tree-cfgcleanup.c (cfgcleanup_altered_bbs): New global variable. 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. */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6b7bcc7..40c811b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2007-04-26 Ian Lance Taylor <iant@google.com> + + PR target/28675 + * gcc.c-torture/compile/pr28675.c: New test. + 2007-04-26 Andrew Pinski <andrew_pinski@playstation.sony.com> PR C++/30016 @@ -79,7 +84,7 @@ 2007-04-24 Ian Lance Taylor <iant@google.com> - PR tree-optimizatoin/31605 + PR tree-optimization/31605 * gcc.c-torture/execute/pr31605.c: New test. 2007-04-24 Francois-Xavier Coudert <fxcoudert@gcc.gnu.org> diff --git a/gcc/testsuite/gcc.c-torture/compile/pr28675.c b/gcc/testsuite/gcc.c-torture/compile/pr28675.c new file mode 100644 index 0000000..0d78353 --- /dev/null +++ b/gcc/testsuite/gcc.c-torture/compile/pr28675.c @@ -0,0 +1,38 @@ +struct fb_cmap { + unsigned int start; + unsigned int len; + unsigned short *red; + unsigned short *green; + unsigned short *blue; + unsigned short *transp; +}; + +typedef struct { + int r; + int g; + int b; + int a; +} rgba_t; + +static unsigned int cmap_len; + +extern unsigned int red_len, green_len, blue_len, alpha_len; +extern struct fb_cmap fb_cmap; +extern rgba_t *clut; +extern int fb_set_cmap(void); + +void directcolor_update_cmap(void) +{ + unsigned int i; + + for (i = 0; i < cmap_len; i++) { + if (i < red_len) + fb_cmap.red[i] = clut[i].r; + if (i < green_len) + fb_cmap.green[i] = clut[i].g; + if (i < blue_len) + fb_cmap.blue[i] = clut[i].b; + if (fb_cmap.transp && i < alpha_len) + fb_cmap.transp[i] = clut[i].a; + } +} |