2
0
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:
Richard Henderson 2001-12-11 18:47:55 -08:00 committed by Richard Henderson
parent 0051b6cae4
commit e7dfe4bb07
4 changed files with 90 additions and 6 deletions

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