]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
backport: [multiple changes]
authorRichard Biener <rguenther@suse.de>
Thu, 21 Jun 2018 07:24:06 +0000 (07:24 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Thu, 21 Jun 2018 07:24:06 +0000 (07:24 +0000)
2018-06-21  Richard Biener  <rguenther@suse.de>

Backport from mainline
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.

2017-05-04  Richard Biener  <rguenther@suse.de>

  * tree.c (array_at_struct_end_p): Handle arrays at struct
end with flexarrays more conservatively.  Refactor and treat
arrays of arrays or aggregates more strict.  Fix
VIEW_CONVERT_EXPR handling.

2018-04-06  Richard Biener  <rguenther@suse.de>

PR middle-end/85244
* tree-dfa.c (get_ref_base_and_extent): Reset seen_variable_array_ref
after seeing a component reference with an adjacent field.  Treat
refs to arrays at struct end of external decls similar to
refs to unconstrained commons.

* gcc.dg/torture/pr85244-1.c: New testcase.
* gcc.dg/torture/pr85244-2.c: Likewise.

* gcc.dg/tree-prof/pr66295.c: Remove unsupported dg-error scanning.

From-SVN: r261833

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

index 0da795e96588ca9dce2386d04e88305fface063a..0ad4c907ac7afb155f21aae9c3af71b3057c534d 100644 (file)
@@ -1,3 +1,27 @@
+2018-06-21  Richard Biener  <rguenther@suse.de>
+
+       Backport from mainline
+       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-05-04  Richard Biener  <rguenther@suse.de>
+       * tree.c (array_at_struct_end_p): Handle arrays at struct
+       end with flexarrays more conservatively.  Refactor and treat
+       arrays of arrays or aggregates more strict.  Fix
+       VIEW_CONVERT_EXPR handling.
+
+       2018-04-06  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/85244
+       * tree-dfa.c (get_ref_base_and_extent): Reset seen_variable_array_ref
+       after seeing a component reference with an adjacent field.  Treat
+       refs to arrays at struct end of external decls similar to
+       refs to unconstrained commons.
+
 2018-06-20  Richard Biener  <rguenther@suse.de>
 
        * tree-ssa-alias.c (stmt_kills_ref_p): Revert accidentially
index 67095b8a5146e49bdb9658fb6fcc9555a18be10c..bc02092f8bfc8935356e5f4096f15b5646278fc6 100644 (file)
@@ -1,3 +1,19 @@
+2018-06-21  Richard Biener  <rguenther@suse.de>
+
+       Backport from mainline
+       2017-08-21  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/81884
+       * g++.dg/torture/pr81884.C: New testcase.
+
+       2018-04-06  Richard Biener  <rguenther@suse.de>
+
+       PR middle-end/85244
+       * gcc.dg/torture/pr85244-1.c: New testcase.
+       * gcc.dg/torture/pr85244-2.c: Likewise.
+
+       * gcc.dg/tree-prof/pr66295.c: Remove unsupported dg-error scanning.
+
 2018-06-20  Richard Biener  <rguenther@suse.de>
 
        Backport from mainline
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 ();
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr85244-1.c b/gcc/testsuite/gcc.dg/torture/pr85244-1.c
new file mode 100644 (file)
index 0000000..44716aa
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do run } */
+/* { dg-additional-sources "pr85244-2.c" } */
+
+struct s {
+ long a;
+ int b;
+ int tab[];
+};
+
+extern const struct s val;
+extern int idx;
+extern void abort (void);
+
+int main()
+{
+  if (val.tab[0] != 42 || val.tab[1] != 1337 || val.tab[idx] != 1337)
+    abort ();
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.dg/torture/pr85244-2.c b/gcc/testsuite/gcc.dg/torture/pr85244-2.c
new file mode 100644 (file)
index 0000000..d57cb71
--- /dev/null
@@ -0,0 +1,8 @@
+struct s {
+    long a;
+    int b;
+    int tab[];
+};
+
+int idx = 1;
+const struct s val = { 0, 0, { 42, 1337 } };
index e83e821387ff814538c0cd7e3ea4bc991382310c..d7d64c41b075a866ed16d1d9f4ada6515be01816 100644 (file)
@@ -12,7 +12,7 @@ foo (double *__restrict a, double *__restrict b, int n)
 }
 
 double
-bar (double *__restrict a, double *__restrict b, int n)        /* { dg-error "attribute\[^\n\r]*foo\[^\n\r]* is unknown" } */
+bar (double *__restrict a, double *__restrict b, int n)
 {
   double s;
   int i;
index f133abc79bda1d1fbb317019d3af6a1f6a6ee98e..2ebd974baf8fa29d970e463d75884374917abe40 100644 (file)
@@ -433,7 +433,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
                   referenced the last field of a struct or a union member
                   then we have to adjust maxsize by the padding at the end
                   of our field.  */
-               if (seen_variable_array_ref && maxsize != -1)
+               if (seen_variable_array_ref)
                  {
                    tree stype = TREE_TYPE (TREE_OPERAND (exp, 0));
                    tree next = DECL_CHAIN (field);
@@ -449,7 +449,7 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
                            || ssize == NULL
                            || TREE_CODE (ssize) != INTEGER_CST)
                          maxsize = -1;
-                       else
+                       else if (maxsize != -1)
                          {
                            offset_int tem = (wi::to_offset (ssize)
                                              - wi::to_offset (fsize));
@@ -458,6 +458,11 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
                            maxsize += tem;
                          }
                      }
+                   /* An component ref with an adjacent field up in the
+                      structure hierarchy constrains the size of any variable
+                      array ref lower in the access hierarchy.  */
+                   else
+                     seen_variable_array_ref = false;
                  }
              }
            else
@@ -612,8 +617,9 @@ get_ref_base_and_extent (tree exp, HOST_WIDE_INT *poffset,
 
   if (DECL_P (exp))
     {
-      if (flag_unconstrained_commons
-         && TREE_CODE (exp) == VAR_DECL && DECL_COMMON (exp))
+      if (VAR_P (exp)
+         && ((flag_unconstrained_commons && DECL_COMMON (exp))
+             || (DECL_EXTERNAL (exp) && seen_variable_array_ref)))
        {
          tree sz_tree = TYPE_SIZE (TREE_TYPE (exp));
          /* If size is unknown, or we have read to the end, assume there
index 08f10e5248b568f7252d4b54868bd22ab7767d12..3f0011f3d100f9488393144a4b93de635a79c171 100644 (file)
@@ -2235,6 +2235,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;
@@ -2254,6 +2255,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;
                }
@@ -2262,15 +2268,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;
        }
 
index 84f324f03f1003fadfe1a39723e5b624797422b6..e25cbb700c2e1c6f449b71569251cf5f5395e9e0 100644 (file)
@@ -12944,15 +12944,26 @@ array_ref_up_bound (tree exp)
   return NULL_TREE;
 }
 
-/* Returns true if REF is an array reference to an array at the end of
-   a structure.  If this is the case, the array may be allocated larger
+/* Returns true if REF is an array reference or a component reference
+   to an array at the end of a structure.
+   If this is the case, the array may be allocated larger
    than its upper bound implies.  */
 
 bool
 array_at_struct_end_p (tree ref)
 {
-  if (TREE_CODE (ref) != ARRAY_REF
-      && TREE_CODE (ref) != ARRAY_RANGE_REF)
+  tree atype;
+
+  if (TREE_CODE (ref) == ARRAY_REF
+      || TREE_CODE (ref) == ARRAY_RANGE_REF)
+    {
+      atype = TREE_TYPE (TREE_OPERAND (ref, 0));
+      ref = TREE_OPERAND (ref, 0);
+    }
+  else if (TREE_CODE (ref) == COMPONENT_REF
+          && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 1))) == ARRAY_TYPE)
+    atype = TREE_TYPE (TREE_OPERAND (ref, 1));
+  else
     return false;
 
   while (handled_component_p (ref))
@@ -12960,24 +12971,47 @@ array_at_struct_end_p (tree ref)
       /* If the reference chain contains a component reference to a
          non-union type and there follows another field the reference
         is not at the end of a structure.  */
-      if (TREE_CODE (ref) == COMPONENT_REF
-         && TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
+      if (TREE_CODE (ref) == COMPONENT_REF)
        {
-         tree nextf = DECL_CHAIN (TREE_OPERAND (ref, 1));
-         while (nextf && TREE_CODE (nextf) != FIELD_DECL)
-           nextf = DECL_CHAIN (nextf);
-         if (nextf)
-           return false;
+         if (TREE_CODE (TREE_TYPE (TREE_OPERAND (ref, 0))) == RECORD_TYPE)
+           {
+             tree nextf = DECL_CHAIN (TREE_OPERAND (ref, 1));
+             while (nextf && TREE_CODE (nextf) != FIELD_DECL)
+               nextf = DECL_CHAIN (nextf);
+             if (nextf)
+               return false;
+           }
        }
+      /* If we have a multi-dimensional array we do not consider
+         a non-innermost dimension as flex array if the whole
+        multi-dimensional array is at struct end.
+        Same for an array of aggregates with a trailing array
+        member.  */
+      else if (TREE_CODE (ref) == ARRAY_REF)
+       return false;
+      else if (TREE_CODE (ref) == ARRAY_RANGE_REF)
+       ;
+      /* If we view an underlying object as sth else then what we
+         gathered up to now is what we have to rely on.  */
+      else if (TREE_CODE (ref) == VIEW_CONVERT_EXPR)
+       break;
+      else
+       gcc_unreachable ();
 
       ref = TREE_OPERAND (ref, 0);
     }
 
+  /* The array now is at struct end.  Treat flexible arrays as
+     always subject to extend, even into just padding constrained by
+     an underlying decl.  */
+  if (! TYPE_SIZE (atype))
+    return true;
+
   /* If the reference is based on a declared entity, the size of the array
      is constrained by its given domain.  (Do not trust commons PR/69368).  */
   if (DECL_P (ref)
       && !(flag_unconstrained_commons
-          && TREE_CODE (ref) == VAR_DECL && DECL_COMMON (ref)))
+          && VAR_P (ref) && DECL_COMMON (ref)))
     return false;
 
   return true;