aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Biener <rguenther@suse.de>2014-03-11 12:42:18 +0000
committerRichard Biener <rguenth@gcc.gnu.org>2014-03-11 12:42:18 +0000
commitaf1ab44914e9d544f7b24c21634e02f62ef086ff (patch)
treeaf561b689b875e166348ce17ab0dfa579443ef87
parent75b107f5942b75e085958c04b09dbcbf12ff68ac (diff)
downloadgcc-af1ab44914e9d544f7b24c21634e02f62ef086ff.zip
gcc-af1ab44914e9d544f7b24c21634e02f62ef086ff.tar.gz
gcc-af1ab44914e9d544f7b24c21634e02f62ef086ff.tar.bz2
re PR middle-end/60429 (Miscompilation (aliasing) with -finline-functions)
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. * gcc.dg/pr60485-1.c: New testcase. * gcc.dg/pr60485-2.c: Likewise. From-SVN: r208479
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/testsuite/ChangeLog7
-rw-r--r--gcc/testsuite/gcc.dg/pr60485-1.c29
-rw-r--r--gcc/testsuite/gcc.dg/pr60485-2.c38
-rw-r--r--gcc/tree-ssa-structalias.c110
5 files changed, 141 insertions, 53 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 073c9c4..a382415 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 41b6875..241f619 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
index 0000000..2e5c2e5
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr60485-1.c
@@ -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
index 0000000..767e61d
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/pr60485-2.c
@@ -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;
+}
diff --git a/gcc/tree-ssa-structalias.c b/gcc/tree-ssa-structalias.c
index 402b3d1..e1e1147 100644
--- a/gcc/tree-ssa-structalias.c
+++ b/gcc/tree-ssa-structalias.c
@@ -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;