diff options
author | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-09-29 14:29:10 +0000 |
---|---|---|
committer | rguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-09-29 14:29:10 +0000 |
commit | 3804203d6ff7f19553bfc8c80642a6d2b9a97c12 (patch) | |
tree | 8c4c73f3b4d3a8dec8a928d7d5e7fe50afb453b2 /gcc/alias.c | |
parent | afa4238d6204df4ee6056f0cfd1038de9605b93f (diff) | |
download | gcc-3804203d6ff7f19553bfc8c80642a6d2b9a97c12.tar.gz |
2009-09-29 Richard Guenther <rguenther@suse.de>
* alias.c (ao_ref_from_mem): Properly deal with off decl accesses
resulting from stack temporaries on STRICT_ALIGNMENT targets.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@152278 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/alias.c')
-rw-r--r-- | gcc/alias.c | 68 |
1 files changed, 30 insertions, 38 deletions
diff --git a/gcc/alias.c b/gcc/alias.c index 6bb051e62b5..694498ab55a 100644 --- a/gcc/alias.c +++ b/gcc/alias.c @@ -265,6 +265,11 @@ ao_ref_from_mem (ao_ref *ref, const_rtx mem) if (!expr) return false; + /* If MEM_OFFSET or MEM_SIZE are NULL punt. */ + if (!MEM_OFFSET (mem) + || !MEM_SIZE (mem)) + return false; + ao_ref_init (ref, expr); /* Get the base of the reference and see if we have to reject or @@ -302,45 +307,32 @@ ao_ref_from_mem (ao_ref *ref, const_rtx mem) ref->ref_alias_set = MEM_ALIAS_SET (mem); - /* For NULL MEM_OFFSET the MEM_EXPR may have been stripped arbitrarily - without recording offset or extent adjustments properly. */ - if (MEM_OFFSET (mem) == NULL_RTX) - { - ref->offset = 0; - ref->max_size = -1; - } - else if (INTVAL (MEM_OFFSET (mem)) < 0 - && MEM_EXPR (mem) != get_spill_slot_decl (false)) - { - /* Negative MEM_OFFSET happens for promoted subregs on bigendian - targets. We need to compensate both the size and the offset here, - which get_ref_base_and_extent will have done based on the MEM_EXPR - already. */ - gcc_assert (((INTVAL (MEM_SIZE (mem)) + INTVAL (MEM_OFFSET (mem))) - * BITS_PER_UNIT) - == ref->size); - return true; - } - else - { - ref->offset += INTVAL (MEM_OFFSET (mem)) * BITS_PER_UNIT; - } + /* If the base decl is a parameter we can have negative MEM_OFFSET in + case of promoted subregs on bigendian targets. Trust the MEM_EXPR + here. */ + if (INTVAL (MEM_OFFSET (mem)) < 0 + && ((INTVAL (MEM_SIZE (mem)) + INTVAL (MEM_OFFSET (mem))) + * BITS_PER_UNIT) == ref->size) + return true; - /* NULL MEM_SIZE should not really happen with a non-NULL MEM_EXPR, - but just play safe here. The size may have been adjusted together - with the offset, so we need to take it if it is set and not rely - on MEM_EXPR here (which has the size determining parts potentially - stripped anyway). We lose precision for max_size which is only - available from the remaining MEM_EXPR. */ - if (MEM_SIZE (mem) == NULL_RTX) - { - ref->size = -1; - ref->max_size = -1; - } - else - { - ref->size = INTVAL (MEM_SIZE (mem)) * BITS_PER_UNIT; - } + ref->offset += INTVAL (MEM_OFFSET (mem)) * BITS_PER_UNIT; + ref->size = INTVAL (MEM_SIZE (mem)) * BITS_PER_UNIT; + + /* The MEM may extend into adjacent fields, so adjust max_size if + necessary. */ + if (ref->max_size != -1 + && ref->size > ref->max_size) + ref->max_size = ref->size; + + /* If MEM_OFFSET and MEM_SIZE get us outside of the base object of + the MEM_EXPR punt. This happens for STRICT_ALIGNMENT targets a lot. */ + if (MEM_EXPR (mem) != get_spill_slot_decl (false) + && (ref->offset < 0 + || (DECL_P (ref->base) + && (!host_integerp (DECL_SIZE (ref->base), 1) + || (TREE_INT_CST_LOW (DECL_SIZE ((ref->base))) + < (unsigned HOST_WIDE_INT)(ref->offset + ref->size)))))) + return false; return true; } |