From e7a71ff849749f19d5b738f90a06d2f2dd78581e Mon Sep 17 00:00:00 2001 From: rguenth Date: Tue, 11 Mar 2014 12:42:18 +0000 Subject: [PATCH] 2014-03-11 Richard Biener 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 | 10 ++++ gcc/testsuite/ChangeLog | 7 +++ gcc/testsuite/gcc.dg/pr60485-1.c | 29 +++++++++++ gcc/testsuite/gcc.dg/pr60485-2.c | 38 ++++++++++++++ gcc/tree-ssa-structalias.c | 110 ++++++++++++++++++++------------------- 5 files changed, 141 insertions(+), 53 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/pr60485-1.c create mode 100644 gcc/testsuite/gcc.dg/pr60485-2.c 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 + + 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 * 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 + + 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 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; -- 2.7.4