mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-18 07:20:25 +08:00
emit-rtl.c (widen_memory_access): New.
* emit-rtl.c (widen_memory_access): New. * expr.h (widen_memory_access): Declare it. * config/alpha/alpha.c (get_aligned_mem): Use it. From-SVN: r47913
This commit is contained in:
parent
0051b6cae4
commit
e7dfe4bb07
gcc
@ -1,3 +1,9 @@
|
||||
2001-12-11 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* emit-rtl.c (widen_memory_access): New.
|
||||
* expr.h (widen_memory_access): Declare it.
|
||||
* config/alpha/alpha.c (get_aligned_mem): Use it.
|
||||
|
||||
2001-12-11 Richard Henderson <rth@redhat.com>
|
||||
|
||||
* combine.c (simplify_shift_const): Move SHIFT_COUNT_TRUNCATED
|
||||
|
@ -1822,12 +1822,8 @@ get_aligned_mem (ref, paligned_mem, pbitnum)
|
||||
if (GET_CODE (base) == PLUS)
|
||||
offset += INTVAL (XEXP (base, 1)), base = XEXP (base, 0);
|
||||
|
||||
*paligned_mem = gen_rtx_MEM (SImode, plus_constant (base, offset & ~3));
|
||||
MEM_COPY_ATTRIBUTES (*paligned_mem, ref);
|
||||
|
||||
/* Sadly, we cannot use alias sets here because we may overlap other
|
||||
data in a different alias set. */
|
||||
set_mem_alias_set (*paligned_mem, 0);
|
||||
*paligned_mem
|
||||
= widen_memory_access (ref, SImode, (offset & ~3) - offset);
|
||||
|
||||
if (WORDS_BIG_ENDIAN)
|
||||
*pbitnum = GEN_INT (32 - (GET_MODE_BITSIZE (GET_MODE (ref))
|
||||
|
@ -2072,6 +2072,84 @@ replace_equiv_address_nv (memref, addr)
|
||||
{
|
||||
return change_address_1 (memref, VOIDmode, addr, 0);
|
||||
}
|
||||
|
||||
/* Return a memory reference like MEMREF, but with its mode widened to
|
||||
MODE and offset by OFFSET. This would be used by targets that e.g.
|
||||
cannot issue QImode memory operations and have to use SImode memory
|
||||
operations plus masking logic. */
|
||||
|
||||
rtx
|
||||
widen_memory_access (memref, mode, offset)
|
||||
rtx memref;
|
||||
enum machine_mode mode;
|
||||
HOST_WIDE_INT offset;
|
||||
{
|
||||
rtx new = adjust_address_1 (memref, mode, offset, 1, 1);
|
||||
tree expr = MEM_EXPR (new);
|
||||
rtx memoffset = MEM_OFFSET (new);
|
||||
unsigned int size = GET_MODE_SIZE (mode);
|
||||
|
||||
/* If we don't know what offset we were at within the expression, then
|
||||
we can't know if we've overstepped the bounds. */
|
||||
if (! memoffset && offset != 0)
|
||||
expr = NULL_TREE;
|
||||
|
||||
while (expr)
|
||||
{
|
||||
if (TREE_CODE (expr) == COMPONENT_REF)
|
||||
{
|
||||
tree field = TREE_OPERAND (expr, 1);
|
||||
|
||||
if (! DECL_SIZE_UNIT (field))
|
||||
{
|
||||
expr = NULL_TREE;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Is the field at least as large as the access? If so, ok,
|
||||
otherwise strip back to the containing structure. */
|
||||
if (compare_tree_int (DECL_SIZE_UNIT (field), size) >= 0
|
||||
&& INTVAL (memoffset) >= 0)
|
||||
break;
|
||||
|
||||
if (! host_integerp (DECL_FIELD_OFFSET (field), 1))
|
||||
{
|
||||
expr = NULL_TREE;
|
||||
break;
|
||||
}
|
||||
|
||||
expr = TREE_OPERAND (expr, 0);
|
||||
memoffset = (GEN_INT (INTVAL (memoffset)
|
||||
+ tree_low_cst (DECL_FIELD_OFFSET (field), 1)
|
||||
+ (tree_low_cst (DECL_FIELD_BIT_OFFSET (field), 1)
|
||||
/ BITS_PER_UNIT)));
|
||||
}
|
||||
/* Similarly for the decl. */
|
||||
else if (DECL_P (expr)
|
||||
&& DECL_SIZE_UNIT (expr)
|
||||
&& compare_tree_int (DECL_SIZE_UNIT (expr), size) >= 0
|
||||
&& (! memoffset || INTVAL (memoffset) >= 0))
|
||||
break;
|
||||
else
|
||||
{
|
||||
/* The widened memory access overflows the expression, which means
|
||||
that it could alias another expression. Zap it. */
|
||||
expr = NULL_TREE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! expr)
|
||||
memoffset = NULL_RTX;
|
||||
|
||||
/* The widened memory may alias other stuff, so zap the alias set. */
|
||||
/* ??? Maybe use get_alias_set on any remaining expression. */
|
||||
|
||||
MEM_ATTRS (new) = get_mem_attrs (0, expr, memoffset, GEN_INT (size),
|
||||
MEM_ALIGN (new), mode);
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
/* Return a newly created CODE_LABEL rtx with a unique label number. */
|
||||
|
||||
|
@ -646,6 +646,10 @@ extern rtx replace_equiv_address PARAMS ((rtx, rtx));
|
||||
/* Likewise, but the reference is not required to be valid. */
|
||||
extern rtx replace_equiv_address_nv PARAMS ((rtx, rtx));
|
||||
|
||||
/* Return a memory reference like MEMREF, but with its mode widened to
|
||||
MODE and adjusted by OFFSET. */
|
||||
extern rtx widen_memory_access PARAMS ((rtx, enum machine_mode, HOST_WIDE_INT));
|
||||
|
||||
/* Return a memory reference like MEMREF, but which is known to have a
|
||||
valid address. */
|
||||
extern rtx validize_mem PARAMS ((rtx));
|
||||
|
Loading…
x
Reference in New Issue
Block a user