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
This commit is contained in:
Richard Guenther 2009-09-29 14:29:10 +00:00 committed by Richard Biener
parent 4b653ed5a4
commit b0e96404c1
2 changed files with 35 additions and 38 deletions

View File

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

View File

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