re PR lto/61886 (LTO breaks fread with _FORTIFY_SOURCE=2)
authorJan Hubicka <hubicka@ucw.cz>
Wed, 9 Dec 2015 23:28:01 +0000 (00:28 +0100)
committerJan Hubicka <hubicka@gcc.gnu.org>
Wed, 9 Dec 2015 23:28:01 +0000 (23:28 +0000)
PR ipa/61886
PR middle-end/25140
* tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Use compare_base_decls
(nonoverlapping_component_refs_of_decl_p): Update sanity check.
(decl_refs_may_alias_p): Use compare_base_decls.
* alias.c: Include cgraph.h
(rtx_equal_for_memref_p): Use rtx_equal_for_memref_p.
(compare_base_decls): New function.
(base_alias_check): Likewise.
(memrefs_conflict_p): Likewise.
(nonoverlapping_memrefs_p): Likewise.
* alias.h (compare_base_decls): Declare.

* gcc.c-torture/execute/alias-2.c: New testcase.

From-SVN: r231478

gcc/ChangeLog
gcc/alias.c
gcc/alias.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.c-torture/execute/alias-2.c [new file with mode: 0644]
gcc/tree-ssa-alias.c

index 44f621b73f2dbd7ca1885c90e101cb11e2c2c63f..13d31852a9077145741c802e8186606720f05619 100644 (file)
@@ -1,3 +1,18 @@
+2015-12-08  Jan Hubicka  <hubicka@ucw.cz>
+
+       PR ipa/61886
+       PR middle-end/25140
+       * tree-ssa-alias.c (ptr_deref_may_alias_decl_p): Use compare_base_decls
+       (nonoverlapping_component_refs_of_decl_p): Update sanity check.
+       (decl_refs_may_alias_p): Use compare_base_decls.
+       * alias.c: Include cgraph.h
+       (rtx_equal_for_memref_p): Use rtx_equal_for_memref_p.
+       (compare_base_decls): New function.
+       (base_alias_check): Likewise.
+       (memrefs_conflict_p): Likewise.
+       (nonoverlapping_memrefs_p): Likewise.
+       * alias.h (compare_base_decls): Declare.
+
 2015-12-08  Jan Hubicka  <hubicka@ucw.cz>
 
        PR ipa/61886
index 66aedcef4c904e21836cf91c6223852bb17213f8..095b2ade180b7cd09f8c0473201b7945b4fc8256 100644 (file)
@@ -37,6 +37,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "langhooks.h"
 #include "cfganal.h"
 #include "rtl-iter.h"
+#include "cgraph.h"
 
 /* The aliasing API provided here solves related but different problems:
 
@@ -990,6 +991,14 @@ get_alias_set (tree t)
           || TREE_CODE (p) == VECTOR_TYPE;
           p = TREE_TYPE (p))
        {
+         /* Ada supports recusive pointers.  Instead of doing recrusion check
+            just give up once the preallocated space of 8 elements is up.
+            In this case just punt to void * alias set.  */
+         if (reference.length () == 8)
+           {
+             p = ptr_type_node;
+             break;
+           }
          if (TREE_CODE (p) == REFERENCE_TYPE)
            /* In LTO we want languages that use references to be compatible
               with languages that use pointers.  */
@@ -1747,7 +1756,15 @@ rtx_equal_for_memref_p (const_rtx x, const_rtx y)
       return LABEL_REF_LABEL (x) == LABEL_REF_LABEL (y);
 
     case SYMBOL_REF:
-      return XSTR (x, 0) == XSTR (y, 0);
+      {
+       tree x_decl = SYMBOL_REF_DECL (x);
+       tree y_decl = SYMBOL_REF_DECL (y);
+
+       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.  */
@@ -2010,6 +2027,31 @@ may_be_sp_based_p (rtx x)
   return !base || base == static_reg_base_value[STACK_POINTER_REGNUM];
 }
 
+/* BASE1 and BASE2 are decls.  Return 1 if they refer to same object, 0
+   if they refer to different objects and -1 if we can not decide.  */
+
+int
+compare_base_decls (tree base1, tree base2)
+{
+  int ret;
+  gcc_checking_assert (DECL_P (base1) && DECL_P (base2));
+  if (base1 == base2)
+    return 1;
+
+  bool in_symtab1 = decl_in_symtab_p (base1);
+  bool in_symtab2 = decl_in_symtab_p (base2);
+
+  /* Declarations of non-automatic variables may have aliases.  All other
+     decls are unique.  */
+  if (in_symtab1 != in_symtab2 || !in_symtab1)
+    return 0;
+  ret = symtab_node::get_create (base1)->equal_address_to
+                (symtab_node::get_create (base2), true);
+  if (ret == 2)
+    return -1;
+  return ret;
+}
+
 /* 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.  */
 
@@ -2047,6 +2089,17 @@ base_alias_check (rtx x, rtx x_base, rtx y, rtx y_base,
   if (rtx_equal_p (x_base, y_base))
     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);
+
+      /* 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
@@ -2268,7 +2321,33 @@ memrefs_conflict_p (int xsize, rtx x, int ysize, rtx y, HOST_WIDE_INT c)
   else
     y = addr_side_effect_eval (y, abs (ysize), 0);
 
-  if (rtx_equal_for_memref_p (x, y))
+  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;
+
+      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))
+       return 0;
+      /* Decls may or may not be different and offsets overlap....*/
+      return -1;
+    }
+  else if (rtx_equal_for_memref_p (x, y))
     {
       return offset_overlap_p (c, xsize, ysize);
     }
@@ -2636,7 +2715,7 @@ nonoverlapping_memrefs_p (const_rtx x, const_rtx y, bool loop_invariant)
      are constants or if one is a constant and the other a pointer into the
      stack frame.  Otherwise a different base means we can't tell if they
      overlap or not.  */
-  if (! rtx_equal_p (basex, basey))
+  if (compare_base_decls (exprx, expry) == 0)
     return ((CONSTANT_P (basex) && CONSTANT_P (basey))
            || (CONSTANT_P (basex) && REG_P (basey)
                && REGNO_PTR_FRAME_P (REGNO (basey)))
@@ -2647,6 +2726,10 @@ nonoverlapping_memrefs_p (const_rtx x, const_rtx y, bool loop_invariant)
   if (loop_invariant)
     return 0;              
 
+  /* Offset based disambiguation is OK even if we do not know that the
+     declarations are necessarily different
+    (i.e. compare_base_decls (exprx, expry) == -1)  */
+
   sizex = (!MEM_P (rtlx) ? (int) GET_MODE_SIZE (GET_MODE (rtlx))
           : MEM_SIZE_KNOWN_P (rtlx) ? MEM_SIZE (rtlx)
           : -1);
index 8762effe2f2a707ece840d875923ccc4ccf16e87..45cbb1b60dc33e414958f3aa8f602a22160bae74 100644 (file)
@@ -36,6 +36,7 @@ extern int nonoverlapping_memrefs_p (const_rtx, const_rtx, bool);
 extern void dump_alias_stats_in_alias_c (FILE *s);
 tree reference_alias_ptr_type (tree);
 bool alias_ptr_types_compatible_p (tree, tree);
+int compare_base_decls (tree, tree);
 
 /* This alias set can be used to force a memory to conflict with all
    other memories, creating a barrier across which no memory reference
index f09a875ec24a308b5782a2f45c3e14eeac0b9329..ef7857a393597453dd563b721c5b7ebea86b5736 100644 (file)
@@ -1,3 +1,9 @@
+2015-12-08  Jan Hubicka  <hubicka@ucw.cz>
+
+       PR ipa/61886
+       PR middle-end/25140
+       * gcc.c-torture/execute/alias-2.c: New testcase.
+
 2015-12-09  Tobias Burnus  <burnus@net-b.de>
            Alessandro Fanfarillo <fanfarillo.gcc@gmail.com>
 
diff --git a/gcc/testsuite/gcc.c-torture/execute/alias-2.c b/gcc/testsuite/gcc.c-torture/execute/alias-2.c
new file mode 100644 (file)
index 0000000..c62d506
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-require-alias "" } */
+int a[10]={};
+extern int b[10] __attribute__ ((alias("a")));
+int off;
+main()
+{
+  b[off]=1;
+  a[off]=2;
+  if (b[off]!=2)
+   __builtin_abort ();
+  return 0;
+}
index b0ab6fb46aa0e467ad56c83b9a4b2b610be1801e..b5165461bc4370b1f0a0e834478362b5904fd607 100644 (file)
@@ -194,7 +194,7 @@ ptr_deref_may_alias_decl_p (tree ptr, tree decl)
        ptr = TREE_OPERAND (base, 0);
       else if (base
               && DECL_P (base))
-       return base == decl;
+       return compare_base_decls (base, decl) != 0;
       else if (base
               && CONSTANT_CLASS_P (base))
        return false;
@@ -805,8 +805,10 @@ nonoverlapping_component_refs_of_decl_p (tree ref1, tree ref2)
       ref2 = TREE_OPERAND (TREE_OPERAND (ref2, 0), 0);
     }
 
-  /* We must have the same base DECL.  */
-  gcc_assert (ref1 == ref2);
+  /* Bases must be either same or uncomparable.  */
+  gcc_checking_assert (ref1 == ref2
+                      || (DECL_P (ref1) && DECL_P (ref2)
+                          && compare_base_decls (ref1, ref2) != 0));
 
   /* Pop the stacks in parallel and examine the COMPONENT_REFs of the same
      rank.  This is sufficient because we start from the same DECL and you
@@ -989,7 +991,7 @@ decl_refs_may_alias_p (tree ref1, tree base1,
   gcc_checking_assert (DECL_P (base1) && DECL_P (base2));
 
   /* If both references are based on different variables, they cannot alias.  */
-  if (base1 != base2)
+  if (compare_base_decls (base1, base2) == 0)
     return false;
 
   /* If both references are based on the same variable, they cannot alias if