This fixes bogus non-overlap considerations based on TBAA.  Since
we also have to care for punning through unions the following
uses only align-based checks which are always valid.

Bootstrapped and tested on x86_64-unknown-linux-gnu, applied to trunk.

Variant for the branch below, also boostrapped/tested and applied to
GCC 9 sofar, backport to GCC 8 pending.

Richard.

2019-07-08  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/91108
        * tree-ssa-sccvn.c: Include builtins.h.
        (vn_reference_lookup_3): Use only alignment constraints to
        verify same-valued store disambiguation.

        * gcc.dg/tree-ssa/ssa-fre-61.c: Adjust back.
        * gcc.dg/tree-ssa/ssa-fre-78.c: New testcase.

Index: gcc/tree-ssa-sccvn.c
===================================================================
--- gcc/tree-ssa-sccvn.c        (revision 273194)
+++ gcc/tree-ssa-sccvn.c        (working copy)
@@ -70,6 +70,7 @@ along with GCC; see the file COPYING3.
 #include "tree-ssa-loop.h"
 #include "tree-scalar-evolution.h"
 #include "tree-ssa-loop-niter.h"
+#include "builtins.h"
 #include "tree-ssa-sccvn.h"
 
 /* This algorithm is based on the SCC algorithm presented by Keith
@@ -2248,24 +2249,10 @@ vn_reference_lookup_3 (ao_ref *ref, tree
       /* If we reach a clobbering statement try to skip it and see if
          we find a VN result with exactly the same value as the
         possible clobber.  In this case we can ignore the clobber
-        and return the found value.
-        Note that we don't need to worry about partial overlapping
-        accesses as we then can use TBAA to disambiguate against the
-        clobbering statement when looking up a load (thus the
-        VN_WALKREWRITE guard).  */
-      if (data->vn_walk_kind == VN_WALKREWRITE
-         && is_gimple_reg_type (TREE_TYPE (lhs))
+        and return the found value.  */
+      if (is_gimple_reg_type (TREE_TYPE (lhs))
          && types_compatible_p (TREE_TYPE (lhs), vr->type)
-         /* The overlap restriction breaks down when either access
-            alias-set is zero.  Still for accesses of the size of
-            an addressable unit there can be no overlaps.  Overlaps
-            between different union members are not an issue since
-            activation of a union member via a store makes the
-            values of untouched bytes unspecified.  */
-         && (known_eq (ref->size, BITS_PER_UNIT)
-             || (flag_strict_aliasing
-                 && get_alias_set (lhs) != 0
-                 && ao_ref_alias_set (ref) != 0)))
+         && ref->ref)
        {
          tree *saved_last_vuse_ptr = data->last_vuse_ptr;
          /* Do not update last_vuse_ptr in vn_reference_lookup_2.  */
@@ -2284,7 +2271,14 @@ vn_reference_lookup_3 (ao_ref *ref, tree
              if (TREE_CODE (rhs) == SSA_NAME)
                rhs = SSA_VAL (rhs);
              if (vnresult->result
-                 && operand_equal_p (vnresult->result, rhs, 0))
+                 && operand_equal_p (vnresult->result, rhs, 0)
+                 /* We have to honor our promise about union type punning
+                    and also support arbitrary overlaps with
+                    -fno-strict-aliasing.  So simply resort to alignment to
+                    rule out overlaps.  Do this check last because it is
+                    quite expensive compared to the hash-lookup above.  */
+                 && multiple_p (get_object_alignment (ref->ref), ref->size)
+                 && multiple_p (get_object_alignment (lhs), ref->size))
                return res;
            }
        }
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-61.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-61.c  (revision 273194)
+++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-61.c  (working copy)
@@ -1,5 +1,5 @@
 /* { dg-do link } */
-/* { dg-options "-O -fstrict-aliasing -fdump-tree-fre1-details" } */
+/* { dg-options "-O -fdump-tree-fre1-details" } */
 
 void link_error (void);
 
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-78.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-78.c  (nonexistent)
+++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-78.c  (working copy)
@@ -0,0 +1,27 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -fstrict-aliasing" } */
+
+union U {
+  struct A { int : 2; int x : 8; } a;
+  struct B { int : 6; int x : 8; } b;
+};
+
+int __attribute__((noipa))
+foo (union U *p, union U *q)
+{
+  p->a.x = 1;
+  q->b.x = 1;
+  return p->a.x;
+}
+
+int
+main()
+{
+  union U x;
+  if (foo (&x, &x) != x.a.x)
+    __builtin_abort ();
+  return 0;
+}
+
+/* We support arbitrary punning through unions when it happens through
+   the union type and thus p == q is valid here.  */


2019-07-08  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/91108
        * tree-ssa-sccvn.c: Include builtins.h.
        (vn_reference_lookup_3): Use only alignment constraints to
        verify same-valued store disambiguation.

        * gcc.dg/tree-ssa/pr91091-1.c: New testcase.
        * gcc.dg/tree-ssa/ssa-fre-78.c: Likewise.

Index: gcc/testsuite/gcc.dg/tree-ssa/pr91091-1.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/pr91091-1.c   (nonexistent)
+++ gcc/testsuite/gcc.dg/tree-ssa/pr91091-1.c   (working copy)
@@ -0,0 +1,23 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -fno-strict-aliasing" } */
+
+struct s { int x; } __attribute__((packed));
+struct t { int x; };
+
+void __attribute__((noinline,noipa))
+swap(struct s* p, struct t* q)
+{
+  p->x = q->x;
+  q->x = p->x;
+}
+
+int main()
+{    
+  struct t a[2];
+  a[0].x = 0x12345678;
+  a[1].x = 0x98765432;
+  swap ((struct s *)((char *)a + 1), a);
+  if (a[0].x != 0x12345678)
+    __builtin_abort ();
+  return 0;
+}
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-78.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-78.c  (nonexistent)
+++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-78.c  (working copy)
@@ -0,0 +1,27 @@
+/* { dg-do run } */
+/* { dg-options "-O3 -fstrict-aliasing" } */
+
+union U {
+  struct A { int : 2; int x : 8; } a;
+  struct B { int : 6; int x : 8; } b;
+};
+
+int __attribute__((noipa))
+foo (union U *p, union U *q)
+{
+  p->a.x = 1;
+  q->b.x = 1;
+  return p->a.x;
+}
+
+int
+main()
+{
+  union U x;
+  if (foo (&x, &x) != x.a.x)
+    __builtin_abort ();
+  return 0;
+}
+
+/* We support arbitrary punning through unions when it happens through
+   the union type and thus p == q is valid here.  */
Index: gcc/tree-ssa-sccvn.c
===================================================================
--- gcc/tree-ssa-sccvn.c        (revision 273226)
+++ gcc/tree-ssa-sccvn.c        (working copy)
@@ -69,6 +69,7 @@ along with GCC; see the file COPYING3.
 #include "tree-ssa-loop.h"
 #include "tree-scalar-evolution.h"
 #include "tree-ssa-loop-niter.h"
+#include "builtins.h"
 #include "tree-ssa-sccvn.h"
 
 /* This algorithm is based on the SCC algorithm presented by Keith
@@ -1993,23 +1994,11 @@ vn_reference_lookup_3 (ao_ref *ref, tree
       /* If we reach a clobbering statement try to skip it and see if
          we find a VN result with exactly the same value as the
         possible clobber.  In this case we can ignore the clobber
-        and return the found value.
-        Note that we don't need to worry about partial overlapping
-        accesses as we then can use TBAA to disambiguate against the
-        clobbering statement when looking up a load (thus the
-        VN_WALKREWRITE guard).  */
+        and return the found value.  */
       if (vn_walk_kind == VN_WALKREWRITE
          && is_gimple_reg_type (TREE_TYPE (lhs))
          && types_compatible_p (TREE_TYPE (lhs), vr->type)
-         /* The overlap restriction breaks down when either access
-            alias-set is zero.  Still for accesses of the size of
-            an addressable unit there can be no overlaps.  Overlaps
-            between different union members are not an issue since
-            activation of a union member via a store makes the
-            values of untouched bytes unspecified.  */
-         && (known_eq (ref->size, BITS_PER_UNIT)
-             || (get_alias_set (lhs) != 0
-                 && ao_ref_alias_set (ref) != 0)))
+         && ref->ref)
        {
          tree *saved_last_vuse_ptr = last_vuse_ptr;
          /* Do not update last_vuse_ptr in vn_reference_lookup_2.  */
@@ -2026,7 +2015,14 @@ vn_reference_lookup_3 (ao_ref *ref, tree
              vn_reference_t vnresult = (vn_reference_t) res;
              if (vnresult->result
                  && operand_equal_p (vnresult->result,
-                                     gimple_assign_rhs1 (def_stmt), 0))
+                                     gimple_assign_rhs1 (def_stmt), 0)
+                 /* We have to honor our promise about union type punning
+                    and also support arbitrary overlaps with
+                    -fno-strict-aliasing.  So simply resort to alignment to
+                    rule out overlaps.  Do this check last because it is
+                    quite expensive compared to the hash-lookup above.  */
+                 && multiple_p (get_object_alignment (ref->ref), ref->size)
+                 && multiple_p (get_object_alignment (lhs), ref->size))
                return res;
            }
        }

Reply via email to