aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Guenther <rguenther@suse.de>2009-09-29 14:29:10 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2009-09-29 14:29:10 +0000
commitb0e96404c1e530a59b2e52a3894a67508f04817d (patch)
tree8c4c73f3b4d3a8dec8a928d7d5e7fe50afb453b2
parent4b653ed5a4a7478172199ac88a6a0811bb862f1e (diff)
downloadgcc-b0e96404c1e530a59b2e52a3894a67508f04817d.zip
gcc-b0e96404c1e530a59b2e52a3894a67508f04817d.tar.gz
gcc-b0e96404c1e530a59b2e52a3894a67508f04817d.tar.bz2
alias.c (ao_ref_from_mem): Properly deal with off decl accesses resulting from stack temporaries on...
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. From-SVN: r152278
-rw-r--r--gcc/ChangeLog5
-rw-r--r--gcc/alias.c68
2 files changed, 35 insertions, 38 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 7ab49af..7088e56 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,8 @@
+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.
+
2009-09-29 Nick Clifton <nickc@redhat.com>
* function.c (current_function_name): If there is no current
diff --git a/gcc/alias.c b/gcc/alias.c
index 6bb051e..694498a 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;
}