summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2009-03-04 01:57:29 +0000
committerJoseph Myers <jsm28@gcc.gnu.org>2009-03-04 01:57:29 +0000
commita6fe9ed43e2cb62e8616dbb825172b9e9db7ed98 (patch)
tree09145ea9afe18888cc75a7347dcca1bd063003f5 /gcc
parentdd7d0a4f8f91b346bb409b70a53351517668952f (diff)
downloadgcc-a6fe9ed43e2cb62e8616dbb825172b9e9db7ed98.tar.gz
emit-rtl.c (adjust_address_1): Reduce offset to a signed value that fits within Pmode.
* emit-rtl.c (adjust_address_1): Reduce offset to a signed value that fits within Pmode. testsuite: * gcc.c-torture/compile/20090303-1.c, gcc.c-torture/compile/20090303-2.c: New tests. From-SVN: r144595
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/emit-rtl.c11
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20090303-1.c20
-rw-r--r--gcc/testsuite/gcc.c-torture/compile/20090303-2.c20
5 files changed, 61 insertions, 0 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index f145fbe74d1..661f0d7e7da 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+2009-03-03 Joseph Myers <joseph@codesourcery.com>
+
+ * emit-rtl.c (adjust_address_1): Reduce offset to a signed value
+ that fits within Pmode.
+
2009-03-03 Steve Ellcey <sje@cup.hp.com>
PR middle-end/10109
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 679e95ea8a2..ca033824c0d 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -2008,6 +2008,7 @@ adjust_address_1 (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset,
rtx memoffset = MEM_OFFSET (memref);
rtx size = 0;
unsigned int memalign = MEM_ALIGN (memref);
+ int pbits;
/* If there are no changes, just return the original memory reference. */
if (mode == GET_MODE (memref) && !offset
@@ -2019,6 +2020,16 @@ adjust_address_1 (rtx memref, enum machine_mode mode, HOST_WIDE_INT offset,
(plus (plus reg reg) const_int) -- so do this always. */
addr = copy_rtx (addr);
+ /* Convert a possibly large offset to a signed value within the
+ range of the target address space. */
+ pbits = GET_MODE_BITSIZE (Pmode);
+ if (HOST_BITS_PER_WIDE_INT > pbits)
+ {
+ int shift = HOST_BITS_PER_WIDE_INT - pbits;
+ offset = (((HOST_WIDE_INT) ((unsigned HOST_WIDE_INT) offset << shift))
+ >> shift);
+ }
+
if (adjust)
{
/* If MEMREF is a LO_SUM and the offset is within the alignment of the
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index a4bfe792d4f..2851a70a338 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2009-03-03 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.c-torture/compile/20090303-1.c,
+ gcc.c-torture/compile/20090303-2.c: New tests.
+
2009-03-03 Jakub Jelinek <jakub@redhat.com>
PR fortran/39354
diff --git a/gcc/testsuite/gcc.c-torture/compile/20090303-1.c b/gcc/testsuite/gcc.c-torture/compile/20090303-1.c
new file mode 100644
index 00000000000..18a3d91fd1c
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20090303-1.c
@@ -0,0 +1,20 @@
+/* The array offset became 0x1ffffffffffffffe via a conversion from
+ signed to unsigned HOST_WIDE_INT, causing an ICE compiling for
+ Thumb. */
+
+int r (unsigned short *);
+void s (unsigned short *, unsigned short *);
+
+int
+f (int x)
+{
+ unsigned short a[1], c[1];
+
+ if (r (a))
+ return x;
+
+ if (c[-1])
+ s (a, c);
+
+ return 0;
+}
diff --git a/gcc/testsuite/gcc.c-torture/compile/20090303-2.c b/gcc/testsuite/gcc.c-torture/compile/20090303-2.c
new file mode 100644
index 00000000000..69cee36e0b9
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/compile/20090303-2.c
@@ -0,0 +1,20 @@
+/* The array offset became 0x1ffffffffffffffe via a conversion from
+ signed to unsigned HOST_WIDE_INT, causing an ICE compiling for
+ Thumb. */
+
+int r (unsigned short *);
+void s (unsigned short *, unsigned short *);
+
+int
+f (int x)
+{
+ unsigned short a[1], c[1];
+
+ if (r (a))
+ return x;
+
+ if (c[0x7fffffff])
+ s (a, c);
+
+ return 0;
+}