re PR tree-optimization/91091 ([missed optimization] Missing optimization in unaliase...
authorRichard Biener <rguenther@suse.de>
Fri, 5 Jul 2019 12:50:45 +0000 (12:50 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Fri, 5 Jul 2019 12:50:45 +0000 (12:50 +0000)
2019-07-05  Richard Biener  <rguenther@suse.de>

PR tree-optimization/91091
* tree-ssa-alias.h (get_continuation_for_phi): Add tbaa_p parameter.
(walk_non_aliased_vuses): Likewise.
* tree-ssa-alias.c (maybe_skip_until): Pass down tbaa_p.
(get_continuation_for_phi): New tbaa_p parameter and pass
it down.
(walk_non_aliased_vuses): Likewise.
* ipa-prop.c (determine_known_aggregate_parts): Adjust.
* tree-ssa-pre.c (translate_vuse_through_block): Likewise.
* tree-ssa-scopedtables.c (avail_exprs_stack::lookup_avail_expr):
Likewise.
* tree-ssa-sccvn.c (struct vn_walk_cb_data): Add tbaa_p flag.
(adjust_offsets_for_equal_base_address): New function.
(vn_reference_lookup_3): Use it to catch more base equivalences.
Handle and pass down tbaa_p flag.
(vn_reference_lookup_pieces): Adjust.
(vn_reference_lookup): Remove alias-set altering, instead pass
down false as tbaa_p.

* gcc.dg/tree-ssa/pr91091-2.c: New testcase.
* gcc.dg/tree-ssa/ssa-fre-70.c: Likewise.
* gcc.dg/tree-ssa/ssa-fre-71.c: Likewise.
* gcc.dg/tree-ssa/ssa-fre-72.c: Likewise.

From-SVN: r273135

12 files changed:
gcc/ChangeLog
gcc/ipa-prop.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/tree-ssa/pr91091-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-70.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-71.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-72.c [new file with mode: 0644]
gcc/tree-ssa-alias.c
gcc/tree-ssa-alias.h
gcc/tree-ssa-pre.c
gcc/tree-ssa-sccvn.c
gcc/tree-ssa-scopedtables.c

index 25e539f..6dd97ab 100644 (file)
@@ -1,6 +1,27 @@
 2019-07-05  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/91091
+       * tree-ssa-alias.h (get_continuation_for_phi): Add tbaa_p parameter.
+       (walk_non_aliased_vuses): Likewise.
+       * tree-ssa-alias.c (maybe_skip_until): Pass down tbaa_p.
+       (get_continuation_for_phi): New tbaa_p parameter and pass
+       it down.
+       (walk_non_aliased_vuses): Likewise.
+       * ipa-prop.c (determine_known_aggregate_parts): Adjust.
+       * tree-ssa-pre.c (translate_vuse_through_block): Likewise.
+       * tree-ssa-scopedtables.c (avail_exprs_stack::lookup_avail_expr):
+       Likewise.
+       * tree-ssa-sccvn.c (struct vn_walk_cb_data): Add tbaa_p flag.
+       (adjust_offsets_for_equal_base_address): New function.
+       (vn_reference_lookup_3): Use it to catch more base equivalences.
+       Handle and pass down tbaa_p flag.
+       (vn_reference_lookup_pieces): Adjust.
+       (vn_reference_lookup): Remove alias-set altering, instead pass
+       down false as tbaa_p.
+
+2019-07-05  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/91091
        * tree-ssa-sccvn.c (vn_reference_lookup_3): Overlap of
        accesses can happen with -fno-strict-aliasing.
 
index a53a6ec..f5f8c75 100644 (file)
@@ -1678,7 +1678,8 @@ determine_known_aggregate_parts (gcall *call, tree arg,
 
       if (gimple_code (stmt) == GIMPLE_PHI)
        {
-         dom_vuse = get_continuation_for_phi (stmt, &r, *aa_walk_budget_p,
+         dom_vuse = get_continuation_for_phi (stmt, &r, true,
+                                              *aa_walk_budget_p,
                                               &visited, false, NULL, NULL);
          continue;
        }
index 6c049d0..5656a5b 100644 (file)
@@ -1,6 +1,14 @@
 2019-07-05  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/91091
+       * gcc.dg/tree-ssa/pr91091-2.c: New testcase.
+       * gcc.dg/tree-ssa/ssa-fre-70.c: Likewise.
+       * gcc.dg/tree-ssa/ssa-fre-71.c: Likewise.
+       * gcc.dg/tree-ssa/ssa-fre-72.c: Likewise.
+
+2019-07-05  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/91091
        * gcc.dg/tree-ssa/pr91091-1.c: New testcase.
        * gcc.dg/tree-ssa/ssa-fre-61.c: Adjust.
 
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr91091-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr91091-2.c
new file mode 100644 (file)
index 0000000..b578de7
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-fre1" } */
+
+struct s { int x; };
+struct t { int x; };
+
+void swap(struct s* p, struct t* q)
+{
+  p->x = q->x;
+  q->x = p->x;
+}
+
+/* The second statement is redundant.  */
+/* { dg-final { scan-tree-dump-times "x = " 1 "fre1" } } */
+/* { dg-final { scan-tree-dump-times " = \[^;\]*x;" 1 "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-70.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-70.c
new file mode 100644 (file)
index 0000000..612d753
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple -O -fdump-tree-fre1" } */
+
+__GIMPLE (ssa, startwith("fre")) char foo(char *p)
+{
+  char _1;
+
+__BB(2):
+  __MEM <char[4]> (p) = _Literal (char[4]) {};
+  _1 = __MEM <char> (p + 1);
+  return _1;
+}
+
+/* { dg-final { scan-tree-dump "return 0;" "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-71.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-71.c
new file mode 100644 (file)
index 0000000..edc8899
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple -O -fdump-tree-fre1-details" } */
+
+__GIMPLE (ssa, startwith("fre")) char foo(char *p)
+{
+  char _1;
+
+__BB(2):
+  __MEM <int> (p) = 0;
+  _1 = __MEM <char> (p + 1);
+  return _1;
+}
+
+/* { dg-final { scan-tree-dump "return 0;" "fre1" } } */
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-72.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-72.c
new file mode 100644 (file)
index 0000000..b95709f
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-fgimple -O -fdump-tree-fre1" } */
+
+__GIMPLE (ssa,startwith("fre")) char foo(char *p, int i)
+{
+  char _1;
+
+__BB(2):
+  __MEM <int> (p) = i_2(D);
+  _1 = __MEM <char> (p + 1);
+  return _1;
+}
+
+/* { dg-final { scan-tree-dump "BIT_FIELD_REF" "fre1" } } */
index d52d47c..b5e980d 100644 (file)
@@ -3054,8 +3054,8 @@ stmt_kills_ref_p (gimple *stmt, tree ref)
 
 static bool
 maybe_skip_until (gimple *phi, tree &target, basic_block target_bb,
-                 ao_ref *ref, tree vuse, unsigned int &limit, bitmap *visited,
-                 bool abort_on_visited,
+                 ao_ref *ref, tree vuse, bool tbaa_p, unsigned int &limit,
+                 bitmap *visited, bool abort_on_visited,
                  void *(*translate)(ao_ref *, tree, void *, bool *),
                  void *data)
 {
@@ -3089,7 +3089,7 @@ maybe_skip_until (gimple *phi, tree &target, basic_block target_bb,
          /* An already visited PHI node ends the walk successfully.  */
          if (bitmap_bit_p (*visited, SSA_NAME_VERSION (PHI_RESULT (def_stmt))))
            return !abort_on_visited;
-         vuse = get_continuation_for_phi (def_stmt, ref, limit,
+         vuse = get_continuation_for_phi (def_stmt, ref, tbaa_p, limit,
                                           visited, abort_on_visited,
                                           translate, data);
          if (!vuse)
@@ -3104,7 +3104,7 @@ maybe_skip_until (gimple *phi, tree &target, basic_block target_bb,
          if ((int)limit <= 0)
            return false;
          --limit;
-         if (stmt_may_clobber_ref_p_1 (def_stmt, ref))
+         if (stmt_may_clobber_ref_p_1 (def_stmt, ref, tbaa_p))
            {
              bool disambiguate_only = true;
              if (translate
@@ -3136,7 +3136,7 @@ maybe_skip_until (gimple *phi, tree &target, basic_block target_bb,
    Returns NULL_TREE if no suitable virtual operand can be found.  */
 
 tree
-get_continuation_for_phi (gimple *phi, ao_ref *ref,
+get_continuation_for_phi (gimple *phi, ao_ref *ref, bool tbaa_p,
                          unsigned int &limit, bitmap *visited,
                          bool abort_on_visited,
                          void *(*translate)(ao_ref *, tree, void *, bool *),
@@ -3179,7 +3179,8 @@ get_continuation_for_phi (gimple *phi, ao_ref *ref,
       arg1 = PHI_ARG_DEF (phi, i);
       if (arg1 == arg0)
        ;
-      else if (! maybe_skip_until (phi, arg0, dom, ref, arg1, limit, visited,
+      else if (! maybe_skip_until (phi, arg0, dom, ref, arg1, tbaa_p,
+                                  limit, visited,
                                   abort_on_visited,
                                   /* Do not translate when walking over
                                      backedges.  */
@@ -3223,7 +3224,7 @@ get_continuation_for_phi (gimple *phi, ao_ref *ref,
    TODO: Cache the vector of equivalent vuses per ref, vuse pair.  */
 
 void *
-walk_non_aliased_vuses (ao_ref *ref, tree vuse,
+walk_non_aliased_vuses (ao_ref *ref, tree vuse, bool tbaa_p,
                        void *(*walker)(ao_ref *, tree, void *),
                        void *(*translate)(ao_ref *, tree, void *, bool *),
                        tree (*valueize)(tree),
@@ -3264,7 +3265,7 @@ walk_non_aliased_vuses (ao_ref *ref, tree vuse,
       if (gimple_nop_p (def_stmt))
        break;
       else if (gimple_code (def_stmt) == GIMPLE_PHI)
-       vuse = get_continuation_for_phi (def_stmt, ref, limit,
+       vuse = get_continuation_for_phi (def_stmt, ref, tbaa_p, limit,
                                         &visited, translated, translate, data);
       else
        {
@@ -3274,7 +3275,7 @@ walk_non_aliased_vuses (ao_ref *ref, tree vuse,
              break;
            }
          --limit;
-         if (stmt_may_clobber_ref_p_1 (def_stmt, ref))
+         if (stmt_may_clobber_ref_p_1 (def_stmt, ref, tbaa_p))
            {
              if (!translate)
                break;
index cee8449..ddd28ec 100644 (file)
@@ -131,11 +131,11 @@ extern bool call_may_clobber_ref_p (gcall *, tree);
 extern bool call_may_clobber_ref_p_1 (gcall *, ao_ref *);
 extern bool stmt_kills_ref_p (gimple *, tree);
 extern bool stmt_kills_ref_p (gimple *, ao_ref *);
-extern tree get_continuation_for_phi (gimple *, ao_ref *,
+extern tree get_continuation_for_phi (gimple *, ao_ref *, bool,
                                      unsigned int &, bitmap *, bool,
                                      void *(*)(ao_ref *, tree, void *, bool *),
                                      void *);
-extern void *walk_non_aliased_vuses (ao_ref *, tree,
+extern void *walk_non_aliased_vuses (ao_ref *, tree, bool,
                                     void *(*)(ao_ref *, tree, void *),
                                     void *(*)(ao_ref *, tree, void *, bool *),
                                     tree (*)(tree), unsigned &, void *);
index 086f8c3..231ac00 100644 (file)
@@ -1185,8 +1185,8 @@ translate_vuse_through_block (vec<vn_reference_op_s> operands,
          bitmap visited = NULL;
          /* Try to find a vuse that dominates this phi node by skipping
             non-clobbering statements.  */
-         vuse = get_continuation_for_phi (phi, &ref, cnt, &visited, false,
-                                          NULL, NULL);
+         vuse = get_continuation_for_phi (phi, &ref, true,
+                                          cnt, &visited, false, NULL, NULL);
          if (visited)
            BITMAP_FREE (visited);
        }
index 2cc76d8..6d4ad75 100644 (file)
@@ -1648,9 +1648,16 @@ vn_reference_lookup_1 (vn_reference_t vr, vn_reference_t *vnresult)
 
 struct vn_walk_cb_data
 {
+  vn_walk_cb_data (vn_reference_t vr_, tree *last_vuse_ptr_,
+                   vn_lookup_kind vn_walk_kind_, bool tbaa_p_)
+    : vr (vr_), last_vuse_ptr (last_vuse_ptr_), vn_walk_kind (vn_walk_kind_),
+      tbaa_p (tbaa_p_)
+    {}
+
   vn_reference_t vr;
   tree *last_vuse_ptr;
   vn_lookup_kind vn_walk_kind;
+  bool tbaa_p;
 };
 
 /* Callback for walk_non_aliased_vuses.  Adjusts the vn_reference_t VR_
@@ -1927,6 +1934,33 @@ public:
 static rpo_elim *rpo_avail;
 basic_block vn_context_bb;
 
+/* Return true if BASE1 and BASE2 can be adjusted so they have the
+   same address and adjust *OFFSET1 and *OFFSET2 accordingly.
+   Otherwise return false.  */
+
+static bool
+adjust_offsets_for_equal_base_address (tree base1, poly_int64 *offset1,
+                                      tree base2, poly_int64 *offset2)
+{
+  poly_int64 soff;
+  if (TREE_CODE (base1) == MEM_REF
+      && TREE_CODE (base2) == MEM_REF)
+    {
+      if (mem_ref_offset (base1).to_shwi (&soff))
+       {
+         base1 = TREE_OPERAND (base1, 0);
+         *offset1 += soff * BITS_PER_UNIT;
+       }
+      if (mem_ref_offset (base2).to_shwi (&soff))
+       {
+         base2 = TREE_OPERAND (base2, 0);
+         *offset2 += soff * BITS_PER_UNIT;
+       }
+      return operand_equal_p (base1, base2, 0);
+    }
+  return operand_equal_p (base1, base2, OEP_ADDRESS_OF);
+}
+
 /* Callback for walk_non_aliased_vuses.  Tries to perform a lookup
    from the statement defining VUSE and if not successful tries to
    translate *REFP and VR_ through an aggregate copy at the definition
@@ -1966,7 +2000,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
                                                      get_alias_set (lhs),
                                                      TREE_TYPE (lhs), lhs_ops);
          if (lhs_ref_ok
-             && !refs_may_alias_p_1 (ref, &lhs_ref, true))
+             && !refs_may_alias_p_1 (ref, &lhs_ref, data->tbaa_p))
            {
              *disambiguate_only = true;
              return NULL;
@@ -2055,7 +2089,9 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
        }
     }
 
-  if (*disambiguate_only)
+  /* If we are looking for redundant stores do not create new hashtable
+     entries from aliasing defs with made up alias-sets.  */
+  if (*disambiguate_only || !data->tbaa_p)
     return (void *)-1;
 
   /* If we cannot constrain the size of the reference we cannot
@@ -2186,7 +2222,8 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
                                       &offset2, &size2, &maxsize2, &reverse);
       if (known_size_p (maxsize2)
          && known_eq (maxsize2, size2)
-         && operand_equal_p (base, base2, 0)
+         && adjust_offsets_for_equal_base_address (base, &offset,
+                                                   base2, &offset2)
          && known_subrange_p (offset, maxsize, offset2, size2))
        {
          tree val = build_zero_cst (vr->type);
@@ -2213,15 +2250,20 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
                   && is_gimple_min_invariant (SSA_VAL (gimple_assign_rhs1 (def_stmt))))))
     {
       tree base2;
-      HOST_WIDE_INT offset2, size2;
+      poly_int64 offset2, size2, maxsize2;
+      HOST_WIDE_INT offset2i;
       bool reverse;
-      base2 = get_ref_base_and_extent_hwi (gimple_assign_lhs (def_stmt),
-                                          &offset2, &size2, &reverse);
+      base2 = get_ref_base_and_extent (gimple_assign_lhs (def_stmt),
+                                      &offset2, &size2, &maxsize2, &reverse);
       if (base2
          && !reverse
-         && size2 % BITS_PER_UNIT == 0
-         && offset2 % BITS_PER_UNIT == 0
-         && operand_equal_p (base, base2, 0)
+         && known_eq (maxsize2, size2)
+         && multiple_p (size2, BITS_PER_UNIT)
+         && multiple_p (offset2, BITS_PER_UNIT)
+         && adjust_offsets_for_equal_base_address (base, &offset,
+                                                   base2, &offset2)
+         && offset.is_constant (&offseti)
+         && offset2.is_constant (&offset2i)
          && known_subrange_p (offseti, maxsizei, offset2, size2))
        {
          /* We support up to 512-bit values (for V8DFmode).  */
@@ -2233,12 +2275,12 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
            rhs = SSA_VAL (rhs);
          len = native_encode_expr (rhs,
                                    buffer, sizeof (buffer),
-                                   (offseti - offset2) / BITS_PER_UNIT);
+                                   (offseti - offset2i) / BITS_PER_UNIT);
          if (len > 0 && len * BITS_PER_UNIT >= maxsizei)
            {
              tree type = vr->type;
              /* Make sure to interpret in a type that has a range
-                covering the whole access size.  */
+                covering the whole access size.  */
              if (INTEGRAL_TYPE_P (vr->type)
                  && maxsizei != TYPE_PRECISION (vr->type))
                type = build_nonstandard_integer_type (maxsizei,
@@ -2283,7 +2325,8 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_,
       if (!reverse
          && known_size_p (maxsize2)
          && known_eq (maxsize2, size2)
-         && operand_equal_p (base, base2, 0)
+         && adjust_offsets_for_equal_base_address (base, &offset,
+                                                   base2, &offset2)
          && known_subrange_p (offset, maxsize, offset2, size2)
          /* ???  We can't handle bitfield precision extracts without
             either using an alternate type for the BIT_FIELD_REF and
@@ -2653,10 +2696,10 @@ vn_reference_lookup_pieces (tree vuse, alias_set_type set, tree type,
     {
       ao_ref r;
       unsigned limit = PARAM_VALUE (PARAM_SCCVN_MAX_ALIAS_QUERIES_PER_ACCESS);
-      vn_walk_cb_data data = { &vr1, NULL, kind };
+      vn_walk_cb_data data (&vr1, NULL, kind, true);
       if (ao_ref_init_from_vn_reference (&r, set, type, vr1.operands))
        *vnresult =
-         (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
+         (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse, true,
                                                  vn_reference_lookup_2,
                                                  vn_reference_lookup_3,
                                                  vuse_valueize, limit, &data);
@@ -2693,7 +2736,7 @@ vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind,
   vr1.operands = operands
     = valueize_shared_reference_ops_from_ref (op, &valuezied_anything);
   vr1.type = TREE_TYPE (op);
-  vr1.set = tbaa_p ? get_alias_set (op) : 0;
+  vr1.set = get_alias_set (op);
   vr1.hashcode = vn_reference_compute_hash (&vr1);
   if ((cst = fully_constant_vn_reference_p (&vr1)))
     return cst;
@@ -2710,11 +2753,9 @@ vn_reference_lookup (tree op, tree vuse, vn_lookup_kind kind,
          || !ao_ref_init_from_vn_reference (&r, vr1.set, vr1.type,
                                             vr1.operands))
        ao_ref_init (&r, op);
-      if (! tbaa_p)
-       r.ref_alias_set = r.base_alias_set = 0;
-      vn_walk_cb_data data = { &vr1, last_vuse_ptr, kind };
+      vn_walk_cb_data data (&vr1, last_vuse_ptr, kind, tbaa_p);
       wvnresult =
-       (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse,
+       (vn_reference_t)walk_non_aliased_vuses (&r, vr1.vuse, tbaa_p,
                                                vn_reference_lookup_2,
                                                vn_reference_lookup_3,
                                                vuse_valueize, limit, &data);
index 50413eb..838cf8f 100644 (file)
@@ -298,7 +298,7 @@ avail_exprs_stack::lookup_avail_expr (gimple *stmt, bool insert, bool tbaa_p)
            && TREE_CODE (gimple_assign_lhs (stmt)) == SSA_NAME
            && (ao_ref_init (&ref, gimple_assign_rhs1 (stmt)),
                ref.base_alias_set = ref.ref_alias_set = tbaa_p ? -1 : 0, true)
-           && walk_non_aliased_vuses (&ref, vuse2, vuse_eq, NULL, NULL,
+           && walk_non_aliased_vuses (&ref, vuse2, true, vuse_eq, NULL, NULL,
                                       limit, vuse1) != NULL))
        {
          if (insert)