emit-rtl.c (adjust_address_1): Add ADJUST argument.

* 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.

From-SVN: r46988
This commit is contained in:
Jakub Jelinek 2001-11-13 17:45:18 +01:00 committed by Jakub Jelinek
parent 1d974ca723
commit 630036c6a3
5 changed files with 107 additions and 24 deletions

View file

@ -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.

View file

@ -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 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)
addr = gen_rtx_LO_SUM (Pmode, XEXP (addr, 0),
plus_constant (XEXP (addr, 1), offset));
else if (offset == 0)
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. */
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
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). */

View file

@ -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);

View file

@ -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.

View file

@ -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);
}