summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2001-11-13 16:45:18 +0000
committerjakub <jakub@138bc75d-0d04-0410-961f-82ee72b054a4>2001-11-13 16:45:18 +0000
commitbf42c62d563e07d9742288cf34dd937591335103 (patch)
treed66cd731e9536db2b2295ea3338e767b3dac7a71
parentbd276a5ad2656aa694e0e0161a2123cd37e7404b (diff)
downloadgcc-bf42c62d563e07d9742288cf34dd937591335103.tar.gz
* emit-rtl.c (adjust_address_1): Add ADJUST argument.
(adjust_automodify_address_1): New. * expr.h (adjust_address, adjust_address_nv): Adjust. (adjust_automodify_address, adjust_automodify_address_nv): Define. (adjust_address_1): Update prototype. (adjust_automodify_address_1): Add prototype. * expr.c (move_by_pieces_1): Use adjust_automodify_address. (store_by_pieces_2): Likewise. * gcc.c-torture/execute/20011113-1.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@46988 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog11
-rw-r--r--gcc/emit-rtl.c39
-rw-r--r--gcc/expr.c18
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.c-torture/execute/20011113-1.c55
5 files changed, 105 insertions, 22 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index d17f8969f9d..e3c672f2266 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,14 @@
+2001-11-13 Jakub Jelinek <jakub@redhat.com>
+
+ * emit-rtl.c (adjust_address_1): Add ADJUST argument.
+ (adjust_automodify_address_1): New.
+ * expr.h (adjust_address, adjust_address_nv): Adjust.
+ (adjust_automodify_address, adjust_automodify_address_nv): Define.
+ (adjust_address_1): Update prototype.
+ (adjust_automodify_address_1): Add prototype.
+ * expr.c (move_by_pieces_1): Use adjust_automodify_address.
+ (store_by_pieces_2): Likewise.
+
Tue Nov 13 05:45:40 2001 Richard Kenner <kenner@vlsi1.ultra.nyu.edu>
* Makefile.in (explow.o): Now depends on ggc.h.
diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c
index 6460a947e5f..3729233ff99 100644
--- a/gcc/emit-rtl.c
+++ b/gcc/emit-rtl.c
@@ -1870,14 +1870,16 @@ change_address (memref, mode, addr)
/* Return a memory reference like MEMREF, but with its mode changed
to MODE and its address offset by OFFSET bytes. If VALIDATE is
- nonzero, the memory address is forced to be valid. */
+ nonzero, the memory address is forced to be valid.
+ If ADJUST is zero, OFFSET is only used to update MEM_ATTRS
+ and caller is responsible for adjusting MEMREF base register. */
rtx
-adjust_address_1 (memref, mode, offset, validate)
+adjust_address_1 (memref, mode, offset, validate, adjust)
rtx memref;
enum machine_mode mode;
HOST_WIDE_INT offset;
- int validate;
+ int validate, adjust;
{
rtx addr = XEXP (memref, 0);
rtx new;
@@ -1885,17 +1887,17 @@ adjust_address_1 (memref, mode, offset, validate)
rtx size = 0;
unsigned int memalign = MEM_ALIGN (memref);
+ if (adjust == 0 || offset == 0)
+ /* ??? Prefer to create garbage instead of creating shared rtl. */
+ addr = copy_rtx (addr);
/* If MEMREF is a LO_SUM and the offset is within the alignment of the
object, we can merge it into the LO_SUM. */
- if (GET_MODE (memref) != BLKmode && GET_CODE (addr) == LO_SUM
- && offset >= 0
- && (unsigned HOST_WIDE_INT) offset
- < GET_MODE_ALIGNMENT (GET_MODE (memref)) / BITS_PER_UNIT)
+ else if (GET_MODE (memref) != BLKmode && GET_CODE (addr) == LO_SUM
+ && offset >= 0
+ && (unsigned HOST_WIDE_INT) offset
+ < GET_MODE_ALIGNMENT (GET_MODE (memref)) / BITS_PER_UNIT)
addr = gen_rtx_LO_SUM (Pmode, XEXP (addr, 0),
plus_constant (XEXP (addr, 1), offset));
- else if (offset == 0)
- /* ??? Prefer to create garbage instead of creating shared rtl. */
- addr = copy_rtx (addr);
else
addr = plus_constant (addr, offset);
@@ -1926,6 +1928,23 @@ adjust_address_1 (memref, mode, offset, validate)
return new;
}
+/* Return a memory reference like MEMREF, but with its mode changed
+ to MODE and its address changed to ADDR, which is assumed to be
+ MEMREF offseted by OFFSET bytes. If VALIDATE is
+ nonzero, the memory address is forced to be valid. */
+
+rtx
+adjust_automodify_address_1 (memref, mode, addr, offset, validate)
+ rtx memref;
+ enum machine_mode mode;
+ rtx addr;
+ HOST_WIDE_INT offset;
+ int validate;
+{
+ memref = change_address_1 (memref, VOIDmode, addr, validate);
+ return adjust_address_1 (memref, mode, offset, validate, 0);
+}
+
/* Return a memory reference like MEMREF, but whose address is changed by
adding OFFSET, an RTX, to it. POW2 is the highest power of two factor
known to be in OFFSET (possibly 1). */
diff --git a/gcc/expr.c b/gcc/expr.c
index 42372b1aa72..d48227a0bb2 100644
--- a/gcc/expr.c
+++ b/gcc/expr.c
@@ -1577,19 +1577,15 @@ move_by_pieces_1 (genfun, mode, data)
if (data->to)
{
if (data->autinc_to)
- {
- to1 = replace_equiv_address (data->to, data->to_addr);
- to1 = adjust_address (to1, mode, 0);
- }
+ to1 = adjust_automodify_address (data->to, mode, data->to_addr,
+ data->offset);
else
to1 = adjust_address (data->to, mode, data->offset);
}
if (data->autinc_from)
- {
- from1 = replace_equiv_address (data->from, data->from_addr);
- from1 = adjust_address (from1, mode, 0);
- }
+ from1 = adjust_automodify_address (data->from, mode, data->from_addr,
+ data->offset);
else
from1 = adjust_address (data->from, mode, data->offset);
@@ -2525,10 +2521,8 @@ store_by_pieces_2 (genfun, mode, data)
data->offset -= size;
if (data->autinc_to)
- {
- to1 = replace_equiv_address (data->to, data->to_addr);
- to1 = adjust_address (to1, mode, 0);
- }
+ to1 = adjust_automodify_address (data->to, mode, data->to_addr,
+ data->offset);
else
to1 = adjust_address (data->to, mode, data->offset);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 7fa8c9ef43e..f52f1b8c439 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2001-11-13 Jakub Jelinek <jakub@redhat.com>
+
+ * gcc.c-torture/execute/20011113-1.c: New test.
+
2001-11-09 Geoffrey Keating <geoffk@redhat.com>
* gcc.c-torture/execute/20011109-2.c: New test.
diff --git a/gcc/testsuite/gcc.c-torture/execute/20011113-1.c b/gcc/testsuite/gcc.c-torture/execute/20011113-1.c
new file mode 100644
index 00000000000..a2eb86b6df6
--- /dev/null
+++ b/gcc/testsuite/gcc.c-torture/execute/20011113-1.c
@@ -0,0 +1,55 @@
+typedef __SIZE_TYPE__ size_t;
+extern void *memcpy (void *__restrict, const void *__restrict, size_t);
+extern void abort (void);
+extern void exit (int);
+
+typedef struct t
+{
+ unsigned a : 16;
+ unsigned b : 8;
+ unsigned c : 8;
+ long d[4];
+} *T;
+
+typedef struct {
+ long r[3];
+} U;
+
+T bar (U, unsigned int);
+
+T foo (T x)
+{
+ U d, u;
+
+ memcpy (&u, &x->d[1], sizeof u);
+ d = u;
+ return bar (d, x->b);
+}
+
+T baz (T x)
+{
+ U d, u;
+
+ d.r[0] = 0x123456789;
+ d.r[1] = 0xfedcba987;
+ d.r[2] = 0xabcdef123;
+ memcpy (&u, &x->d[1], sizeof u);
+ d = u;
+ return bar (d, x->b);
+}
+
+T bar (U d, unsigned int m)
+{
+ if (d.r[0] != 21 || d.r[1] != 22 || d.r[2] != 23)
+ abort ();
+ return 0;
+}
+
+struct t t = { 26, 0, 0, { 0, 21, 22, 23 }};
+
+int main (void)
+{
+ baz (&t);
+ foo (&t);
+ exit (0);
+}