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:
parent
1d974ca723
commit
630036c6a3
5 changed files with 107 additions and 24 deletions
|
@ -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.
|
||||
|
|
|
@ -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). */
|
||||
|
|
18
gcc/expr.c
18
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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
55
gcc/testsuite/gcc.c-torture/execute/20011113-1.c
Normal file
55
gcc/testsuite/gcc.c-torture/execute/20011113-1.c
Normal 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);
|
||||
}
|
Loading…
Add table
Reference in a new issue