I've spent some time robustifying the original idea (fixing some
latent wrong-code on the way...).

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

Richard.

2019-10-11  Richard Biener  <rguent...@suse.de>

        PR tree-optimization/90883
        PR tree-optimization/91091
        * tree-ssa-sccvn.c (vn_reference_lookup_3): Use correct
        alias-sets both for recording VN table entries and continuing
        walking after translating through copies.  Handle same-sized
        reads from SSA names by returning the plain SSA name.
        (eliminate_dom_walker::eliminate_stmt): Properly handle
        non-size precision stores in redundant store elimination.

        * gcc.dg/torture/20191011-1.c: New testcase.
        * gcc.dg/tree-ssa/ssa-fre-82.c: Likewise.
        * gcc.dg/tree-ssa/ssa-fre-83.c: Likewise.
        * gcc.dg/tree-ssa/redundant-assign-zero-1.c: Disable FRE.
        * gcc.dg/tree-ssa/redundant-assign-zero-2.c: Likewise.

Index: gcc/tree-ssa-sccvn.c
===================================================================
--- gcc/tree-ssa-sccvn.c        (revision 276858)
+++ gcc/tree-ssa-sccvn.c        (working copy)
@@ -1877,8 +1877,10 @@
       if (dump_file && (dump_flags & TDF_DETAILS))
        fprintf (dump_file,
                 "Successfully combined %u partial definitions\n", ndefs);
+      /* ???  If we track partial defs alias-set we could use that if it
+         is the same for all.  Use zero for now.  */
       return vn_reference_lookup_or_insert_for_pieces
-               (first_vuse, vr->set, vr->type, vr->operands, val);
+               (first_vuse, 0, vr->type, vr->operands, val);
     }
   else
     {
@@ -2333,7 +2335,7 @@
 
   /* If we are looking for redundant stores do not create new hashtable
      entries from aliasing defs with made up alias-sets.  */
-  if (*disambiguate_only > TR_TRANSLATE || !data->tbaa_p)
+  if (*disambiguate_only > TR_TRANSLATE)
     return (void *)-1;
 
   /* If we cannot constrain the size of the reference we cannot
@@ -2449,7 +2451,7 @@
                return (void *)-1;
            }
          return vn_reference_lookup_or_insert_for_pieces
-                  (vuse, vr->set, vr->type, vr->operands, val);
+                  (vuse, 0, vr->type, vr->operands, val);
        }
       /* For now handle clearing memory with partial defs.  */
       else if (known_eq (ref->size, maxsize)
@@ -2499,7 +2501,7 @@
            {
              tree val = build_zero_cst (vr->type);
              return vn_reference_lookup_or_insert_for_pieces
-                 (vuse, vr->set, vr->type, vr->operands, val);
+                 (vuse, get_alias_set (lhs), vr->type, vr->operands, val);
            }
          else if (known_eq (ref->size, maxsize)
                   && maxsize.is_constant (&maxsizei)
@@ -2614,7 +2616,7 @@
 
                  if (val)
                    return vn_reference_lookup_or_insert_for_pieces
-                       (vuse, vr->set, vr->type, vr->operands, val);
+                     (vuse, get_alias_set (lhs), vr->type, vr->operands, val);
                }
            }
          else if (ranges_known_overlap_p (offseti, maxsizei, offset2i, size2i))
@@ -2672,23 +2674,26 @@
             according to endianness.  */
          && (! INTEGRAL_TYPE_P (vr->type)
              || known_eq (ref->size, TYPE_PRECISION (vr->type)))
-         && multiple_p (ref->size, BITS_PER_UNIT)
-         && (! INTEGRAL_TYPE_P (TREE_TYPE (def_rhs))
-             || type_has_mode_precision_p (TREE_TYPE (def_rhs))))
+         && multiple_p (ref->size, BITS_PER_UNIT))
        {
-         gimple_match_op op (gimple_match_cond::UNCOND,
-                             BIT_FIELD_REF, vr->type,
-                             vn_valueize (def_rhs),
-                             bitsize_int (ref->size),
-                             bitsize_int (offset - offset2));
-         tree val = vn_nary_build_or_lookup (&op);
-         if (val
-             && (TREE_CODE (val) != SSA_NAME
-                 || ! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (val)))
+         if (known_eq (ref->size, size2))
+           return vn_reference_lookup_or_insert_for_pieces
+               (vuse, get_alias_set (lhs), vr->type, vr->operands,
+                SSA_VAL (def_rhs));
+         else if (! INTEGRAL_TYPE_P (TREE_TYPE (def_rhs))
+                  || type_has_mode_precision_p (TREE_TYPE (def_rhs)))
            {
-             vn_reference_t res = vn_reference_lookup_or_insert_for_pieces
-                 (vuse, vr->set, vr->type, vr->operands, val);
-             return res;
+             gimple_match_op op (gimple_match_cond::UNCOND,
+                                 BIT_FIELD_REF, vr->type,
+                                 vn_valueize (def_rhs),
+                                 bitsize_int (ref->size),
+                                 bitsize_int (offset - offset2));
+             tree val = vn_nary_build_or_lookup (&op);
+             if (val
+                 && (TREE_CODE (val) != SSA_NAME
+                     || ! SSA_NAME_OCCURS_IN_ABNORMAL_PHI (val)))
+               return vn_reference_lookup_or_insert_for_pieces
+                   (vuse, get_alias_set (lhs), vr->type, vr->operands, val);
            }
        }
     }
@@ -2770,7 +2775,8 @@
        }
 
       /* Now re-write REF to be based on the rhs of the assignment.  */
-      copy_reference_ops_from_ref (gimple_assign_rhs1 (def_stmt), &rhs);
+      tree rhs1 = gimple_assign_rhs1 (def_stmt);
+      copy_reference_ops_from_ref (rhs1, &rhs);
 
       /* Apply an extra offset to the inner MEM_REF of the RHS.  */
       if (maybe_ne (extra_off, 0))
@@ -2806,7 +2812,7 @@
        {
          if (data->partial_defs.is_empty ())
            return vn_reference_lookup_or_insert_for_pieces
-               (vuse, vr->set, vr->type, vr->operands, val);
+             (vuse, get_alias_set (rhs1), vr->type, vr->operands, val);
          /* This is the only interesting case for partial-def handling
             coming from targets that like to gimplify init-ctors as
             aggregate copies from constant data like aarch64 for
@@ -2829,7 +2835,8 @@
        return (void *)-1;
 
       /* Adjust *ref from the new operands.  */
-      if (!ao_ref_init_from_vn_reference (&r, vr->set, vr->type, vr->operands))
+      if (!ao_ref_init_from_vn_reference (&r, get_alias_set (rhs1),
+                                         vr->type, vr->operands))
        return (void *)-1;
       /* This can happen with bitfields.  */
       if (maybe_ne (ref->size, r.size))
@@ -2990,10 +2997,10 @@
       tree val = fully_constant_vn_reference_p (vr);
       if (val)
        return vn_reference_lookup_or_insert_for_pieces
-                (vuse, vr->set, vr->type, vr->operands, val);
+                (vuse, 0, vr->type, vr->operands, val);
 
       /* Adjust *ref from the new operands.  */
-      if (!ao_ref_init_from_vn_reference (&r, vr->set, vr->type, vr->operands))
+      if (!ao_ref_init_from_vn_reference (&r, 0, vr->type, vr->operands))
        return (void *)-1;
       /* This can happen with bitfields.  */
       if (maybe_ne (ref->size, r.size))
@@ -5539,8 +5546,48 @@
       tree val;
       tree rhs = gimple_assign_rhs1 (stmt);
       vn_reference_t vnresult;
-      val = vn_reference_lookup (lhs, gimple_vuse (stmt), VN_WALKREWRITE,
-                                &vnresult, false);
+      /* ???  gcc.dg/torture/pr91445.c shows that we lookup a boolean
+         typed load of a byte known to be 0x11 as 1 so a store of
+        a boolean 1 is detected as redundant.  Because of this we
+        have to make sure to lookup with a ref where its size
+        matches the precision.  */
+      tree lookup_lhs = lhs;
+      if (INTEGRAL_TYPE_P (TREE_TYPE (lhs))
+         && (TREE_CODE (lhs) != COMPONENT_REF
+             || !DECL_BIT_FIELD_TYPE (TREE_OPERAND (lhs, 1)))
+         && !type_has_mode_precision_p (TREE_TYPE (lhs)))
+       {
+         if (TREE_CODE (lhs) == COMPONENT_REF
+             || TREE_CODE (lhs) == MEM_REF)
+           {
+             tree ltype = build_nonstandard_integer_type
+                               (TREE_INT_CST_LOW (TYPE_SIZE (TREE_TYPE (lhs))),
+                                TYPE_UNSIGNED (TREE_TYPE (lhs)));
+             if (TREE_CODE (lhs) == COMPONENT_REF)
+               {
+                 tree foff = component_ref_field_offset (lhs);
+                 tree f = TREE_OPERAND (lhs, 1);
+                 if (!poly_int_tree_p (foff))
+                   lookup_lhs = NULL_TREE;
+                 else
+                   lookup_lhs = build3 (BIT_FIELD_REF, ltype,
+                                        TREE_OPERAND (lhs, 0),
+                                        TYPE_SIZE (TREE_TYPE (lhs)),
+                                        bit_from_pos
+                                          (foff, DECL_FIELD_BIT_OFFSET (f)));
+               }
+             else
+               lookup_lhs = build2 (MEM_REF, ltype,
+                                    TREE_OPERAND (lhs, 0),
+                                    TREE_OPERAND (lhs, 1));
+           }
+         else
+           lookup_lhs = NULL_TREE;
+       }
+      val = NULL_TREE;
+      if (lookup_lhs)
+       val = vn_reference_lookup (lookup_lhs, gimple_vuse (stmt), VN_WALK,
+                                  &vnresult, false);
       if (TREE_CODE (rhs) == SSA_NAME)
        rhs = VN_INFO (rhs)->valnum;
       if (val
Index: gcc/testsuite/gcc.dg/torture/20191011-1.c
===================================================================
--- gcc/testsuite/gcc.dg/torture/20191011-1.c   (nonexistent)
+++ gcc/testsuite/gcc.dg/torture/20191011-1.c   (working copy)
@@ -0,0 +1,32 @@
+/* { dg-do run } */
+/* { dg-additional-options "-fgimple -fstrict-aliasing" } */
+
+#if __SIZEOF_INT__ != __SIZEOF_FLOAT__
+int main() { return 0; }
+#else
+struct X { int i; };
+float f;
+
+int __GIMPLE (ssa,startwith("fre")) __attribute__((noipa))
+foo (float *p)
+{
+  struct X x;
+  float tem;
+  int _2;
+
+  __BB(2):
+  f = 0.0f;
+  __MEM <float> (p_1(D)) = 1.0f;
+  x = __VIEW_CONVERT <struct X> (f);
+  _2 = x.i;
+  return _2;
+}
+
+int
+main()
+{
+  if (foo (&f) == 0)
+    __builtin_abort ();
+  return 0;
+}
+#endif
Index: gcc/testsuite/gcc.dg/tree-ssa/redundant-assign-zero-1.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/redundant-assign-zero-1.c     (revision 
276858)
+++ gcc/testsuite/gcc.dg/tree-ssa/redundant-assign-zero-1.c     (working copy)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-dse-details" } */
+/* { dg-options "-O2 -fno-tree-fre -fdump-tree-dse-details" } */
 
 void blah (char *);
 
Index: gcc/testsuite/gcc.dg/tree-ssa/redundant-assign-zero-2.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/redundant-assign-zero-2.c     (revision 
276858)
+++ gcc/testsuite/gcc.dg/tree-ssa/redundant-assign-zero-2.c     (working copy)
@@ -1,5 +1,5 @@
 /* { dg-do compile } */
-/* { dg-options "-O2 -fdump-tree-dse-details" } */
+/* { dg-options "-O2 -fno-tree-fre -fdump-tree-dse-details" } */
 
 #include <string.h>
 
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-82.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-82.c  (nonexistent)
+++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-82.c  (working copy)
@@ -0,0 +1,25 @@
+/* { dg-do run } */
+/* { dg-options "-O -fdump-tree-fre1-details" } */
+
+struct S { _Bool x; };
+
+void
+foo (struct S *s)
+{
+  __builtin_memset (s, 1, sizeof (struct S));
+  s->x = 1;
+}
+
+int
+main ()
+{
+  struct S s;
+  foo (&s);
+  char c;
+  __builtin_memcpy (&c, &s.x, 1);
+  if (c != 1)
+    __builtin_abort ();
+  return 0;
+}
+
+/* { dg-final { scan-tree-dump "Deleted redundant store" "fre1" } } */
Index: gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-83.c
===================================================================
--- gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-83.c  (nonexistent)
+++ gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-83.c  (working copy)
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-options "-O -fdump-tree-fre1-details" } */
+
+struct X
+{
+   int a : 1;
+   int b : 1;
+} x;
+
+void foo (int v)
+{
+  x.a = 1;
+  x.b = v;
+  x.a = 1;
+  x.b = v;
+}
+
+struct Y
+{
+   _Bool a;
+   _Bool b;
+} y;
+
+void bar (int v)
+{
+  y.a = 1;
+  y.b = v;
+  y.a = 1;
+  y.b = v;
+}
+
+/* { dg-final { scan-tree-dump-times "Deleted redundant store" 4 "fre1" } } */

Reply via email to