Hi,
the alias-2.c testcase fails on targets with anchors.  The reason is that
the variable itself is anchored while the alias is not and they point to the
same location.   I folllowed the docs of SYMBOL_REF claiming that
SYMBOL_REF_DECL if the symbol is label and tought it is safe to disambiguate
them.

This patch commonizes the logic to compare_base_symbol_refs which acts
equivalently to compare_base_decls but on tRTL's SYMBOL_REF and can handle
querries when one parameter is DECL while other is anchor.

I am not fully sure about the case where we know that the variable is
in a block and we know its offset.  With current implementation I do not think
it is safe to use offset orracle because one offset is offset inside a variable,
while other is offset inside of the block.  This can be compensated for.
Also it seems that the alias code should not ignore the base informaiton it has
in memory attributes as it can be more precise.

This patch fixes the alias-2.c testcase and was bootstrapped/regtsted on arm.
OK?

I will look into anchor code - it seems it should create anchor for the alias,
too because it is non-interposable, but for some reason it does not.

Honza

        PR middle-end/68832
        * alias.c (compare_base_symbol_refs): New function.
        (rtx_equal_for_memref_p, base_alias_check, memrefs_conflict_p): Use it.
        
Index: alias.c
===================================================================
--- alias.c     (revision 231722)
+++ alias.c     (working copy)
@@ -158,6 +158,7 @@
 static int write_dependence_p (const_rtx,
                               const_rtx, machine_mode, rtx,
                               bool, bool, bool);
+static int compare_base_symbol_refs (const_rtx, const_rtx);
 
 static void memory_modified_1 (rtx, const_rtx, void *);
 
@@ -1756,16 +1757,8 @@
       return LABEL_REF_LABEL (x) == LABEL_REF_LABEL (y);
 
     case SYMBOL_REF:
-      {
-       tree x_decl = SYMBOL_REF_DECL (x);
-       tree y_decl = SYMBOL_REF_DECL (y);
+      return compare_base_symbol_refs (x, y) == 1;
 
-       if (!x_decl || !y_decl)
-         return XSTR (x, 0) == XSTR (y, 0);
-       else
-         return compare_base_decls (x_decl, y_decl) == 1;
-      }
-
     case ENTRY_VALUE:
       /* This is magic, don't go through canonicalization et al.  */
       return rtx_equal_p (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y));
@@ -2052,6 +2045,65 @@
   return ret;
 }
 
+/* Same as compare_base_decls but for SYMBOL_REF.
+   Return -2 if the offset based oracle can not be used (i.e.
+   we have a symbol and section anchor which is located insite
+   the same block.  */
+
+static int
+compare_base_symbol_refs (const_rtx x_base, const_rtx y_base)
+{
+  tree x_decl = SYMBOL_REF_DECL (x_base);
+  tree y_decl = SYMBOL_REF_DECL (y_base);
+  bool binds_def = true;
+  if (x_decl && y_decl)
+    return compare_base_decls (x_decl, y_decl);
+  if (x_decl || y_decl)
+    {
+      if (!x_decl)
+       {
+         std::swap (x_decl, y_decl);
+         std::swap (x_base, y_base);
+       }
+      /* Variable and anchor representing the variable alias.  If x_base
+        is not a static variable or y_base is not an anchor (it is a label)
+        we are safe.  */
+      if (!SYMBOL_REF_HAS_BLOCK_INFO_P (y_base)
+         || (TREE_CODE (x_decl) != VAR_DECL
+             || (!TREE_STATIC (x_decl) && !TREE_PUBLIC (x_decl))))
+       return 0;
+      symtab_node *x_node = symtab_node::get_create (x_decl)
+                           ->ultimate_alias_target ();
+      /* External variable can not be in section anchor.  */
+      if (!x_node->definition)
+       return 0;
+      x_base = XEXP (DECL_RTL (x_node->decl), 0);
+      /* If not in anchor, we can disambiguate.  */
+      if (!SYMBOL_REF_HAS_BLOCK_INFO_P (x_base))
+       return 0;
+
+      /* We have an alias of anchored variable.  If it can be interposed;
+        we must assume it may or may not alias its anchor.  */
+      binds_def = decl_binds_to_current_def_p (x_decl);
+    }
+  /* If we have variable in section anchor, we can compare by offset.  */
+  if (SYMBOL_REF_HAS_BLOCK_INFO_P (x_base)
+      && SYMBOL_REF_HAS_BLOCK_INFO_P (y_base))
+    {
+      if (SYMBOL_REF_BLOCK (x_base) != SYMBOL_REF_BLOCK (y_base))
+       return 0;
+      if (SYMBOL_REF_BLOCK_OFFSET (x_base) == SYMBOL_REF_BLOCK_OFFSET (y_base))
+       return binds_def ? 1 : -1;
+      /* Mixing anchors and non-anchors may result to false negative.
+        We probably never do that.  */
+      if (SYMBOL_REF_ANCHOR_P (x_base) != SYMBOL_REF_ANCHOR_P (y_base))
+       return -2;
+      return 0;
+    }
+  /* Label and label or label and section anchor. Copare symbol name.  */
+  return XSTR (x_base, 0) == XSTR (y_base, 0);
+}
+
 /* Return 0 if the addresses X and Y are known to point to different
    objects, 1 if they might be pointers to the same object.  */
 
@@ -2090,16 +2142,8 @@
     return 1;
 
   if (GET_CODE (x_base) == SYMBOL_REF && GET_CODE (y_base) == SYMBOL_REF)
-    {
-      tree x_decl = SYMBOL_REF_DECL (x_base);
-      tree y_decl = SYMBOL_REF_DECL (y_base);
+    return compare_base_symbol_refs (x_base, y_base) != 0;
 
-      /* We can assume that no stores are made to labels.  */
-      if (!x_decl || !y_decl)
-       return 0;
-      return compare_base_decls (x_decl, y_decl) != 0;
-    }
-
   /* The base addresses are different expressions.  If they are not accessed
      via AND, there is no conflict.  We can bring knowledge of object
      alignment into play here.  For example, on alpha, "char a, b;" can
@@ -2323,26 +2367,14 @@
 
   if (GET_CODE (x) == SYMBOL_REF && GET_CODE (y) == SYMBOL_REF)
     {
-      tree x_decl = SYMBOL_REF_DECL (x);
-      tree y_decl = SYMBOL_REF_DECL (y);
-      int cmp;
+      int cmp = compare_base_symbol_refs (x,y);
 
-      if (!x_decl || !y_decl)
-       {
-         /* Label and normal symbol are never the same. */
-         if (x_decl != y_decl)
-           return 0;
-         return offset_overlap_p (c, xsize, ysize);
-       }
-      else
-        cmp = compare_base_decls (x_decl, y_decl);
-
       /* If both decls are the same, decide by offsets.  */
       if (cmp == 1)
         return offset_overlap_p (c, xsize, ysize);
       /* If decls are different or we know by offsets that there is no overlap,
         we win.  */
-      if (!cmp || !offset_overlap_p (c, xsize, ysize))
+      if (!cmp || (cmp != -2 && !offset_overlap_p (c, xsize, ysize)))
        return 0;
       /* Decls may or may not be different and offsets overlap....*/
       return -1;

Reply via email to