2014-03-11 Richard Biener <rguenther@suse.de>
authorrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 11 Mar 2014 12:42:18 +0000 (12:42 +0000)
committerrguenth <rguenth@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 11 Mar 2014 12:42:18 +0000 (12:42 +0000)
PR tree-optimization/60429
PR tree-optimization/60485
* tree-ssa-structalias.c (set_union_with_increment): Properly
take into account all fields that overlap the shifted vars.
(do_sd_constraint): Likewise.
(do_ds_constraint): Likewise.
(get_constraint_for_ptr_offset): Likewise.

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

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@208479 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/pr60485-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/pr60485-2.c [new file with mode: 0644]
gcc/tree-ssa-structalias.c

index 073c9c4..a382415 100644 (file)
@@ -1,3 +1,13 @@
+2014-03-11  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/60429
+       PR tree-optimization/60485
+       * tree-ssa-structalias.c (set_union_with_increment): Properly
+       take into account all fields that overlap the shifted vars.
+       (do_sd_constraint): Likewise.
+       (do_ds_constraint): Likewise.
+       (get_constraint_for_ptr_offset): Likewise.
+
 2014-03-11  Chung-Lin Tang  <cltang@codesourcery.com>
 
        * config/nios2/nios2.c (machine_function): Add fp_save_offset field.
index 41b6875..241f619 100644 (file)
@@ -1,3 +1,10 @@
+2014-03-11  Richard Biener  <rguenther@suse.de>
+
+       PR tree-optimization/60429
+       PR tree-optimization/60485
+       * gcc.dg/pr60485-1.c: New testcase.
+       * gcc.dg/pr60485-2.c: Likewise.
+
 2014-03-10  Jakub Jelinek  <jakub@redhat.com>
 
        PR ipa/60457
diff --git a/gcc/testsuite/gcc.dg/pr60485-1.c b/gcc/testsuite/gcc.dg/pr60485-1.c
new file mode 100644 (file)
index 0000000..2e5c2e5
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+extern void abort (void);
+struct S {
+    int *i[4];
+    int *p1;
+    int *p2;
+    int *p3;
+    int *p4;
+};
+int **b;
+int main()
+{
+  int i = 1;
+  struct S s;
+  s.p3 = &i;
+  int **p;
+  if (b)
+    p = b;
+  else
+    p = &s.i[2];
+  p += 4;
+  if (!b)
+    **p = 0;
+  if (i != 0)
+    abort ();
+  return i;
+}
diff --git a/gcc/testsuite/gcc.dg/pr60485-2.c b/gcc/testsuite/gcc.dg/pr60485-2.c
new file mode 100644 (file)
index 0000000..767e61d
--- /dev/null
@@ -0,0 +1,38 @@
+/* { dg-do run } */
+/* { dg-options "-O2" } */
+
+extern void abort (void);
+struct S {
+    int *i[4];
+    int *p1;
+    int *p2;
+    int *p3;
+    int *p4;
+    int **x;
+};
+int **b;
+int main()
+{
+  int i = 1;
+  struct S s;
+  s.p3 = &i;
+  int **p;
+  if (b)
+    p = b;
+  else
+    p = &s.i[2];
+  p += 4;
+  /* prevert fowrprop from creating an offsetted sd constraint and
+     preserve the pointer offsetting constraint.  */
+  s.x = p;
+  p = s.x;
+  if (!b)
+    {
+      int *z = *p;
+      /* z should point to i (and non-local/escaped).  */
+      *z = 0;
+    }
+  if (i != 0)
+    abort ();
+  return i;
+}
index 402b3d1..e1e1147 100644 (file)
@@ -993,23 +993,28 @@ set_union_with_increment  (bitmap to, bitmap delta, HOST_WIDE_INT inc,
        changed |= bitmap_set_bit (to, i);
       else
        {
-         unsigned HOST_WIDE_INT fieldoffset = vi->offset + inc;
+         HOST_WIDE_INT fieldoffset = vi->offset + inc;
+         unsigned HOST_WIDE_INT size = vi->size;
 
          /* If the offset makes the pointer point to before the
             variable use offset zero for the field lookup.  */
-         if (inc < 0
-             && fieldoffset > vi->offset)
-           fieldoffset = 0;
-
-         vi = first_or_preceding_vi_for_offset (vi, fieldoffset);
-
-         changed |= bitmap_set_bit (to, vi->id);
-         /* If the result is not exactly at fieldoffset include the next
-            field as well.  See get_constraint_for_ptr_offset for more
-            rationale.  */
-         if (vi->offset != fieldoffset
-             && vi->next != 0)
-           changed |= bitmap_set_bit (to, vi->next);
+         if (fieldoffset < 0)
+           vi = get_varinfo (vi->head);
+         else
+           vi = first_or_preceding_vi_for_offset (vi, fieldoffset);
+
+         do
+           {
+             changed |= bitmap_set_bit (to, vi->id);
+             if (vi->is_full_var
+                 || vi->next == 0)
+               break;
+
+             /* We have to include all fields that overlap the current field
+                shifted by inc.  */
+             vi = vi_next (vi);
+           }
+         while (vi->offset < fieldoffset + size);
        }
     }
 
@@ -1618,16 +1623,21 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c,
     {
       varinfo_t v = get_varinfo (j);
       HOST_WIDE_INT fieldoffset = v->offset + roffset;
+      unsigned HOST_WIDE_INT size = v->size;
       unsigned int t;
 
       if (v->is_full_var)
-       fieldoffset = v->offset;
+       ;
       else if (roffset != 0)
-       v = first_vi_for_offset (v, fieldoffset);
-      /* If the access is outside of the variable we can ignore it.  */
-      if (!v)
-       continue;
+       {
+         if (fieldoffset < 0)
+           v = get_varinfo (v->head);
+         else
+           v = first_or_preceding_vi_for_offset (v, fieldoffset);
+       }
 
+      /* We have to include all fields that overlap the current field
+        shifted by roffset.  */
       do
        {
          t = find (v->id);
@@ -1644,16 +1654,13 @@ do_sd_constraint (constraint_graph_t graph, constraint_t c,
                   && add_graph_edge (graph, lhs, t))
            flag |= bitmap_ior_into (sol, get_varinfo (t)->solution);
 
-         /* If the variable is not exactly at the requested offset
-            we have to include the next one.  */
-         if (v->offset == (unsigned HOST_WIDE_INT)fieldoffset
+         if (v->is_full_var
              || v->next == 0)
            break;
 
          v = vi_next (v);
-         fieldoffset = v->offset;
        }
-      while (1);
+      while (v->offset < fieldoffset + size);
     }
 
 done:
@@ -1716,15 +1723,20 @@ do_ds_constraint (constraint_t c, bitmap delta, bitmap *expanded_delta)
       varinfo_t v = get_varinfo (j);
       unsigned int t;
       HOST_WIDE_INT fieldoffset = v->offset + loff;
+      unsigned HOST_WIDE_INT size = v->size;
 
       if (v->is_full_var)
-       fieldoffset = v->offset;
+       ;
       else if (loff != 0)
-       v = first_vi_for_offset (v, fieldoffset);
-      /* If the access is outside of the variable we can ignore it.  */
-      if (!v)
-       continue;
+       {
+         if (fieldoffset < 0)
+           v = get_varinfo (v->head);
+         else
+           v = first_or_preceding_vi_for_offset (v, fieldoffset);
+       }
 
+      /* We have to include all fields that overlap the current field
+        shifted by loff.  */
       do
        {
          if (v->may_have_pointers)
@@ -1750,16 +1762,13 @@ do_ds_constraint (constraint_t c, bitmap delta, bitmap *expanded_delta)
                bitmap_set_bit (changed, t);
            }
 
-         /* If the variable is not exactly at the requested offset
-            we have to include the next one.  */
-         if (v->offset == (unsigned HOST_WIDE_INT)fieldoffset
+         if (v->is_full_var
              || v->next == 0)
            break;
 
          v = vi_next (v);
-         fieldoffset = v->offset;
        }
-      while (1);
+      while (v->offset < fieldoffset + size);
     }
 }
 
@@ -3109,35 +3118,30 @@ get_constraint_for_ptr_offset (tree ptr, tree offset,
          varinfo_t temp;
          unsigned HOST_WIDE_INT offset = curr->offset + rhsoffset;
 
-         /* Search the sub-field which overlaps with the
-            pointed-to offset.  If the result is outside of the variable
-            we have to provide a conservative result, as the variable is
-            still reachable from the resulting pointer (even though it
-            technically cannot point to anything).  The last and first
-            sub-fields are such conservative results.
-            ???  If we always had a sub-field for &object + 1 then
-            we could represent this in a more precise way.  */
+         /* If curr->offset + rhsoffset is less than zero adjust it.  */
          if (rhsoffset < 0
              && curr->offset < offset)
            offset = 0;
-         temp = first_or_preceding_vi_for_offset (curr, offset);
 
-         /* If the found variable is not exactly at the pointed to
-            result, we have to include the next variable in the
-            solution as well.  Otherwise two increments by offset / 2
-            do not result in the same or a conservative superset
-            solution.  */
-         if (temp->offset != offset
-             && temp->next != 0)
+         /* We have to include all fields that overlap the current
+            field shifted by rhsoffset.  And we include at least
+            the last or the first field of the variable to represent
+            reachability of off-bound addresses, in particular &object + 1,
+            conservatively correct.  */
+         temp = first_or_preceding_vi_for_offset (curr, offset);
+         c.var = temp->id;
+         c.offset = 0;
+         temp = vi_next (temp);
+         while (temp
+                && temp->offset < offset + curr->size)
            {
              struct constraint_expr c2;
-             c2.var = temp->next;
+             c2.var = temp->id;
              c2.type = ADDRESSOF;
              c2.offset = 0;
              results->safe_push (c2);
+             temp = vi_next (temp);
            }
-         c.var = temp->id;
-         c.offset = 0;
        }
       else
        c.offset = rhsoffset;