This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH] Fix issue with RTL alias-export and promoted subregs
- From: Richard Guenther <rguenther at suse dot de>
- To: Uros Bizjak <ubizjak at gmail dot com>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>, Pat Haugen <pthaugen at us dot ibm dot com>, rth at redhat dot com
- Date: Mon, 28 Sep 2009 12:36:42 +0200 (CEST)
- Subject: Re: [PATCH] Fix issue with RTL alias-export and promoted subregs
- References: <4ABFE8B8.9040804@gmail.com> <alpine.LNX.2.00.0909281147510.4520@zhemvz.fhfr.qr>
On Mon, 28 Sep 2009, Richard Guenther wrote:
> On Mon, 28 Sep 2009, Uros Bizjak wrote:
>
> > Hello!
> >
> > > It happens that with promoted subregs we have to deal with
> > > MEMs like [9 p_initial+-4 S8 A64] which access 8 bytes starting
> > > 4 bytes before a decl with 4 bytes in size. Not very nice.
> > >
> > > Fixed like the following. Bootstrapped and tested on
> > > x86_64-unknown-linux-gnu and ppc64 (by Pat).
> > >
> > > Applied to trunk.
> > >
> > > Richard.
> > >
> > > 2009-09-23 Richard Guenther<rguenther@suse.de>
> > >
> > > * alias.c (ao_ref_from_mem): Correct for negative MEM_OFFSET
> > > produced for bigendian targets with promoted subregs.
> > >
> >
> > This patch breaks a couple of testcases on alpha-linux-gnu [1]:
> >
> > FAIL: gcc.c-torture/execute/20030408-1.c compilation, -O3
> > -fomit-frame-pointer (internal compiler error)
> > UNRESOLVED: gcc.c-torture/execute/20030408-1.c execution, -O3
> > -fomit-frame-pointer
> > FAIL: gcc.c-torture/execute/20030408-1.c compilation, -O3 -g (internal
> > compiler error)
> > UNRESOLVED: gcc.c-torture/execute/20030408-1.c execution, -O3 -g
> > FAIL: gcc.c-torture/execute/pr27285.c compilation, -O1 (internal compiler
> > error)
> > UNRESOLVED: gcc.c-torture/execute/pr27285.c execution, -O1
> > FAIL: gcc.c-torture/execute/pr27285.c compilation, -O2 (internal compiler
> > error)
> > UNRESOLVED: gcc.c-torture/execute/pr27285.c execution, -O2
> > FAIL: gcc.c-torture/execute/pr27285.c compilation, -Os (internal compiler
> > error)
> > UNRESOLVED: gcc.c-torture/execute/pr27285.c execution, -Os
> >
> >
> > This failure can be reproduced by a cross (from x86_64-pc-linux-gnu):
> >
> > ~/gcc-build-alpha/gcc/cc1 -O2 -quiet pr27285.c
> > pr27285.c: In function âmainâ:
> > pr27285.c:46:1: internal compiler error: in ao_ref_from_mem, at alias.c:321
> > Please submit a full bug report,
> > with preprocessed source if appropriate.
> > See <http://gcc.gnu.org/bugs.html> for instructions.
> >
> > [1] http://gcc.gnu.org/ml/gcc-testresults/2009-09/msg02383.html
>
> There's some weird things going on with stack slot allocations.
> x is allocated from [virtual-stack-vars, virtual-stack-vars + 18]
> and y is allocated from [virtual-stack-vars + 19, virtual-stack-vars + 34]
> for some reason (so &y - 3 is DImode aligned, as is &x)!?
Ok, it's obviously densely allocated on the stack.
Hmm. I guess we need to punt more here, like with the following
(untested). In principle the MEM_EXPR doesn't buy us extra
disambiguations here so we could as well avoid emitting it.
So, I'm testing the following.
Richard.
Index: alias.c
===================================================================
--- alias.c (revision 152231)
+++ alias.c (working copy)
@@ -265,6 +265,11 @@ ao_ref_from_mem (ao_ref *ref, const_rtx
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,31 @@ ao_ref_from_mem (ao_ref *ref, const_rtx
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)
+ && ((signed HOST_WIDE_INT)ref->offset < 0
+ || !host_integerp (DECL_SIZE (ref->base), 1)
+ || (TREE_INT_CST_LOW (DECL_SIZE (ref->base))
+ < ref->offset + ref->size)))
+ return false;
return true;
}
@@ -569,9 +560,13 @@ component_uses_parent_alias_set (const_t
case IMAGPART_EXPR:
break;
- default:
+ case BIT_FIELD_REF:
+ case VIEW_CONVERT_EXPR:
/* Bitfields and casts are never addressable. */
return true;
+
+ default:
+ gcc_unreachable ();
}
t = TREE_OPERAND (t, 0);
@@ -599,7 +594,7 @@ get_deref_alias_set_1 (tree t)
/* If we have an INDIRECT_REF via a void pointer, we don't
know anything about what that might alias. Likewise if the
pointer is marked that way. */
- if (TREE_CODE (TREE_TYPE (t)) == VOID_TYPE
+ if (VOID_TYPE_P (TREE_TYPE (t))
|| TYPE_REF_CAN_ALIAS_ALL (t))
return 0;
@@ -657,8 +652,7 @@ get_alias_set (tree t)
if (set != -1)
return set;
- /* First see if the actual object referenced is an INDIRECT_REF from a
- restrict-qualified pointer or a "void *". */
+ /* First see if the actual object referenced is an INDIRECT_REF. */
while (handled_component_p (inner))
{
inner = TREE_OPERAND (inner, 0);