This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Fix issue with RTL alias-export and promoted subregs


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);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]