From e7dfe4bb07b757be04083465eb6630cd3aa6a79f Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 11 Dec 2001 18:47:55 -0800 Subject: [PATCH] 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 --- gcc/ChangeLog | 6 ++++ gcc/config/alpha/alpha.c | 8 ++--- gcc/emit-rtl.c | 78 ++++++++++++++++++++++++++++++++++++++++ gcc/expr.h | 4 +++ 4 files changed, 90 insertions(+), 6 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 981bcc30aa5d..1c6b2539b18d 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2001-12-11 Richard Henderson + + * 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 * combine.c (simplify_shift_const): Move SHIFT_COUNT_TRUNCATED diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c index 66ed07947f7b..1120bfb95995 100644 --- a/gcc/config/alpha/alpha.c +++ b/gcc/config/alpha/alpha.c @@ -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)) diff --git a/gcc/emit-rtl.c b/gcc/emit-rtl.c index 4238b8c7762c..7c7dfd3f1722 100644 --- a/gcc/emit-rtl.c +++ b/gcc/emit-rtl.c @@ -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. */ diff --git a/gcc/expr.h b/gcc/expr.h index 192733b9a5c1..e5b488aec330 100644 --- a/gcc/expr.h +++ b/gcc/expr.h @@ -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)); -- 2.43.5