re PR tree-optimization/81884 (Invalid code generation with zero size arrays or flexi...
authorRichard Biener <rguenther@suse.de>
Mon, 21 Aug 2017 07:37:59 +0000 (07:37 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 21 Aug 2017 07:37:59 +0000 (07:37 +0000)
2017-08-21  Richard Biener  <rguenther@suse.de>

PR middle-end/81884
* tree-ssa-alias.c (stmt_kills_ref_p): Handle array accesses
at struct end conservatively when comparing common bases.

* g++.dg/torture/pr81884.C: New testcase.

From-SVN: r251217

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/torture/pr81884.C [new file with mode: 0644]
gcc/tree-ssa-alias.c

index f4f12e072c8ea7cc3ac58d14d3f1609fab8bc171..213b5c803ab9d03c791f6672ebfcab0b9dc8a913 100644 (file)
@@ -1,3 +1,9 @@
+2017-08-21  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/81884
+       * tree-ssa-alias.c (stmt_kills_ref_p): Handle array accesses
+       at struct end conservatively when comparing common bases.
+
 2017-08-21  Richard Biener  <rguenther@suse.de>
 
        * tree-ssa-loop-im.c (struct lim_aux_data): Add ref index member.
index 749847f1914b1d5fce4c3e72ef7f239f2e0c632d..35d0be15c0e106a502708b949ea0035d1fe1bca5 100644 (file)
@@ -1,3 +1,8 @@
+2017-08-21  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/81884
+       * g++.dg/torture/pr81884.C: New testcase.
+
 2017-08-20  John David Anglin  <danglin@gcc.gnu.org>
 
        PR ipa/77732
diff --git a/gcc/testsuite/g++.dg/torture/pr81884.C b/gcc/testsuite/g++.dg/torture/pr81884.C
new file mode 100644 (file)
index 0000000..f545355
--- /dev/null
@@ -0,0 +1,39 @@
+/* { dg-do run } */
+
+typedef unsigned long uint64_t;
+
+struct value_t {
+    uint64_t _count;
+    value_t(uint64_t c) : _count(c) {}
+};
+
+struct X {
+    value_t eventTime;
+    uint64_t arr[0];
+};
+
+X* x;
+
+__attribute__((noclone, noinline))
+void initialize()
+{
+  x->arr[0] = 11;
+  x->arr[1] = 12;
+  x->eventTime = value_t(10);
+  x->arr[2] = 13;
+  x->arr[3] = 14;
+}
+
+int main()
+{
+  char buffer[sizeof(X) + sizeof(uint64_t)*4];
+  x = (X*)buffer;
+  x->eventTime = value_t(999);
+  x->arr[0] = 1;
+  x->arr[1] = 2;
+  x->arr[2] = 3;
+  x->arr[3] = 4;
+  initialize();
+  if (x->arr[0] != 11 || x->arr[1] != 12 || x->arr[2] != 13 || x->arr[3] != 14)
+    __builtin_abort ();
+}
index 5794d227fe53c5f6eb72c7594813fd0f5897812a..9bbc163b1c3206c5b7a9065dbac2a96acf8e7fb3 100644 (file)
@@ -2416,6 +2416,7 @@ stmt_kills_ref_p (gimple *stmt, ao_ref *ref)
       if (ref->ref)
        {
          tree base = ref->ref;
+         tree innermost_dropped_array_ref = NULL_TREE;
          if (handled_component_p (base))
            {
              tree saved_lhs0 = NULL_TREE;
@@ -2435,6 +2436,11 @@ stmt_kills_ref_p (gimple *stmt, ao_ref *ref)
                  TREE_OPERAND (base, 0) = saved_base0;
                  if (res)
                    break;
+                 /* Remember if we drop an array-ref that we need to
+                    double-check not being at struct end.  */ 
+                 if (TREE_CODE (base) == ARRAY_REF
+                     || TREE_CODE (base) == ARRAY_RANGE_REF)
+                   innermost_dropped_array_ref = base;
                  /* Otherwise drop handled components of the access.  */
                  base = saved_base0;
                }
@@ -2443,15 +2449,22 @@ stmt_kills_ref_p (gimple *stmt, ao_ref *ref)
                TREE_OPERAND (lhs, 0) = saved_lhs0;
            }
          /* Finally check if the lhs has the same address and size as the
-            base candidate of the access.  */
-         if (lhs == base
-             || (((TYPE_SIZE (TREE_TYPE (lhs))
-                   == TYPE_SIZE (TREE_TYPE (base)))
-                  || (TYPE_SIZE (TREE_TYPE (lhs))
-                      && TYPE_SIZE (TREE_TYPE (base))
-                      && operand_equal_p (TYPE_SIZE (TREE_TYPE (lhs)),
-                                          TYPE_SIZE (TREE_TYPE (base)), 0)))
-                 && operand_equal_p (lhs, base, OEP_ADDRESS_OF)))
+            base candidate of the access.  Watch out if we have dropped
+            an array-ref that was at struct end, this means ref->ref may
+            be outside of the TYPE_SIZE of its base.  */
+         if ((! innermost_dropped_array_ref
+              || ! array_at_struct_end_p (innermost_dropped_array_ref))
+             && (lhs == base
+                 || (((TYPE_SIZE (TREE_TYPE (lhs))
+                       == TYPE_SIZE (TREE_TYPE (base)))
+                      || (TYPE_SIZE (TREE_TYPE (lhs))
+                          && TYPE_SIZE (TREE_TYPE (base))
+                          && operand_equal_p (TYPE_SIZE (TREE_TYPE (lhs)),
+                                              TYPE_SIZE (TREE_TYPE (base)),
+                                              0)))
+                     && operand_equal_p (lhs, base,
+                                         OEP_ADDRESS_OF
+                                         | OEP_MATCH_SIDE_EFFECTS))))
            return true;
        }