for  gcc/ChangeLog
from  Alexandre Oliva  <aoliva@redhat.com>

	PR debug/52001
	* alias.c (refs_newer_value_cb, refs_newer_value_p): New.
	(get_addr): Walk canonical value's locs.  Avoid returning VALUEs
	and locs that reference values newer than the non-canonical value
	at hand.  Return the canonical value as a worst case.
	(memrefs_conflict_p): Walk canonical value's locs.

Index: gcc/alias.c
===================================================================
--- gcc/alias.c.orig	2012-02-17 01:14:43.734347934 -0200
+++ gcc/alias.c	2012-02-17 01:47:33.506632170 -0200
@@ -1773,6 +1773,29 @@ base_alias_check (rtx x, rtx y, enum mac
   return 1;
 }
 
+/* Callback for for_each_rtx, that returns 1 upon encountering a VALUE
+   whose UID is greater than the int uid that D points to.  */
+
+static int
+refs_newer_value_cb (rtx *x, void *d)
+{
+  if (GET_CODE (*x) == VALUE && CSELIB_VAL_PTR (*x)->uid > *(int *)d)
+    return 1;
+
+  return 0;
+}
+
+/* Return TRUE if EXPR refers to a VALUE whose uid is greater than
+   that of V.  */
+
+static bool
+refs_newer_value_p (rtx expr, rtx v)
+{
+  int minuid = CSELIB_VAL_PTR (v)->uid;
+
+  return for_each_rtx (&expr, refs_newer_value_cb, &minuid);
+}
+
 /* Convert the address X into something we can use.  This is done by returning
    it unchanged unless it is a value; in the latter case we call cselib to get
    a more useful rtx.  */
@@ -1788,14 +1811,20 @@ get_addr (rtx x)
   v = CSELIB_VAL_PTR (x);
   if (v)
     {
+      v = canonical_cselib_val (v);
       for (l = v->locs; l; l = l->next)
 	if (CONSTANT_P (l->loc))
 	  return l->loc;
       for (l = v->locs; l; l = l->next)
-	if (!REG_P (l->loc) && !MEM_P (l->loc))
+	if (!REG_P (l->loc) && !MEM_P (l->loc) && GET_CODE (l->loc) != VALUE
+	    && !refs_newer_value_p (l->loc, x))
+	  return l->loc;
+      for (l = v->locs; l; l = l->next)
+	if (REG_P (l->loc) || (GET_CODE (l->loc) != VALUE
+			       && !refs_newer_value_p (l->loc, x)))
 	  return l->loc;
-      if (v->locs)
-	return v->locs->loc;
+      /* Return the canonical value.  */
+      return v->val_rtx;
     }
   return x;
 }
@@ -1873,7 +1902,8 @@ memrefs_conflict_p (int xsize, rtx x, in
 	{
 	  struct elt_loc_list *l = NULL;
 	  if (CSELIB_VAL_PTR (x))
-	    for (l = CSELIB_VAL_PTR (x)->locs; l; l = l->next)
+	    for (l = canonical_cselib_val (CSELIB_VAL_PTR (x))->locs;
+		 l; l = l->next)
 	      if (REG_P (l->loc) && rtx_equal_for_memref_p (l->loc, y))
 		break;
 	  if (l)
@@ -1891,7 +1921,8 @@ memrefs_conflict_p (int xsize, rtx x, in
 	{
 	  struct elt_loc_list *l = NULL;
 	  if (CSELIB_VAL_PTR (y))
-	    for (l = CSELIB_VAL_PTR (y)->locs; l; l = l->next)
+	    for (l = canonical_cselib_val (CSELIB_VAL_PTR (y))->locs;
+		 l; l = l->next)
 	      if (REG_P (l->loc) && rtx_equal_for_memref_p (l->loc, x))
 		break;
 	  if (l)
