aboutsummaryrefslogtreecommitdiff
path: root/gcc
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
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')
-rw-r--r--gcc/ChangeLog7
-rw-r--r--gcc/reload.c27
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/pr28675.c38
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;
+ }
+}